@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,4 +1,6 @@
1
1
  <script lang="ts">
2
+ import { stopPropagation } from 'svelte/legacy';
3
+
2
4
  import {
3
5
  type CurveAnchor, type CurveConfig,
4
6
  CURVE_H, CURVE_PAD_Y, CURVE_Y_PAD,
@@ -7,15 +9,29 @@
7
9
  serializeCurve, deserializeCurve,
8
10
  } from './curveEngine';
9
11
 
10
- export let anchors: CurveAnchor[];
11
- export let cfg: CurveConfig;
12
- export let stepCount: number;
13
- export let padX: number = 0;
14
- export let offset: number = 0;
15
- export let defaultAnchors: CurveAnchor[] | null = null;
16
- export let lockedAnchorIndex: number | null = null;
17
- export let onAnchorsChange: (anchors: CurveAnchor[]) => void = () => {};
18
- export let onOffsetChange: (offset: number) => void = () => {};
12
+ interface Props {
13
+ anchors: CurveAnchor[];
14
+ cfg: CurveConfig;
15
+ stepCount: number;
16
+ padX?: number;
17
+ offset?: number;
18
+ defaultAnchors?: CurveAnchor[] | null;
19
+ lockedAnchorIndex?: number | null;
20
+ onAnchorsChange?: (anchors: CurveAnchor[]) => void;
21
+ onOffsetChange?: (offset: number) => void;
22
+ }
23
+
24
+ let {
25
+ anchors,
26
+ cfg,
27
+ stepCount,
28
+ padX = 0,
29
+ offset = 0,
30
+ defaultAnchors = null,
31
+ lockedAnchorIndex = null,
32
+ onAnchorsChange = () => {},
33
+ onOffsetChange = () => {}
34
+ }: Props = $props();
19
35
 
20
36
  function resetToDefault() {
21
37
  if (!defaultAnchors) return;
@@ -24,14 +40,14 @@
24
40
  }
25
41
 
26
42
  const CURVE_W_DEFAULT = 720;
27
- let svgEl: SVGSVGElement | null = null;
28
- let dims = CURVE_W_DEFAULT;
29
- let shiftActive = false;
43
+ let svgEl: SVGSVGElement | null = $state(null);
44
+ let dims = $state(CURVE_W_DEFAULT);
45
+ let shiftActive = $state(false);
30
46
 
31
47
  const clipId = `curve-clip-${Math.random().toString(36).slice(2, 8)}`;
32
48
 
33
- $: w = dims;
34
- $: offsetPx = -(offset / ((cfg.yMax - cfg.yMin) * (1 + 2 * CURVE_Y_PAD))) * (CURVE_H - 2 * CURVE_PAD_Y);
49
+ let w = $derived(dims);
50
+ let offsetPx = $derived(-(offset / ((cfg.yMax - cfg.yMin) * (1 + 2 * CURVE_Y_PAD))) * (CURVE_H - 2 * CURVE_PAD_Y));
35
51
 
