@motion-proto/live-tokens 0.3.9 → 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 (103) hide show
  1. package/package.json +9 -8
  2. package/src/component-editor/BadgeEditor.svelte +24 -22
  3. package/src/component-editor/CalloutEditor.svelte +3 -3
  4. package/src/component-editor/CardEditor.svelte +25 -21
  5. package/src/component-editor/CollapsibleSectionEditor.svelte +27 -25
  6. package/src/component-editor/CornerBadgeEditor.svelte +37 -35
  7. package/src/component-editor/DialogEditor.svelte +26 -24
  8. package/src/component-editor/ImageEditor.svelte +11 -9
  9. package/src/component-editor/InlineEditActionsEditor.svelte +17 -15
  10. package/src/component-editor/NotificationEditor.svelte +32 -30
  11. package/src/component-editor/ProgressBarEditor.svelte +3 -3
  12. package/src/component-editor/RadioButtonEditor.svelte +31 -29
  13. package/src/component-editor/SectionDividerEditor.svelte +30 -28
  14. package/src/component-editor/SegmentedControlEditor.svelte +29 -25
  15. package/src/component-editor/StandardButtonsEditor.svelte +42 -38
  16. package/src/component-editor/TabBarEditor.svelte +20 -18
  17. package/src/component-editor/TableEditor.svelte +4 -4
  18. package/src/component-editor/TooltipEditor.svelte +11 -9
  19. package/src/component-editor/registry.ts +2 -2
  20. package/src/component-editor/scaffolding/AngleDial.svelte +20 -19
  21. package/src/component-editor/scaffolding/ComponentEditorBase.svelte +44 -20
  22. package/src/component-editor/scaffolding/ComponentFileManager.svelte +260 -37
  23. package/src/component-editor/scaffolding/ComponentFileMenu.svelte +41 -29
  24. package/src/component-editor/scaffolding/ComponentsTab.svelte +7 -3
  25. package/src/component-editor/scaffolding/CopyFromMenu.svelte +21 -12
  26. package/src/component-editor/scaffolding/DemoHeader.svelte +13 -4
  27. package/src/component-editor/scaffolding/DividerEditor.svelte +27 -14
  28. package/src/component-editor/scaffolding/FieldsetWrapper.svelte +10 -4
  29. package/src/component-editor/scaffolding/GradientCard.svelte +25 -20
  30. package/src/component-editor/scaffolding/LinkageChart.svelte +43 -34
  31. package/src/component-editor/scaffolding/LinkedBlock.svelte +24 -21
  32. package/src/component-editor/scaffolding/NonStylableConfig.svelte +6 -1
  33. package/src/component-editor/scaffolding/SaveAsDialog.svelte +39 -35
  34. package/src/component-editor/scaffolding/ShadowBackdrop.svelte +21 -9
  35. package/src/component-editor/scaffolding/ShadowBackdropControls.svelte +8 -3
  36. package/src/component-editor/scaffolding/StateBlock.svelte +30 -13
  37. package/src/component-editor/scaffolding/TokenLayout.svelte +46 -30
  38. package/src/component-editor/scaffolding/TypeEditor.svelte +52 -26
  39. package/src/component-editor/scaffolding/VariantGroup.svelte +81 -48
  40. package/src/component-editor/scaffolding/componentSectionType.ts +2 -2
  41. package/src/components/Badge.svelte +45 -26
  42. package/src/components/Button.svelte +44 -21
  43. package/src/components/Callout.svelte +17 -12
  44. package/src/components/Card.svelte +23 -11
  45. package/src/components/CollapsibleSection.svelte +56 -27
  46. package/src/components/CornerBadge.svelte +32 -18
  47. package/src/components/Dialog.svelte +55 -31
  48. package/src/components/Image.svelte +14 -5
  49. package/src/components/InlineEditActions.svelte +22 -10
  50. package/src/components/Notification.svelte +39 -19
  51. package/src/components/ProgressBar.svelte +27 -17
  52. package/src/components/RadioButton.svelte +27 -10
  53. package/src/components/SectionDivider.svelte +34 -26
  54. package/src/components/SegmentedControl.svelte +23 -9
  55. package/src/components/TabBar.svelte +23 -10
  56. package/src/components/Table.svelte +8 -3
  57. package/src/components/Tooltip.svelte +15 -5
  58. package/src/lib/ColumnsOverlay.svelte +3 -3
  59. package/src/lib/LiveEditorOverlay.svelte +57 -36
  60. package/src/pages/ComponentEditorPage.svelte +17 -13
  61. package/src/pages/EditorShell.svelte +24 -20
  62. package/src/styles/form-controls.css +2 -2
  63. package/src/styles/tokens.css +59 -81
  64. package/src/ui/BezierCurveEditor.svelte +59 -43
  65. package/src/ui/ColorEditPanel.svelte +71 -44
  66. package/src/ui/EditorViewSwitcher.svelte +9 -5
  67. package/src/ui/FontStackEditor.svelte +16 -15
  68. package/src/ui/GradientEditor.svelte +42 -33
  69. package/src/ui/GradientStopPicker.svelte +18 -29
  70. package/src/ui/PaletteEditor.svelte +238 -212
  71. package/src/ui/PresetFileManager.svelte +20 -18
  72. package/src/ui/ProjectFontsSection.svelte +30 -30
  73. package/src/ui/SurfacesTab.svelte +3 -3
  74. package/src/ui/TextTab.svelte +2 -2
  75. package/src/ui/ThemeFileManager.svelte +38 -35
  76. package/src/ui/Toggle.svelte +11 -9
  77. package/src/ui/UICopyPopover.svelte +19 -15
  78. package/src/ui/UIDialog.svelte +48 -30
  79. package/src/ui/UIFontFamilySelector.svelte +104 -78
  80. package/src/ui/UIFontSizeSelector.svelte +38 -20
  81. package/src/ui/UIFontWeightSelector.svelte +33 -13
  82. package/src/ui/UILineHeightSelector.svelte +33 -13
  83. package/src/ui/UILinkToggle.svelte +7 -6
  84. package/src/ui/UIOptionItem.svelte +21 -7
  85. package/src/ui/UIOptionList.svelte +9 -3
  86. package/src/ui/UIPaddingSelector.svelte +108 -82
  87. package/src/ui/UIPaletteSelector.svelte +186 -161
  88. package/src/ui/UIRadio.svelte +23 -8
  89. package/src/ui/UIRadioGroup.svelte +9 -8
  90. package/src/ui/UIRelinkConfirmPopover.svelte +26 -16
  91. package/src/ui/UITokenSelector.svelte +112 -68
  92. package/src/ui/UIVariantSelector.svelte +79 -57
  93. package/src/ui/VariablesTab.svelte +15 -15
  94. package/src/ui/palette/GradientStopEditor.svelte +45 -26
  95. package/src/ui/palette/OverridesPanel.svelte +85 -49
  96. package/src/ui/palette/PaletteBase.svelte +60 -32
  97. package/src/ui/palette/ScaleCurveEditor.svelte +25 -10
  98. package/src/ui/sections/ColumnsSection.svelte +13 -13
  99. package/src/ui/sections/GradientsSection.svelte +12 -9
  100. package/src/ui/sections/OverlaysSection.svelte +50 -47
  101. package/src/ui/sections/ShadowsSection.svelte +110 -104
  102. package/src/ui/sections/TokenScaleTable.svelte +38 -22
  103. package/src/ui/sections/tokenScales.ts +2 -2
@@ -1,8 +1,14 @@
1
1
  <script lang="ts">
2
- /** When set, the list becomes a CSS grid using these columns; rows are
2
+
3
+ interface Props {
4
+ /** When set, the list becomes a CSS grid using these columns; rows are
3
5
  * expected to use `display: grid; grid-template-columns: subgrid` so cells
4
6
  * align across rows. */
5
- export let gridColumns: string = '';
7
+ gridColumns?: string;
8
+ children?: import('svelte').Snippet;
9
+ }
10
+
11
+ let { gridColumns = '', children }: Props = $props();
6
12
  </script>
7
13
 
8
14
  <div
@@ -10,7 +16,7 @@
10
16
  class:grid={!!gridColumns}
11
17
  style:grid-template-columns={gridColumns || null}
12
18
  >
13
- <slot />
19
+ {@render children?.()}
14
20
  </div>
15
21
 
16
22
  <style>
@@ -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 { fade, fly, slide } from 'svelte/transition';
4
6
  import { cubicOut, cubicIn, cubicInOut } from 'svelte/easing';
5
7
  import UITokenSelector from './UITokenSelector.svelte';
@@ -19,19 +21,31 @@
19
21
  import UIRelinkConfirmPopover from './UIRelinkConfirmPopover.svelte';
