@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,5 +1,6 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import {
|
|
2
|
+
import { run } from 'svelte/legacy';
|
|
3
|
+
|
|
3
4
|
import { slide } from 'svelte/transition';
|
|
4
5
|
import { cubicOut, cubicIn } from 'svelte/easing';
|
|
5
6
|
import { resolveAliasChain } from '../lib/tokenRegistry';
|
|
@@ -29,13 +30,23 @@
|
|
|
29
30
|
return name.endsWith('-surface') || name.endsWith('-fill');
|
|
30
31
|
}
|
|
31
32
|
|
|
32
|
-
|
|
33
|
+
interface Props {
|
|
34
|
+
variable: string;
|
|
35
|
+
component?: string | undefined;
|
|
36
|
+
canBeLinked?: boolean;
|
|
37
|
+
disabled?: boolean;
|
|
38
|
+
selectionsLocked?: boolean;
|
|
39
|
+
onchange?: () => void;
|
|
40
|
+
}
|
|
33
41
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
42
|
+
let {
|
|
43
|
+
variable,
|
|
44
|
+
component = undefined,
|
|
45
|
+
canBeLinked = false,
|
|
46
|
+
disabled = false,
|
|
47
|
+
selectionsLocked = false,
|
|
48
|
+
onchange,
|
|
49
|
+
}: Props = $props();
|
|
39
50
|
|
|
40
51
|
type Category = 'palette' | 'surface' | 'border' | 'text';
|
|
41
52
|
|
|
@@ -95,9 +106,9 @@
|
|
|
95
106
|
{ id: 'text', label: 'Text' },
|
|
96
107
|
];
|
|
97
108
|
|
|
98
|
-
let selector: UITokenSelector;
|
|
99
|
-
let selectedFamily: string | null = null;
|
|
100
|
-
let selectedTab: Category = 'palette';
|
|
109
|
+
let selector: UITokenSelector | undefined = $state();
|
|
110
|
+
let selectedFamily: string | null = $state(null);
|
|
111
|
+
let selectedTab: Category = $state('palette');
|
|
101
112
|
|
|
102
113
|
/** Compass-rose layout for the orientation grid. Angles follow the CSS
|
|
103
114
|
* linear-gradient convention (0° points up, 90° points right). */
|
|
@@ -114,24 +125,24 @@
|
|
|
114
125
|
|
|
115
126
|
/** Numeric input value. Kept in sync with chosenAngle/token-default by the
|
|
116
127
|
* reactive block below; user edits flow back through `applyOrientation`. */
|
|
117
|
-
let angleInput: number = 0;
|
|
128
|
+
let angleInput: number = $state(0);
|
|
118
129
|
|
|
119
|
-
let chosenCategory
|
|
120
|
-
let chosenFamily
|
|
121
|
-
let chosenStep
|
|
122
|
-
let chosenNone
|
|
123
|
-
let chosenGradient
|
|
130
|
+
let chosenCategory = $state<Category | null>(null);
|
|
131
|
+
let chosenFamily = $state<string | null>(null);
|
|
132
|
+
let chosenStep = $state<string | null>(null);
|
|
133
|
+
let chosenNone = $state(false);
|
|
134
|
+
let chosenGradient = $state<string | null>(null);
|
|
124
135
|
/** Per-slot angle override on the chosen linear gradient. Null means
|
|
125
136
|
* "no override" — the slot writes `var(--gradient-N)` and inherits the
|
|
126
137
|
* token's natural angle. Non-null means the slot writes a materialized
|
|
127
138
|
* `linear-gradient(<angle>, <token's stops>)` so the angle is locally
|
|
128
139
|
* pinned while stop colors keep flowing from the token's `var()` refs. */
|
|
129
|
-
let chosenAngle
|
|
130
|
-
let opacity: number = 100;
|
|
140
|
+
let chosenAngle = $state<number | null>(null);
|
|
141
|
+
let opacity: number = $state(100);
|
|
131
142
|
let selfDefaultHex: string = '';
|
|
132
143
|
|
|
133
|
-
|
|
134
|
-
|
|
144
|
+
let gradientsAllowed = $derived(acceptsGradient(variable));
|
|
145
|
+
let gradientTokens = $derived($editorState.gradients.tokens);
|
|
135
146
|
|
|
136
147
|
function captureSelfDefault() {
|
|
137
148
|
const root = document.documentElement;
|
|
@@ -236,8 +247,8 @@
|
|
|
236
247
|
opacity = Math.max(0, Math.min(100, Math.round(opacity)));
|
|
237
248
|
if (chosenCategory === null || chosenFamily === null || chosenStep === null) return;
|
|
238
249
|
const varName = getVarName(chosenCategory, chosenFamily, chosenStep);
|
|
239
|
-
selector
|
|
240
|
-
|
|
250
|
+
selector?.writeOverride(buildValue(varName));
|
|
251
|
+
onchange?.();
|
|
241
252
|
}
|
|
242
253
|
|
|
243
254
|
/** Apply (or clear) a per-slot angle override on the chosen linear gradient.
|
|
@@ -251,18 +262,18 @@
|
|
|
251
262
|
const normalized = ((Math.round(nextAngle) % 360) + 360) % 360;
|
|
252
263
|
chosenAngle = normalized;
|
|
253
264
|
if (normalized === token.angle) {
|
|
254
|
-
selector
|
|
265
|
+
selector?.writeOverride(chosenGradient);
|
|
255
266
|
} else {
|
|
256
|
-
selector
|
|
267
|
+
selector?.writeOverride(materializeGradient(token, normalized));
|
|
257
268
|
}
|
|
258
|
-
|
|
269
|
+
onchange?.();
|
|
259
270
|
}
|
|
260
271
|
|
|
261
272
|
function resetOrientation() {
|
|
262
273
|
if (chosenGradient === null) return;
|
|
263
274
|
chosenAngle = null;
|
|
264
|
-
selector
|
|
265
|
-
|
|
275
|
+
selector?.writeOverride(chosenGradient);
|
|
276
|
+
onchange?.();
|
|
266
277
|
}
|
|
267
278
|
|
|
268
279
|
function isGradientToken(name: string): boolean {
|
|
@@ -386,7 +397,7 @@
|
|
|
386
397
|
chosenNone = false;
|
|
387
398
|
initFromCurrent();
|
|
388
399
|
selectedFamily = null;
|
|
389
|
-
|
|
400
|
+
onchange?.();
|
|
390
401
|
}
|
|
391
402
|
|
|
392
403
|
function handleClose() {
|
|
@@ -412,10 +423,10 @@
|
|
|
412
423
|
chosenGradient = null;
|
|
413
424
|
chosenAngle = null;
|
|
414
425
|
opacity = 100;
|
|
415
|
-
selector
|
|
426
|
+
selector?.writeOverride('transparent');
|
|
416
427
|
selectedFamily = null;
|
|
417
428
|
close();
|
|
418
|
-
|
|
429
|
+
onchange?.();
|
|
419
430
|
}
|
|
420
431
|
|
|
421
432
|
function selectSwatch(category: Category, step: string, close: () => void) {
|
|
@@ -426,10 +437,10 @@
|
|
|
426
437
|
chosenCategory = category;
|
|
427
438
|
chosenFamily = selectedFamily;
|
|
428
439
|
chosenStep = step;
|
|
429
|
-
selector
|
|
440
|
+
selector?.writeOverride(buildValue(varName));
|
|
430
441
|
selectedFamily = null;
|
|
431
442
|
close();
|
|
432
|
-
|
|
443
|
+
onchange?.();
|
|
433
444
|
}
|
|
434
445
|
|
|
435
446
|
// Picking any gradient is a fresh start: any prior angle override is
|
|
@@ -444,10 +455,10 @@
|
|
|
444
455
|
chosenGradient = gradientVar;
|
|
445
456
|
chosenAngle = null;
|
|
446
457
|
opacity = 100;
|
|
447
|
-
selector
|
|
458
|
+
selector?.writeOverride(gradientVar);
|
|
448
459
|
selectedFamily = null;
|
|
449
460
|
close();
|
|
450
|
-
|
|
461
|
+
onchange?.();
|
|
451
462
|
}
|
|
452
463
|
|
|
453
464
|
// Re-derive trigger state when the bound `variable` changes (e.g. when a
|
|
@@ -455,35 +466,41 @@
|
|
|
455
466
|
// The wrapper UITokenSelector forwards `var-change` only for the currently
|
|
456
467
|
// bound variable, so prop swaps wouldn't otherwise refresh `chosenCategory`
|
|
457
468
|
// / `chosenFamily` / `chosenStep` and the meta label drifts from the swatch.
|
|
458
|
-
let lastSeenVariable: string | null = null;
|
|
459
|
-
|
|
460
|
-
lastSeenVariable
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
469
|
+
let lastSeenVariable: string | null = $state(null);
|
|
470
|
+
run(() => {
|
|
471
|
+
if (variable !== lastSeenVariable) {
|
|
472
|
+
lastSeenVariable = variable;
|
|
473
|
+
initFromCurrent();
|
|
474
|
+
captureSelfDefault();
|
|
475
|
+
}
|
|
476
|
+
});
|
|
464
477
|
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
478
|
+
let chosenGradientToken = $derived(chosenGradient ? getGradientToken(chosenGradient) : undefined);
|
|
479
|
+
let isLinearGradientChosen = $derived(!!chosenGradientToken && chosenGradientToken.type === 'linear');
|
|
480
|
+
let effectiveAngle = $derived(chosenGradientToken
|
|
468
481
|
? (chosenAngle ?? chosenGradientToken.angle)
|
|
469
|
-
: 0;
|
|
470
|
-
|
|
482
|
+
: 0);
|
|
483
|
+
run(() => {
|
|
484
|
+
angleInput = effectiveAngle;
|
|
485
|
+
});
|
|
471
486
|
|
|
472
|
-
|
|
487
|
+
let metaLabel = $derived(chosenNone
|
|
473
488
|
? 'none'
|
|
474
489
|
: chosenGradient
|
|
475
490
|
? chosenGradient.replace(/^--/, '') + (chosenAngle !== null ? ` (${effectiveAngle}°)` : '')
|
|
476
491
|
: (chosenCategory && chosenFamily && chosenStep !== null
|
|
477
492
|
? getVarName(chosenCategory, chosenFamily, chosenStep).replace(/^--/, '') + (opacity < 100 ? ` (${opacity}%)` : '')
|
|
478
|
-
: '');
|
|
493
|
+
: ''));
|
|
479
494
|
|
|
480
|
-
|
|
495
|
+
let availableTabs = $derived(selectedFamily
|
|
481
496
|
? allCategories.filter(c => c.id !== 'text' || familiesWithText.includes(selectedFamily!))
|
|
482
|
-
: allCategories;
|
|
497
|
+
: allCategories);
|
|
483
498
|
|
|
484
|
-
|
|
485
|
-
selectedTab
|
|
486
|
-
|
|
499
|
+
run(() => {
|
|
500
|
+
if (selectedFamily && !availableTabs.find(t => t.id === selectedTab)) {
|
|
501
|
+
selectedTab = 'palette';
|
|
502
|
+
}
|
|
503
|
+
});
|
|
487
504
|
</script>
|
|
488
505
|
|
|
489
506
|
<UITokenSelector
|
|
@@ -496,125 +513,131 @@
|
|
|
496
513
|
dropdownMinWidth="14rem"
|
|
497
514
|
dropdownMaxWidth="calc(100vw - 2rem)"
|
|
498
515
|
hideDefaultHeader={!!selectedFamily}
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
516
|
+
onreset={handleReset}
|
|
517
|
+
onclose={handleClose}
|
|
518
|
+
onvarChange={initFromCurrent}
|
|
502
519
|
>
|
|
503
|
-
|
|
504
|
-
<div class="swatch"
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
<
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
{#each families as fam}
|
|
524
|
-
<button class="family-item" class:active={!chosenNone && chosenFamily === fam.name} on:click={() => selectFamily(fam.name)}>
|
|
520
|
+
{#snippet triggerPreview()}
|
|
521
|
+
<div class="swatch-wrap">
|
|
522
|
+
<div class="swatch" style="background: var({variable});"></div>
|
|
523
|
+
</div>
|
|
524
|
+
{/snippet}
|
|
525
|
+
{#snippet subheader()}
|
|
526
|
+
<div class="opacity-control" class:hidden={chosenGradient !== null}>
|
|
527
|
+
<span class="opacity-label">opacity</span>
|
|
528
|
+
<input type="range" min="0" max="100" bind:value={opacity} class="opacity-slider" oninput={applyOpacity} />
|
|
529
|
+
<input type="number" min="0" max="100" bind:value={opacity} class="opacity-input" onchange={applyOpacity} />
|
|
530
|
+
<span class="opacity-unit">%</span>
|
|
531
|
+
</div>
|
|
532
|
+
{/snippet}
|
|
533
|
+
{#snippet triggerMeta()}{metaLabel}{/snippet}
|
|
534
|
+
|
|
535
|
+
{#snippet children({ close })}
|
|
536
|
+
|
|
537
|
+
{#if selectedFamily === null}
|
|
538
|
+
<div class="family-list">
|
|
539
|
+
<button class="family-item" class:active={chosenNone} onclick={() => selectNone(close)}>
|
|
525
540
|
<div class="family-swatches">
|
|
526
|
-
<div class="
|
|
527
|
-
<div class="mini-swatch" style="background: var(--color-{fam.name}-500);"></div>
|
|
528
|
-
<div class="mini-swatch" style="background: var(--color-{fam.name}-700);"></div>
|
|
541
|
+
<div class="none-swatch"></div>
|
|
529
542
|
</div>
|
|
530
|
-
<span class="family-label">
|
|
531
|
-
<i class="fas fa-chevron-right family-arrow"></i>
|
|
543
|
+
<span class="family-label">None</span>
|
|
532
544
|
</button>
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
<div class="family-divider">Gradients</div>
|
|
536
|
-
{#each gradientTokens as g}
|
|
537
|
-
<button class="family-item" class:active={chosenGradient === g.variable} on:click={() => selectGradient(g.variable, close)}>
|
|
545
|
+
{#each families as fam}
|
|
546
|
+
<button class="family-item" class:active={!chosenNone && chosenFamily === fam.name} onclick={() => selectFamily(fam.name)}>
|
|
538
547
|
<div class="family-swatches">
|
|
539
|
-
<div class="
|
|
548
|
+
<div class="mini-swatch" style="background: var(--color-{fam.name}-300);"></div>
|
|
549
|
+
<div class="mini-swatch" style="background: var(--color-{fam.name}-500);"></div>
|
|
550
|
+
<div class="mini-swatch" style="background: var(--color-{fam.name}-700);"></div>
|
|
540
551
|
</div>
|
|
541
|
-
<span class="family-label">
|
|
542
|
-
|
|
543
|
-
{/each}
|
|
544
|
-
{/if}
|
|
545
|
-
</div>
|
|
546
|
-
{:else}
|
|
547
|
-
<button class="dropdown-back" on:click={backToFamilies}>
|
|
548
|
-
<i class="fas fa-chevron-left"></i>
|
|
549
|
-
<span>{families.find(f => f.name === selectedFamily)?.label}</span>
|
|
550
|
-
</button>
|
|
551
|
-
|
|
552
|
-
<div class="tab-bar">
|
|
553
|
-
{#each availableTabs as tab}
|
|
554
|
-
<button
|
|
555
|
-
class="tab-btn"
|
|
556
|
-
class:selected={selectedTab === tab.id}
|
|
557
|
-
class:assigned={chosenCategory === tab.id && chosenFamily === selectedFamily}
|
|
558
|
-
on:click={() => selectedTab = tab.id}
|
|
559
|
-
>{tab.label}</button>
|
|
560
|
-
{/each}
|
|
561
|
-
</div>
|
|
562
|
-
|
|
563
|
-
{#if selectedTab === 'palette'}
|
|
564
|
-
<div class="step-grid">
|
|
565
|
-
{#each paletteSteps as step}
|
|
566
|
-
<button
|
|
567
|
-
class="step-item"
|
|
568
|
-
class:active={chosenCategory === 'palette' && chosenFamily === selectedFamily && chosenStep === step}
|
|
569
|
-
on:click={() => selectSwatch('palette', step, close)}
|
|
570
|
-
>
|
|
571
|
-
<div class="step-swatch" style="background: var(--color-{selectedFamily}-{step});"></div>
|
|
572
|
-
<span class="step-label">{step}</span>
|
|
552
|
+
<span class="family-label">{fam.label}</span>
|
|
553
|
+
<i class="fas fa-chevron-right family-arrow"></i>
|
|
573
554
|
</button>
|
|
574
555
|
{/each}
|
|
556
|
+
{#if gradientsAllowed && gradientTokens.length > 0}
|
|
557
|
+
<div class="family-divider">Gradients</div>
|
|
558
|
+
{#each gradientTokens as g}
|
|
559
|
+
<button class="family-item" class:active={chosenGradient === g.variable} onclick={() => selectGradient(g.variable, close)}>
|
|
560
|
+
<div class="family-swatches">
|
|
561
|
+
<div class="gradient-swatch" style="background: var({g.variable});"></div>
|
|
562
|
+
</div>
|
|
563
|
+
<span class="family-label">Gradient {g.variable.replace(/^--gradient-/, '')}</span>
|
|
564
|
+
</button>
|
|
565
|
+
{/each}
|
|
566
|
+
{/if}
|
|
575
567
|
</div>
|
|
576
|
-
{:else
|
|
577
|
-
<
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
<div class="step-swatch" style="background: {previewBg('surface', selectedFamily, step.key)};"></div>
|
|
585
|
-
<span class="step-label">{step.label}</span>
|
|
586
|
-
</button>
|
|
587
|
-
{/each}
|
|
588
|
-
</div>
|
|
589
|
-
{:else if selectedTab === 'border'}
|
|
590
|
-
<div class="step-grid">
|
|
591
|
-
{#each borderSteps as step}
|
|
592
|
-
<button
|
|
593
|
-
class="step-item"
|
|
594
|
-
class:active={chosenCategory === 'border' && chosenFamily === selectedFamily && chosenStep === step.key}
|
|
595
|
-
on:click={() => selectSwatch('border', step.key, close)}
|
|
596
|
-
>
|
|
597
|
-
<div class="step-swatch" style="background: {previewBg('border', selectedFamily, step.key)};"></div>
|
|
598
|
-
<span class="step-label">{step.label}</span>
|
|
599
|
-
</button>
|
|
600
|
-
{/each}
|
|
601
|
-
</div>
|
|
602
|
-
{:else if selectedTab === 'text'}
|
|
603
|
-
<div class="step-grid">
|
|
604
|
-
{#each textSteps as step}
|
|
568
|
+
{:else}
|
|
569
|
+
<button class="dropdown-back" onclick={backToFamilies}>
|
|
570
|
+
<i class="fas fa-chevron-left"></i>
|
|
571
|
+
<span>{families.find(f => f.name === selectedFamily)?.label}</span>
|
|
572
|
+
</button>
|
|
573
|
+
|
|
574
|
+
<div class="tab-bar">
|
|
575
|
+
{#each availableTabs as tab}
|
|
605
576
|
<button
|
|
606
|
-
class="
|
|
607
|
-
class:
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
<span class="step-label">{step.label}</span>
|
|
612
|
-
</button>
|
|
577
|
+
class="tab-btn"
|
|
578
|
+
class:selected={selectedTab === tab.id}
|
|
579
|
+
class:assigned={chosenCategory === tab.id && chosenFamily === selectedFamily}
|
|
580
|
+
onclick={() => selectedTab = tab.id}
|
|
581
|
+
>{tab.label}</button>
|
|
613
582
|
{/each}
|
|
614
583
|
</div>
|
|
584
|
+
|
|
585
|
+
{#if selectedTab === 'palette'}
|
|
586
|
+
<div class="step-grid">
|
|
587
|
+
{#each paletteSteps as step}
|
|
588
|
+
<button
|
|
589
|
+
class="step-item"
|
|
590
|
+
class:active={chosenCategory === 'palette' && chosenFamily === selectedFamily && chosenStep === step}
|
|
591
|
+
onclick={() => selectSwatch('palette', step, close)}
|
|
592
|
+
>
|
|
593
|
+
<div class="step-swatch" style="background: var(--color-{selectedFamily}-{step});"></div>
|
|
594
|
+
<span class="step-label">{step}</span>
|
|
595
|
+
</button>
|
|
596
|
+
{/each}
|
|
597
|
+
</div>
|
|
598
|
+
{:else if selectedTab === 'surface'}
|
|
599
|
+
<div class="step-grid">
|
|
600
|
+
{#each surfaceSteps as step}
|
|
601
|
+
<button
|
|
602
|
+
class="step-item"
|
|
603
|
+
class:active={chosenCategory === 'surface' && chosenFamily === selectedFamily && chosenStep === step.key}
|
|
604
|
+
onclick={() => selectSwatch('surface', step.key, close)}
|
|
605
|
+
>
|
|
606
|
+
<div class="step-swatch" style="background: {previewBg('surface', selectedFamily, step.key)};"></div>
|
|
607
|
+
<span class="step-label">{step.label}</span>
|
|
608
|
+
</button>
|
|
609
|
+
{/each}
|
|
610
|
+
</div>
|
|
611
|
+
{:else if selectedTab === 'border'}
|
|
612
|
+
<div class="step-grid">
|
|
613
|
+
{#each borderSteps as step}
|
|
614
|
+
<button
|
|
615
|
+
class="step-item"
|
|
616
|
+
class:active={chosenCategory === 'border' && chosenFamily === selectedFamily && chosenStep === step.key}
|
|
617
|
+
onclick={() => selectSwatch('border', step.key, close)}
|
|
618
|
+
>
|
|
619
|
+
<div class="step-swatch" style="background: {previewBg('border', selectedFamily, step.key)};"></div>
|
|
620
|
+
<span class="step-label">{step.label}</span>
|
|
621
|
+
</button>
|
|
622
|
+
{/each}
|
|
623
|
+
</div>
|
|
624
|
+
{:else if selectedTab === 'text'}
|
|
625
|
+
<div class="step-grid">
|
|
626
|
+
{#each textSteps as step}
|
|
627
|
+
<button
|
|
628
|
+
class="step-item"
|
|
629
|
+
class:active={chosenCategory === 'text' && chosenFamily === selectedFamily && chosenStep === step.key}
|
|
630
|
+
onclick={() => selectSwatch('text', step.key, close)}
|
|
631
|
+
>
|
|
632
|
+
<div class="step-swatch" style="background: {previewBg('text', selectedFamily, step.key)};"></div>
|
|
633
|
+
<span class="step-label">{step.label}</span>
|
|
634
|
+
</button>
|
|
635
|
+
{/each}
|
|
636
|
+
</div>
|
|
637
|
+
{/if}
|
|
615
638
|
{/if}
|
|
616
|
-
|
|
617
|
-
|
|
639
|
+
|
|
640
|
+
{/snippet}
|
|
618
641
|
</UITokenSelector>
|
|
619
642
|
|
|
620
643
|
<!--
|
|
@@ -640,7 +663,7 @@
|
|
|
640
663
|
class="dir-btn"
|
|
641
664
|
class:active={d.angle === ((effectiveAngle % 360) + 360) % 360}
|
|
642
665
|
style="grid-column: {d.col}; grid-row: {d.row};"
|
|
643
|
-
|
|
666
|
+
onclick={() => applyOrientation(d.angle)}
|
|
644
667
|
title="{d.label} ({d.angle}°)"
|
|
645
668
|
>{d.glyph}</button>
|
|
646
669
|
{/each}
|
|
@@ -652,7 +675,7 @@
|
|
|
652
675
|
max="359"
|
|
653
676
|
class="angle-input"
|
|
654
677
|
bind:value={angleInput}
|
|
655
|
-
|
|
678
|
+
onchange={() => applyOrientation(angleInput)}
|
|
656
679
|
/>
|
|
657
680
|
<span class="angle-unit">°</span>
|
|
658
681
|
</div>
|
|
@@ -660,7 +683,7 @@
|
|
|
660
683
|
type="button"
|
|
661
684
|
class="orientation-reset"
|
|
662
685
|
class:active={chosenAngle !== null}
|
|
663
|
-
|
|
686
|
+
onclick={resetOrientation}
|
|
664
687
|
disabled={chosenAngle === null}
|
|
665
688
|
title="Reset to gradient default"
|
|
666
689
|
>
|
|
@@ -739,6 +762,7 @@
|
|
|
739
762
|
font-family: var(--ui-font-mono);
|
|
740
763
|
text-align: right;
|
|
741
764
|
-moz-appearance: textfield;
|
|
765
|
+
appearance: textfield;
|
|
742
766
|
}
|
|
743
767
|
|
|
744
768
|
.opacity-input::-webkit-inner-spin-button,
|
|
@@ -1069,6 +1093,7 @@
|
|
|
1069
1093
|
font-family: var(--ui-font-mono);
|
|
1070
1094
|
text-align: right;
|
|
1071
1095
|
-moz-appearance: textfield;
|
|
1096
|
+
appearance: textfield;
|
|
1072
1097
|
}
|
|
1073
1098
|
|
|
1074
1099
|
.angle-input::-webkit-inner-spin-button,
|
package/src/ui/UIRadio.svelte
CHANGED
|
@@ -8,13 +8,28 @@
|
|
|
8
8
|
<UIRadio bind:group={selected} value="beta" disabled />
|
|
9
9
|
-->
|
|
10
10
|
<script lang="ts">
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
11
|
+
import { createBubbler } from 'svelte/legacy';
|
|
12
|
+
|
|
13
|
+
const bubble = createBubbler();
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
interface Props {
|
|
18
|
+
/** Value this radio represents within its group. */
|
|
19
|
+
value: string;
|
|
20
|
+
/** Two-way bound group selection. The radio is checked when `group === value`. */
|
|
21
|
+
group: string;
|
|
22
|
+
/** Optional native name; omit to let Svelte's `bind:group` wire it automatically. */
|
|
23
|
+
name?: string;
|
|
24
|
+
disabled?: boolean;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
let {
|
|
28
|
+
value,
|
|
29
|
+
group = $bindable(),
|
|
30
|
+
name = '',
|
|
31
|
+
disabled = false
|
|
32
|
+
}: Props = $props();
|
|
18
33
|
</script>
|
|
19
34
|
|
|
20
35
|
<input
|
|
@@ -24,7 +39,7 @@
|
|
|
24
39
|
{name}
|
|
25
40
|
{disabled}
|
|
26
41
|
bind:group
|
|
27
|
-
|
|
42
|
+
onchange={bubble('change')}
|
|
28
43
|
/>
|
|
29
44
|
|
|
30
45
|
<style>
|
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
2
|
+
interface Props {
|
|
3
|
+
value: string;
|
|
4
|
+
options: ReadonlyArray<{ value: string; label: string }>;
|
|
5
|
+
name: string;
|
|
6
|
+
onchange?: (value: string) => void;
|
|
7
|
+
}
|
|
7
8
|
|
|
8
|
-
|
|
9
|
+
let { value = $bindable(), options, name, onchange }: Props = $props();
|
|
9
10
|
|
|
10
11
|
function select(v: string) {
|
|
11
12
|
if (v === value) return;
|
|
12
13
|
value = v;
|
|
13
|
-
|
|
14
|
+
onchange?.(v);
|
|
14
15
|
}
|
|
15
16
|
</script>
|
|
16
17
|
|
|
@@ -22,7 +23,7 @@
|
|
|
22
23
|
{name}
|
|
23
24
|
value={opt.value}
|
|
24
25
|
checked={value === opt.value}
|
|
25
|
-
|
|
26
|
+
onchange={() => select(opt.value)}
|
|
26
27
|
/>
|
|
27
28
|
<span>{opt.label}</span>
|
|
28
29
|
</label>
|