|
1 |
| -<svelte:options runes={false} /> |
| 1 | +<svelte:options runes /> |
2 | 2 |
|
3 | 3 | <aside
|
4 | 4 | bind:this={element}
|
|
10 | 10 | 'mdc-snackbar--leading': leading,
|
11 | 11 | ...internalClasses,
|
12 | 12 | })}
|
13 |
| - {...exclude($$restProps, ['surface$'])} |
| 13 | + {...exclude(restProps, ['surface$'])} |
14 | 14 | onkeydown={(e) => {
|
15 | 15 | if (instance) {
|
16 | 16 | instance.handleKeyDown(e);
|
17 | 17 | }
|
18 |
| - $$restProps.onkeydown?.(e); |
| 18 | + restProps.onkeydown?.(e); |
19 | 19 | }}
|
20 | 20 | onSMUISnackbarClosed={(e) => {
|
21 | 21 | handleClosed();
|
22 |
| - $$restProps.onSMUISnackbarClosed?.(e); |
| 22 | + restProps.onSMUISnackbarClosed?.(e); |
23 | 23 | }}
|
24 | 24 | >
|
25 | 25 | <div
|
|
30 | 30 | })}
|
31 | 31 | role="status"
|
32 | 32 | aria-relevant="additions"
|
33 |
| - {...prefixFilter($$restProps, 'surface$')} |
| 33 | + {...prefixFilter(restProps, 'surface$')} |
34 | 34 | onclick={(e) => {
|
35 | 35 | handleSurfaceClick(e);
|
36 |
| - $$restProps.surface$onclick?.(e); |
| 36 | + restProps.surface$onclick?.(e); |
37 | 37 | }}
|
38 | 38 | >
|
39 |
| - <slot /> |
| 39 | + {@render children?.()} |
40 | 40 | </div>
|
41 | 41 | </aside>
|
42 | 42 |
|
|
47 | 47 | <script lang="ts">
|
48 | 48 | import { MDCSnackbarFoundation, util } from '@material/snackbar';
|
49 | 49 | import { ponyfill } from '@material/dom';
|
| 50 | + import type { Snippet } from 'svelte'; |
50 | 51 | import { onMount, setContext } from 'svelte';
|
51 | 52 | import type { SmuiAttrs, SmuiElementPropMap } from '@smui/common';
|
52 | 53 | import type { ActionArray } from '@smui/common/internal';
|
|
60 | 61 |
|
61 | 62 | const { closest } = ponyfill;
|
62 | 63 |
|
| 64 | + interface UninitializedValue extends Function {} |
| 65 | + let uninitializedValue: UninitializedValue = () => {}; |
| 66 | + function isUninitializedValue(value: any): value is UninitializedValue { |
| 67 | + return value === uninitializedValue; |
| 68 | + } |
| 69 | +
|
63 | 70 | type OwnProps = {
|
| 71 | + /** |
| 72 | + * An array of Action or [Action, ActionProps] to be applied to the element. |
| 73 | + */ |
64 | 74 | use?: ActionArray;
|
| 75 | + /** |
| 76 | + * A space separated list of CSS classes. |
| 77 | + */ |
65 | 78 | class?: string;
|
66 |
| - variant?: string; |
| 79 | + /** |
| 80 | + * The styling variant of the snackbar. |
| 81 | + * |
| 82 | + * Undefined is the default variant. Stacked means the text goes above the |
| 83 | + * actions and icons. |
| 84 | + */ |
| 85 | + variant?: 'stacked' | undefined; |
| 86 | + /** |
| 87 | + * Whether to position the snackbar in the leading portion of the screen. |
| 88 | + */ |
67 | 89 | leading?: boolean;
|
| 90 | + /** |
| 91 | + * How many milliseconds to wait before automatically closing. |
| 92 | + */ |
68 | 93 | timeoutMs?: number;
|
| 94 | + /** |
| 95 | + * Whether to close the snackbar when the escape key is pressed. |
| 96 | + * |
| 97 | + * This only works when an element inside the snackbar has focus. |
| 98 | + */ |
69 | 99 | closeOnEscape?: boolean;
|
| 100 | + /** |
| 101 | + * Text content to place in the label. |
| 102 | + */ |
70 | 103 | labelText?: string;
|
| 104 | + /** |
| 105 | + * Text content to place in the action button. |
| 106 | + */ |
71 | 107 | actionButtonText?: string;
|
72 |
| - surface$class?: string; |
| 108 | + /** |
| 109 | + * An array of Action or [Action, ActionProps] to be applied to the element. |
| 110 | + */ |
73 | 111 | surface$use?: ActionArray;
|
| 112 | + /** |
| 113 | + * A space separated list of CSS classes. |
| 114 | + */ |
| 115 | + surface$class?: string; |
| 116 | +
|
| 117 | + children?: Snippet; |
74 | 118 | };
|
75 |
| - type $$Props = OwnProps & |
| 119 | + let { |
| 120 | + use = [], |
| 121 | + class: className = '', |
| 122 | + variant, |
| 123 | + leading = false, |
| 124 | + timeoutMs = 5000, |
| 125 | + closeOnEscape = true, |
| 126 | + labelText = uninitializedValue as unknown as string, |
| 127 | + actionButtonText = uninitializedValue as unknown as string, |
| 128 | + surface$use = [], |
| 129 | + surface$class = '', |
| 130 | + children, |
| 131 | + ...restProps |
| 132 | + }: OwnProps & |
76 | 133 | SmuiAttrs<'aside', keyof OwnProps> & {
|
77 | 134 | [k in keyof SmuiElementPropMap['div'] as `surface\$${k}`]?: SmuiElementPropMap['div'][k];
|
78 |
| - }; |
79 |
| -
|
80 |
| - interface UninitializedValue extends Function {} |
81 |
| - let uninitializedValue: UninitializedValue = () => {}; |
82 |
| - function isUninitializedValue(value: any): value is UninitializedValue { |
83 |
| - return value === uninitializedValue; |
84 |
| - } |
85 |
| -
|
86 |
| - // Remember to update $$Props if you add/remove/rename props. |
87 |
| - export let use: ActionArray = []; |
88 |
| - let className = ''; |
89 |
| - export { className as class }; |
90 |
| - export let variant = ''; |
91 |
| - export let leading = false; |
92 |
| - export let timeoutMs = 5000; |
93 |
| - export let closeOnEscape = true; |
94 |
| - export let labelText: UninitializedValue | string = uninitializedValue; |
95 |
| - export let actionButtonText: UninitializedValue | string = uninitializedValue; |
96 |
| - export let surface$class = ''; |
97 |
| - export let surface$use: ActionArray = []; |
| 135 | + } = $props(); |
98 | 136 |
|
99 | 137 | let element: HTMLElement;
|
100 |
| - let instance: MDCSnackbarFoundation; |
101 |
| - let internalClasses: { [k: string]: boolean } = {}; |
| 138 | + let instance: MDCSnackbarFoundation | undefined = $state(); |
| 139 | + let internalClasses: { [k: string]: boolean } = $state({}); |
102 | 140 | let closeResolve: (value: void) => void;
|
103 | 141 | let closePromise = new Promise<void>((resolve) => (closeResolve = resolve));
|
104 | 142 |
|
105 | 143 | setContext('SMUI:label:context', 'snackbar');
|
106 | 144 |
|
107 |
| - $: if (instance && instance.getTimeoutMs() !== timeoutMs) { |
108 |
| - instance.setTimeoutMs(timeoutMs); |
109 |
| - } |
| 145 | + $effect(() => { |
| 146 | + if (instance && instance.getTimeoutMs() !== timeoutMs) { |
| 147 | + instance.setTimeoutMs(timeoutMs); |
| 148 | + } |
| 149 | + }); |
110 | 150 |
|
111 |
| - $: if (instance && instance.getCloseOnEscape() !== closeOnEscape) { |
112 |
| - instance.setCloseOnEscape(closeOnEscape); |
113 |
| - } |
| 151 | + $effect(() => { |
| 152 | + if (instance && instance.getCloseOnEscape() !== closeOnEscape) { |
| 153 | + instance.setCloseOnEscape(closeOnEscape); |
| 154 | + } |
| 155 | + }); |
114 | 156 |
|
115 |
| - $: if ( |
116 |
| - instance && |
117 |
| - !isUninitializedValue(labelText) && |
118 |
| - getLabelElement().textContent !== labelText |
119 |
| - ) { |
120 |
| - getLabelElement().textContent = labelText; |
121 |
| - } |
| 157 | + $effect(() => { |
| 158 | + if ( |
| 159 | + instance && |
| 160 | + !isUninitializedValue(labelText) && |
| 161 | + getLabelElement().textContent !== labelText |
| 162 | + ) { |
| 163 | + getLabelElement().textContent = labelText; |
| 164 | + } |
| 165 | + }); |
122 | 166 |
|
123 |
| - $: if ( |
124 |
| - instance && |
125 |
| - !isUninitializedValue(actionButtonText) && |
126 |
| - getActionButtonElement().textContent !== actionButtonText |
127 |
| - ) { |
128 |
| - getActionButtonElement().textContent = actionButtonText; |
129 |
| - } |
| 167 | + $effect(() => { |
| 168 | + if ( |
| 169 | + instance && |
| 170 | + !isUninitializedValue(actionButtonText) && |
| 171 | + getActionButtonElement().textContent !== actionButtonText |
| 172 | + ) { |
| 173 | + getActionButtonElement().textContent = actionButtonText; |
| 174 | + } |
| 175 | + }); |
130 | 176 |
|
131 | 177 | onMount(() => {
|
132 | 178 | instance = new MDCSnackbarFoundation({
|
|
144 | 190 | instance.init();
|
145 | 191 |
|
146 | 192 | return () => {
|
147 |
| - instance.destroy(); |
| 193 | + instance?.destroy(); |
148 | 194 | };
|
149 | 195 | });
|
150 | 196 |
|
|
178 | 224 |
|
179 | 225 | export function open() {
|
180 | 226 | waiting = waiting.then(() => {
|
181 |
| - instance.open(); |
| 227 | + instance?.open(); |
182 | 228 | return closePromise;
|
183 | 229 | });
|
184 | 230 | }
|
185 | 231 |
|
186 | 232 | export function forceOpen() {
|
187 |
| - return instance.open(); |
| 233 | + return instance?.open(); |
188 | 234 | }
|
189 | 235 |
|
190 | 236 | export function close(reason?: string) {
|
191 |
| - return instance.close(reason); |
| 237 | + return instance?.close(reason); |
192 | 238 | }
|
193 | 239 |
|
194 | 240 | export function isOpen() {
|
| 241 | + if (instance == null) { |
| 242 | + throw new Error('Instance is undefined.'); |
| 243 | + } |
195 | 244 | return instance.isOpen();
|
196 | 245 | }
|
197 | 246 |
|
|
0 commit comments