This repository has been archived by the owner on Nov 22, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 34
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #21 from illright/feature/modals
Modals
- Loading branch information
Showing
8 changed files
with
238 additions
and
65 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
<script> | ||
import { | ||
Button, | ||
Card, | ||
TextField, | ||
} from '../src/index.js'; | ||
export let doYou; | ||
export let closeCallback; | ||
</script> | ||
|
||
<Card> | ||
<h1>Do you {doYou}?</h1> | ||
<TextField /> | ||
<Button on:click={closeCallback}>close this</Button> | ||
</Card> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export default {}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
@import '../var-defaults.scss'; | ||
@import '_attractions-theme.scss'; | ||
|
||
.modal-overlay { | ||
position: fixed; | ||
left: 0; | ||
top: 0; | ||
width: 100%; | ||
height: 100%; | ||
overflow: hidden; | ||
background-color: $modal-overlay-bg; | ||
z-index: 1000; | ||
display: none; | ||
|
||
&.open { | ||
display: flex; | ||
align-items: center; | ||
justify-content: center; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
<script> | ||
import { setContext, onDestroy } from 'svelte'; | ||
import { writable } from 'svelte/store'; | ||
import modalContextKey from './modal-context-key.js'; | ||
export const modalOverlayKey = {}; | ||
/* Stores modal registration objects. | ||
A key for such a registration is a store object | ||
that stores the open state of the modal. */ | ||
let registeredModals = new Map(); | ||
/* Meant to be bound to registration objects and used as a subscription function. */ | ||
function updateOpenState(newState) { | ||
this.open = newState; | ||
registeredModals = registeredModals; | ||
} | ||
/* Register and render a new modal from the `component` and `props`. | ||
Will return the open state store | ||
– the object that is used for identifying the registration. */ | ||
function register(component, props) { | ||
const openState = writable(false); | ||
const registration = { component, props, open: false }; | ||
registration.unsubscribe = openState.subscribe(updateOpenState.bind(registration)); | ||
registeredModals.set(openState, registration); | ||
return openState; | ||
} | ||
/* Unregister and destroy the modal that corresponds to this `openState`. */ | ||
function unregister(openState) { | ||
const registration = registeredModals.get(openState); | ||
if (registration == null) { | ||
return; | ||
} | ||
registration.unsubscribe(); | ||
registeredModals.delete(openState); | ||
} | ||
/* Pass new props to the modal that corresponds to this `openState`. | ||
Needed to support reactivity. */ | ||
function updateProps(openState, newProps) { | ||
const registration = registeredModals.get(openState); | ||
if (registration == null) { | ||
return; | ||
} | ||
registration.props = newProps; | ||
} | ||
setContext(modalContextKey, { register, update: updateProps, unregister }); | ||
onDestroy(() => { | ||
for (let registration of registeredModals.values()) { | ||
registration.unsubscribe(); | ||
} | ||
}); | ||
</script> | ||
|
||
<slot /> | ||
{#each [...registeredModals.entries()] as [openState, registration] (openState)} | ||
<div | ||
class="modal-overlay" | ||
class:open={registration.open} | ||
on:click|self={() => openState.set(false)} | ||
> | ||
<svelte:component | ||
this={registration.component} | ||
{...registration.props} | ||
closeCallback={() => openState.set(false)} | ||
/> | ||
</div> | ||
{/each} | ||
|
||
<style src="./modal-overlay.scss"></style> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
<script> | ||
import { getContext, onMount, onDestroy } from 'svelte'; | ||
import modalContextKey from './modal-context-key.js'; | ||
const { register, update, unregister } = getContext(modalContextKey); | ||
export let open = false; | ||
/* The component to use in creating a modal. */ | ||
export let component; | ||
/* The props to pass to the modal component. | ||
It will also receive the `closeCallback` prop which can be used to close the modal. */ | ||
export let props; | ||
let openState = null; | ||
let unsubscribe = null; | ||
$: syncOpenState(open); | ||
$: update(openState, props); | ||
/* Written out as a separate function to ensure | ||
that the reactive statement only depends on `open`. */ | ||
function syncOpenState(openStateValue) { | ||
openState && openState.set(openStateValue); | ||
} | ||
onMount(() => { | ||
openState = register(component, props); | ||
unsubscribe = openState.subscribe((openStateValue) => { | ||
/* To prevent unneeded invalidation (if Svelte isn't smart enough not to) */ | ||
if (open !== openStateValue) { | ||
open = openStateValue; | ||
} | ||
}); | ||
}); | ||
onDestroy(() => { | ||
unregister(openState); | ||
if (unsubscribe != null) { | ||
unsubscribe(); | ||
} | ||
}); | ||
</script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters