@motion-proto/live-tokens 0.44.0 → 0.46.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/CHANGELOG.md +103 -0
- package/dist-plugin/index.cjs +1 -1
- package/dist-plugin/index.js +1 -1
- package/package.json +1 -1
- package/src/editor/component-editor/scaffolding/ComponentFileManager.svelte +0 -1
- package/src/editor/component-editor/scaffolding/ComponentFileMenu.svelte +1 -1
- package/src/editor/core/palettes/colorHarmony.ts +35 -6
- package/src/editor/core/palettes/paletteDerivation.ts +2 -3
- package/src/editor/core/store/editorTypes.ts +2 -2
- package/src/editor/docs/CodeBlock.svelte +0 -2
- package/src/editor/docs/Docs.svelte +0 -3
- package/src/editor/pages/ComponentEditorPage.svelte +3 -5
- package/src/editor/pages/EditorShell.svelte +3 -5
- package/src/editor/ui/ColorEditPanel.svelte +19 -22
- package/src/editor/ui/EditorViewSwitcher.svelte +2 -3
- package/src/editor/ui/FileLoadList.svelte +7 -9
- package/src/editor/ui/ManifestFileManager.svelte +1 -3
- package/src/editor/ui/ProjectFontsSection.svelte +0 -4
- package/src/editor/ui/SurfacesTab.svelte +3 -3
- package/src/editor/ui/TextStylesSection.svelte +6 -8
- package/src/editor/ui/ThemeFileManager.svelte +1 -3
- package/src/editor/ui/UIEasingSelector.svelte +0 -2
- package/src/editor/ui/UIFontFamilySelector.svelte +9 -3
- package/src/editor/ui/UIMenuButton.svelte +230 -0
- package/src/editor/ui/UIPaletteSelector.svelte +0 -1
- package/src/editor/ui/VariablesTab.svelte +3 -4
- package/src/editor/ui/colors/AxisNumeral.svelte +70 -0
- package/src/editor/ui/colors/ColorReadouts.svelte +0 -2
- package/src/editor/ui/colors/ColorStory.svelte +24 -77
- package/src/editor/ui/colors/ColorWheel.svelte +48 -29
- package/src/editor/ui/colors/ColorsTab.svelte +361 -212
- package/src/editor/ui/colors/HarmonyAxesList.svelte +264 -141
- package/src/editor/ui/colors/LightnessBar.svelte +0 -2
- package/src/editor/ui/colors/harmonyDrag.ts +10 -0
- package/src/editor/ui/colors/harmonyModeIcons.ts +5 -0
- package/src/editor/ui/colors/paletteBaseColor.ts +25 -39
- package/src/live-tokens/data/tokens.generated.css +28 -28
- package/src/system/components/ImageLightbox.svelte +0 -2
- package/src/system/components/SectionDivider.svelte +4 -4
- package/src/editor/core/palettes/recommendText.ts +0 -216
- package/src/editor/core/palettes/solveTextContrast.ts +0 -254
|
@@ -5,7 +5,9 @@
|
|
|
5
5
|
import { editorState, beginScope, commitScope, cancelScope, type Scope } from '../../core/store/editorStore';
|
|
6
6
|
import { setBaseHueChroma, setBaseChroma, setAxisHue, setAxisHues } from './paletteBaseColor';
|
|
7
7
|
import { maxChroma } from './colorWheelMath';
|
|
8
|
-
import { applyHarmonyToAxes,
|
|
8
|
+
import { applyHarmonyToAxes, axisLabel, axisStatuses, type HarmonyMode } from '../../core/palettes/colorHarmony';
|
|
9
|
+
import AxisNumeral from './AxisNumeral.svelte';
|
|
10
|
+
import { modeLabel } from './harmonyModeIcons';
|
|
9
11
|
|
|
10
12
|
interface Props {
|
|
11
13
|
selected: string | null;
|
|
@@ -29,12 +31,12 @@
|
|
|
29
31
|
|
|
30
32
|
let { selected, onSelect, discLightness, onCustomize, absoluteChroma, activeMode, previewMode = null }: Props = $props();
|
|
31
33
|
|
|
32
|
-
// One handle per axis
|
|
33
|
-
//
|
|
34
|
-
//
|
|
34
|
+
// One handle per axis. A bound axis reads its color from the family's
|
|
35
|
+
// baseColor (hue equals axes[i].hue by invariant 1); an unbound axis carries
|
|
36
|
+
// only its stored hue, previewing where an assigned color would land.
|
|
35
37
|
let axisData = $derived(
|
|
36
38
|
$editorState.harmonyAxes.map((axis, i) => {
|
|
37
|
-
const common = { index: i,
|
|
39
|
+
const common = { index: i, label: axisLabel(i), family: axis.family, bound: axis.family !== null };
|
|
38
40
|
if (axis.family !== null) {
|
|
39
41
|
const spec = PALETTE_SPECS.find((s) => s.label === axis.family);
|
|
40
42
|
const { l, c, h } = $editorState.palettes[axis.family]?.baseColor ?? spec!.initialColor;
|
|
@@ -50,8 +52,8 @@
|
|
|
50
52
|
// active in the applied geometry (its slot is a distinct position). A bound
|
|
51
53
|
// inactive axis keeps its family's color but is edited in dot mode, not axis
|
|
52
54
|
// mode: the family renders as the free dot and sits out the global spin.
|
|
53
|
-
let
|
|
54
|
-
const isVisible = (t: { index: number }) =>
|
|
55
|
+
let statuses = $derived(axisStatuses(activeMode, $editorState.harmonyAxes));
|
|
56
|
+
const isVisible = (t: { index: number }) => statuses[t.index] === 'on-wheel';
|
|
55
57
|
|
|
56
58
|
// Reserved judgment call: keyboard nudge increments.
|
|
57
59
|
const HUE_STEP = 2;
|
|
@@ -59,6 +61,7 @@
|
|
|
59
61
|
const MARGIN = 52; // ring-to-edge gap: houses the external handles AND the axis numerals outside them
|
|
60
62
|
const EXT_OFFSET = 20; // external handle radius beyond the disc rim (room for the dotted tether)
|
|
61
63
|
const NUM_OFFSET = 24; // numeral radius beyond the external handles
|
|
64
|
+
const FREE_NUM_OFFSET = 15; // free-dot numeral, diagonal clearance past the enlarged dot
|
|
62
65
|
const MIN_SIZE = 240;
|
|
63
66
|
const MAX_SIZE = 560;
|
|
64
67
|
|
|
@@ -87,7 +90,7 @@
|
|
|
87
90
|
// lossy and makes the non-dragged coordinate wobble). Writes also use the
|
|
88
91
|
// pristine hue0/L0, so nothing accumulates across frames.
|
|
89
92
|
type AxisView = {
|
|
90
|
-
index: number;
|
|
93
|
+
index: number; label: string; family: string | null; bound: boolean;
|
|
91
94
|
hex: string; hue: number; chroma: number; lightness: number; rFrac: number;
|
|
92
95
|
};
|
|
93
96
|
|
|
@@ -146,7 +149,9 @@
|
|
|
146
149
|
// Writes go through setBaseHueChroma only — active axes never move; a bound
|
|
147
150
|
// inactive axis follows its family via syncBoundAxisHue.
|
|
148
151
|
let freeDot = $derived.by(() => {
|
|
149
|
-
if (!selected
|
|
152
|
+
if (!selected) return null;
|
|
153
|
+
const axisIndex = $editorState.harmonyAxes.findIndex((a) => a.family === selected);
|
|
154
|
+
if (axisIndex !== -1 && statuses[axisIndex] === 'on-wheel') return null;
|
|
150
155
|
const spec = PALETTE_SPECS.find((s) => s.label === selected);
|
|
151
156
|
if (!spec) return null;
|
|
152
157
|
const { l, c, h } = $editorState.palettes[selected]?.baseColor ?? spec.initialColor;
|
|
@@ -159,11 +164,22 @@
|
|
|
159
164
|
}
|
|
160
165
|
const r = rFrac * discRadius;
|
|
161
166
|
return {
|
|
162
|
-
family: selected,
|
|
167
|
+
family: selected, axisIndex: axisIndex === -1 ? null : axisIndex,
|
|
168
|
+
hex: oklchToHexClamped(l, c, h), hue, chroma: c, lightness: l,
|
|
163
169
|
x: center + r * Math.cos(rad(hue)), y: center - r * Math.sin(rad(hue)),
|
|
164
170
|
};
|
|
165
171
|
});
|
|
166
172
|
|
|
173
|
+
// The dot serves two states: bound to an axis the mode left off the wheel, and
|
|
174
|
+
// unassigned. Only the first has an axis to name.
|
|
175
|
+
let freeDotLabel = $derived.by(() => {
|
|
176
|
+
if (!freeDot) return '';
|
|
177
|
+
const where = freeDot.axisIndex === null
|
|
178
|
+
? 'unassigned'
|
|
179
|
+
: `${axisLabel(freeDot.axisIndex)}. Off the wheel in ${modeLabel(activeMode)}`;
|
|
180
|
+
return `${freeDot.family}, ${where}. Drag to adjust hue and chroma.`;
|
|
181
|
+
});
|
|
182
|
+
|
|
167
183
|
let globalHandle = $derived.by(() => {
|
|
168
184
|
const d = drag;
|
|
169
185
|
const angle = d?.kind === 'global' ? d.angle : globalAngle;
|
|
@@ -315,7 +331,7 @@
|
|
|
315
331
|
if (axis.family !== null) onSelect(axis.family);
|
|
316
332
|
onCustomize();
|
|
317
333
|
capture(e);
|
|
318
|
-
openGesture(`colors: ${axis.
|
|
334
|
+
openGesture(`colors: ${axis.label} rotate`);
|
|
319
335
|
drag = { kind: 'axis', index: axis.index, angle: pointerAngle(e), start: startOf(axis) };
|
|
320
336
|
applyAxis(e);
|
|
321
337
|
}
|
|
@@ -483,7 +499,9 @@
|
|
|
483
499
|
{/each}
|
|
484
500
|
|
|
485
501
|
{#each visibleRender as t (t.index)}
|
|
486
|
-
<span class="axis-num"
|
|
502
|
+
<span class="axis-num" style="left: {t.num.x}px; top: {t.num.y}px" aria-hidden="true">
|
|
503
|
+
<AxisNumeral index={t.index} status={statuses[t.index]} selected={t.selected} />
|
|
504
|
+
</span>
|
|
487
505
|
{/each}
|
|
488
506
|
|
|
489
507
|
{#each visibleRender as t (t.index)}
|
|
@@ -493,7 +511,7 @@
|
|
|
493
511
|
class="dot"
|
|
494
512
|
class:selected={t.selected}
|
|
495
513
|
style="left: {t.dot.x}px; top: {t.dot.y}px; --fill: {t.hex}"
|
|
496
|
-
aria-label={`${t.family}
|
|
514
|
+
aria-label={`${t.family}, drag along the rail to adjust chroma`}
|
|
497
515
|
title={`${t.family} (drag for chroma)`}
|
|
498
516
|
onpointerdown={(e) => startChromaDrag(e, t)}
|
|
499
517
|
onpointermove={moveDrag}
|
|
@@ -513,8 +531,8 @@
|
|
|
513
531
|
class:unbound={!t.bound}
|
|
514
532
|
class:selected={t.selected}
|
|
515
533
|
style="left: {t.ext.x}px; top: {t.ext.y}px; transform: translate(-50%, -50%) rotate({t.iconRot}deg)"
|
|
516
|
-
aria-label={t.bound ? `Rotate ${t.
|
|
517
|
-
title={t.bound ? `Rotate ${t.
|
|
534
|
+
aria-label={t.bound ? `Rotate ${t.label} hue (${t.family})` : `Rotate ${t.label} hue`}
|
|
535
|
+
title={t.bound ? `Rotate ${t.label} hue (${t.family})` : `Rotate ${t.label} hue`}
|
|
518
536
|
onpointerdown={(e) => startAxisDrag(e, t)}
|
|
519
537
|
onpointermove={moveDrag}
|
|
520
538
|
onpointerup={endDrag}
|
|
@@ -526,12 +544,21 @@
|
|
|
526
544
|
{/each}
|
|
527
545
|
|
|
528
546
|
{#if freeDot}
|
|
547
|
+
{#if freeDot.axisIndex !== null}
|
|
548
|
+
<span
|
|
549
|
+
class="axis-num"
|
|
550
|
+
style="left: {freeDot.x + FREE_NUM_OFFSET}px; top: {freeDot.y - FREE_NUM_OFFSET}px"
|
|
551
|
+
aria-hidden="true"
|
|
552
|
+
>
|
|
553
|
+
<AxisNumeral index={freeDot.axisIndex} status={statuses[freeDot.axisIndex]} selected />
|
|
554
|
+
</span>
|
|
555
|
+
{/if}
|
|
529
556
|
<button
|
|
530
557
|
type="button"
|
|
531
558
|
class="dot selected"
|
|
532
559
|
style="left: {freeDot.x}px; top: {freeDot.y}px; --fill: {freeDot.hex}"
|
|
533
|
-
aria-label={
|
|
534
|
-
title={
|
|
560
|
+
aria-label={freeDotLabel}
|
|
561
|
+
title={freeDotLabel}
|
|
535
562
|
onpointerdown={startFreeDrag}
|
|
536
563
|
onpointermove={moveDrag}
|
|
537
564
|
onpointerup={endDrag}
|
|
@@ -632,7 +659,7 @@
|
|
|
632
659
|
}
|
|
633
660
|
|
|
634
661
|
/* Unbound-axis ghost: a hollow greyscale marker on the external track (no color
|
|
635
|
-
to preview, only where
|
|
662
|
+
to preview, only where an assigned color's hue would land). */
|
|
636
663
|
.ghost.unbound {
|
|
637
664
|
width: 0.7rem;
|
|
638
665
|
height: 0.7rem;
|
|
@@ -731,24 +758,16 @@
|
|
|
731
758
|
color: var(--ui-text-primary);
|
|
732
759
|
}
|
|
733
760
|
|
|
734
|
-
/* Axis numeral just outside the handle track.
|
|
735
|
-
so
|
|
761
|
+
/* Axis numeral just outside the handle track. Positioning only — never
|
|
762
|
+
rotated, so the digit stays upright at any angle. */
|
|
736
763
|
.axis-num {
|
|
737
764
|
position: absolute;
|
|
738
765
|
transform: translate(-50%, -50%);
|
|
739
|
-
|
|
740
|
-
font-weight: var(--ui-font-weight-semibold);
|
|
741
|
-
color: var(--ui-text-tertiary);
|
|
766
|
+
display: flex;
|
|
742
767
|
pointer-events: none;
|
|
743
|
-
user-select: none;
|
|
744
768
|
z-index: 3;
|
|
745
769
|
}
|
|
746
770
|
|
|
747
|
-
.axis-num.selected {
|
|
748
|
-
color: var(--ui-text-primary);
|
|
749
|
-
font-size: var(--ui-font-size-sm);
|
|
750
|
-
}
|
|
751
|
-
|
|
752
771
|
.dot:focus-visible,
|
|
753
772
|
.ext-handle:focus-visible,
|
|
754
773
|
.global-handle:focus-visible {
|