@motion-proto/live-tokens 0.1.1 → 0.3.2
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 +168 -21
- package/dist-plugin/index.cjs +823 -336
- package/dist-plugin/index.d.cts +9 -7
- package/dist-plugin/index.d.ts +9 -7
- package/dist-plugin/index.js +822 -335
- package/package.json +46 -20
- package/src/assets/newspaper.webp +0 -0
- package/src/assets/offering.webp +0 -0
- package/src/component-editor/BadgeEditor.svelte +170 -0
- package/src/component-editor/CalloutEditor.svelte +103 -0
- package/src/component-editor/CardEditor.svelte +184 -0
- package/src/component-editor/CollapsibleSectionEditor.svelte +167 -0
- package/src/component-editor/CornerBadgeEditor.svelte +207 -0
- package/src/component-editor/DialogEditor.svelte +172 -0
- package/src/component-editor/ImageEditor.svelte +72 -0
- package/src/component-editor/InlineEditActionsEditor.svelte +83 -0
- package/src/component-editor/NotificationEditor.svelte +160 -0
- package/src/component-editor/ProgressBarEditor.svelte +124 -0
- package/src/component-editor/RadioButtonEditor.svelte +140 -0
- package/src/component-editor/SectionDividerEditor.svelte +263 -0
- package/src/component-editor/SegmentedControlEditor.svelte +154 -0
- package/src/component-editor/StandardButtonsEditor.svelte +178 -0
- package/src/component-editor/TabBarEditor.svelte +137 -0
- package/src/component-editor/TableEditor.svelte +128 -0
- package/src/component-editor/TooltipEditor.svelte +122 -0
- package/src/component-editor/editorTokens.test.ts +93 -0
- package/src/component-editor/groupKeySlots.test.ts +67 -0
- package/src/component-editor/groupKeySnapshot.test.ts +52 -0
- package/src/component-editor/index.ts +5 -0
- package/src/component-editor/registry.ts +246 -0
- package/src/component-editor/scaffolding/AngleDial.svelte +185 -0
- package/src/component-editor/scaffolding/ComponentEditorBase.svelte +96 -0
- package/src/component-editor/scaffolding/ComponentFileManager.svelte +682 -0
- package/src/component-editor/scaffolding/ComponentFileMenu.svelte +312 -0
- package/src/component-editor/scaffolding/ComponentsTab.svelte +69 -0
- package/src/component-editor/scaffolding/CopyFromMenu.svelte +246 -0
- package/src/component-editor/scaffolding/DemoHeader.svelte +21 -0
- package/src/component-editor/scaffolding/DividerEditor.svelte +81 -0
- package/src/component-editor/scaffolding/FieldsetWrapper.svelte +46 -0
- package/src/component-editor/scaffolding/GradientCard.svelte +291 -0
- package/src/component-editor/scaffolding/LinkageChart.svelte +297 -0
- package/src/component-editor/scaffolding/LinkedBlock.svelte +418 -0
- package/src/component-editor/scaffolding/NonStylableConfig.svelte +57 -0
- package/src/component-editor/scaffolding/SaveAsDialog.svelte +177 -0
- package/src/component-editor/scaffolding/ShadowBackdrop.svelte +25 -0
- package/src/component-editor/scaffolding/ShadowBackdropControls.svelte +56 -0
- package/src/component-editor/scaffolding/StateBlock.svelte +115 -0
- package/src/component-editor/scaffolding/TokenLayout.svelte +511 -0
- package/src/component-editor/scaffolding/TypeEditor.svelte +82 -0
- package/src/component-editor/scaffolding/VariantGroup.svelte +277 -0
- package/src/component-editor/scaffolding/buildTypeGroupTokens.ts +97 -0
- package/src/component-editor/scaffolding/componentSectionType.ts +8 -0
- package/src/component-editor/scaffolding/componentSources.ts +9 -0
- package/src/component-editor/scaffolding/defaultSections.ts +16 -0
- package/src/component-editor/scaffolding/editorContext.ts +44 -0
- package/src/component-editor/scaffolding/linkedBlock.ts +226 -0
- package/src/component-editor/scaffolding/siblings.ts +33 -0
- package/src/component-editor/scaffolding/types.ts +39 -0
- package/src/components/Badge.svelte +231 -42
- package/src/components/Button.svelte +324 -124
- package/src/components/Callout.svelte +145 -0
- package/src/components/Card.svelte +123 -25
- package/src/components/CollapsibleSection.svelte +213 -35
- package/src/components/CornerBadge.svelte +224 -0
- package/src/components/Dialog.svelte +137 -114
- package/src/components/Image.svelte +43 -0
- package/src/components/InlineEditActions.svelte +74 -14
- package/src/components/Notification.svelte +184 -163
- package/src/components/ProgressBar.svelte +216 -22
- package/src/components/RadioButton.svelte +110 -40
- package/src/components/SectionDivider.svelte +428 -74
- package/src/components/SegmentedControl.svelte +203 -0
- package/src/components/TabBar.svelte +146 -21
- package/src/components/Table.svelte +102 -0
- package/src/components/Tooltip.svelte +45 -19
- package/src/components/types.ts +51 -0
- package/src/data/google-fonts.json +75 -0
- package/src/lib/ColumnsOverlay.svelte +20 -7
- package/src/lib/LiveEditorOverlay.svelte +257 -78
- package/src/lib/columnsOverlay.ts +21 -17
- package/src/lib/componentConfig.test.ts +204 -0
- package/src/lib/componentConfigKeys.ts +19 -0
- package/src/lib/componentConfigService.ts +88 -0
- package/src/lib/copyPopover.ts +30 -0
- package/src/lib/cssVarSync.ts +59 -7
- package/src/lib/editorConfigStore.ts +0 -10
- package/src/lib/editorCore.ts +402 -0
- package/src/lib/editorKeybindings.ts +52 -0
- package/src/lib/editorPersistence.ts +106 -0
- package/src/lib/editorRenderer.ts +74 -0
- package/src/lib/editorStore.test.ts +328 -0
- package/src/lib/editorStore.ts +412 -0
- package/src/lib/editorTypes.ts +100 -0
- package/src/lib/editorViewStore.ts +55 -0
- package/src/lib/files/versionedFileResource.ts +140 -0
- package/src/lib/fontLoader.ts +130 -0
- package/src/lib/fontMigration.ts +140 -0
- package/src/lib/fontParse.ts +168 -0
- package/src/lib/index.ts +48 -30
- package/src/lib/lazyConfig.test.ts +54 -0
- package/src/lib/migrations/2026-04-24-component-prefix-and-suffix-renames.ts +64 -0
- package/src/lib/migrations/2026-04-24-legacy-keys-and-bg-to-canvas.ts +71 -0
- package/src/lib/migrations/2026-04-27-segmentedcontrol-disabled-flatten.ts +43 -0
- package/src/lib/migrations/2026-05-08-collapsiblesection-frame-and-cleanup.ts +68 -0
- package/src/lib/migrations/2026-05-08-collapsiblesection-variant-namespace.ts +35 -0
- package/src/lib/migrations/2026-05-10-sectiondivider-gradient-stops.ts +50 -0
- package/src/lib/migrations/2026-05-13-primary-to-brand.ts +90 -0
- package/src/lib/migrations/index.ts +93 -0
- package/src/lib/migrations/migrations.test.ts +341 -0
- package/src/lib/navLinkTypes.ts +1 -0
- package/src/lib/overlayState.ts +3 -0
- package/src/lib/paletteDerivation.ts +300 -0
- package/src/lib/parentRouteStore.ts +42 -0
- package/src/lib/parsers/globalRootBlock.ts +32 -0
- package/src/lib/presetService.ts +94 -0
- package/src/lib/router.ts +42 -10
- package/src/lib/scrollSection.ts +45 -0
- package/src/lib/slices/columns.ts +59 -0
- package/src/lib/slices/components.ts +362 -0
- package/src/lib/slices/domainVars.ts +15 -0
- package/src/lib/slices/fonts.ts +30 -0
- package/src/lib/slices/gradients.ts +153 -0
- package/src/lib/slices/overlays.ts +132 -0
- package/src/lib/slices/palettes.ts +26 -0
- package/src/lib/slices/shadows.ts +123 -0
- package/src/lib/storage.ts +88 -0
- package/src/lib/themeInit.ts +74 -0
- package/src/lib/themeService.ts +101 -0
- package/src/lib/themeTypes.ts +146 -0
- package/src/lib/tokenRegistry.ts +148 -0
- package/src/pages/ComponentEditorPage.svelte +384 -0
- package/src/pages/ComponentEditorPage.svelte.d.ts +2 -0
- package/src/pages/Editor.svelte +98 -0
- package/src/pages/Editor.svelte.d.ts +2 -0
- package/src/pages/EditorShell.svelte +348 -0
- package/src/styles/_padding.scss +34 -0
- package/src/styles/fonts/Fraunces/Fraunces-italic-latin-ext.woff2 +0 -0
- package/src/styles/fonts/Fraunces/Fraunces-italic-latin.woff2 +0 -0
- package/src/styles/fonts/Fraunces/Fraunces-roman-latin-ext.woff2 +0 -0
- package/src/styles/fonts/Fraunces/Fraunces-roman-latin.woff2 +0 -0
- package/src/styles/fonts/Manrope/Manrope-latin-ext.woff2 +0 -0
- package/src/styles/fonts/Manrope/Manrope-latin.woff2 +0 -0
- package/src/styles/fonts.css +22 -10
- package/src/styles/form-controls.css +14 -16
- package/src/styles/tokens.css +1322 -0
- package/src/styles/ui-editor.css +126 -0
- package/src/{showcase → ui}/BezierCurveEditor.svelte +14 -14
- package/src/{showcase → ui}/ColorEditPanel.svelte +42 -36
- package/src/ui/EditorViewSwitcher.svelte +180 -0
- package/src/ui/FontStackEditor.svelte +360 -0
- package/src/ui/GradientEditor.svelte +461 -0
- package/src/ui/GradientStopPicker.svelte +74 -0
- package/src/ui/PaletteEditor.svelte +1590 -0
- package/src/ui/PaletteEditor.test.ts +108 -0
- package/src/ui/PresetFileManager.svelte +567 -0
- package/src/ui/ProjectFontsSection.svelte +645 -0
- package/src/{showcase → ui}/SurfacesTab.svelte +39 -39
- package/src/{showcase → ui}/TextTab.svelte +27 -27
- package/src/{showcase/TokenFileManager.svelte → ui/ThemeFileManager.svelte} +196 -112
- package/src/ui/Toggle.svelte +108 -0
- package/src/ui/UICopyPopover.svelte +78 -0
- package/src/{showcase/EditorDialog.svelte → ui/UIDialog.svelte} +66 -25
- package/src/ui/UIFontFamilySelector.svelte +309 -0
- package/src/ui/UIFontSizeSelector.svelte +165 -0
- package/src/ui/UIFontWeightSelector.svelte +52 -0
- package/src/ui/UILineHeightSelector.svelte +47 -0
- package/src/ui/UILinkToggle.svelte +60 -0
- package/src/ui/UIOptionItem.svelte +74 -0
- package/src/ui/UIOptionList.svelte +27 -0
- package/src/ui/UIPaddingSelector.svelte +661 -0
- package/src/ui/UIPaletteSelector.svelte +1084 -0
- package/src/ui/UIRadio.svelte +72 -0
- package/src/ui/UIRadioGroup.svelte +59 -0
- package/src/ui/UIRelinkConfirmPopover.svelte +235 -0
- package/src/ui/UITokenSelector.svelte +509 -0
- package/src/ui/UIVariantSelector.svelte +145 -0
- package/src/ui/VariablesTab.svelte +252 -0
- package/src/ui/index.ts +31 -0
- package/src/ui/keepInViewport.ts +84 -0
- package/src/ui/palette/GradientStopEditor.svelte +482 -0
- package/src/ui/palette/OverridesPanel.svelte +526 -0
- package/src/ui/palette/PaletteBase.svelte +165 -0
- package/src/ui/palette/ScaleCurveEditor.svelte +38 -0
- package/src/ui/palette/paletteEditorState.ts +89 -0
- package/src/ui/sections/ColumnsSection.svelte +273 -0
- package/src/ui/sections/GradientsSection.svelte +147 -0
- package/src/ui/sections/OverlaysSection.svelte +670 -0
- package/src/ui/sections/ShadowsSection.svelte +1250 -0
- package/src/ui/sections/TokenScaleTable.svelte +332 -0
- package/src/ui/sections/tokenScales.ts +81 -0
- package/src/ui/variantScales.ts +108 -0
- package/src/components/DetailNav.svelte +0 -78
- package/src/components/Toggle.svelte +0 -86
- package/src/lib/tokenInit.ts +0 -29
- package/src/lib/tokenService.ts +0 -144
- package/src/lib/tokenTypes.ts +0 -45
- package/src/pages/Admin.svelte +0 -100
- package/src/pages/ShowcasePage.svelte +0 -144
- package/src/showcase/BackupBrowser.svelte +0 -617
- package/src/showcase/ComponentsTab.svelte +0 -105
- package/src/showcase/PaletteEditor.svelte +0 -2579
- package/src/showcase/PaletteSelector.svelte +0 -627
- package/src/showcase/TokenMap.svelte +0 -54
- package/src/showcase/VariablesTab.svelte +0 -2655
- package/src/showcase/VisualsTab.svelte +0 -231
- package/src/showcase/demos/BadgeDemo.svelte +0 -56
- package/src/showcase/demos/CardDemo.svelte +0 -50
- package/src/showcase/demos/ChoiceButtonsDemo.svelte +0 -192
- package/src/showcase/demos/CollapsibleSectionDemo.svelte +0 -54
- package/src/showcase/demos/DialogDemo.svelte +0 -42
- package/src/showcase/demos/InlineEditActionsDemo.svelte +0 -25
- package/src/showcase/demos/NotificationDemo.svelte +0 -147
- package/src/showcase/demos/ProgressBarDemo.svelte +0 -54
- package/src/showcase/demos/RadioButtonDemo.svelte +0 -56
- package/src/showcase/demos/SectionDividerDemo.svelte +0 -77
- package/src/showcase/demos/StandardButtonsDemo.svelte +0 -455
- package/src/showcase/demos/TabBarDemo.svelte +0 -58
- package/src/showcase/demos/TooltipDemo.svelte +0 -52
- package/src/showcase/editor.css +0 -93
- package/src/showcase/index.ts +0 -17
- package/src/styles/fonts/Domine/Domine-VariableFont_wght.ttf +0 -0
- package/src/styles/fonts/Domine/OFL.txt +0 -97
- package/src/styles/fonts/Domine/README.txt +0 -66
- /package/src/{showcase → ui}/curveEngine.ts +0 -0
|
@@ -0,0 +1,328 @@
|
|
|
1
|
+
// @vitest-environment happy-dom
|
|
2
|
+
import { beforeEach, describe, expect, it } from 'vitest';
|
|
3
|
+
import { get } from 'svelte/store';
|
|
4
|
+
import type { PaletteConfig } from './themeTypes';
|
|
5
|
+
import {
|
|
6
|
+
editorState,
|
|
7
|
+
mutate,
|
|
8
|
+
beginScope,
|
|
9
|
+
commitScope,
|
|
10
|
+
cancelScope,
|
|
11
|
+
beginSliderGesture,
|
|
12
|
+
transaction,
|
|
13
|
+
undo,
|
|
14
|
+
redo,
|
|
15
|
+
setPaletteConfig,
|
|
16
|
+
__resetForTests,
|
|
17
|
+
__getHistoryLengths,
|
|
18
|
+
__getPastAt,
|
|
19
|
+
} from './editorStore';
|
|
20
|
+
|
|
21
|
+
function makePaletteConfig(baseColor: string): PaletteConfig {
|
|
22
|
+
return {
|
|
23
|
+
baseColor,
|
|
24
|
+
tintHue: 0,
|
|
25
|
+
tintChroma: 0.04,
|
|
26
|
+
lightnessCurve: [],
|
|
27
|
+
saturationCurve: [],
|
|
28
|
+
grayLightnessCurve: [],
|
|
29
|
+
graySaturationCurve: [],
|
|
30
|
+
scaleCurves: {},
|
|
31
|
+
curveOffset: {},
|
|
32
|
+
overrides: {},
|
|
33
|
+
snappedScales: [],
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const txOpts = { label: 'tx', collapseToOne: true, clipUndoFloor: false } as const;
|
|
38
|
+
const sessionOpts = { label: 'palette session', collapseToOne: true, clipUndoFloor: true } as const;
|
|
39
|
+
|
|
40
|
+
beforeEach(() => {
|
|
41
|
+
__resetForTests();
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
describe('editorStore — mutate() outside a scope', () => {
|
|
45
|
+
it('pushes exactly one past[] entry per call and undo restores', () => {
|
|
46
|
+
setPaletteConfig('Background', makePaletteConfig('#111111'));
|
|
47
|
+
expect(__getHistoryLengths().past).toBe(1);
|
|
48
|
+
|
|
49
|
+
setPaletteConfig('Background', makePaletteConfig('#222222'));
|
|
50
|
+
expect(__getHistoryLengths().past).toBe(2);
|
|
51
|
+
|
|
52
|
+
expect(get(editorState).palettes.Background.baseColor).toBe('#222222');
|
|
53
|
+
expect(undo()).toBe(true);
|
|
54
|
+
expect(get(editorState).palettes.Background.baseColor).toBe('#111111');
|
|
55
|
+
expect(undo()).toBe(true);
|
|
56
|
+
expect(get(editorState).palettes.Background).toBeUndefined();
|
|
57
|
+
expect(undo()).toBe(false);
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
describe('editorStore — non-clipping scopes group gestures', () => {
|
|
62
|
+
it('beginScope + multiple mutate() + commitScope → one past entry equal to pre-gesture snapshot', () => {
|
|
63
|
+
setPaletteConfig('Background', makePaletteConfig('#111111'));
|
|
64
|
+
const baselinePast = __getHistoryLengths().past;
|
|
65
|
+
const preGesture = structuredClone(get(editorState));
|
|
66
|
+
|
|
67
|
+
const scope = beginScope({ label: 'drag hue', collapseToOne: true, clipUndoFloor: false });
|
|
68
|
+
mutate('hue step 1', (s) => { s.palettes.Background.baseColor = '#222222'; });
|
|
69
|
+
mutate('hue step 2', (s) => { s.palettes.Background.baseColor = '#333333'; });
|
|
70
|
+
mutate('hue step 3', (s) => { s.palettes.Background.baseColor = '#444444'; });
|
|
71
|
+
commitScope(scope);
|
|
72
|
+
|
|
73
|
+
expect(__getHistoryLengths().past).toBe(baselinePast + 1);
|
|
74
|
+
const lastEntry = __getPastAt(__getHistoryLengths().past - 1)!;
|
|
75
|
+
expect(lastEntry.palettes.Background.baseColor).toBe(preGesture.palettes.Background.baseColor);
|
|
76
|
+
expect(get(editorState).palettes.Background.baseColor).toBe('#444444');
|
|
77
|
+
|
|
78
|
+
// One undo rolls the whole gesture back
|
|
79
|
+
undo();
|
|
80
|
+
expect(get(editorState).palettes.Background.baseColor).toBe('#111111');
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
it('beginSliderGesture opens a scope that groups updates into one entry', () => {
|
|
84
|
+
setPaletteConfig('Background', makePaletteConfig('#111111'));
|
|
85
|
+
const baselinePast = __getHistoryLengths().past;
|
|
86
|
+
|
|
87
|
+
beginSliderGesture('drag');
|
|
88
|
+
mutate('step', (s) => { s.palettes.Background.baseColor = '#222222'; });
|
|
89
|
+
mutate('step', (s) => { s.palettes.Background.baseColor = '#333333'; });
|
|
90
|
+
// Simulate pointerup
|
|
91
|
+
window.dispatchEvent(new Event('pointerup'));
|
|
92
|
+
|
|
93
|
+
expect(__getHistoryLengths().past).toBe(baselinePast + 1);
|
|
94
|
+
expect(get(editorState).palettes.Background.baseColor).toBe('#333333');
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
it('empty scope (no mutate calls) does not push history', () => {
|
|
98
|
+
const baselinePast = __getHistoryLengths().past;
|
|
99
|
+
const scope = beginScope({ ...txOpts, label: 'unused' });
|
|
100
|
+
commitScope(scope);
|
|
101
|
+
expect(__getHistoryLengths().past).toBe(baselinePast);
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
it('cancelScope on a non-clipping scope restores pre-gesture state and does not push history', () => {
|
|
105
|
+
setPaletteConfig('Background', makePaletteConfig('#111111'));
|
|
106
|
+
const baselinePast = __getHistoryLengths().past;
|
|
107
|
+
|
|
108
|
+
const scope = beginScope({ ...txOpts, label: 'drag' });
|
|
109
|
+
mutate('step', (s) => { s.palettes.Background.baseColor = '#999999'; });
|
|
110
|
+
cancelScope(scope, { silent: true });
|
|
111
|
+
|
|
112
|
+
expect(__getHistoryLengths().past).toBe(baselinePast);
|
|
113
|
+
expect(get(editorState).palettes.Background.baseColor).toBe('#111111');
|
|
114
|
+
});
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
describe('editorStore — clipping scopes (palette edit sessions)', () => {
|
|
118
|
+
it('beginScope with clipUndoFloor does not push history', () => {
|
|
119
|
+
setPaletteConfig('Background', makePaletteConfig('#111111'));
|
|
120
|
+
const before = __getHistoryLengths().past;
|
|
121
|
+
beginScope({ ...sessionOpts });
|
|
122
|
+
expect(__getHistoryLengths().past).toBe(before);
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
it('undo is clipped to the scope floor while open', () => {
|
|
126
|
+
setPaletteConfig('Background', makePaletteConfig('#111111'));
|
|
127
|
+
setPaletteConfig('Background', makePaletteConfig('#222222'));
|
|
128
|
+
const floor = __getHistoryLengths().past;
|
|
129
|
+
|
|
130
|
+
beginScope({ ...sessionOpts });
|
|
131
|
+
setPaletteConfig('Background', makePaletteConfig('#333333'));
|
|
132
|
+
setPaletteConfig('Background', makePaletteConfig('#444444'));
|
|
133
|
+
expect(__getHistoryLengths().past).toBe(floor + 2);
|
|
134
|
+
|
|
135
|
+
expect(undo()).toBe(true);
|
|
136
|
+
expect(get(editorState).palettes.Background.baseColor).toBe('#333333');
|
|
137
|
+
expect(undo()).toBe(true);
|
|
138
|
+
expect(get(editorState).palettes.Background.baseColor).toBe('#222222');
|
|
139
|
+
|
|
140
|
+
// Floor reached — further undo returns false, state unchanged
|
|
141
|
+
expect(undo()).toBe(false);
|
|
142
|
+
expect(get(editorState).palettes.Background.baseColor).toBe('#222222');
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
it('commitScope on a clipping scope collapses intra-scope history into one entry equal to the snapshot', () => {
|
|
146
|
+
setPaletteConfig('Background', makePaletteConfig('#111111'));
|
|
147
|
+
const preSessionPastLen = __getHistoryLengths().past;
|
|
148
|
+
|
|
149
|
+
const session = beginScope({ ...sessionOpts });
|
|
150
|
+
setPaletteConfig('Background', makePaletteConfig('#222222'));
|
|
151
|
+
setPaletteConfig('Background', makePaletteConfig('#333333'));
|
|
152
|
+
setPaletteConfig('Background', makePaletteConfig('#444444'));
|
|
153
|
+
commitScope(session);
|
|
154
|
+
|
|
155
|
+
expect(__getHistoryLengths().past).toBe(preSessionPastLen + 1);
|
|
156
|
+
|
|
157
|
+
const committedEntry = __getPastAt(__getHistoryLengths().past - 1)!;
|
|
158
|
+
expect(committedEntry.palettes.Background.baseColor).toBe('#111111');
|
|
159
|
+
expect(get(editorState).palettes.Background.baseColor).toBe('#444444');
|
|
160
|
+
|
|
161
|
+
// One undo restores pre-scope state
|
|
162
|
+
undo();
|
|
163
|
+
expect(get(editorState).palettes.Background.baseColor).toBe('#111111');
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
it('commitScope on a clipping scope with no net change pushes nothing', () => {
|
|
167
|
+
setPaletteConfig('Background', makePaletteConfig('#111111'));
|
|
168
|
+
const preSessionPastLen = __getHistoryLengths().past;
|
|
169
|
+
|
|
170
|
+
const session = beginScope({ ...sessionOpts });
|
|
171
|
+
// Mutate and revert to snapshot value
|
|
172
|
+
setPaletteConfig('Background', makePaletteConfig('#222222'));
|
|
173
|
+
setPaletteConfig('Background', makePaletteConfig('#111111'));
|
|
174
|
+
commitScope(session);
|
|
175
|
+
|
|
176
|
+
expect(__getHistoryLengths().past).toBe(preSessionPastLen);
|
|
177
|
+
expect(get(editorState).palettes.Background.baseColor).toBe('#111111');
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
it('cancelScope on a clipping scope restores snapshot, drops intra-scope entries, clears future', () => {
|
|
181
|
+
setPaletteConfig('Background', makePaletteConfig('#111111'));
|
|
182
|
+
const preSessionPastLen = __getHistoryLengths().past;
|
|
183
|
+
|
|
184
|
+
const session = beginScope({ ...sessionOpts });
|
|
185
|
+
setPaletteConfig('Background', makePaletteConfig('#222222'));
|
|
186
|
+
setPaletteConfig('Background', makePaletteConfig('#333333'));
|
|
187
|
+
expect(__getHistoryLengths().past).toBe(preSessionPastLen + 2);
|
|
188
|
+
|
|
189
|
+
cancelScope(session);
|
|
190
|
+
|
|
191
|
+
expect(__getHistoryLengths().past).toBe(preSessionPastLen);
|
|
192
|
+
expect(__getHistoryLengths().future).toBe(0);
|
|
193
|
+
expect(get(editorState).palettes.Background.baseColor).toBe('#111111');
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
it('nested clipping beginScope auto-commits the prior scope', () => {
|
|
197
|
+
setPaletteConfig('Background', makePaletteConfig('#111111'));
|
|
198
|
+
setPaletteConfig('Accent', makePaletteConfig('#aaaaaa'));
|
|
199
|
+
const preSessionPastLen = __getHistoryLengths().past;
|
|
200
|
+
|
|
201
|
+
beginScope({ ...sessionOpts });
|
|
202
|
+
setPaletteConfig('Background', makePaletteConfig('#222222'));
|
|
203
|
+
const second = beginScope({ ...sessionOpts }); // auto-commits prior
|
|
204
|
+
expect(__getHistoryLengths().past).toBe(preSessionPastLen + 1);
|
|
205
|
+
|
|
206
|
+
setPaletteConfig('Accent', makePaletteConfig('#bbbbbb'));
|
|
207
|
+
commitScope(second);
|
|
208
|
+
|
|
209
|
+
// Two collapsed entries: prior Background scope, then Accent scope
|
|
210
|
+
expect(__getHistoryLengths().past).toBe(preSessionPastLen + 2);
|
|
211
|
+
// One undo: revert Accent to pre-scope value
|
|
212
|
+
undo();
|
|
213
|
+
expect(get(editorState).palettes.Accent.baseColor).toBe('#aaaaaa');
|
|
214
|
+
expect(get(editorState).palettes.Background.baseColor).toBe('#222222');
|
|
215
|
+
// Another undo: revert Background to pre-scope value
|
|
216
|
+
undo();
|
|
217
|
+
expect(get(editorState).palettes.Background.baseColor).toBe('#111111');
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
it('undo() with a pending non-clipping scope cancels it first (drag-in-flight is discarded)', () => {
|
|
221
|
+
setPaletteConfig('Background', makePaletteConfig('#111111'));
|
|
222
|
+
const pastLenBefore = __getHistoryLengths().past;
|
|
223
|
+
|
|
224
|
+
beginScope({ ...txOpts, label: 'drag' });
|
|
225
|
+
mutate('step', (s) => { s.palettes.Background.baseColor = '#ffffff'; });
|
|
226
|
+
// An in-flight drag holds pre-drag state in the scope's snapshot;
|
|
227
|
+
// `undo()` cancels it (restoring that snapshot) before consulting history.
|
|
228
|
+
undo();
|
|
229
|
+
// The cancelled in-flight change is gone; history count unchanged by the cancel.
|
|
230
|
+
// (Current impl also consumes one history step after cancelling — the
|
|
231
|
+
// cross-boundary behavior is a separate concern tracked in the plan.)
|
|
232
|
+
expect(__getHistoryLengths().past).toBe(pastLenBefore - 1);
|
|
233
|
+
// The pending mutation did not survive: '#ffffff' is not current.
|
|
234
|
+
expect(get(editorState).palettes.Background?.baseColor).not.toBe('#ffffff');
|
|
235
|
+
});
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
describe('editorStore — apply + undo matches spec end-to-end', () => {
|
|
239
|
+
it('after Apply, one Cmd+Z restores to pre-session state', () => {
|
|
240
|
+
setPaletteConfig('Background', makePaletteConfig('#8d7f74'));
|
|
241
|
+
const preSessionState = structuredClone(get(editorState));
|
|
242
|
+
|
|
243
|
+
const session = beginScope({ ...sessionOpts });
|
|
244
|
+
// Simulate three slider drags during the session
|
|
245
|
+
for (const hex of ['#702030', '#503090', '#205090']) {
|
|
246
|
+
const drag = beginScope({ ...txOpts, label: `drag ${hex}` });
|
|
247
|
+
setPaletteConfig('Background', makePaletteConfig(hex));
|
|
248
|
+
commitScope(drag);
|
|
249
|
+
}
|
|
250
|
+
commitScope(session);
|
|
251
|
+
|
|
252
|
+
expect(get(editorState).palettes.Background.baseColor).toBe('#205090');
|
|
253
|
+
|
|
254
|
+
const undone = undo();
|
|
255
|
+
expect(undone).toBe(true);
|
|
256
|
+
expect(get(editorState).palettes.Background.baseColor).toBe(preSessionState.palettes.Background.baseColor);
|
|
257
|
+
expect(JSON.stringify(get(editorState))).toBe(JSON.stringify(preSessionState));
|
|
258
|
+
});
|
|
259
|
+
|
|
260
|
+
it('after Cancel, Cmd+Z does not resurrect discarded drags', () => {
|
|
261
|
+
setPaletteConfig('Background', makePaletteConfig('#8d7f74'));
|
|
262
|
+
const preSessionState = structuredClone(get(editorState));
|
|
263
|
+
|
|
264
|
+
const session = beginScope({ ...sessionOpts });
|
|
265
|
+
for (const hex of ['#702030', '#503090', '#205090']) {
|
|
266
|
+
const drag = beginScope({ ...txOpts, label: `drag ${hex}` });
|
|
267
|
+
setPaletteConfig('Background', makePaletteConfig(hex));
|
|
268
|
+
commitScope(drag);
|
|
269
|
+
}
|
|
270
|
+
cancelScope(session);
|
|
271
|
+
|
|
272
|
+
// State is pre-session; no new history entry
|
|
273
|
+
expect(JSON.stringify(get(editorState))).toBe(JSON.stringify(preSessionState));
|
|
274
|
+
// One undo walks back to before the palette existed (setPaletteConfig before scope)
|
|
275
|
+
undo();
|
|
276
|
+
expect(get(editorState).palettes.Background).toBeUndefined();
|
|
277
|
+
});
|
|
278
|
+
});
|
|
279
|
+
|
|
280
|
+
describe('editorStore — intra-session slider-drag tracking', () => {
|
|
281
|
+
// Regression guard for the two-writer feedback loop fixed in the
|
|
282
|
+
// PaletteEditor single-source-of-truth refactor: during a drag inside a
|
|
283
|
+
// palette edit session, every per-tick mutation must be visible in the
|
|
284
|
+
// store immediately (not pulled back to a stale pre-session value).
|
|
285
|
+
it('store reflects every per-tick mutation during a slider-drag session', () => {
|
|
286
|
+
setPaletteConfig('Background', makePaletteConfig('#8d7f74'));
|
|
287
|
+
|
|
288
|
+
const session = beginScope({ ...sessionOpts });
|
|
289
|
+
beginSliderGesture('drag base');
|
|
290
|
+
|
|
291
|
+
const tickHexes = ['#8c7f73', '#8b7f72', '#8a7f71', '#897f70', '#887f6f'];
|
|
292
|
+
for (const hex of tickHexes) {
|
|
293
|
+
mutate('drag tick', (s) => { s.palettes.Background.baseColor = hex; });
|
|
294
|
+
// Each tick must be visible on read — no stale pre-session value
|
|
295
|
+
expect(get(editorState).palettes.Background.baseColor).toBe(hex);
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
window.dispatchEvent(new Event('pointerup'));
|
|
299
|
+
commitScope(session);
|
|
300
|
+
|
|
301
|
+
expect(get(editorState).palettes.Background.baseColor).toBe('#887f6f');
|
|
302
|
+
|
|
303
|
+
// One undo after Apply restores to pre-session
|
|
304
|
+
undo();
|
|
305
|
+
expect(get(editorState).palettes.Background.baseColor).toBe('#8d7f74');
|
|
306
|
+
});
|
|
307
|
+
|
|
308
|
+
it('Cmd+Z during a session walks one tick back per press', () => {
|
|
309
|
+
setPaletteConfig('Background', makePaletteConfig('#8d7f74'));
|
|
310
|
+
|
|
311
|
+
beginScope({ ...sessionOpts });
|
|
312
|
+
for (const hex of ['#702030', '#503090', '#205090']) {
|
|
313
|
+
const drag = beginScope({ ...txOpts, label: `drag ${hex}` });
|
|
314
|
+
mutate('tick', (s) => { s.palettes.Background.baseColor = hex; });
|
|
315
|
+
commitScope(drag);
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
expect(get(editorState).palettes.Background.baseColor).toBe('#205090');
|
|
319
|
+
undo();
|
|
320
|
+
expect(get(editorState).palettes.Background.baseColor).toBe('#503090');
|
|
321
|
+
undo();
|
|
322
|
+
expect(get(editorState).palettes.Background.baseColor).toBe('#702030');
|
|
323
|
+
undo();
|
|
324
|
+
expect(get(editorState).palettes.Background.baseColor).toBe('#8d7f74');
|
|
325
|
+
// Session floor reached — further undo no-ops
|
|
326
|
+
expect(undo()).toBe(false);
|
|
327
|
+
});
|
|
328
|
+
});
|