@motion-proto/live-tokens 0.3.7 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (104) hide show
  1. package/README.md +1 -1
  2. package/package.json +11 -9
  3. package/src/component-editor/BadgeEditor.svelte +24 -22
  4. package/src/component-editor/CalloutEditor.svelte +3 -3
  5. package/src/component-editor/CardEditor.svelte +25 -21
  6. package/src/component-editor/CollapsibleSectionEditor.svelte +27 -25
  7. package/src/component-editor/CornerBadgeEditor.svelte +37 -35
  8. package/src/component-editor/DialogEditor.svelte +26 -24
  9. package/src/component-editor/ImageEditor.svelte +11 -9
  10. package/src/component-editor/InlineEditActionsEditor.svelte +17 -15
  11. package/src/component-editor/NotificationEditor.svelte +32 -30
  12. package/src/component-editor/ProgressBarEditor.svelte +3 -3
  13. package/src/component-editor/RadioButtonEditor.svelte +31 -29
  14. package/src/component-editor/SectionDividerEditor.svelte +30 -28
  15. package/src/component-editor/SegmentedControlEditor.svelte +29 -25
  16. package/src/component-editor/StandardButtonsEditor.svelte +42 -38
  17. package/src/component-editor/TabBarEditor.svelte +20 -18
  18. package/src/component-editor/TableEditor.svelte +4 -4
  19. package/src/component-editor/TooltipEditor.svelte +11 -9
  20. package/src/component-editor/registry.ts +2 -2
  21. package/src/component-editor/scaffolding/AngleDial.svelte +20 -19
  22. package/src/component-editor/scaffolding/ComponentEditorBase.svelte +44 -20
  23. package/src/component-editor/scaffolding/ComponentFileManager.svelte +260 -37
  24. package/src/component-editor/scaffolding/ComponentFileMenu.svelte +41 -29
  25. package/src/component-editor/scaffolding/ComponentsTab.svelte +7 -3
  26. package/src/component-editor/scaffolding/CopyFromMenu.svelte +21 -12
  27. package/src/component-editor/scaffolding/DemoHeader.svelte +13 -4
  28. package/src/component-editor/scaffolding/DividerEditor.svelte +27 -14
  29. package/src/component-editor/scaffolding/FieldsetWrapper.svelte +10 -4
  30. package/src/component-editor/scaffolding/GradientCard.svelte +25 -20
  31. package/src/component-editor/scaffolding/LinkageChart.svelte +43 -34
  32. package/src/component-editor/scaffolding/LinkedBlock.svelte +24 -21
  33. package/src/component-editor/scaffolding/NonStylableConfig.svelte +6 -1
  34. package/src/component-editor/scaffolding/SaveAsDialog.svelte +39 -35
  35. package/src/component-editor/scaffolding/ShadowBackdrop.svelte +21 -9
  36. package/src/component-editor/scaffolding/ShadowBackdropControls.svelte +8 -3
  37. package/src/component-editor/scaffolding/StateBlock.svelte +30 -13
  38. package/src/component-editor/scaffolding/TokenLayout.svelte +46 -30
  39. package/src/component-editor/scaffolding/TypeEditor.svelte +52 -26
  40. package/src/component-editor/scaffolding/VariantGroup.svelte +81 -48
  41. package/src/component-editor/scaffolding/componentSectionType.ts +2 -2
  42. package/src/components/Badge.svelte +45 -26
  43. package/src/components/Button.svelte +44 -21
  44. package/src/components/Callout.svelte +17 -12
  45. package/src/components/Card.svelte +23 -11
  46. package/src/components/CollapsibleSection.svelte +56 -27
  47. package/src/components/CornerBadge.svelte +32 -18
  48. package/src/components/Dialog.svelte +55 -31
  49. package/src/components/Image.svelte +14 -5
  50. package/src/components/InlineEditActions.svelte +22 -10
  51. package/src/components/Notification.svelte +39 -19
  52. package/src/components/ProgressBar.svelte +27 -17
  53. package/src/components/RadioButton.svelte +27 -10
  54. package/src/components/SectionDivider.svelte +34 -26
  55. package/src/components/SegmentedControl.svelte +23 -9
  56. package/src/components/TabBar.svelte +23 -10
  57. package/src/components/Table.svelte +8 -3
  58. package/src/components/Tooltip.svelte +15 -5
  59. package/src/lib/ColumnsOverlay.svelte +3 -3
  60. package/src/lib/LiveEditorOverlay.svelte +73 -36
  61. package/src/pages/ComponentEditorPage.svelte +17 -13
  62. package/src/pages/EditorShell.svelte +24 -20
  63. package/src/styles/form-controls.css +2 -2
  64. package/src/styles/tokens.css +59 -81
  65. package/src/ui/BezierCurveEditor.svelte +59 -43
  66. package/src/ui/ColorEditPanel.svelte +71 -44
  67. package/src/ui/EditorViewSwitcher.svelte +9 -5
  68. package/src/ui/FontStackEditor.svelte +16 -15
  69. package/src/ui/GradientEditor.svelte +42 -33
  70. package/src/ui/GradientStopPicker.svelte +18 -29
  71. package/src/ui/PaletteEditor.svelte +238 -212
  72. package/src/ui/PresetFileManager.svelte +20 -18
  73. package/src/ui/ProjectFontsSection.svelte +30 -30
  74. package/src/ui/SurfacesTab.svelte +3 -3
  75. package/src/ui/TextTab.svelte +2 -2
  76. package/src/ui/ThemeFileManager.svelte +38 -35
  77. package/src/ui/Toggle.svelte +11 -9
  78. package/src/ui/UICopyPopover.svelte +19 -15
  79. package/src/ui/UIDialog.svelte +48 -30
  80. package/src/ui/UIFontFamilySelector.svelte +104 -78
  81. package/src/ui/UIFontSizeSelector.svelte +38 -20
  82. package/src/ui/UIFontWeightSelector.svelte +33 -13
  83. package/src/ui/UILineHeightSelector.svelte +33 -13
  84. package/src/ui/UILinkToggle.svelte +7 -6
  85. package/src/ui/UIOptionItem.svelte +21 -7
  86. package/src/ui/UIOptionList.svelte +9 -3
  87. package/src/ui/UIPaddingSelector.svelte +108 -82
  88. package/src/ui/UIPaletteSelector.svelte +186 -161
  89. package/src/ui/UIRadio.svelte +23 -8
  90. package/src/ui/UIRadioGroup.svelte +9 -8
  91. package/src/ui/UIRelinkConfirmPopover.svelte +26 -16
  92. package/src/ui/UITokenSelector.svelte +112 -68
  93. package/src/ui/UIVariantSelector.svelte +79 -57
  94. package/src/ui/VariablesTab.svelte +15 -15
  95. package/src/ui/palette/GradientStopEditor.svelte +45 -26
  96. package/src/ui/palette/OverridesPanel.svelte +85 -49
  97. package/src/ui/palette/PaletteBase.svelte +60 -32
  98. package/src/ui/palette/ScaleCurveEditor.svelte +25 -10
  99. package/src/ui/sections/ColumnsSection.svelte +13 -13
  100. package/src/ui/sections/GradientsSection.svelte +12 -9
  101. package/src/ui/sections/OverlaysSection.svelte +50 -47
  102. package/src/ui/sections/ShadowsSection.svelte +110 -104
  103. package/src/ui/sections/TokenScaleTable.svelte +38 -22
  104. package/src/ui/sections/tokenScales.ts +2 -2
