Skip to content

Commit 9cdef78

Browse files
committed
more docs
1 parent 796536d commit 9cdef78

16 files changed

+359
-273
lines changed

src/app.css

+14
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,17 @@ button:not(.unstyled) {
2121
margin-top: initial !important;
2222
margin-bottom: initial !important;
2323
}
24+
25+
.backdrop {
26+
z-index: 1;
27+
position: fixed;
28+
top: 0;
29+
bottom: 0;
30+
right: 0;
31+
left: 0;
32+
background: rgba(0, 0, 0, 0.5);
33+
}
34+
35+
[role='dialog'] {
36+
z-index: 2;
37+
}

src/lib/ModalStack.svelte

+74-68
Original file line numberDiff line numberDiff line change
@@ -1,99 +1,105 @@
11
<script context="module">
2-
export function useModals() {
3-
return getContext('svelte-modal-stack')
4-
}
2+
export function useModals() {
3+
const ctx = getContext('svelte-modal-stack')
4+
5+
if (!ctx) {
6+
throw Error('useModals() requires a parent <ModalStack /> component')
7+
}
8+
9+
return ctx
10+
}
511
612
</script>
713

814
<script>
9-
import { getContext, setContext } from 'svelte'
10-
import { writable } from 'svelte/store'
15+
import { getContext, setContext } from 'svelte'
16+
import { writable } from 'svelte/store'
1117
12-
let stack = writable([])
13-
let action = writable(null)
18+
let stack = writable([])
19+
let action = writable(null)
1420
15-
let exitBeforeEnter = false
16-
let transitioning = null
21+
let exitBeforeEnter = false
22+
let transitioning = null
1723
18-
function pop(amount = 1) {
19-
$stack = [...$stack].slice(0, $stack.length - amount)
20-
}
24+
function pop(amount = 1) {
25+
$stack = [...$stack].slice(0, $stack.length - amount)
26+
}
2127
22-
function closeAllModals() {
23-
$stack = []
24-
}
28+
function closeAllModals() {
29+
$stack = []
30+
}
2531
26-
function closeModals(amount = 1) {
27-
if (transitioning) {
28-
return
29-
}
32+
function closeModals(amount = 1) {
33+
if (transitioning) {
34+
return
35+
}
3036
31-
if (exitBeforeEnter && $stack.length > 0) {
32-
transitioning = true
33-
}
34-
exitBeforeEnter = false
37+
if (exitBeforeEnter && $stack.length > 0) {
38+
transitioning = true
39+
}
40+
exitBeforeEnter = false
3541
36-
$action = 'pop'
42+
$action = 'pop'
3743
38-
if ($stack.length === 1) {
39-
closeAllModals()
40-
} else {
41-
pop(amount)
42-
}
43-
}
44+
if ($stack.length === 1) {
45+
closeAllModals()
46+
} else {
47+
pop(amount)
48+
}
49+
}
4450
45-
function openModal(component, props, options) {
46-
let newStack = [...$stack]
51+
function openModal(component, props, options) {
52+
let newStack = [...$stack]
4753
48-
if (transitioning) {
49-
return
50-
}
54+
if (transitioning) {
55+
return
56+
}
5157
52-
$action = 'push'
58+
$action = 'push'
5359
54-
if (options?.replace) {
55-
newStack = $stack.slice(0, $stack.length - 1)
56-
}
60+
if (options?.replace) {
61+
newStack = $stack.slice(0, $stack.length - 1)
62+
}
5763
58-
if (exitBeforeEnter && $stack.length > 0) {
59-
transitioning = true
60-
}
61-
exitBeforeEnter = false
64+
if (exitBeforeEnter && $stack.length > 0) {
65+
transitioning = true
66+
}
67+
exitBeforeEnter = false
6268
63-
$stack = [...newStack, { component, props }]
64-
}
69+
$stack = [...newStack, { component, props }]
70+
}
6571
66-
const context = {
67-
openModal,
68-
closeModal: () => closeModals(1),
69-
closeModals,
70-
closeAllModals,
71-
stack,
72-
action
73-
}
72+
const context = {
73+
openModal,
74+
closeModal: () => closeModals(1),
75+
closeModals,
76+
closeAllModals,
77+
stack,
78+
action
79+
}
7480
75-
setContext('svelte-modal-stack', context)
81+
setContext('svelte-modal-stack', context)
7682
7783
</script>
7884
7985
{#if $stack.length > 0}
80-
<slot name="backdrop" />
86+
<slot name="backdrop" />
8187
{/if}
8288
8389
<slot name="modals">
84-
{#each $stack as modal, i (i)}
85-
<svelte:component
86-
this={modal.component}
87-
isOpen={i === $stack.length - 1 && !transitioning}
88-
on:introstart={() => {
89-
exitBeforeEnter = true
90-
}}
91-
on:outroend={() => {
92-
transitioning = false
93-
}}
94-
{...modal.props || {}}
95-
/>
96-
{/each}
90+
{#each $stack as modal, i (i)}
91+
<svelte:component
92+
this={modal.component}
93+
isOpen={i === $stack.length - 1 && !transitioning}
94+
on:introstart={() => {
95+
exitBeforeEnter = true
96+
}}
97+
on:outroend={() => {
98+
transitioning = false
99+
}}
100+
{...modal.props || {}}
101+
/>
102+
{/each}
97103
</slot>
98104
99105
<slot {...context} stack={$stack} />

src/lib/ModalStack.svelte.d.ts

+52-48
Original file line numberDiff line numberDiff line change
@@ -1,57 +1,61 @@
1-
import { SvelteComponent, SvelteComponentTyped } from 'svelte'
1+
import { SvelteComponent, SvelteComponentTyped, SvelteComponentDev } from 'svelte'
22
import { Writable } from 'svelte/store'
33

44
export interface ModalStackContext {
5-
/**
6-
* Adds a Modal component to the stack
7-
*/
8-
openModal: <T>(component: SvelteComponent, props?: T, options?: { replace?: boolean }) => void
9-
10-
/**
11-
* Closes the current modal component
12-
*/
13-
closeModal: () => void
14-
15-
/**
16-
* Closes the last `amount` of modals in the stack
17-
*/
18-
closeModals: (amount: number) => void
19-
20-
/**
21-
* Closes all modals in the stack
22-
*/
23-
closeAllModals: () => void
24-
25-
/**
26-
* A Svelte store containing the current modal stack
27-
*/
28-
stack: Writable<Array<{ component: SvelteComponent; props?: unknown }>>
29-
30-
/**
31-
* If `exitBeforeEnter` is enabled on the ModalStack component, this store will contain
32-
* the current transition state (either null, 'in' or 'out')
33-
*/
34-
transitioning: Writable<null | 'in' | 'out'>
35-
36-
/**
37-
* A store describing how the current modal came to be active. "push" means it was
38-
* newly added (from openModal), "pop" means the modal ahead of it was closed (closeModal).
39-
*
40-
* This can be useful for animations
41-
*/
42-
action: Writable<null | 'push' | 'pop'>
5+
/**
6+
* Adds a Modal component to the stack
7+
*/
8+
openModal: <T>(
9+
component: SvelteComponent | SvelteComponentTyped<T> | SvelteComponentDev,
10+
props?: T,
11+
options?: { replace?: boolean }
12+
) => void
13+
14+
/**
15+
* Closes the current modal component
16+
*/
17+
closeModal: () => void
18+
19+
/**
20+
* Closes the last `amount` of modals in the stack
21+
*/
22+
closeModals: (amount: number) => void
23+
24+
/**
25+
* Closes all modals in the stack
26+
*/
27+
closeAllModals: () => void
28+
29+
/**
30+
* A Svelte store containing the current modal stack
31+
*/
32+
stack: Writable<Array<{ component: SvelteComponent; props?: unknown }>>
33+
34+
/**
35+
* If `exitBeforeEnter` is enabled on the ModalStack component, this store will contain
36+
* the current transition state (either null, 'in' or 'out')
37+
*/
38+
transitioning: Writable<null | 'in' | 'out'>
39+
40+
/**
41+
* A store describing how the current modal came to be active. "push" means it was
42+
* newly added (from openModal), "pop" means the modal ahead of it was closed (closeModal).
43+
*
44+
* This can be useful for animations
45+
*/
46+
action: Writable<null | 'push' | 'pop'>
4347
}
4448

4549
export function useModals(): ModalStackContext
4650

4751
export default class ModalStack extends SvelteComponentTyped<
48-
{
49-
exitBeforeEnter?: boolean
50-
},
51-
Record<string, never>,
52-
{
53-
backdrop: ModalStackContext
54-
modals: ModalStackContext
55-
default: ModalStackContext
56-
}
52+
{
53+
exitBeforeEnter?: boolean
54+
},
55+
Record<string, never>,
56+
{
57+
backdrop: ModalStackContext
58+
modals: ModalStackContext
59+
default: ModalStackContext
60+
}
5761
> {}

0 commit comments

Comments
 (0)