36
52
  function stepToX(index: number): number {
37
53
  return stepCount > 1 ? (index / (stepCount - 1)) * 100 : 50;
@@ -281,21 +297,21 @@
281
297
  <!-- Curve content group — offset vertically, clipped -->
282
298
  <g transform="translate(0,{offsetPx})" clip-path="url(#{clipId})">
283
299
  {#if shiftActive}
284
- <!-- svelte-ignore a11y-no-static-element-interactions -->
300
+ <!-- svelte-ignore a11y_no_static_element_interactions -->
285
301
  <rect
286
302
  x="0" y={-CURVE_H} width={w} height={CURVE_H * 3}
287
303
  class="shift-overlay"
288
- on:pointerdown={handleShiftPointerDown}
289
- on:pointermove={handleShiftPointerMove}
290
- on:pointerup={handleShiftPointerUp}
304
+ onpointerdown={handleShiftPointerDown}
305
+ onpointermove={handleShiftPointerMove}
306
+ onpointerup={handleShiftPointerUp}
291
307
  />
292
308
  {:else}
293
- <!-- svelte-ignore a11y-click-events-have-key-events -->
294
- <!-- svelte-ignore a11y-no-static-element-interactions -->
309
+ <!-- svelte-ignore a11y_click_events_have_key_events -->
310
+ <!-- svelte-ignore a11y_no_static_element_interactions -->
295
311
  <path
296
312
  d={buildCurvePath(anchors, cfg, w, padX)}
297
313
  class="curve-hit"
298
- on:click={insertPointOnPath}
314
+ onclick={insertPointOnPath}
299
315
  />
300
316
  {/if}
301
317
 
@@ -311,13 +327,13 @@
311
327
  x2={curveXToSvg(pt.x + pt.inDx, w, padX)} y2={curveYToSvg(pt.y + pt.inDy, cfg)}
312
328
  class="handle-line"
313
329
  />
314
- <!-- svelte-ignore a11y-no-static-element-interactions -->
330
+ <!-- svelte-ignore a11y_no_static_element_interactions -->
315
331
  <circle
316
332
  cx={curveXToSvg(pt.x + pt.inDx, w, padX)} cy={curveYToSvg(pt.y + pt.inDy, cfg)}
317
333
  r="3.5" class="handle-grip"
318
- on:pointerdown={(e) => handlePointerDown(e, { kind: 'handleIn', index: i })}
319
- on:pointermove={handlePointerMove}
320
- on:pointerup={handlePointerUp}
334
+ onpointerdown={(e) => handlePointerDown(e, { kind: 'handleIn', index: i })}
335
+ onpointermove={handlePointerMove}
336
+ onpointerup={handlePointerUp}
321
337
  />
322
338
  {/if}
323
339
  {#if i < anchors.length - 1 && !isCornerAnchor(pt)}
@@ -326,16 +342,16 @@
326
342
  x2={curveXToSvg(pt.x + pt.outDx, w, padX)} y2={curveYToSvg(pt.y + pt.outDy, cfg)}
327
343
  class="handle-line"
328
344
  />
329
- <!-- svelte-ignore a11y-no-static-element-interactions -->
345
+ <!-- svelte-ignore a11y_no_static_element_interactions -->
330
346
  <circle
331
347
  cx={curveXToSvg(pt.x + pt.outDx, w, padX)} cy={curveYToSvg(pt.y + pt.outDy, cfg)}
332
348
  r="3.5" class="handle-grip"
333
- on:pointerdown={(e) => handlePointerDown(e, { kind: 'handleOut', index: i })}
334
- on:pointermove={handlePointerMove}
335
- on:pointerup={handlePointerUp}
349
+ onpointerdown={(e) => handlePointerDown(e, { kind: 'handleOut', index: i })}
350
+ onpointermove={handlePointerMove}
351
+ onpointerup={handlePointerUp}
336
352
  />
337
353
  {/if}
338
- <!-- svelte-ignore a11y-no-static-element-interactions -->
354
+ <!-- svelte-ignore a11y_no_static_element_interactions -->
339
355
  {#if i === lockedAnchorIndex}
340
356
  <path
341
357
  d="M{curveXToSvg(pt.x, w, padX)},{curveYToSvg(pt.y, cfg) - 6} l5,6 l-5,6 l-5,-6 Z"
@@ -346,19 +362,19 @@
346
362
  x={curveXToSvg(pt.x, w, padX) - 4} y={curveYToSvg(pt.y, cfg) - 4}
347
363
  width="8" height="8"
348
364
  class="curve-handle corner"
349
- on:pointerdown={(e) => handlePointerDown(e, { kind: 'anchor', index: i })}
350
- on:pointermove={handlePointerMove}
351
- on:pointerup={handlePointerUp}
352
- on:dblclick|stopPropagation={() => toggleAnchorSmooth(i)}
365
+ onpointerdown={(e) => handlePointerDown(e, { kind: 'anchor', index: i })}
366
+ onpointermove={handlePointerMove}
367
+ onpointerup={handlePointerUp}
368
+ ondblclick={stopPropagation(() => toggleAnchorSmooth(i))}
353
369
  />
354
370
  {:else}
355
371
  <circle
356
372
  cx={curveXToSvg(pt.x, w, padX)} cy={curveYToSvg(pt.y, cfg)}
357
373
  r="5" class="curve-handle"
358
- on:pointerdown={(e) => handlePointerDown(e, { kind: 'anchor', index: i })}
359
- on:pointermove={handlePointerMove}
360
- on:pointerup={handlePointerUp}
361
- on:dblclick|stopPropagation={() => toggleAnchorSmooth(i)}
374
+ onpointerdown={(e) => handlePointerDown(e, { kind: 'anchor', index: i })}
375
+ onpointermove={handlePointerMove}
376
+ onpointerup={handlePointerUp}
377
+ ondblclick={stopPropagation(() => toggleAnchorSmooth(i))}
362
378
  />
363
379
  {/if}
364
380
  {/each}
@@ -373,7 +389,7 @@
373
389
  class:active={shiftActive}
374
390
  type="button"
375
391
  title="Vertical offset"
376
- on:click={() => shiftActive = !shiftActive}
392
+ onclick={() => shiftActive = !shiftActive}
377
393
  >
378
394
  <svg viewBox="0 0 12 20" class="curve-tool-icon">
379
395
  <path d="M6,2 L10,7 L7,7 L7,13 L10,13 L6,18 L2,13 L5,13 L5,7 L2,7 Z" />
@@ -381,8 +397,8 @@
381
397
  <span>Offset{offset !== 0 ? ` ${offset > 0 ? '+' : ''}${offset}` : ''}</span>
382
398
  </button>
383
399
  <span class="curve-hint">&x2325;-click to remove point</span>
384
- <button class="curve-tool-btn" type="button" title="Copy curve" on:click={copyToClipboard}>Copy</button>
385
- <button class="curve-tool-btn" type="button" title="Paste curve" on:click={pasteFromClipboard}>Paste</button>
400
+ <button class="curve-tool-btn" type="button" title="Copy curve" onclick={copyToClipboard}>Copy</button>
401
+ <button class="curve-tool-btn" type="button" title="Paste curve" onclick={pasteFromClipboard}>Paste</button>
386
402
  </div>
387
403
  <div class="curve-templates">
388
404
  {#each curveTemplates as tpl}
@@ -390,7 +406,7 @@
390
406
  class="curve-template-btn"
391
407
  type="button"
392
408
  title={tpl.name}
393
- on:click={() => applyTemplate(tpl)}
409
+ onclick={() => applyTemplate(tpl)}
394
410
  >
395
411
  <svg viewBox="0 0 20 12" class="curve-template-icon">
396
412
  <path d={tpl.icon} />
@@ -402,7 +418,7 @@
402
418
  class="curve-tool-btn"
403
419
  type="button"
404
420
  title="Reset to default"
405
- on:click={resetToDefault}
421
+ onclick={resetToDefault}
406
422
  >Reset</button>
407
423
  {/if}
408
424
  </div>
@@ -3,25 +3,46 @@
3
3
  import InlineEditActions from '../components/InlineEditActions.svelte';
4
4
  import Button from '../components/Button.svelte';
5
5
 
6
- export let color: string;
7
- export let title: string | null = null;
8
- export let showRemoveOverride: boolean = false;
9
- export let onColorChange: (hex: string) => void = () => {};
10
- export let onConfirm: () => void = () => {};
11
- export let onCancel: () => void = () => {};
12
- export let onRemoveOverride: () => void = () => {};
13
- /**
6
+
7
+
8
+
9
+ interface Props {
10
+ color: string;
11
+ title?: string | null;
12
+ showRemoveOverride?: boolean;
13
+ onColorChange?: (hex: string) => void;
14
+ onConfirm?: () => void;
15
+ onCancel?: () => void;
16
+ onRemoveOverride?: () => void;
17
+ /**
14
18
  * Optional pointerdown hook for slider drags — lets parents open a store
15
19
  * transaction so the whole drag collapses to one undo step. If the parent
16
20
  * doesn't route slider writes through the editor store, leave this unset.
17
21
  */
18
- export let onSliderStart: () => void = () => {};
19
-
20
- // Hue-chroma mode props (for neutral/gray base editing)
21
- export let mode: 'hsl' | 'hue-chroma' = 'hsl';
22
- export let hue: number = 0;
23
- export let chroma: number = 0.04;
24
- export let onHueChromaChange: (hue: number, chroma: number) => void = () => {};
22
+ onSliderStart?: () => void;
23
+ // Hue-chroma mode props (for neutral/gray base editing)
24
+ mode?: 'hsl' | 'hue-chroma';
25
+ hue?: number;
26
+ chroma?: number;
27
+ onHueChromaChange?: (hue: number, chroma: number) => void;
28
+ actions?: import('svelte').Snippet;
29
+ }
30
+
31
+ let {
32
+ color,
33
+ title = null,
34
+ showRemoveOverride = false,
35
+ onColorChange = () => {},
36
+ onConfirm = () => {},
37
+ onCancel = () => {},
38
+ onRemoveOverride = () => {},
39
+ onSliderStart = () => {},
40
+ mode = 'hsl',
41
+ hue = 0,
42
+ chroma = 0.04,
43
+ onHueChromaChange = () => {},
44
+ actions
45
+ }: Props = $props();
25
46
 
26
47
  const hasEyeDropper = typeof window !== 'undefined' && 'EyeDropper' in window;
27
48
  const PREVIEW_LIGHTNESS = 0.55;
@@ -59,7 +80,7 @@
59
80
 
60
81
  // --- HSL mode reactives ---
61
82
 
62
- $: hsl = hexToHsl(color);
83
+ let hsl = $derived(hexToHsl(color));
63
84
 
64
85
  function hueGrad(s: number, l: number): string {
65
86
  return `linear-gradient(to right, ${
@@ -83,11 +104,11 @@
83
104
 
84
105
  // --- Hue-chroma mode reactives ---
85
106
 
86
- $: previewHex = mode === 'hue-chroma'
107
+ let previewHex = $derived(mode === 'hue-chroma'
87
108
  ? (() => { const c = gamutClamp(PREVIEW_LIGHTNESS, chroma, hue); return oklchToHex(c.l, c.c, c.h); })()
88
- : color;
109
+ : color);
89
110
 
90
- $: hueGradient = (() => {
111
+ let hueGradient = $derived((() => {
91
112
  const _c = chroma;
92
113
  const displayChroma = Math.max(_c, CHROMA_MAX);
93
114
  const stops = Array.from({ length: 13 }, (_, i) => {
@@ -96,9 +117,9 @@
96
117
  return oklchToHex(c.l, c.c, c.h);
97
118
  });
98
119
  return `linear-gradient(to right, ${stops.join(',')})`;
99
- })();
120
+ })());
100
121
 
101
- $: chromaGradient = (() => {
122
+ let chromaGradient = $derived((() => {
102
123
  const _h = hue;
103
124
  const stops = Array.from({ length: 8 }, (_, i) => {
104
125
  const c = (i / 7) * CHROMA_MAX;
@@ -106,7 +127,7 @@
106
127
  return oklchToHex(clamped.l, clamped.c, clamped.h);
107
128
  });
108
129
  return `linear-gradient(to right, ${stops.join(',')})`;
109
- })();
130
+ })());
110
131
 
111
132
  // --- Shared ---
112
133
 
@@ -127,8 +148,8 @@
127
148
  }
128
149
  }
129
150
 
130
- let hexEditing = false;
131
- let hexDraft = '';
151
+ let hexEditing = $state(false);
152
+ let hexDraft = $state('');
132
153
 
133
154
  function startHexEdit() {
134
155
  hexDraft = previewHex;
@@ -165,7 +186,7 @@
165
186
  class="eyedropper-btn"
166
187
  type="button"
167
188
  title="Pick color from screen"
168
- on:click={pickScreenColor}
189
+ onclick={pickScreenColor}
169
190
  ><i class="fas fa-eye-dropper"></i></button>
170
191
  {/if}
171
192
  {#if title}
@@ -176,20 +197,20 @@
176
197
  class="hsl-hex-input"
177
198
  type="text"
178
199
  bind:value={hexDraft}
179
- on:keydown={handleHexKeydown}
180
- on:blur={commitHex}
200
+ onkeydown={handleHexKeydown}
201
+ onblur={commitHex}
181
202
  maxlength="7"
182
203
  use:autoFocus
183
204
  />
184
205
  {:else}
185
- <button class="hsl-hex" on:click={startHexEdit} title="Click to edit hex">{previewHex}</button>
206
+ <button class="hsl-hex" onclick={startHexEdit} title="Click to edit hex">{previewHex}</button>
186
207
  {/if}
187
208
  {#if mode === 'hue-chroma'}
188
209
  <code class="hsl-values">oklch({PREVIEW_LIGHTNESS}, {chroma.toFixed(3)}, {Math.round(hue)})</code>
189
210
  {:else}
190
211
  <code class="hsl-values">hsl({hsl[0]}, {hsl[1]}%, {hsl[2]}%)</code>
191
212
  {/if}
192
- <slot name="actions" />
213
+ {@render actions?.()}
193
214
  <div class="hsl-panel-actions">
194
215
  {#if showRemoveOverride}
195
216
  <Button
@@ -211,9 +232,10 @@
211
232
  {#if mode === 'hue-chroma'}
212
233
  <div class="hsl-slider-row">
213
234
  <span class="hsl-slider-label">H</span>
214
- <div class="slider-track" style="background: {hueGradient}" on:pointerdown={onSliderStart}>
235
+ <!-- svelte-ignore a11y_no_static_element_interactions -->
236
+ <div class="slider-track" style="background: {hueGradient}" onpointerdown={onSliderStart}>
215
237
  <input type="range" min="0" max="360" value={hue}
216
- on:input={(e) => onHueChromaChange(+e.currentTarget.value, chroma)} />
238
+ oninput={(e) => onHueChromaChange(+e.currentTarget.value, chroma)} />
217
239
  </div>
218
240
  <input
219
241
  class="hsl-slider-input"
@@ -221,14 +243,15 @@
221
243
  min="0"
222
244
  max="360"
223
245
  value={hue}
224
- on:change={(e) => onHueChromaChange(Math.min(360, Math.max(0, +e.currentTarget.value)), chroma)}
246
+ onchange={(e) => onHueChromaChange(Math.min(360, Math.max(0, +e.currentTarget.value)), chroma)}
225
247
  /><span class="hsl-slider-unit">&deg;</span>
226
248
  </div>
227
249
  <div class="hsl-slider-row">
228
250
  <span class="hsl-slider-label">C</span>
229
- <div class="slider-track" style="background: {chromaGradient}" on:pointerdown={onSliderStart}>
251
+ <!-- svelte-ignore a11y_no_static_element_interactions -->
252
+ <div class="slider-track" style="background: {chromaGradient}" onpointerdown={onSliderStart}>
230
253
  <input type="range" min="0" max={CHROMA_MAX} step="0.001" value={chroma}
231
- on:input={(e) => onHueChromaChange(hue, +e.currentTarget.value)} />
254
+ oninput={(e) => onHueChromaChange(hue, +e.currentTarget.value)} />
232
255
  </div>
233
256
  <input
234
257
  class="hsl-slider-input chroma-input"
@@ -237,15 +260,16 @@
237
260
  max={CHROMA_MAX}
238
261
  step="0.001"
239
262
  value={chroma.toFixed(3)}
240
- on:change={(e) => onHueChromaChange(hue, Math.min(CHROMA_MAX, Math.max(0, +e.currentTarget.value)))}
263
+ onchange={(e) => onHueChromaChange(hue, Math.min(CHROMA_MAX, Math.max(0, +e.currentTarget.value)))}
241
264
  />
242
265
  </div>
243
266
  {:else}
244
267
  <div class="hsl-slider-row">
245
268
  <span class="hsl-slider-label">H</span>
246
- <div class="slider-track" style="background: {hueGrad(hsl[1], hsl[2])}" on:pointerdown={onSliderStart}>
269
+ <!-- svelte-ignore a11y_no_static_element_interactions -->
270
+ <div class="slider-track" style="background: {hueGrad(hsl[1], hsl[2])}" onpointerdown={onSliderStart}>
247
271
  <input type="range" min="0" max="360" value={hsl[0]}
248
- on:input={(e) => updateHsl(0, +e.currentTarget.value)} />
272
+ oninput={(e) => updateHsl(0, +e.currentTarget.value)} />
249
273
  </div>
250
274
  <input
251
275
  class="hsl-slider-input"
@@ -253,14 +277,15 @@
253
277
  min="0"
254
278
  max="360"
255
279
  value={hsl[0]}
256
- on:change={(e) => updateHsl(0, Math.min(360, Math.max(0, +e.currentTarget.value)))}
280
+ onchange={(e) => updateHsl(0, Math.min(360, Math.max(0, +e.currentTarget.value)))}
257
281
  /><span class="hsl-slider-unit">&deg;</span>
258
282
  </div>
259
283
  <div class="hsl-slider-row">
260
284
  <span class="hsl-slider-label">S</span>
261
- <div class="slider-track" style="background: {satGrad(hsl[0], hsl[2])}" on:pointerdown={onSliderStart}>
285
+ <!-- svelte-ignore a11y_no_static_element_interactions -->
286
+ <div class="slider-track" style="background: {satGrad(hsl[0], hsl[2])}" onpointerdown={onSliderStart}>
262
287
  <input type="range" min="0" max="100" value={hsl[1]}
263
- on:input={(e) => updateHsl(1, +e.currentTarget.value)} />
288
+ oninput={(e) => updateHsl(1, +e.currentTarget.value)} />
264
289
  </div>
265
290
  <input
266
291
  class="hsl-slider-input"
@@ -268,14 +293,15 @@
268
293
  min="0"
269
294
  max="100"
270
295
  value={hsl[1]}
271
- on:change={(e) => updateHsl(1, Math.min(100, Math.max(0, +e.currentTarget.value)))}
296
+ onchange={(e) => updateHsl(1, Math.min(100, Math.max(0, +e.currentTarget.value)))}
272
297
  /><span class="hsl-slider-unit">%</span>
273
298
  </div>
274
299
  <div class="hsl-slider-row">
275
300
  <span class="hsl-slider-label">L</span>
276
- <div class="slider-track" style="background: {lightGrad(hsl[0], hsl[1])}" on:pointerdown={onSliderStart}>
301
+ <!-- svelte-ignore a11y_no_static_element_interactions -->
302
+ <div class="slider-track" style="background: {lightGrad(hsl[0], hsl[1])}" onpointerdown={onSliderStart}>
277
303
  <input type="range" min="0" max="100" value={hsl[2]}
278
- on:input={(e) => updateHsl(2, +e.currentTarget.value)} />
304
+ oninput={(e) => updateHsl(2, +e.currentTarget.value)} />
279
305
  </div>
280
306
  <input
281
307
  class="hsl-slider-input"
@@ -283,7 +309,7 @@
283
309
  min="0"
284
310
  max="100"
285
311
  value={hsl[2]}
286
- on:change={(e) => updateHsl(2, Math.min(100, Math.max(0, +e.currentTarget.value)))}
312
+ onchange={(e) => updateHsl(2, Math.min(100, Math.max(0, +e.currentTarget.value)))}
287
313
  /><span class="hsl-slider-unit">%</span>
288
314
  </div>
289
315
  {/if}
@@ -477,6 +503,7 @@
477
503
  border-radius: var(--ui-radius-sm);
478
504
  padding: var(--ui-space-2) var(--ui-space-4);
479
505
  -moz-appearance: textfield;
506
+ appearance: textfield;
480
507
  }
481
508
 
482
509
  .hsl-slider-input.chroma-input {
@@ -2,13 +2,17 @@
2
2
  import { editorView } from '../lib/editorViewStore';
3
3
  import { parentRoute } from '../lib/parentRouteStore';
4
4
 
5
- export let condensed = false;
5
+ interface Props {
6
+ condensed?: boolean;
7
+ }
8
+
9
+ let { condensed = false }: Props = $props();
6
10
 
7
11
  // On /components the host page is already the components editor — the
8
12
  // overlay's components view would just stack on top of it, so disable the
9
13
  // switch. The switcher renders inside the editor iframe, so we read the
10
14
  // *parent* route, not this iframe's own route.
11
- $: componentsDisabled = $parentRoute === '/components';
15
+ let componentsDisabled = $derived($parentRoute === '/components');
12
16
 
13
17
  function set(v: 'tokens' | 'components') {
14
18
  editorView.set(v);
@@ -26,7 +30,7 @@
26
30
  class="compact"
27
31
  aria-label={$editorView === 'tokens' ? 'Switch to components' : 'Switch to tokens'}
28
32
  title={$editorView === 'tokens' ? 'Tokens (click for components)' : 'Components (click for tokens)'}
29
- on:click={toggle}
33
+ onclick={toggle}
30
34
  >
31
35
  <i class="fas {$editorView === 'tokens' ? 'fa-palette' : 'fa-cubes'}"></i>
32
36
  </button>
@@ -40,7 +44,7 @@
40
44
  class="seg-btn"
41
45
  class:active={$editorView === 'tokens'}
42
46
  aria-selected={$editorView === 'tokens'}
43
- on:click={() => set('tokens')}
47
+ onclick={() => set('tokens')}
44
48
  >
45
49
  <span class="radio" aria-hidden="true"></span>
46
50
  <span>Tokens</span>
@@ -53,7 +57,7 @@
53
57
  aria-selected={$editorView === 'components'}
54
58
  disabled={componentsDisabled}
55
59
  title={componentsDisabled ? 'Already viewing the Components page' : undefined}
56
- on:click={() => set('components')}
60
+ onclick={() => set('components')}
57
61
  >
58
62
  <span class="radio" aria-hidden="true"></span>
59
63
  <span>Components</span>
@@ -21,17 +21,17 @@
21
21
  '--font-mono',
22
22
  ];
23
23
 
24
- $: fontSourcesList = $editorState.fonts.sources;
25
- $: fontStacksList = $editorState.fonts.stacks;
26
- $: allFamilies = (fontSourcesList as FontSource[]).flatMap((s) => s.families.map((f) => ({ ...f, sourceLabel: s.label ?? s.kind })));
27
- $: familyById = new Map<string, FontFamily>(allFamilies.map((f) => [f.id, f]));
24
+ let fontSourcesList = $derived($editorState.fonts.sources);
25
+ let fontStacksList = $derived($editorState.fonts.stacks);
26
+ let allFamilies = $derived((fontSourcesList as FontSource[]).flatMap((s) => s.families.map((f) => ({ ...f, sourceLabel: s.label ?? s.kind }))));
27
+ let familyById = $derived(new Map<string, FontFamily>(allFamilies.map((f) => [f.id, f])));
28
28
 
29
29
  function ensureAllStacksPresent(current: FontStack[]): FontStack[] {
30
30
  const byVar = new Map(current.map((s) => [s.variable, s]));
31
31
  return STACK_VARIABLES.map((v) => byVar.get(v) ?? { variable: v, slots: [{ kind: 'generic', value: 'sans-serif' } as FontStackSlot] });
32
32
  }
33
33
 
34
- $: stacks = ensureAllStacksPresent(fontStacksList);
34
+ let stacks = $derived(ensureAllStacksPresent(fontStacksList));
35
35
 
36
36
  function slotKey(slot: FontStackSlot): string {
37
37
  if (slot.kind === 'project') return `project:${slot.familyId}`;
@@ -108,8 +108,8 @@
108
108
  });
109
109
  }
110
110
 
111
- let dragSource: { variable: FontStackVariable; index: number } | null = null;
112
- let dragOver: { variable: FontStackVariable; index: number; position: 'before' | 'on' | 'after' } | null = null;
111
+ let dragSource: { variable: FontStackVariable; index: number } | null = $state(null);
112
+ let dragOver: { variable: FontStackVariable; index: number; position: 'before' | 'on' | 'after' } | null = $state(null);
113
113
 
114
114
  function onDragStart(e: DragEvent, variable: FontStackVariable, index: number) {
115
115
  if (!e.dataTransfer) return;
@@ -167,6 +167,7 @@
167
167
  </div>
168
168
  <div class="font-stack-list">
169
169
  {#each stack.slots as slot, i (i + ':' + slotKey(slot))}
170
+ <!-- svelte-ignore a11y_no_static_element_interactions -->
170
171
  <div
171
172
  class="slot-row"
172
173
  class:drop-on={dragOver?.variable === stack.variable && dragOver?.index === i && dragOver?.position === 'on'}
@@ -174,11 +175,11 @@
174
175
  class:drop-after={dragOver?.variable === stack.variable && dragOver?.index === i && dragOver?.position === 'after'}
175
176
  class:dragging={dragSource?.variable === stack.variable && dragSource?.index === i}
176
177
  draggable="true"
177
- on:dragstart={(e) => onDragStart(e, stack.variable, i)}
178
- on:dragover={(e) => onDragOver(e, stack.variable, i)}
179
- on:dragleave={onDragLeave}
180
- on:drop={(e) => onDrop(e, stack.variable, i)}
181
- on:dragend={onDragEnd}
178
+ ondragstart={(e) => onDragStart(e, stack.variable, i)}
179
+ ondragover={(e) => onDragOver(e, stack.variable, i)}
180
+ ondragleave={onDragLeave}
181
+ ondrop={(e) => onDrop(e, stack.variable, i)}
182
+ ondragend={onDragEnd}
182
183
  >
183
184
  <span class="drag-handle" aria-hidden="true">⋮⋮</span>
184
185
  <span class="slot-position">{i + 1}.</span>
@@ -190,7 +191,7 @@
190
191
  <select
191
192
  class="form-select slot-select"
192
193
  value={slotKey(slot)}
193
- on:change={(e) => onSelectChange(e, stack.variable, i)}
194
+ onchange={(e) => onSelectChange(e, stack.variable, i)}
194
195
  >
195
196
  {#if allFamilies.length > 0}
196
197
  <optgroup label="Project fonts">
@@ -216,13 +217,13 @@
216
217
  class="slot-remove"
217
218
  aria-label="Remove slot"
218
219
  title="Remove"
219
- on:click={() => removeSlot(stack.variable, i)}
220
+ onclick={() => removeSlot(stack.variable, i)}
220
221
  disabled={stack.slots.length <= 1}
221
222
  >×</button>
222
223
  </div>
223
224
  {/each}
224
225
  </div>
225
- <button type="button" class="add-fallback" on:click={() => addSlot(stack.variable)}>
226
+ <button type="button" class="add-fallback" onclick={() => addSlot(stack.variable)}>
226
227
  + add fallback
227
228
  </button>
228
229
  </div>