20
22
  import UILinkToggle from './UILinkToggle.svelte';
21
23
 
22
- const dispatch = createEventDispatcher();
23
-
24
- export let variable: string;
25
- export let component: string | undefined = undefined;
26
- export let canBeLinked: boolean = false;
27
- export let disabled: boolean = false;
28
- export let selectionsLocked: boolean = false;
29
- /** When 'sides', renders the per-side rows alongside the link/merge header.
24
+ interface Props {
25
+ variable: string;
26
+ component?: string | undefined;
27
+ canBeLinked?: boolean;
28
+ disabled?: boolean;
29
+ selectionsLocked?: boolean;
30
+ /** When 'sides', renders the per-side rows alongside the link/merge header.
30
31
  The header occupies cols 2-3 of the parent token-row (sharing row 1 with
31
32
  TokenLayout's .token-label) and the side rows fill cols 1-3 of row 2. */
32
- export let mode: 'single' | 'sides' = 'single';
33
- /** When false, hide the split-to-sides affordance (e.g. for non-box spacing like gap). */
34
- export let splittable: boolean = true;
33
+ mode?: 'single' | 'sides';
34
+ /** When false, hide the split-to-sides affordance (e.g. for non-box spacing like gap). */
35
+ splittable?: boolean;
36
+ onchange?: () => void;
37
+ }
38
+
39
+ let {
40
+ variable,
41
+ component = undefined,
42
+ canBeLinked = false,
43
+ disabled = false,
44
+ selectionsLocked = false,
45
+ mode = 'single',
46
+ splittable = true,
47
+ onchange,
48
+ }: Props = $props();
35
49
 
36
50
  type Side = 'top' | 'right' | 'bottom' | 'left';
37
51
  const SIDES: readonly Side[] = ['top', 'right', 'bottom', 'left'];
@@ -131,10 +145,10 @@
131
145
  }
132
146
  }
133
147
 
134
- let chosenKey: string | null = null;
135
- let resolvedSize = '';
136
- let sideKeys: Record<Side, string | null> = { top: null, right: null, bottom: null, left: null };
137
- let sideResolved: Record<Side, string> = { top: '', right: '', bottom: '', left: '' };
148
+ let chosenKey: string | null = $state(null);
149
+ let resolvedSize = $state('');
150
+ let sideKeys: Record<Side, string | null> = $state({ top: null, right: null, bottom: null, left: null });
151
+ let sideResolved: Record<Side, string> = $state({ top: '', right: '', bottom: '', left: '' });
138
152
 