@@ -1,58 +1,76 @@
1
1
  <script lang="ts">
2
- import { tick, createEventDispatcher } from 'svelte';
3
-
4
- export let show: boolean = false;
5
- export let title: string = '';
6
- export let cancelLabel: string = 'Cancel';
7
- export let showCancel: boolean = true;
8
- export let confirmLabel: string = '';
9
- export let confirmDisabled: boolean = false;
10
- export let width: string = '500px';
11
-
12
- const dispatch = createEventDispatcher();
13
-
14
- let closeButtonRef: HTMLButtonElement;
15
- let cancelButtonRef: HTMLButtonElement;
16
- let confirmButtonRef: HTMLButtonElement;
17
-
18
- $: if (show) {
19
- tick().then(() => {
20
- if (confirmLabel && confirmButtonRef) confirmButtonRef.focus();
21
- else if (showCancel && cancelButtonRef) cancelButtonRef.focus();
22
- else if (closeButtonRef) closeButtonRef.focus();
23
- });
24
- }
2
+ import { run, self } from 'svelte/legacy';
3
+
4
+ import { tick } from 'svelte';
5
+
6
+ interface Props {
7
+ show?: boolean;
8
+ title?: string;
9
+ cancelLabel?: string;
10
+ showCancel?: boolean;
11
+ confirmLabel?: string;
12
+ confirmDisabled?: boolean;
13
+ width?: string;
14
+ children?: import('svelte').Snippet;
15
+ onconfirm?: () => void;
16
+ }
17
+
18
+ let {
19
+ show = $bindable(false),
20
+ title = '',
21
+ cancelLabel = 'Cancel',
22
+ showCancel = true,
23
+ confirmLabel = '',
24
+ confirmDisabled = false,
25
+ width = '500px',
26
+ children,
27
+ onconfirm
28
+ }: Props = $props();
29
+
30
+ let closeButtonRef: HTMLButtonElement | undefined = $state();
31
+ let cancelButtonRef: HTMLButtonElement | undefined = $state();
32
+ let confirmButtonRef: HTMLButtonElement | undefined = $state();
33
+
34
+ run(() => {
35
+ if (show) {
36
+ tick().then(() => {
37
+ if (confirmLabel && confirmButtonRef) confirmButtonRef.focus();
38
+ else if (showCancel && cancelButtonRef) cancelButtonRef.focus();
39
+ else if (closeButtonRef) closeButtonRef.focus();
40
+ });
41
+ }
42
+ });
25
43
 
