@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.
- package/README.md +1 -1
- package/package.json +11 -9
- package/src/component-editor/BadgeEditor.svelte +24 -22
- package/src/component-editor/CalloutEditor.svelte +3 -3
- package/src/component-editor/CardEditor.svelte +25 -21
- package/src/component-editor/CollapsibleSectionEditor.svelte +27 -25
- package/src/component-editor/CornerBadgeEditor.svelte +37 -35
- package/src/component-editor/DialogEditor.svelte +26 -24
- package/src/component-editor/ImageEditor.svelte +11 -9
- package/src/component-editor/InlineEditActionsEditor.svelte +17 -15
- package/src/component-editor/NotificationEditor.svelte +32 -30
- package/src/component-editor/ProgressBarEditor.svelte +3 -3
- package/src/component-editor/RadioButtonEditor.svelte +31 -29
- package/src/component-editor/SectionDividerEditor.svelte +30 -28
- package/src/component-editor/SegmentedControlEditor.svelte +29 -25
- package/src/component-editor/StandardButtonsEditor.svelte +42 -38
- package/src/component-editor/TabBarEditor.svelte +20 -18
- package/src/component-editor/TableEditor.svelte +4 -4
- package/src/component-editor/TooltipEditor.svelte +11 -9
- package/src/component-editor/registry.ts +2 -2
- package/src/component-editor/scaffolding/AngleDial.svelte +20 -19
- package/src/component-editor/scaffolding/ComponentEditorBase.svelte +44 -20
- package/src/component-editor/scaffolding/ComponentFileManager.svelte +260 -37
- package/src/component-editor/scaffolding/ComponentFileMenu.svelte +41 -29
- package/src/component-editor/scaffolding/ComponentsTab.svelte +7 -3
- package/src/component-editor/scaffolding/CopyFromMenu.svelte +21 -12
- package/src/component-editor/scaffolding/DemoHeader.svelte +13 -4
- package/src/component-editor/scaffolding/DividerEditor.svelte +27 -14
- package/src/component-editor/scaffolding/FieldsetWrapper.svelte +10 -4
- package/src/component-editor/scaffolding/GradientCard.svelte +25 -20
- package/src/component-editor/scaffolding/LinkageChart.svelte +43 -34
- package/src/component-editor/scaffolding/LinkedBlock.svelte +24 -21
- package/src/component-editor/scaffolding/NonStylableConfig.svelte +6 -1
- package/src/component-editor/scaffolding/SaveAsDialog.svelte +39 -35
- package/src/component-editor/scaffolding/ShadowBackdrop.svelte +21 -9
- package/src/component-editor/scaffolding/ShadowBackdropControls.svelte +8 -3
- package/src/component-editor/scaffolding/StateBlock.svelte +30 -13
- package/src/component-editor/scaffolding/TokenLayout.svelte +46 -30
- package/src/component-editor/scaffolding/TypeEditor.svelte +52 -26
- package/src/component-editor/scaffolding/VariantGroup.svelte +81 -48
- package/src/component-editor/scaffolding/componentSectionType.ts +2 -2
- package/src/components/Badge.svelte +45 -26
- package/src/components/Button.svelte +44 -21
- package/src/components/Callout.svelte +17 -12
- package/src/components/Card.svelte +23 -11
- package/src/components/CollapsibleSection.svelte +56 -27
- package/src/components/CornerBadge.svelte +32 -18
- package/src/components/Dialog.svelte +55 -31
- package/src/components/Image.svelte +14 -5
- package/src/components/InlineEditActions.svelte +22 -10
- package/src/components/Notification.svelte +39 -19
- package/src/components/ProgressBar.svelte +27 -17
- package/src/components/RadioButton.svelte +27 -10
- package/src/components/SectionDivider.svelte +34 -26
- package/src/components/SegmentedControl.svelte +23 -9
- package/src/components/TabBar.svelte +23 -10
- package/src/components/Table.svelte +8 -3
- package/src/components/Tooltip.svelte +15 -5
- package/src/lib/ColumnsOverlay.svelte +3 -3
- package/src/lib/LiveEditorOverlay.svelte +73 -36
- package/src/pages/ComponentEditorPage.svelte +17 -13
- package/src/pages/EditorShell.svelte +24 -20
- package/src/styles/form-controls.css +2 -2
- package/src/styles/tokens.css +59 -81
- package/src/ui/BezierCurveEditor.svelte +59 -43
- package/src/ui/ColorEditPanel.svelte +71 -44
- package/src/ui/EditorViewSwitcher.svelte +9 -5
- package/src/ui/FontStackEditor.svelte +16 -15
- package/src/ui/GradientEditor.svelte +42 -33
- package/src/ui/GradientStopPicker.svelte +18 -29
- package/src/ui/PaletteEditor.svelte +238 -212
- package/src/ui/PresetFileManager.svelte +20 -18
- package/src/ui/ProjectFontsSection.svelte +30 -30
- package/src/ui/SurfacesTab.svelte +3 -3
- package/src/ui/TextTab.svelte +2 -2
- package/src/ui/ThemeFileManager.svelte +38 -35
- package/src/ui/Toggle.svelte +11 -9
- package/src/ui/UICopyPopover.svelte +19 -15
- package/src/ui/UIDialog.svelte +48 -30
- package/src/ui/UIFontFamilySelector.svelte +104 -78
- package/src/ui/UIFontSizeSelector.svelte +38 -20
- package/src/ui/UIFontWeightSelector.svelte +33 -13
- package/src/ui/UILineHeightSelector.svelte +33 -13
- package/src/ui/UILinkToggle.svelte +7 -6
- package/src/ui/UIOptionItem.svelte +21 -7
- package/src/ui/UIOptionList.svelte +9 -3
- package/src/ui/UIPaddingSelector.svelte +108 -82
- package/src/ui/UIPaletteSelector.svelte +186 -161
- package/src/ui/UIRadio.svelte +23 -8
- package/src/ui/UIRadioGroup.svelte +9 -8
- package/src/ui/UIRelinkConfirmPopover.svelte +26 -16
- package/src/ui/UITokenSelector.svelte +112 -68
- package/src/ui/UIVariantSelector.svelte +79 -57
- package/src/ui/VariablesTab.svelte +15 -15
- package/src/ui/palette/GradientStopEditor.svelte +45 -26
- package/src/ui/palette/OverridesPanel.svelte +85 -49
- package/src/ui/palette/PaletteBase.svelte +60 -32
- package/src/ui/palette/ScaleCurveEditor.svelte +25 -10
- package/src/ui/sections/ColumnsSection.svelte +13 -13
- package/src/ui/sections/GradientsSection.svelte +12 -9
- package/src/ui/sections/OverlaysSection.svelte +50 -47
- package/src/ui/sections/ShadowsSection.svelte +110 -104
- package/src/ui/sections/TokenScaleTable.svelte +38 -22
- 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
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
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
|
-
|
|
34
|
-
|
|
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
|
|
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
|
-
|
|
289
|
-
|
|
290
|
-
|
|
304
|
+
onpointerdown={handleShiftPointerDown}
|
|
305
|
+
onpointermove={handleShiftPointerMove}
|
|
306
|
+
onpointerup={handleShiftPointerUp}
|
|
291
307
|
/>
|
|
292
308
|
{:else}
|
|
293
|
-
<!-- svelte-ignore
|
|
294
|
-
<!-- svelte-ignore
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
319
|
-
|
|
320
|
-
|
|
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
|
|
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
|
-
|
|
334
|
-
|
|
335
|
-
|
|
349
|
+
onpointerdown={(e) => handlePointerDown(e, { kind: 'handleOut', index: i })}
|
|
350
|
+
onpointermove={handlePointerMove}
|
|
351
|
+
onpointerup={handlePointerUp}
|
|
336
352
|
/>
|
|
337
353
|
{/if}
|
|
338
|
-
<!-- svelte-ignore
|
|
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
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
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
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
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
|
-
|
|
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"
|
|
385
|
-
<button class="curve-tool-btn" type="button" title="Paste curve"
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
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
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
180
|
-
|
|
200
|
+
onkeydown={handleHexKeydown}
|
|
201
|
+
onblur={commitHex}
|
|
181
202
|
maxlength="7"
|
|
182
203
|
use:autoFocus
|
|
183
204
|
/>
|
|
184
205
|
{:else}
|
|
185
|
-
<button class="hsl-hex"
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
246
|
+
onchange={(e) => onHueChromaChange(Math.min(360, Math.max(0, +e.currentTarget.value)), chroma)}
|
|
225
247
|
/><span class="hsl-slider-unit">°</span>
|
|
226
248
|
</div>
|
|
227
249
|
<div class="hsl-slider-row">
|
|
228
250
|
<span class="hsl-slider-label">C</span>
|
|
229
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
280
|
+
onchange={(e) => updateHsl(0, Math.min(360, Math.max(0, +e.currentTarget.value)))}
|
|
257
281
|
/><span class="hsl-slider-unit">°</span>
|
|
258
282
|
</div>
|
|
259
283
|
<div class="hsl-slider-row">
|
|
260
284
|
<span class="hsl-slider-label">S</span>
|
|
261
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
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
|
-
|
|
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
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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"
|
|
226
|
+
<button type="button" class="add-fallback" onclick={() => addSlot(stack.variable)}>
|
|
226
227
|
+ add fallback
|
|
227
228
|
</button>
|
|
228
229
|
</div>
|