|
1 |
| -<svelte:options runes={false} /> |
| 1 | +<svelte:options runes /> |
2 | 2 |
|
3 |
| -<svelte:component |
4 |
| - this={component} |
| 3 | +<MyComponent |
5 | 4 | {tag}
|
6 | 5 | bind:this={element}
|
7 | 6 | use={[
|
|
29 | 28 | .concat([style])
|
30 | 29 | .join(' ')}
|
31 | 30 | role="row"
|
32 |
| - {...$$restProps} |
| 31 | + {...restProps} |
33 | 32 | ontransitionend={(e: TransitionEvent) => {
|
34 | 33 | if (instance) {
|
35 | 34 | instance.handleTransitionEnd(e);
|
36 | 35 | }
|
37 |
| - $$restProps.ontransitionend?.(e); |
| 36 | + restProps.ontransitionend?.(e); |
38 | 37 | }}
|
39 | 38 | onclick={(e: MouseEvent) => {
|
40 | 39 | if (instance) {
|
41 | 40 | instance.handleClick();
|
42 | 41 | }
|
43 |
| - $$restProps.onclick?.(e); |
| 42 | + restProps.onclick?.(e); |
44 | 43 | }}
|
45 | 44 | onkeydown={(e: KeyboardEvent) => {
|
46 | 45 | if (instance) {
|
47 | 46 | instance.handleKeydown(e);
|
48 | 47 | }
|
49 |
| - $$restProps.onkeydown?.(e); |
| 48 | + restProps.onkeydown?.(e); |
50 | 49 | }}
|
51 | 50 | onfocusin={(e: FocusEvent) => {
|
52 | 51 | if (instance) {
|
53 | 52 | instance.handleFocusIn(e);
|
54 | 53 | }
|
55 |
| - $$restProps.onfocusin?.(e); |
| 54 | + restProps.onfocusin?.(e); |
56 | 55 | }}
|
57 | 56 | onfocusout={(e: FocusEvent) => {
|
58 | 57 | if (instance) {
|
59 | 58 | instance.handleFocusOut(e);
|
60 | 59 | }
|
61 |
| - $$restProps.onfocusout?.(e); |
| 60 | + restProps.onfocusout?.(e); |
62 | 61 | }}
|
63 |
| - onSMUIChipTrailingActionInteraction={(e: CustomEvent) => { |
| 62 | + onSMUIChipTrailingActionInteraction={( |
| 63 | + e: CustomEvent<{ |
| 64 | + trigger: InteractionTrigger; |
| 65 | + }> & { currentTarget: EventTarget & SmuiElementMap[TagName] }, |
| 66 | + ) => { |
64 | 67 | if (instance) {
|
65 | 68 | instance.handleTrailingActionInteraction();
|
66 | 69 | }
|
67 |
| - $$restProps.onSMUIChipTrailingActionInteraction?.(e); |
| 70 | + restProps.onSMUIChipTrailingActionInteraction?.(e); |
68 | 71 | }}
|
69 |
| - onSMUIChipTrailingActionNavigation={(e: CustomEvent) => { |
| 72 | + onSMUIChipTrailingActionNavigation={( |
| 73 | + e: CustomEvent<{ key: string }> & { |
| 74 | + currentTarget: EventTarget & SmuiElementMap[TagName]; |
| 75 | + }, |
| 76 | + ) => { |
70 | 77 | if (instance) {
|
71 | 78 | instance.handleTrailingActionNavigation(e);
|
72 | 79 | }
|
73 |
| - $$restProps.onSMUIChipTrailingActionNavigation?.(e); |
| 80 | + restProps.onSMUIChipTrailingActionNavigation?.(e); |
74 | 81 | }}
|
75 | 82 | >
|
76 | 83 | {#if ripple && !$nonInteractive}
|
77 | 84 | <div class="mdc-chip__ripple"></div>
|
78 | 85 | {/if}
|
79 |
| - <slot /> |
| 86 | + {@render children?.()} |
80 | 87 | {#if touch}
|
81 | 88 | <div class="mdc-chip__touch"></div>
|
82 | 89 | {/if}
|
83 |
| -</svelte:component> |
| 90 | +</MyComponent> |
84 | 91 |
|
85 |
| -<script lang="ts" generics="TagName extends SmuiEveryElement = 'div'"> |
| 92 | +<script |
| 93 | + lang="ts" |
| 94 | + generics="ChipKey extends Object | string | number, TagName extends SmuiEveryElement = 'div'" |
| 95 | +> |
| 96 | + import type { InteractionTrigger } from '@material/chips/deprecated/trailingaction/constants'; |
86 | 97 | import { deprecated } from '@material/chips';
|
| 98 | + import type { Snippet } from 'svelte'; |
87 | 99 | import { onMount, setContext, getContext } from 'svelte';
|
88 | 100 | import { writable } from 'svelte/store';
|
89 | 101 | import type { ActionArray } from '@smui/common/internal';
|
|
104 | 116 | const { MDCChipFoundation } = deprecated;
|
105 | 117 |
|
106 | 118 | type OwnProps = {
|
| 119 | + /** |
| 120 | + * An array of Action or [Action, ActionProps] to be applied to the element. |
| 121 | + */ |
107 | 122 | use?: ActionArray;
|
| 123 | + /** |
| 124 | + * A space separated list of CSS classes. |
| 125 | + */ |
108 | 126 | class?: string;
|
| 127 | + /** |
| 128 | + * A list of CSS styles. |
| 129 | + */ |
109 | 130 | style?: string;
|
110 |
| - chip: any; |
| 131 | + /** |
| 132 | + * The chip object this chip is for. |
| 133 | + */ |
| 134 | + chip: ChipKey; |
| 135 | + /** |
| 136 | + * Whether to show a ripple animation. |
| 137 | + */ |
111 | 138 | ripple?: boolean;
|
| 139 | + /** |
| 140 | + * Whether to use touch styling |
| 141 | + */ |
112 | 142 | touch?: boolean;
|
| 143 | + /** |
| 144 | + * Whether this chip should be removed when user clicks the trailing icon. |
| 145 | + */ |
113 | 146 | shouldRemoveOnTrailingIconClick?: boolean;
|
| 147 | + /** |
| 148 | + * Whether primary action should focus when user clicks the chip. |
| 149 | + */ |
114 | 150 | shouldFocusPrimaryActionOnClick?: boolean;
|
| 151 | + /** |
| 152 | + * The component to use to render the element. |
| 153 | + */ |
115 | 154 | component?: SmuiComponent<SmuiElementMap[TagName]>;
|
| 155 | + /** |
| 156 | + * The tag name of the element to create. |
| 157 | + */ |
116 | 158 | tag?: TagName;
|
| 159 | +
|
| 160 | + children?: Snippet; |
117 | 161 | };
|
118 |
| - type $$Props = OwnProps & SmuiAttrs<TagName, keyof OwnProps>; |
119 |
| -
|
120 |
| - // Remember to update $$Props if you add/remove/rename props. |
121 |
| - export let use: ActionArray = []; |
122 |
| - let className = ''; |
123 |
| - export { className as class }; |
124 |
| - export let style = ''; |
125 |
| - let chipId: any; |
126 |
| - export { chipId as chip }; |
127 |
| - export let ripple = true; |
128 |
| - export let touch = false; |
129 |
| - export let shouldRemoveOnTrailingIconClick = true; |
130 |
| - export let shouldFocusPrimaryActionOnClick = true; |
| 162 | + let { |
| 163 | + use = [], |
| 164 | + class: className = '', |
| 165 | + style = '', |
| 166 | + chip: chipId, |
| 167 | + ripple = true, |
| 168 | + touch = false, |
| 169 | + shouldRemoveOnTrailingIconClick = true, |
| 170 | + shouldFocusPrimaryActionOnClick = true, |
| 171 | + component: MyComponent = SmuiElement, |
| 172 | + tag = 'div' as TagName, |
| 173 | + children, |
| 174 | + ...restProps |
| 175 | + }: OwnProps & SmuiAttrs<TagName, keyof OwnProps> = $props(); |
131 | 176 |
|
132 | 177 | let element: ReturnType<SmuiComponent<SmuiElementMap[TagName]>>;
|
133 |
| - let instance: deprecated.MDCChipFoundation; |
134 |
| - let internalClasses: { [k: string]: boolean } = {}; |
135 |
| - let leadingIconClasses: { [k: string]: boolean } = {}; |
136 |
| - let internalStyles: { [k: string]: string } = {}; |
| 178 | + let instance: deprecated.MDCChipFoundation | undefined = $state(); |
| 179 | + let internalClasses: { [k: string]: boolean } = $state({}); |
| 180 | + let leadingIconClasses: { [k: string]: boolean } = $state({}); |
| 181 | + let internalStyles: { [k: string]: string } = $state({}); |
137 | 182 | const initialSelectedStore = getContext<SvelteStore<boolean>>(
|
138 | 183 | 'SMUI:chips:chip:initialSelected',
|
139 | 184 | );
|
140 |
| - let selected = $initialSelectedStore; |
| 185 | + let selected = $state($initialSelectedStore); |
141 | 186 | let primaryActionAccessor: SMUIChipsPrimaryActionAccessor | undefined =
|
142 | 187 | undefined;
|
143 | 188 | let trailingActionAccessor: SMUIChipsTrailingActionAccessor | undefined =
|
|
148 | 193 | const choice = getContext<SvelteStore<boolean>>('SMUI:chips:choice');
|
149 | 194 | const index = getContext<SvelteStore<number>>('SMUI:chips:chip:index');
|
150 | 195 |
|
151 |
| - export let component: SmuiComponent<SmuiElementMap[TagName]> = SmuiElement; |
152 |
| - export let tag: SmuiEveryElement | undefined = |
153 |
| - component === SmuiElement ? 'div' : undefined; |
154 |
| -
|
155 | 196 | const shouldRemoveOnTrailingIconClickStore = writable(
|
156 | 197 | shouldRemoveOnTrailingIconClick,
|
157 | 198 | );
|
158 |
| - $: $shouldRemoveOnTrailingIconClickStore = shouldRemoveOnTrailingIconClick; |
| 199 | + $effect(() => { |
| 200 | + $shouldRemoveOnTrailingIconClickStore = shouldRemoveOnTrailingIconClick; |
| 201 | + }); |
159 | 202 | setContext(
|
160 | 203 | 'SMUI:chips:chip:shouldRemoveOnTrailingIconClick',
|
161 | 204 | shouldRemoveOnTrailingIconClickStore,
|
162 | 205 | );
|
| 206 | +
|
163 | 207 | const isSelectedStore = writable(selected);
|
164 |
| - $: $isSelectedStore = selected; |
| 208 | + $effect(() => { |
| 209 | + $isSelectedStore = selected; |
| 210 | + }); |
165 | 211 | setContext('SMUI:chips:chip:isSelected', isSelectedStore);
|
| 212 | +
|
166 | 213 | const leadingIconClassesStore = writable(leadingIconClasses);
|
167 |
| - $: $leadingIconClassesStore = leadingIconClasses; |
| 214 | + $effect(() => { |
| 215 | + $leadingIconClassesStore = leadingIconClasses; |
| 216 | + }); |
168 | 217 | setContext('SMUI:chips:chip:leadingIconClasses', leadingIconClassesStore);
|
| 218 | +
|
169 | 219 | setContext(
|
170 | 220 | 'SMUI:chips:chip:focusable',
|
171 | 221 | ($choice && selected) || $index === 0,
|
172 | 222 | );
|
173 | 223 |
|
174 |
| - if (!chipId) { |
175 |
| - throw new Error( |
176 |
| - 'The chip property is required! It should be passed down from the Set to the Chip.', |
177 |
| - ); |
178 |
| - } |
179 |
| -
|
180 |
| - $: if ( |
181 |
| - instance && |
182 |
| - instance.getShouldRemoveOnTrailingIconClick() !== |
183 |
| - shouldRemoveOnTrailingIconClick |
184 |
| - ) { |
185 |
| - instance.setShouldRemoveOnTrailingIconClick( |
186 |
| - shouldRemoveOnTrailingIconClick, |
187 |
| - ); |
188 |
| - } |
| 224 | + $effect(() => { |
| 225 | + if ( |
| 226 | + instance && |
| 227 | + instance.getShouldRemoveOnTrailingIconClick() !== |
| 228 | + shouldRemoveOnTrailingIconClick |
| 229 | + ) { |
| 230 | + instance.setShouldRemoveOnTrailingIconClick( |
| 231 | + shouldRemoveOnTrailingIconClick, |
| 232 | + ); |
| 233 | + } |
| 234 | + }); |
189 | 235 |
|
190 |
| - $: if (instance) { |
191 |
| - instance.setShouldFocusPrimaryActionOnClick( |
192 |
| - shouldFocusPrimaryActionOnClick, |
193 |
| - ); |
194 |
| - } |
| 236 | + $effect(() => { |
| 237 | + if (instance) { |
| 238 | + instance.setShouldFocusPrimaryActionOnClick( |
| 239 | + shouldFocusPrimaryActionOnClick, |
| 240 | + ); |
| 241 | + } |
| 242 | + }); |
195 | 243 |
|
196 | 244 | setContext(
|
197 | 245 | 'SMUI:chips:primary-action:mount',
|
|
316 | 364 | return () => {
|
317 | 365 | SMUIChipsChipUnmount && SMUIChipsChipUnmount(accessor);
|
318 | 366 |
|
319 |
| - instance.destroy(); |
| 367 | + instance?.destroy(); |
320 | 368 | };
|
321 | 369 | });
|
322 | 370 |
|
|
372 | 420 | shouldNotifyClients: boolean,
|
373 | 421 | ) {
|
374 | 422 | selected = value;
|
375 |
| - instance.setSelectedFromChipSet(selected, shouldNotifyClients); |
| 423 | + instance?.setSelectedFromChipSet(selected, shouldNotifyClients); |
376 | 424 | }
|
377 | 425 |
|
378 | 426 | function focusPrimaryAction() {
|
379 |
| - instance.focusPrimaryAction(); |
| 427 | + instance?.focusPrimaryAction(); |
380 | 428 | }
|
381 | 429 |
|
382 | 430 | function focusTrailingAction() {
|
383 |
| - instance.focusTrailingAction(); |
| 431 | + instance?.focusTrailingAction(); |
384 | 432 | }
|
385 | 433 |
|
386 | 434 | function removeFocus() {
|
387 |
| - instance.removeFocus(); |
| 435 | + instance?.removeFocus(); |
388 | 436 | }
|
389 | 437 |
|
390 | 438 | export function getElement() {
|
|
0 commit comments