26
44
  function handleClose() {
27
45
  show = false;
28
46
  }
29
47
 
30
48
  function handleConfirm() {
31
- dispatch('confirm');
49
+ onconfirm?.();
32
50
  }
33
51
  </script>
34
52
 
35
53
  {#if show}
36
- <!-- svelte-ignore a11y-click-events-have-key-events a11y-no-noninteractive-element-interactions -->
37
- <div class="ui-dialog-backdrop" on:click|self={handleClose}>
54
+ <!-- svelte-ignore a11y_click_events_have_key_events, a11y_no_noninteractive_element_interactions, a11y_no_static_element_interactions -->
55
+ <div class="ui-dialog-backdrop" onclick={self(handleClose)}>
38
56
  <div class="ui-dialog" style="width: {width}; max-width: {width};">
39
57
  {#if title}
40
58
  <div class="ui-dialog-header">
41
59
  <h3 class="ui-dialog-title">{title}</h3>
42
- <button bind:this={closeButtonRef} class="ui-dialog-close" on:click={handleClose} aria-label="Close">
60
+ <button bind:this={closeButtonRef} class="ui-dialog-close" onclick={handleClose} aria-label="Close">
43
61
  <i class="fas fa-times"></i>
44
62
  </button>
45
63
  </div>
46
64
  {/if}
47
65
 
48
66
  <div class="ui-dialog-body">
49
- <slot />
67
+ {@render children?.()}
50
68
  </div>
51
69
 
52
70
  {#if showCancel || confirmLabel}
53
71
  <div class="ui-dialog-footer">
54
72
  {#if showCancel}
55
- <button bind:this={cancelButtonRef} class="ui-dialog-btn" on:click={handleClose}>
73
+ <button bind:this={cancelButtonRef} class="ui-dialog-btn" onclick={handleClose}>
56
74
  {cancelLabel}
57
75
  </button>
58
76
  {/if}
@@ -60,7 +78,7 @@
60
78
  <button
61
79
  bind:this={confirmButtonRef}
62
80
  class="ui-dialog-btn primary"
63
- on:click={handleConfirm}
81
+ onclick={handleConfirm}
64
82
  disabled={confirmDisabled}
65
83
  >
66
84
  {confirmLabel}
@@ -1,5 +1,7 @@
1
1
  <script lang="ts">
2
- import { onMount, onDestroy, createEventDispatcher } from 'svelte';
2
+ import { run } from 'svelte/legacy';
3
+
4
+ import { onMount, onDestroy } from 'svelte';
3
5
  import { resolveAliasChain } from '../lib/tokenRegistry';
4
6
  import { editorState } from '../lib/editorStore';
5
7
  import { CSS_VAR_CHANGE_EVENT } from '../lib/cssVarSync';
@@ -8,13 +10,23 @@
8
10
  import UIOptionList from './UIOptionList.svelte';
9
11
  import UIOptionItem from './UIOptionItem.svelte';
10
12
 
11
- const dispatch = createEventDispatcher();
13
+ interface Props {
14
+ variable: string;
15
+ component?: string | undefined;
16
+ canBeLinked?: boolean;
17
+ disabled?: boolean;
18
+ selectionsLocked?: boolean;
19
+ onchange?: () => void;
20
+ }
12
21
 
13
- export let variable: string;
14
- export let component: string | undefined = undefined;
15
- export let canBeLinked: boolean = false;
16
- export let disabled: boolean = false;
17
- export let selectionsLocked: boolean = false;
22
+ let {
23
+ variable,
24
+ component = undefined,
25
+ canBeLinked = false,
26
+ disabled = false,
27
+ selectionsLocked = false,
28
+ onchange,
29
+ }: Props = $props();
18
30
 
19
31
  const options = [
20
32
  { key: 'display', label: 'Display' },
@@ -23,15 +35,15 @@
23
35
  { key: 'mono', label: 'Mono' },
24
36
  ];
25
37
 
26
- let selector: UITokenSelector;
27
- let chosenKey: string | null = null;
28
- let chosenFamilyId: string | null = null;
29
- let currentStack: string = '';
30
- let familyNameByKey: Record<string, string> = {};
38
+ let selector: UITokenSelector | undefined = $state();
39
+ let chosenKey: string | null = $state(null);
40
+ let chosenFamilyId: string | null = $state(null);
41
+ let currentStack: string = $state('');
42
+ let familyNameByKey: Record<string, string> = $state({});
31
43
 
32
- $: fontSources = $editorState.fonts.sources;
33
- $: allFamilies = (fontSources as FontSource[]).flatMap((s) => s.families);
34
- $: hasProjectFonts = allFamilies.length > 0;
44
+ let fontSources = $derived($editorState.fonts.sources);
45
+ let allFamilies = $derived((fontSources as FontSource[]).flatMap((s) => s.families));
46
+ let hasProjectFonts = $derived(allFamilies.length > 0);
35
47
 
36
48
  function parseRef(value: string): string | null {
37
49
  const m = value.match(/var\((--font-[a-z]+)\)/);
@@ -111,41 +123,43 @@
111
123
  chosenKey = null;
112
124
  chosenFamilyId = null;
113
125
  readResolved();
114
- dispatch('change');
126
+ onchange?.();
115
127
  }
116
128
 
117
129
  function selectOption(key: string, close: () => void) {
118
130
  const target = `--font-${key}`;
119
131
  if (target === variable) {
120
- selector.writeOverride(null);
132
+ selector?.writeOverride(null);
121
133
  chosenKey = null;
122
134
  } else {
123
- selector.writeOverride(target);
135
+ selector?.writeOverride(target);
124
136
  chosenKey = key;
125
137
  }
126
138
  chosenFamilyId = null;
127
139
  readResolved();
128
140
  close();
129
- dispatch('change');
141
+ onchange?.();
130
142
  }
131
143
 
132
144
  function selectProjectFamily(family: FontFamily, close: () => void) {
133
145
  const stack = `'${family.cssName}', ${genericFor(variable)}`;
134
- selector.writeOverride(stack);
146
+ selector?.writeOverride(stack);
135
147
  chosenKey = null;
136
148
  chosenFamilyId = family.id;
137
149
  readResolved();
138
150
  close();
139
- dispatch('change');
151
+ onchange?.();
140
152
  }
141
153
 
142
154
  // Re-derive `chosenKey` / `chosenFamilyId` when `variable` changes (the
143
155
  // VariantGroup tabs view reuses the same selector instance across states).
144
- let lastSeenVariable: string | null = null;
145
- $: if (variable !== lastSeenVariable) {
146
- lastSeenVariable = variable;
147
- initFromCurrent();
148
- }
156
+ let lastSeenVariable: string | null = $state(null);
157
+ run(() => {
158
+ if (variable !== lastSeenVariable) {
159
+ lastSeenVariable = variable;
160
+ initFromCurrent();
161
+ }
162
+ });
149
163
 
150
164
  onMount(() => {
151
165
  document.addEventListener(CSS_VAR_CHANGE_EVENT, handleVarChange);
@@ -154,10 +168,10 @@
154
168
  document.removeEventListener(CSS_VAR_CHANGE_EVENT, handleVarChange);
155
169
  });
156
170
 
157
- $: activeLabel = chosenFamilyId
171
+ let activeLabel = $derived(chosenFamilyId
158
172
  ? (allFamilies.find((f) => f.id === chosenFamilyId)?.name ?? 'Project font')
159
- : (options.find((o) => o.key === chosenKey)?.label ?? '');
160
- $: displayFamily = firstFamilyName(currentStack);
173
+ : (options.find((o) => o.key === chosenKey)?.label ?? ''));
174
+ let displayFamily = $derived(firstFamilyName(currentStack));
161
175
  </script>
162
176
 
163
177
  <UITokenSelector
@@ -168,57 +182,69 @@
168
182
  {disabled}
169
183
  {selectionsLocked}
170
184
  dropdownMinWidth="14rem"
171
- on:reset={handleReset}
172
- on:var-change={initFromCurrent}
185
+ onreset={handleReset}
186
+ onvarChange={initFromCurrent}
173
187
  >
174
- <svelte:fragment slot="trigger-title">{activeLabel}</svelte:fragment>
175
- <svelte:fragment slot="trigger-meta">{displayFamily || '—'}</svelte:fragment>
176
-
177
- <svelte:fragment let:close>
178
- <UIOptionList>
179
- {#each options as opt}
180
- <UIOptionItem
181
- active={chosenKey === opt.key}
182
- on:click={() => selectOption(opt.key, close)}
183
- >
184
- <span slot="preview" class="font-sample" style="font-family: var(--font-{opt.key});">Aa</span>
185
- <svelte:fragment slot="label">{opt.label}</svelte:fragment>
186
- <svelte:fragment slot="meta">{familyNameByKey[opt.key] ?? ''}</svelte:fragment>
187
- </UIOptionItem>
188
- {/each}
189
-
190
- {#if hasProjectFonts}
191
- <div class="pfs-divider" role="separator"></div>
192
- <div class="pfs-section">
193
- <div class="pfs-trigger" class:active={chosenFamilyId !== null}>
194
- <span class="pfs-label">Project Fonts</span>
195
- <span class="pfs-count">{allFamilies.length}</span>
196
- <i class="fas fa-chevron-right pfs-chevron" aria-hidden="true"></i>
197
- </div>
198
- <div class="pfs-submenu">
199
- {#each fontSources as source (source.id)}
200
- {#if source.families.length > 0}
201
- <div class="pfs-source-label">{source.label ?? source.kind}</div>
202
- {#each source.families as fam (fam.id)}
203
- <UIOptionItem
204
- active={chosenFamilyId === fam.id}
205
- on:click={() => selectProjectFamily(fam, close)}
206
- >
207
- <span
208
- slot="preview"
209
- class="font-sample"
210
- style="font-family: '{fam.cssName}', {genericFor(variable)};"
211
- >Aa</span>
212
- <svelte:fragment slot="label">{fam.name}</svelte:fragment>
213
- </UIOptionItem>
214
- {/each}
215
- {/if}
216
- {/each}
188
+ {#snippet triggerTitle()}{activeLabel}{/snippet}
189
+ {#snippet triggerMeta()}{displayFamily || '—'}{/snippet}
190
+
191
+ {#snippet children({ close })}
192
+
193
+ <UIOptionList>
194
+ {#each options as opt}
195
+ <UIOptionItem
196
+ active={chosenKey === opt.key}
197
+ onclick={() => selectOption(opt.key, close)}
198
+ >
199
+ {#snippet preview()}
200
+ <span class="font-sample" style="font-family: var(--font-{opt.key});">Aa</span>
201
+ {/snippet}
202
+ {#snippet label()}
203
+ {opt.label}
204
+ {/snippet}
205
+ {#snippet meta()}
206
+ {familyNameByKey[opt.key] ?? ''}
207
+ {/snippet}
208
+ </UIOptionItem>
209
+ {/each}
210
+
211
+ {#if hasProjectFonts}
212
+ <div class="pfs-divider" role="separator"></div>
213
+ <div class="pfs-section">
214
+ <div class="pfs-trigger" class:active={chosenFamilyId !== null}>
215
+ <span class="pfs-label">Project Fonts</span>
216
+ <span class="pfs-count">{allFamilies.length}</span>
217
+ <i class="fas fa-chevron-right pfs-chevron" aria-hidden="true"></i>
218
+ </div>
219
+ <div class="pfs-submenu">
220
+ {#each fontSources as source (source.id)}
221
+ {#if source.families.length > 0}
222
+ <div class="pfs-source-label">{source.label ?? source.kind}</div>
223
+ {#each source.families as fam (fam.id)}
224
+ <UIOptionItem
225
+ active={chosenFamilyId === fam.id}
226
+ onclick={() => selectProjectFamily(fam, close)}
227
+ >
228
+ {#snippet preview()}
229
+ <span
230
+
231
+ class="font-sample"
232
+ style="font-family: '{fam.cssName}', {genericFor(variable)};"
233
+ >Aa</span>
234
+ {/snippet}
235
+ {#snippet label()}
236
+ {fam.name}
237
+ {/snippet}
238
+ </UIOptionItem>
239
+ {/each}
240
+ {/if}
241
+ {/each}
242
+ </div>
217
243
  </div>
218
- </div>
219
- {/if}
220
- </UIOptionList>
221
- </svelte:fragment>
244
+ {/if}
245
+ </UIOptionList>
246
+
247
+ {/snippet}
222
248
  </UITokenSelector>
223
249
 
224
250
  <style>
@@ -1,17 +1,31 @@
1
1
  <script lang="ts">
2
+ import { run } from 'svelte/legacy';
3
+
2
4
  import { onMount, onDestroy } from 'svelte';
3
5
  import { CSS_VAR_CHANGE_EVENT } from '../lib/cssVarSync';
4
6
  import UIVariantSelector from './UIVariantSelector.svelte';
5
7
 
6
- export let variable: string;
7
- export let component: string | undefined = undefined;
8
- export let canBeLinked: boolean = false;
9
- export let disabled: boolean = false;
10
- export let selectionsLocked: boolean = false;
8
+ interface Props {
9
+ variable: string;
10
+ component?: string | undefined;
11
+ canBeLinked?: boolean;
12
+ disabled?: boolean;
13
+ selectionsLocked?: boolean;
14
+ onchange?: () => void;
15
+ }
16
+
17
+ let {
18
+ variable,
19
+ component = undefined,
20
+ canBeLinked = false,
21
+ disabled = false,
22
+ selectionsLocked = false,
23
+ onchange,
24
+ }: Props = $props();
11
25
 
12
26
  // Icon-size variables (e.g. --tabbar-default-icon-size) pick from the
13
27
  // --icon-size-* scale; everything else from --font-size-*.
14
- $: scalePrefix = variable.endsWith('-icon-size') ? '--icon-size-' : '--font-size-';
28
+ let scalePrefix = $derived(variable.endsWith('-icon-size') ? '--icon-size-' : '--font-size-');
15
29
 
16
30
  const options = [
17
31
  { key: 'xs', label: 'XS' },
@@ -26,8 +40,8 @@
26
40
  { key: '6xl', label: '6XL' },
27
41
  ] as const;
28
42
 
29
- let pxByKey: Record<string, string> = {};
30
- let remByKey: Record<string, string> = {};
43
+ let pxByKey: Record<string, string> = $state({});
44
+ let remByKey: Record<string, string> = $state({});
31
45
 
32
46
  function formatRem(value: number): string {
33
47
  const rounded = Math.round(value * 1000) / 1000;
@@ -66,7 +80,9 @@
66
80
 
67
81
  // Re-read sizes when the target variable's scale changes
68
82
  // (mounting one selector, then opening another whose variable resolves to a different scale).
69
- $: if (typeof document !== 'undefined' && scalePrefix) readPxValues();
83
+ run(() => {
84
+ if (typeof document !== 'undefined' && scalePrefix) readPxValues();
85
+ });
70
86
 
71
87
  onMount(() => {
72
88
  readPxValues();
@@ -86,18 +102,20 @@
86
102
  varPrefix={scalePrefix}
87
103
  {options}
88
104
  dropdownGridColumns="auto auto auto auto"
89
- on:change
105
+ {onchange}
90
106
  >
91
- <svelte:fragment slot="option" let:opt let:active let:select>
92
- <button class="font-size-row" class:active on:click={select}>
93
- <span class="size-sample-cell">
94
- <span class="size-sample" style="font-size: calc(var({scalePrefix}{opt.key}) * 1.5);">A</span>
95
- </span>
96
- <span class="size-label">{opt.label}</span>
97
- <code class="size-measure">{pxByKey[opt.key] ?? ''}</code>
98
- <code class="size-measure">{remByKey[opt.key] ?? ''}</code>
99
- </button>
100
- </svelte:fragment>
107
+ {#snippet option({ opt, active, select })}
108
+
109
+ <button class="font-size-row" class:active onclick={select}>
110
+ <span class="size-sample-cell">
111
+ <span class="size-sample" style="font-size: calc(var({scalePrefix}{opt.key}) * 1.5);">A</span>
112
+ </span>
113
+ <span class="size-label">{opt.label}</span>
114
+ <code class="size-measure">{pxByKey[opt.key] ?? ''}</code>
115
+ <code class="size-measure">{remByKey[opt.key] ?? ''}</code>
116
+ </button>
117
+
118
+ {/snippet}
101
119
  </UIVariantSelector>
102
120
 
103
121
  <style>
@@ -2,11 +2,23 @@
2
2
  import UIVariantSelector from './UIVariantSelector.svelte';
3
3
  import UIOptionItem from './UIOptionItem.svelte';
4
4
 
5
- export let variable: string;
6
- export let component: string | undefined = undefined;
7
- export let canBeLinked: boolean = false;
8
- export let disabled: boolean = false;
9
- export let selectionsLocked: boolean = false;
5
+ interface Props {
6
+ variable: string;
7
+ component?: string | undefined;
8
+ canBeLinked?: boolean;
9
+ disabled?: boolean;
10
+ selectionsLocked?: boolean;
11
+ onchange?: () => void;
12
+ }
13
+
14
+ let {
15
+ variable,
16
+ component = undefined,
17
+ canBeLinked = false,
18
+ disabled = false,
19
+ selectionsLocked = false,
20
+ onchange,
21
+ }: Props = $props();
10
22
 
11
23
  const options = [
12
24
  { key: 'thin', label: 'Thin', value: '100' },
@@ -29,15 +41,23 @@
29
41
  {selectionsLocked}
30
42
  varPrefix="--font-weight-"
31
43
  {options}
32
- on:change
44
+ {onchange}
33
45
  >
34
- <svelte:fragment slot="option" let:opt let:active let:select>
35
- <UIOptionItem {active} on:click={select}>
36
- <span slot="preview" class="weight-sample" style="font-weight: var(--font-weight-{opt.key});">A</span>
37
- <svelte:fragment slot="label">{opt.label}</svelte:fragment>
38
- <svelte:fragment slot="meta">{opt.value}</svelte:fragment>
39
- </UIOptionItem>
40
- </svelte:fragment>
46
+ {#snippet option({ opt, active, select })}
47
+
48
+ <UIOptionItem {active} onclick={select}>
49
+ {#snippet preview()}
50
+ <span class="weight-sample" style="font-weight: var(--font-weight-{opt.key});">A</span>
51
+ {/snippet}
52
+ {#snippet label()}
53
+ {opt.label}
54
+ {/snippet}
55
+ {#snippet meta()}
56
+ {opt.value}
57
+ {/snippet}
58
+ </UIOptionItem>
59
+
60
+ {/snippet}
41
61
  </UIVariantSelector>
42
62
 
43
63
  <style>
@@ -2,11 +2,23 @@
2
2
  import UIVariantSelector from './UIVariantSelector.svelte';
3
3
  import UIOptionItem from './UIOptionItem.svelte';
4
4
 
5
- export let variable: string;
6
- export let component: string | undefined = undefined;
7
- export let canBeLinked: boolean = false;
8
- export let disabled: boolean = false;
9
- export let selectionsLocked: boolean = false;
5
+ interface Props {
6
+ variable: string;
7
+ component?: string | undefined;
8
+ canBeLinked?: boolean;
9
+ disabled?: boolean;
10
+ selectionsLocked?: boolean;
11
+ onchange?: () => void;
12
+ }
13
+
14
+ let {
15
+ variable,
16
+ component = undefined,
17
+ canBeLinked = false,
18
+ disabled = false,
19
+ selectionsLocked = false,
20
+ onchange,
21
+ }: Props = $props();
10
22
 
11
23
  const options = [
12
24
  { key: 'tight', label: 'Tight', value: '1' },
@@ -25,15 +37,23 @@
25
37
  {selectionsLocked}
26
38
  varPrefix="--line-height-"
27
39
  {options}
28
- on:change
40
+ {onchange}
29
41
  >
30
- <svelte:fragment slot="option" let:opt let:active let:select>
31
- <UIOptionItem {active} on:click={select}>
32
- <span slot="preview" class="lh-sample" style="line-height: var(--line-height-{opt.key});">≡</span>
33
- <svelte:fragment slot="label">{opt.label}</svelte:fragment>
34
- <svelte:fragment slot="meta">{opt.value}</svelte:fragment>
35
- </UIOptionItem>
36
- </svelte:fragment>
42
+ {#snippet option({ opt, active, select })}
43
+
44
+ <UIOptionItem {active} onclick={select}>
45
+ {#snippet preview()}
46
+ <span class="lh-sample" style="line-height: var(--line-height-{opt.key});">≡</span>
47
+ {/snippet}
48
+ {#snippet label()}
49
+ {opt.label}
50
+ {/snippet}
51
+ {#snippet meta()}
52
+ {opt.value}
53
+ {/snippet}
54
+ </UIOptionItem>
55
+
56
+ {/snippet}
37
57
  </UIVariantSelector>
38
58
 
39
59
  <style>
@@ -1,13 +1,14 @@
1
1
  <script lang="ts">
2
- import { createEventDispatcher } from 'svelte';
3
-
4
- export let linked: boolean = false;
2
+ interface Props {
3
+ linked?: boolean;
4
+ ontoggle?: () => void;
5
+ }
5
6
 
6
- const dispatch = createEventDispatcher();
7
+ let { linked = false, ontoggle }: Props = $props();
7
8
 
8
9
  function handleClick(e: Event) {
9
10
  e.stopPropagation();
10
- dispatch('toggle');
11
+ ontoggle?.();
11
12
  }
12
13
  </script>
13
14
 
@@ -16,7 +17,7 @@
16
17
  class="ui-link-toggle"
17
18
  class:linked
18
19
  title={linked ? 'Locked across variants — click to unlink' : 'Click to link across all variants'}
19
- on:click={handleClick}
20
+ onclick={handleClick}
20
21
  >
21
22
  <i class="fas" class:fa-lock={linked} class:fa-lock-open={!linked} aria-hidden="true"></i>
22
23
  <span>{linked ? 'Unlink' : 'Link'}</span>
@@ -1,19 +1,33 @@
1
1
  <script lang="ts">
2
- export let active: boolean = false;
2
+ interface Props {
3
+ active?: boolean;
4
+ preview?: import('svelte').Snippet;
5
+ label?: import('svelte').Snippet;
6
+ meta?: import('svelte').Snippet;
7
+ onclick?: (event: MouseEvent) => void;
8
+ }
9
+
10
+ let {
11
+ active = false,
12
+ preview,
13
+ label,
14
+ meta,
15
+ onclick
16
+ }: Props = $props();
3
17
  </script>
4
18
 
5
- <button class="ui-option-item" class:active on:click>
6
- {#if $$slots.preview}
19
+ <button class="ui-option-item" class:active {onclick}>
20
+ {#if preview}
7
21
  <span class="ui-option-preview">
8
- <slot name="preview" />
22
+ {@render preview?.()}
9
23
  </span>
10
24
  {/if}
11
25
  <span class="ui-option-label">
12
- <slot name="label" />
26
+ {@render label?.()}
13
27
  </span>
14
- {#if $$slots.meta}
28
+ {#if meta}
15
29
  <code class="ui-option-meta">
16
- <slot name="meta" />
30
+ {@render meta?.()}
17
31
  </code>
18
32
  {/if}
19
33
  </button>