139
153
  function refreshFromState() {
140
154
  chosenKey = parseKey(readAlias(variable));
@@ -152,31 +166,31 @@
152
166
  function selectSingle(key: string, close: () => void) {
153
167
  writeAliasLinked(variable, tokenForKey(key));
154
168
  close();
155
- dispatch('change');
169
+ onchange?.();
156
170
  }
157
171
 
158
172
  function selectSide(s: Side, key: string, close: () => void) {
159
173
  writeAliasLinked(sideVar(s), tokenForKey(key));
160
174
  close();
161
- dispatch('change');
175
+ onchange?.();
162
176
  }
163
177
 
164
178
  function handleResetAll() {
165
179
  for (const s of SIDES) writeAliasLinked(sideVar(s), null);
166
180
  writeAliasLinked(variable, null);
167
- dispatch('change');
181
+ onchange?.();
168
182
  }
169
183
 
170
184
  function handleResetSide(s: Side) {
171
185
  writeAliasLinked(sideVar(s), null);
172
- dispatch('change');
186
+ onchange?.();
173
187
  }
174
188
 
175
189
  function splitToSides() {
176
190
  if (disabled) return;
177
191
  const seed = readAlias(variable) || tokenForKey('4');
178
192
  for (const s of SIDES) writeAliasLinked(sideVar(s), seed);
179
- dispatch('change');
193
+ onchange?.();
180
194
  }
181
195
 
182
196
  function mergeToSingle() {
@@ -184,7 +198,7 @@
184
198
  const seed = readAlias(sideVar('top')) || readAlias(variable);
185
199
  if (seed && !readAlias(variable)) writeAliasLinked(variable, seed);
186
200
  for (const s of SIDES) writeAliasLinked(sideVar(s), null);
187
- dispatch('change');
201
+ onchange?.();
188
202
  }
189
203
 
190
204
  function handleVarChange() {
@@ -202,32 +216,32 @@
202
216
 
203
217
  // Track `variable` alongside `$editorState` so a VariantGroup tabs view that
204
218
  // reuses this selector across states refreshes when the bound prop swaps.
205
- $: { variable; if ($editorState) refreshFromState(); }
219
+ run(() => { variable; if ($editorState) refreshFromState(); });
206
220
 
207
- $: activeKey = chosenKey ?? (options.find((o) => o.size === resolvedSize)?.key ?? null);
208
- $: activeLabel = options.find((o) => o.key === activeKey)?.label ?? '';
209
- $: sideActiveKey = {
221
+ let activeKey = $derived(chosenKey ?? (options.find((o) => o.size === resolvedSize)?.key ?? null));
222
+ let activeLabel = $derived(options.find((o) => o.key === activeKey)?.label ?? '');
223
+ let sideActiveKey = $derived({
210
224
  top: sideKeys.top ?? (options.find((o) => o.size === sideResolved.top)?.key ?? null),
211
225
  right: sideKeys.right ?? (options.find((o) => o.size === sideResolved.right)?.key ?? null),
212
226
  bottom: sideKeys.bottom ?? (options.find((o) => o.size === sideResolved.bottom)?.key ?? null),
213
227
  left: sideKeys.left ?? (options.find((o) => o.size === sideResolved.left)?.key ?? null),
214
- } as Record<Side, string | null>;
215
- $: sideLabels = {
228
+ } as Record<Side, string | null>);
229
+ let sideLabels = $derived({
216
230
  top: options.find((o) => o.key === sideActiveKey.top)?.label ?? '',
217
231
  right: options.find((o) => o.key === sideActiveKey.right)?.label ?? '',
218
232
  bottom: options.find((o) => o.key === sideActiveKey.bottom)?.label ?? '',
219
233
  left: options.find((o) => o.key === sideActiveKey.left)?.label ?? '',
220
- } as Record<Side, string>;
234
+ } as Record<Side, string>);
221
235
 
222
236
  // Linkage state for the parent token. The split fieldset is a single
223
237
  // linkage unit — peers either share the parent (and their per-side state
224
238
  // mirrors via `writeAliasLinked`) or one peer has detached. Mirrors the
225
239
  // pop-bar/lock-toggle vocabulary used by `UITokenSelector` so the visual
226
240
  // and interaction language is the same at both scales.
227
- $: hasParentSiblings = canBeLinked && component && $editorState
241
+ let hasParentSiblings = $derived(canBeLinked && component && $editorState
228
242
  ? getComponentPropertySiblings(component, variable).length >= 2
229
- : false;
230
- $: showLinkUI = canBeLinked && !!component && hasParentSiblings;
243
+ : false);
244
+ let showLinkUI = $derived(canBeLinked && !!component && hasParentSiblings);
231
245
  /** $editorState is referenced directly so this re-evaluates on every store
232
246
  * update. isComponentPropertyLinked reads `get(store)` internally — Svelte
233
247
  * can't see that as a dependency. Without the explicit reference, an
@@ -235,13 +249,13 @@
235
249
  * would not re-run this expression: Svelte's $$invalidate skips marking
236
250
  * a boolean dirty when the new value equals the old, so the dirty bit
237
251
  * never propagates to isLinkedParent. */
238
- $: isLinkedParent = !!$editorState
252
+ let isLinkedParent = $derived(!!$editorState
239
253
  && showLinkUI
240
254
  && !!component
241
- && isComponentPropertyLinked(component, variable);
255
+ && isComponentPropertyLinked(component, variable));
242
256
 
243
- let relinkOpen = false;
244
- let relinkCandidates: { variable: string; alias: string }[] = [];
257
+ let relinkOpen = $state(false);
258
+ let relinkCandidates: { variable: string; alias: string }[] = $state([]);
245
259
 
246
260
  /** Adopt one peer's entire padding block (parent + four sides) onto every
247
261
  * currently-linked peer. Padding is treated as a single shared unit — when
@@ -293,7 +307,7 @@
293
307
  if (!showLinkUI || !component) return;
294
308
  if (isLinkedParent) {
295
309
  unlinkComponentProperty(component, variable);
296
- dispatch('change');
310
+ onchange?.();
297
311
  return;
298
312
  }
299
313
  const slice = $editorState.components[component];
@@ -307,7 +321,7 @@
307
321
  const currentValue = slice.aliases[variable];
308
322
  if (currentValue) {
309
323
  adoptBlockFromPeer(variable);
310
- dispatch('change');
324
+ onchange?.();
311
325
  }
312
326
  return;
313
327
  }
@@ -323,20 +337,20 @@
323
337
  ? definedCandidates[0].variable
324
338
  : variable;
325
339
  adoptBlockFromPeer(sourcePeer);
326
- dispatch('change');
340
+ onchange?.();
327
341
  return;
328
342
  }
329
343
  relinkCandidates = candidates;
330
344
  relinkOpen = true;
331
345
  }
332
346
 
333
- function handleRelinkConfirm(e: CustomEvent<{ alias: string }>) {
347
+ function handleRelinkConfirm(payload: { alias: string }) {
334
348
  if (!component) return;
335
349
  // Find the peer whose parent alias matches the chosen one — its full
336
350
  // block (split state + side values) becomes canonical.
337
- const sourcePeer = relinkCandidates.find((c) => c.alias === e.detail.alias)?.variable ?? variable;
351
+ const sourcePeer = relinkCandidates.find((c) => c.alias === payload.alias)?.variable ?? variable;
338
352
  adoptBlockFromPeer(sourcePeer);
339
- dispatch('change');
353
+ onchange?.();
340
354
  relinkOpen = false;
341
355
  }
342
356
 
@@ -367,14 +381,14 @@
367
381
  >
368
382
  {#if showLinkUI}
369
383
  <div class="link-toggle-wrap">
370
- <UILinkToggle linked={isLinkedParent} on:toggle={toggleLinkPaddingGroup} />
384
+ <UILinkToggle linked={isLinkedParent} ontoggle={toggleLinkPaddingGroup} />
371
385
  {#if relinkOpen && component}
372
386
  <UIRelinkConfirmPopover
373
387
  candidates={relinkCandidates}
374
388
  initialVariable={variable}
375
389
  prefixToStrip={`--${component}-`}
376
- on:confirm={handleRelinkConfirm}
377
- on:cancel={handleRelinkCancel}
390
+ onconfirm={handleRelinkConfirm}
391
+ oncancel={handleRelinkCancel}
378
392
  />
379
393
  {/if}
380
394
  </div>
@@ -382,7 +396,7 @@
382
396
  <button
383
397
  type="button"
384
398
  class="merge-btn"
385
- on:click={mergeToSingle}
399
+ onclick={mergeToSingle}
386
400
  title="Use the same value for all sides"
387
401
  disabled={disabled || selectionsLocked}
388
402
  >
@@ -405,25 +419,31 @@
405
419
  canBeLinked={false}
406
420
  {disabled}
407
421
  {selectionsLocked}
408
- on:reset={() => handleResetSide(s)}
409
- on:var-change={handleVarChange}
422
+ onreset={() => handleResetSide(s)}
423
+ onvarChange={handleVarChange}
410
424
  >
411
- <svelte:fragment slot="trigger-title">{sideLabels[s] || '—'}</svelte:fragment>
412
- <svelte:fragment slot="trigger-meta">{sideResolved[s] || '—'}</svelte:fragment>
413
-
414
- <svelte:fragment let:close>
415
- <UIOptionList>
416
- {#each options as opt}
417
- <UIOptionItem
418
- active={sideActiveKey[s] === opt.key}
419
- on:click={() => selectSide(s, opt.key, close)}
420
- >
421
- <svelte:fragment slot="label">{opt.label}</svelte:fragment>
422
- <svelte:fragment slot="meta">{opt.size}</svelte:fragment>
423
- </UIOptionItem>
424
- {/each}
425
- </UIOptionList>
426
- </svelte:fragment>
425
+ {#snippet triggerTitle()}{sideLabels[s] || '—'}{/snippet}
426
+ {#snippet triggerMeta()}{sideResolved[s] || '—'}{/snippet}
427
+
428
+ {#snippet children({ close })}
429
+
430
+ <UIOptionList>
431
+ {#each options as opt}
432
+ <UIOptionItem
433
+ active={sideActiveKey[s] === opt.key}
434
+ onclick={() => selectSide(s, opt.key, close)}
435
+ >
436
+ {#snippet label()}
437
+ {opt.label}
438
+ {/snippet}
439
+ {#snippet meta()}
440
+ {opt.size}
441
+ {/snippet}
442
+ </UIOptionItem>
443
+ {/each}
444
+ </UIOptionList>
445
+
446
+ {/snippet}
427
447
  </UITokenSelector>
428
448
  {/each}
429
449
  </div>
@@ -450,30 +470,36 @@
450
470
  {canBeLinked}
451
471
  {disabled}
452
472
  {selectionsLocked}
453
- on:reset={handleResetAll}
454
- on:var-change={handleVarChange}
473
+ onreset={handleResetAll}
474
+ onvarChange={handleVarChange}
455
475
  >
456
- <svelte:fragment slot="trigger-title">{activeLabel || '—'}</svelte:fragment>
457
-
458
- <svelte:fragment let:close>
459
- <UIOptionList>
460
- {#each options as opt}
461
- <UIOptionItem
462
- active={activeKey === opt.key}
463
- on:click={() => selectSingle(opt.key, close)}
464
- >
465
- <svelte:fragment slot="label">{opt.label}</svelte:fragment>
466
- <svelte:fragment slot="meta">{opt.size}</svelte:fragment>
467
- </UIOptionItem>
468
- {/each}
469
- </UIOptionList>
470
- </svelte:fragment>
476
+ {#snippet triggerTitle()}{activeLabel || '—'}{/snippet}
477
+
478
+ {#snippet children({ close })}
479
+
480
+ <UIOptionList>
481
+ {#each options as opt}
482
+ <UIOptionItem
483
+ active={activeKey === opt.key}
484
+ onclick={() => selectSingle(opt.key, close)}
485
+ >
486
+ {#snippet label()}
487
+ {opt.label}
488
+ {/snippet}
489
+ {#snippet meta()}
490
+ {opt.size}
491
+ {/snippet}
492
+ </UIOptionItem>
493
+ {/each}
494
+ </UIOptionList>
495
+
496
+ {/snippet}
471
497
  </UITokenSelector>
472
498
  {#if splittable}
473
499
  <button
474
500
  type="button"
475
501
  class="split-btn"
476
- on:click={splitToSides}
502
+ onclick={splitToSides}
477
503
  title="Set each side independently"
478
504
  disabled={disabled || selectionsLocked}
479
505
  in:fly|local={{ x: 24, opacity: 1, duration: t(220), delay: t(320), easing: cubicOut }}