@motion-proto/live-tokens 0.6.2 → 0.8.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 +14 -13
- package/dist-plugin/index.cjs +854 -226
- package/dist-plugin/index.d.cts +2 -1
- package/dist-plugin/index.d.ts +2 -1
- package/dist-plugin/index.js +852 -225
- package/package.json +26 -40
- package/src/{styles → app}/site.css +1 -1
- package/src/{component-editor → editor/component-editor}/BadgeEditor.svelte +8 -82
- package/src/{component-editor → editor/component-editor}/CalloutEditor.svelte +4 -4
- package/src/{component-editor → editor/component-editor}/CardEditor.svelte +28 -76
- package/src/{component-editor → editor/component-editor}/CollapsibleSectionEditor.svelte +37 -30
- package/src/{component-editor → editor/component-editor}/CornerBadgeEditor.svelte +31 -93
- package/src/{component-editor → editor/component-editor}/DialogEditor.svelte +60 -57
- package/src/editor/component-editor/ImageEditor.svelte +30 -0
- package/src/{component-editor → editor/component-editor}/InlineEditActionsEditor.svelte +6 -4
- package/src/editor/component-editor/MenuSelectEditor.svelte +160 -0
- package/src/{component-editor → editor/component-editor}/NotificationEditor.svelte +67 -38
- package/src/{component-editor → editor/component-editor}/ProgressBarEditor.svelte +5 -4
- package/src/{component-editor → editor/component-editor}/RadioButtonEditor.svelte +3 -3
- package/src/editor/component-editor/SectionDividerEditor.svelte +565 -0
- package/src/{component-editor → editor/component-editor}/SegmentedControlEditor.svelte +2 -2
- package/src/{component-editor → editor/component-editor}/StandardButtonsEditor.svelte +29 -21
- package/src/{component-editor → editor/component-editor}/TabBarEditor.svelte +9 -14
- package/src/{component-editor → editor/component-editor}/TableEditor.svelte +9 -18
- package/src/{component-editor → editor/component-editor}/TooltipEditor.svelte +11 -47
- package/src/editor/component-editor/editors.d.ts +10 -0
- package/src/{component-editor → editor/component-editor}/registry.ts +28 -18
- package/src/{component-editor → editor/component-editor}/scaffolding/AngleDial.svelte +54 -15
- package/src/{component-editor → editor/component-editor}/scaffolding/ComponentEditorBase.svelte +3 -51
- package/src/{component-editor → editor/component-editor}/scaffolding/ComponentFileManager.svelte +151 -424
- package/src/{component-editor → editor/component-editor}/scaffolding/ComponentFileMenu.svelte +18 -170
- package/src/{component-editor → editor/component-editor}/scaffolding/ComponentsTab.svelte +2 -2
- package/src/{component-editor → editor/component-editor}/scaffolding/CopyFromMenu.svelte +44 -4
- package/src/{component-editor → editor/component-editor}/scaffolding/FieldsetWrapper.svelte +1 -1
- package/src/{component-editor → editor/component-editor}/scaffolding/LinkageChart.svelte +6 -6
- package/src/{component-editor → editor/component-editor}/scaffolding/LinkedBlock.svelte +6 -12
- package/src/editor/component-editor/scaffolding/NonStylableConfig.svelte +38 -0
- package/src/editor/component-editor/scaffolding/RadialShapePad.svelte +483 -0
- package/src/{component-editor → editor/component-editor}/scaffolding/SaveAsDialog.svelte +66 -12
- package/src/editor/component-editor/scaffolding/ShadowBackdrop.svelte +85 -0
- package/src/editor/component-editor/scaffolding/ShadowBackdropControls.svelte +132 -0
- package/src/editor/component-editor/scaffolding/StateBlock.svelte +345 -0
- package/src/{component-editor → editor/component-editor}/scaffolding/TokenLayout.svelte +17 -12
- package/src/{component-editor → editor/component-editor}/scaffolding/TypeEditor.svelte +13 -1
- package/src/editor/component-editor/scaffolding/VariantGroup.svelte +858 -0
- package/src/{component-editor → editor/component-editor}/scaffolding/buildTypeGroupTokens.ts +1 -0
- package/src/{component-editor → editor/component-editor}/scaffolding/editorContext.ts +19 -9
- package/src/{component-editor → editor/component-editor}/scaffolding/linkedBlock.ts +2 -2
- package/src/{component-editor → editor/component-editor}/scaffolding/types.ts +25 -0
- package/src/{lib → editor/core/components}/componentConfigKeys.ts +8 -0
- package/src/{lib → editor/core/components}/componentConfigService.ts +3 -3
- package/src/{lib → editor/core/components}/componentPersist.ts +11 -9
- package/src/editor/core/flashStatus.ts +30 -0
- package/src/{lib → editor/core/fonts}/fontLoader.ts +2 -2
- package/src/{lib → editor/core/fonts}/fontMigration.ts +4 -4
- package/src/{lib → editor/core/fonts}/fontParse.ts +1 -1
- package/src/editor/core/manifests/manifestService.ts +171 -0
- package/src/editor/core/palettes/familySwap.ts +99 -0
- package/src/{lib → editor/core/palettes}/paletteDerivation.ts +71 -2
- package/src/{lib → editor/core/palettes}/tokenRegistry.ts +9 -6
- package/src/editor/core/productionPulse.ts +37 -0
- package/src/{lib → editor/core/routing}/router.ts +1 -1
- package/src/{lib/files/versionedFileResource.ts → editor/core/storage/files/versionedFileResourceClient.ts} +8 -1
- package/src/{lib → editor/core/store}/editorCore.ts +24 -8
- package/src/{lib → editor/core/store}/editorPersistence.ts +3 -3
- package/src/{lib → editor/core/store}/editorRenderer.ts +2 -2
- package/src/{lib → editor/core/store}/editorStore.ts +222 -28
- package/src/{lib → editor/core/store}/editorTypes.ts +56 -13
- package/src/editor/core/store/gradientSource.ts +192 -0
- package/src/editor/core/themes/migrations/2026-05-19-collapsiblesection-drop-frame-surface.ts +28 -0
- package/src/editor/core/themes/migrations/2026-05-19-sectiondivider-rich-gradient.ts +35 -0
- package/src/editor/core/themes/migrations/2026-05-20-sectiondivider-slim-variants.ts +82 -0
- package/src/editor/core/themes/migrations/2026-05-21-sectiondivider-spacing-to-padding.ts +24 -0
- package/src/editor/core/themes/migrations/2026-05-22-sectiondivider-intrinsics-to-css.ts +81 -0
- package/src/{lib → editor/core/themes}/migrations/index.ts +10 -0
- package/src/{lib → editor/core/themes}/slices/columns.ts +2 -2
- package/src/{lib → editor/core/themes}/slices/components.ts +20 -6
- package/src/{lib → editor/core/themes}/slices/fonts.ts +1 -1
- package/src/{lib → editor/core/themes}/slices/gradients.ts +89 -14
- package/src/{lib → editor/core/themes}/slices/overlays.ts +1 -1
- package/src/{lib → editor/core/themes}/slices/palettes.ts +1 -1
- package/src/{lib → editor/core/themes}/slices/shadows.ts +3 -3
- package/src/{lib → editor/core/themes}/themeInit.ts +8 -8
- package/src/{lib → editor/core/themes}/themeService.ts +6 -6
- package/src/{lib → editor/core/themes}/themeTypes.ts +67 -8
- package/src/editor/index.ts +69 -0
- package/src/{lib → editor/overlay}/ColumnsOverlay.svelte +0 -1
- package/src/{lib → editor/overlay}/LiveEditorOverlay.svelte +80 -129
- package/src/{lib → editor/overlay}/columnsOverlay.ts +2 -2
- package/src/{pages → editor/pages}/ComponentEditorPage.svelte +12 -12
- package/src/{pages → editor/pages}/Editor.svelte +4 -4
- package/src/{pages → editor/pages}/EditorShell.svelte +18 -36
- package/src/{styles → editor/styles}/ui-editor.css +43 -22
- package/src/{styles → editor/styles}/ui-form-controls.css +23 -24
- package/src/{ui → editor/ui}/BezierCurveEditor.svelte +119 -68
- package/src/{ui → editor/ui}/ColorEditPanel.svelte +13 -13
- package/src/{ui → editor/ui}/EditorViewSwitcher.svelte +7 -6
- package/src/editor/ui/FileLoadList.svelte +367 -0
- package/src/editor/ui/FilePill.svelte +80 -0
- package/src/editor/ui/FontStackEditor.svelte +499 -0
- package/src/editor/ui/GradientEditor.svelte +690 -0
- package/src/{ui → editor/ui}/GradientStopPicker.svelte +12 -4
- package/src/editor/ui/ManifestFileManager.svelte +438 -0
- package/src/{ui → editor/ui}/PaletteEditor.svelte +180 -673
- package/src/editor/ui/ProjectFontsSection.svelte +638 -0
- package/src/{ui → editor/ui}/SurfacesTab.svelte +3 -3
- package/src/{ui → editor/ui}/TextTab.svelte +3 -3
- package/src/editor/ui/ThemeFileManager.svelte +783 -0
- package/src/{ui → editor/ui}/UICopyPopover.svelte +4 -4
- package/src/{ui → editor/ui}/UIFontFamilySelector.svelte +6 -7
- package/src/{ui → editor/ui}/UIFontSizeSelector.svelte +4 -1
- package/src/editor/ui/UIInfoPopover.svelte +243 -0
- package/src/editor/ui/UILetterSpacingSelector.svelte +65 -0
- package/src/{ui → editor/ui}/UILineHeightSelector.svelte +5 -5
- package/src/{ui → editor/ui}/UILinkToggle.svelte +2 -2
- package/src/{ui → editor/ui}/UIPaddingSelector.svelte +6 -6
- package/src/{ui → editor/ui}/UIPaletteSelector.svelte +57 -30
- package/src/editor/ui/UIPillButton.svelte +168 -0
- package/src/{ui → editor/ui}/UIRadio.svelte +2 -2
- package/src/{ui → editor/ui}/UIRelinkConfirmPopover.svelte +4 -4
- package/src/editor/ui/UISegmentedControl.svelte +114 -0
- package/src/editor/ui/UISquareButton.svelte +172 -0
- package/src/{ui → editor/ui}/UITokenSelector.svelte +14 -11
- package/src/{ui → editor/ui}/UIVariantSelector.svelte +1 -1
- package/src/{ui → editor/ui}/VariablesTab.svelte +46 -17
- package/src/{ui → editor/ui}/palette/GradientStopEditor.svelte +13 -13
- package/src/{ui → editor/ui}/palette/OverridesPanel.svelte +24 -47
- package/src/{ui → editor/ui}/palette/PaletteBase.svelte +11 -8
- package/src/{ui → editor/ui}/palette/paletteEditorState.ts +1 -1
- package/src/editor/ui/palette/paletteMath.ts +275 -0
- package/src/{ui → editor/ui}/sections/ColumnsSection.svelte +137 -18
- package/src/{ui → editor/ui}/sections/GradientsSection.svelte +8 -8
- package/src/{ui → editor/ui}/sections/OverlaysSection.svelte +18 -18
- package/src/{ui → editor/ui}/sections/ShadowsSection.svelte +23 -23
- package/src/{ui → editor/ui}/sections/TokenScaleTable.svelte +3 -3
- package/src/{components → system/components}/Badge.svelte +0 -36
- package/src/{components → system/components}/Button.svelte +2 -2
- package/src/{components → system/components}/Card.svelte +34 -60
- package/src/{components → system/components}/CollapsibleSection.svelte +25 -2
- package/src/{components → system/components}/CornerBadge.svelte +8 -24
- package/src/{components → system/components}/Dialog.svelte +1 -1
- package/src/system/components/FloatingTokenTags.css +275 -0
- package/src/system/components/FloatingTokenTags.svelte +543 -0
- package/src/{components → system/components}/InlineEditActions.svelte +6 -4
- package/src/system/components/MenuSelect.svelte +229 -0
- package/src/{components → system/components}/Notification.svelte +8 -1
- package/src/{components → system/components}/ProgressBar.svelte +29 -11
- package/src/system/components/SectionDivider.svelte +560 -0
- package/src/{components → system/components}/SegmentedControl.svelte +49 -43
- package/src/{components → system/components}/TabBar.svelte +81 -65
- package/src/{components → system/components}/Table.svelte +17 -3
- package/src/{components → system/components}/Tooltip.svelte +6 -4
- package/src/system/styles/CONVENTIONS.md +178 -0
- package/src/system/styles/fonts.css +20 -0
- package/src/system/styles/tokens.css +601 -0
- package/src/system/styles/tokens.generated.css +544 -0
- package/src/component-editor/ImageEditor.svelte +0 -74
- package/src/component-editor/SectionDividerEditor.svelte +0 -265
- package/src/component-editor/scaffolding/DividerEditor.svelte +0 -94
- package/src/component-editor/scaffolding/GradientCard.svelte +0 -296
- package/src/component-editor/scaffolding/NonStylableConfig.svelte +0 -62
- package/src/component-editor/scaffolding/ShadowBackdrop.svelte +0 -37
- package/src/component-editor/scaffolding/ShadowBackdropControls.svelte +0 -61
- package/src/component-editor/scaffolding/StateBlock.svelte +0 -132
- package/src/component-editor/scaffolding/VariantGroup.svelte +0 -310
- package/src/components/SectionDivider.svelte +0 -483
- package/src/data/google-fonts.json +0 -75
- package/src/lib/index.ts +0 -68
- package/src/lib/presetService.ts +0 -214
- package/src/lib/productionPulse.ts +0 -32
- package/src/styles/fonts.css +0 -30
- package/src/styles/tokens.css +0 -1324
- package/src/ui/FontStackEditor.svelte +0 -361
- package/src/ui/GradientEditor.svelte +0 -470
- package/src/ui/PresetFileManager.svelte +0 -1116
- package/src/ui/ProjectFontsSection.svelte +0 -645
- package/src/ui/ThemeFileManager.svelte +0 -1020
- package/src/ui/UnsavedComponentsDialog.svelte +0 -315
- /package/src/{component-editor → editor/component-editor}/index.ts +0 -0
- /package/src/{component-editor → editor/component-editor}/scaffolding/DemoHeader.svelte +0 -0
- /package/src/{component-editor → editor/component-editor}/scaffolding/componentSectionType.ts +0 -0
- /package/src/{component-editor → editor/component-editor}/scaffolding/componentSources.ts +0 -0
- /package/src/{component-editor → editor/component-editor}/scaffolding/defaultSections.ts +0 -0
- /package/src/{component-editor → editor/component-editor}/scaffolding/siblings.ts +0 -0
- /package/src/{lib → editor/core}/cssVarSync.ts +0 -0
- /package/src/{lib → editor/core/palettes}/oklch.ts +0 -0
- /package/src/{lib → editor/core/routing}/navLinkTypes.ts +0 -0
- /package/src/{lib → editor/core/routing}/parentRouteStore.ts +0 -0
- /package/src/{lib → editor/core/storage}/storage.ts +0 -0
- /package/src/{lib → editor/core/store}/editorConfig.ts +0 -0
- /package/src/{lib → editor/core/store}/editorConfigStore.ts +0 -0
- /package/src/{lib → editor/core/store}/editorKeybindings.ts +0 -0
- /package/src/{lib → editor/core/store}/editorViewStore.ts +0 -0
- /package/src/{lib → editor/core/themes}/migrations/2026-04-24-component-prefix-and-suffix-renames.ts +0 -0
- /package/src/{lib → editor/core/themes}/migrations/2026-04-24-legacy-keys-and-bg-to-canvas.ts +0 -0
- /package/src/{lib → editor/core/themes}/migrations/2026-04-27-segmentedcontrol-disabled-flatten.ts +0 -0
- /package/src/{lib → editor/core/themes}/migrations/2026-05-08-collapsiblesection-frame-and-cleanup.ts +0 -0
- /package/src/{lib → editor/core/themes}/migrations/2026-05-08-collapsiblesection-variant-namespace.ts +0 -0
- /package/src/{lib → editor/core/themes}/migrations/2026-05-10-sectiondivider-gradient-stops.ts +0 -0
- /package/src/{lib → editor/core/themes}/migrations/2026-05-13-primary-to-brand.ts +0 -0
- /package/src/{lib → editor/core/themes}/parsers/globalRootBlock.ts +0 -0
- /package/src/{lib → editor/core/themes}/slices/domainVars.ts +0 -0
- /package/src/{lib → editor/overlay}/overlayState.ts +0 -0
- /package/src/{pages → editor/pages}/ComponentEditorPage.svelte.d.ts +0 -0
- /package/src/{pages → editor/pages}/Editor.svelte.d.ts +0 -0
- /package/src/{ui → editor/ui}/Toggle.svelte +0 -0
- /package/src/{ui → editor/ui}/UIDialog.svelte +0 -0
- /package/src/{ui → editor/ui}/UIFontWeightSelector.svelte +0 -0
- /package/src/{ui → editor/ui}/UIOptionItem.svelte +0 -0
- /package/src/{ui → editor/ui}/UIOptionList.svelte +0 -0
- /package/src/{ui → editor/ui}/UIRadioGroup.svelte +0 -0
- /package/src/{lib → editor/ui}/copyPopover.ts +0 -0
- /package/src/{ui → editor/ui}/curveEngine.ts +0 -0
- /package/src/{ui → editor/ui}/index.ts +0 -0
- /package/src/{ui → editor/ui}/keepInViewport.ts +0 -0
- /package/src/{ui → editor/ui}/palette/ScaleCurveEditor.svelte +0 -0
- /package/src/{lib → editor/ui}/scrollSection.ts +0 -0
- /package/src/{ui → editor/ui}/sections/tokenScales.ts +0 -0
- /package/src/{ui → editor/ui}/variantScales.ts +0 -0
- /package/src/{assets → system/assets}/newspaper.webp +0 -0
- /package/src/{assets → system/assets}/offering.webp +0 -0
- /package/src/{components → system/components}/Callout.svelte +0 -0
- /package/src/{components → system/components}/Image.svelte +0 -0
- /package/src/{components → system/components}/RadioButton.svelte +0 -0
- /package/src/{components → system/components}/types.ts +0 -0
- /package/src/{styles → system/styles}/_padding.scss +0 -0
- /package/src/{styles → system/styles}/fonts/Fraunces/Fraunces-italic-latin-ext.woff2 +0 -0
- /package/src/{styles → system/styles}/fonts/Fraunces/Fraunces-italic-latin.woff2 +0 -0
- /package/src/{styles → system/styles}/fonts/Fraunces/Fraunces-roman-latin-ext.woff2 +0 -0
- /package/src/{styles → system/styles}/fonts/Fraunces/Fraunces-roman-latin.woff2 +0 -0
- /package/src/{styles → system/styles}/fonts/Manrope/Manrope-latin-ext.woff2 +0 -0
- /package/src/{styles → system/styles}/fonts/Manrope/Manrope-latin.woff2 +0 -0
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { writable } from 'svelte/store';
|
|
2
|
+
import type { ProductionInfo } from './themes/themeService';
|
|
3
|
+
import type { ManifestMeta } from './themes/themeTypes';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Monotonic counter that ticks every time a production pointer flips —
|
|
7
|
+
* theme production or a component's production. UI surfaces that need to
|
|
8
|
+
* react to a sibling Adopt subscribe to this so they refresh without
|
|
9
|
+
* per-pair wiring.
|
|
10
|
+
*
|
|
11
|
+
* Bumpers: `ThemeFileManager.handleApplyToProduction`,
|
|
12
|
+
* `ComponentFileManager.handleUpdateProduction`. Anyone setting
|
|
13
|
+
* `_production.json` should bump.
|
|
14
|
+
*/
|
|
15
|
+
export const productionRevision = writable(0);
|
|
16
|
+
|
|
17
|
+
export function bumpProductionRevision(): void {
|
|
18
|
+
productionRevision.update((n) => n + 1);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Cached production-state stores. The Theme and Manifest file managers live in
|
|
23
|
+
* the sidebar footer, swapping in/out of the DOM as the user toggles between
|
|
24
|
+
* the tokens and components views. Keeping the last-known production state in
|
|
25
|
+
* module-level Svelte stores means a remount renders the correct Adopt-button
|
|
26
|
+
* state on the first frame instead of flashing through "not in sync" while a
|
|
27
|
+
* fresh fetch resolves.
|
|
28
|
+
*/
|
|
29
|
+
export const themeProductionInfo = writable<ProductionInfo | null>(null);
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Last-known active manifest meta. Bumped by ManifestFileManager whenever the
|
|
33
|
+
* active manifest changes (load, save, save-as) and whenever a theme or
|
|
34
|
+
* component Adopt completes (the server patches the active manifest as a
|
|
35
|
+
* side-effect, so consumers re-read it on `productionRevision` ticks).
|
|
36
|
+
*/
|
|
37
|
+
export const activeManifest = writable<ManifestMeta | null>(null);
|
|
@@ -118,7 +118,14 @@ export function versionedFileResource<TItem, TMeta, TProductionInfo>(
|
|
|
118
118
|
body: JSON.stringify({ name: fileName }),
|
|
119
119
|
});
|
|
120
120
|
if (!res.ok) {
|
|
121
|
-
|
|
121
|
+
const body = await res.json().catch(() => ({}));
|
|
122
|
+
const err = new Error(body.error || 'Set production failed') as Error & {
|
|
123
|
+
status?: number;
|
|
124
|
+
code?: string;
|
|
125
|
+
};
|
|
126
|
+
err.status = res.status;
|
|
127
|
+
if (body.code) err.code = body.code;
|
|
128
|
+
throw err;
|
|
122
129
|
}
|
|
123
130
|
return res.json();
|
|
124
131
|
}
|
|
@@ -260,21 +260,37 @@ export function mutate(label: string, fn: (draft: EditorState) => void): void {
|
|
|
260
260
|
if (import.meta.env.DEV && !label) {
|
|
261
261
|
console.warn('[editorStore] mutate() called without a label');
|
|
262
262
|
}
|
|
263
|
+
// Svelte 5's `$derived` uses strict `===` for equality (see
|
|
264
|
+
// node_modules/svelte/src/internal/client/reactivity/deriveds.js → equality.js).
|
|
265
|
+
// If we mutated `s` in place and emitted the same top-level reference, any
|
|
266
|
+
// intermediate `$derived($editorState.someSlice.someObj)` in a component
|
|
267
|
+
// would return the same object reference and short-circuit the whole
|
|
268
|
+
// downstream chain — swatches and previews would freeze even while the
|
|
269
|
+
// renderer's direct `editorState.subscribe(...)` (which uses `safe_not_equal`,
|
|
270
|
+
// always-different for objects) continued to write CSS vars to :root.
|
|
271
|
+
//
|
|
272
|
+
// Cloning the draft before mutation guarantees every nested reference is
|
|
273
|
+
// fresh, so `$derived` chains everywhere propagate correctly. The previous
|
|
274
|
+
// live state (`current`) becomes the immutable history snapshot — no second
|
|
275
|
+
// structuredClone needed.
|
|
263
276
|
if (transactionScope) {
|
|
264
|
-
// Inside a non-clipping scope: don't push individually; just mark the
|
|
265
|
-
// scope dirty and apply. The scope's commit pushes one collapsed entry.
|
|
266
277
|
transactionScope.changed = true;
|
|
267
278
|
if (clippingScope) clippingScope.changed = true;
|
|
268
|
-
store.update((s) => {
|
|
279
|
+
store.update((s) => {
|
|
280
|
+
const next = structuredClone(s);
|
|
281
|
+
fn(next);
|
|
282
|
+
return next;
|
|
283
|
+
});
|
|
269
284
|
return;
|
|
270
285
|
}
|
|
271
|
-
// No transaction scope: each mutate is its own history entry. Inside a
|
|
272
|
-
// clipping scope this still pushes per-mutate entries (so undo within the
|
|
273
|
-
// scope walks them back), and the scope's commit will collapse them.
|
|
274
286
|
if (clippingScope) clippingScope.changed = true;
|
|
275
287
|
const current = get(store);
|
|
276
|
-
pushPast(
|
|
277
|
-
store.update((s) => {
|
|
288
|
+
pushPast(current);
|
|
289
|
+
store.update((s) => {
|
|
290
|
+
const next = structuredClone(s);
|
|
291
|
+
fn(next);
|
|
292
|
+
return next;
|
|
293
|
+
});
|
|
278
294
|
bumpTick();
|
|
279
295
|
persistHook();
|
|
280
296
|
}
|
|
@@ -17,9 +17,9 @@ import { get } from 'svelte/store';
|
|
|
17
17
|
import type { EditorState } from './editorTypes';
|
|
18
18
|
import { storageKey } from './editorConfig';
|
|
19
19
|
import { store } from './editorCore';
|
|
20
|
-
import { quietGet, quietSet } from '
|
|
21
|
-
import { makeDefaultGradients } from '
|
|
22
|
-
import { seedShadowsFromDom } from '
|
|
20
|
+
import { quietGet, quietSet } from '../storage/storage';
|
|
21
|
+
import { makeDefaultGradients } from '../themes/slices/gradients';
|
|
22
|
+
import { seedShadowsFromDom } from '../themes/slices/shadows';
|
|
23
23
|
|
|
24
24
|
// Resolve the persist key lazily (per-call) so library consumers that invoke
|
|
25
25
|
// `configureEditor({storagePrefix})` before the first store write get the
|
|
@@ -12,8 +12,8 @@
|
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
14
|
import type { EditorState } from './editorTypes';
|
|
15
|
-
import { setCssVar, removeCssVar } from '
|
|
16
|
-
import { palettesToVars } from '
|
|
15
|
+
import { setCssVar, removeCssVar } from '../cssVarSync';
|
|
16
|
+
import { palettesToVars } from '../palettes/paletteDerivation';
|
|
17
17
|
import {
|
|
18
18
|
editorState,
|
|
19
19
|
columnsToVars,
|
|
@@ -18,15 +18,15 @@
|
|
|
18
18
|
* orchestrate across slices and stay here.
|
|
19
19
|
*/
|
|
20
20
|
|
|
21
|
-
import type { CssVarRef, EditorState } from './editorTypes';
|
|
22
|
-
import type { Theme } from '
|
|
23
|
-
import { KNOWN_COMPONENT_CONFIG_KEYS } from '
|
|
21
|
+
import type { CssVarRef, EditorState, GradientAliasValue } from './editorTypes';
|
|
22
|
+
import type { AliasDiskValue, Theme } from '../themes/themeTypes';
|
|
23
|
+
import { KNOWN_COMPONENT_CONFIG_KEYS } from '../components/componentConfigKeys';
|
|
24
24
|
import {
|
|
25
25
|
CURRENT_THEME_SCHEMA_VERSION,
|
|
26
26
|
CURRENT_COMPONENT_SCHEMA_VERSION,
|
|
27
27
|
runMigrations,
|
|
28
|
-
} from '
|
|
29
|
-
import { renamePrimaryPaletteKey } from '
|
|
28
|
+
} from '../themes/migrations';
|
|
29
|
+
import { renamePrimaryPaletteKey } from '../themes/migrations/2026-05-13-primary-to-brand';
|
|
30
30
|
import { __resetRendererCacheForTests, installRenderer } from './editorRenderer';
|
|
31
31
|
import {
|
|
32
32
|
store,
|
|
@@ -47,25 +47,25 @@ import {
|
|
|
47
47
|
columnsEqualsDefault,
|
|
48
48
|
columnsToVars,
|
|
49
49
|
loadColumnsFromVars,
|
|
50
|
-
} from '
|
|
50
|
+
} from '../themes/slices/columns';
|
|
51
51
|
import {
|
|
52
52
|
loadOverlaysFromVars,
|
|
53
53
|
makeDefaultOverlaysState,
|
|
54
54
|
overlaysEqualsDefault,
|
|
55
55
|
overlaysToVars,
|
|
56
|
-
} from '
|
|
56
|
+
} from '../themes/slices/overlays';
|
|
57
57
|
import {
|
|
58
58
|
loadShadowsFromVars,
|
|
59
59
|
shadowsToVars,
|
|
60
|
-
} from '
|
|
61
|
-
import { makeDefaultGradients } from '
|
|
60
|
+
} from '../themes/slices/shadows';
|
|
61
|
+
import { makeDefaultGradients } from '../themes/slices/gradients';
|
|
62
62
|
import {
|
|
63
63
|
componentBaseline,
|
|
64
64
|
loadComponentsFromVars,
|
|
65
65
|
notifyComponentSavedChanged,
|
|
66
66
|
setSavedComponentBaseline,
|
|
67
67
|
__resetComponentsForTests,
|
|
68
|
-
} from '
|
|
68
|
+
} from '../themes/slices/components';
|
|
69
69
|
|
|
70
70
|
function emptyState(): EditorState {
|
|
71
71
|
return {
|
|
@@ -121,7 +121,7 @@ store.set(emptyState());
|
|
|
121
121
|
|
|
122
122
|
export {
|
|
123
123
|
DOMAIN_VAR_NAMES,
|
|
124
|
-
} from '
|
|
124
|
+
} from '../themes/slices/domainVars';
|
|
125
125
|
|
|
126
126
|
export {
|
|
127
127
|
columnsToVars,
|
|
@@ -129,7 +129,7 @@ export {
|
|
|
129
129
|
COLUMN_VAR_NAMES,
|
|
130
130
|
DEFAULT_COLUMNS,
|
|
131
131
|
parseColumnVars,
|
|
132
|
-
} from '
|
|
132
|
+
} from '../themes/slices/columns';
|
|
133
133
|
|
|
134
134
|
export {
|
|
135
135
|
overlaysToVars,
|
|
@@ -141,7 +141,7 @@ export {
|
|
|
141
141
|
parseRgba,
|
|
142
142
|
RGBA_RE,
|
|
143
143
|
HEX_RE,
|
|
144
|
-
} from '
|
|
144
|
+
} from '../themes/slices/overlays';
|
|
145
145
|
|
|
146
146
|
export {
|
|
147
147
|
shadowsToVars,
|
|
@@ -153,7 +153,7 @@ export {
|
|
|
153
153
|
defaultShadowOverride,
|
|
154
154
|
parseShadowCss,
|
|
155
155
|
seedShadowsFromDom,
|
|
156
|
-
} from '
|
|
156
|
+
} from '../themes/slices/shadows';
|
|
157
157
|
|
|
158
158
|
export {
|
|
159
159
|
gradientsToVars,
|
|
@@ -166,7 +166,7 @@ export {
|
|
|
166
166
|
removeGradientStop,
|
|
167
167
|
addGradientToken,
|
|
168
168
|
removeGradientToken,
|
|
169
|
-
} from '
|
|
169
|
+
} from '../themes/slices/gradients';
|
|
170
170
|
|
|
171
171
|
export {
|
|
172
172
|
componentsToVars,
|
|
@@ -184,18 +184,18 @@ export {
|
|
|
184
184
|
unlinkComponentProperty,
|
|
185
185
|
relinkComponentProperty,
|
|
186
186
|
markComponentSaved,
|
|
187
|
-
} from '
|
|
187
|
+
} from '../themes/slices/components';
|
|
188
188
|
|
|
189
189
|
export {
|
|
190
190
|
setFontSources,
|
|
191
191
|
setFontStacks,
|
|
192
192
|
seedFontsFromTheme,
|
|
193
|
-
} from '
|
|
193
|
+
} from '../themes/slices/fonts';
|
|
194
194
|
|
|
195
195
|
export {
|
|
196
196
|
setPaletteConfig,
|
|
197
197
|
seedPalettesFromTheme,
|
|
198
|
-
} from '
|
|
198
|
+
} from '../themes/slices/palettes';
|
|
199
199
|
|
|
200
200
|
// ── Component-config load orchestration ───────────────────────────────────
|
|
201
201
|
//
|
|
@@ -205,12 +205,200 @@ export {
|
|
|
205
205
|
// literal-valued knobs (per `KNOWN_COMPONENT_CONFIG_KEYS`) into the config
|
|
206
206
|
// bucket and wraps the remainder as `CssVarRef` discriminated unions.
|
|
207
207
|
|
|
208
|
+
/**
|
|
209
|
+
* Migrate a disk-shape alias bag through the registered migration runner.
|
|
210
|
+
*
|
|
211
|
+
* The runner is string-typed by contract (most migrations only do
|
|
212
|
+
* key/value string rewrites). Object-valued entries — currently just
|
|
213
|
+
* inline `{ kind: 'gradient', value: ... }` payloads — pass through
|
|
214
|
+
* untouched: we split the bag into string/object subsets, run the runner
|
|
215
|
+
* on the string subset, then merge.
|
|
216
|
+
*
|
|
217
|
+
* For sectiondivider's legacy 7-flat-token gradients we run a synthesis
|
|
218
|
+
* step BEFORE the migration runner that would strip those tokens. The
|
|
219
|
+
* synthesized gradient object lands in the object subset and survives
|
|
220
|
+
* the stripping pass.
|
|
221
|
+
*/
|
|
208
222
|
function migrateComponentAliases(
|
|
209
223
|
component: string,
|
|
210
|
-
|
|
224
|
+
aliasesIn: Record<string, AliasDiskValue>,
|
|
225
|
+
rawConfig: Record<string, unknown> | undefined,
|
|
211
226
|
fileVersion: number,
|
|
212
|
-
): Record<string, string> {
|
|
213
|
-
|
|
227
|
+
): { aliases: Record<string, AliasDiskValue>; config: Record<string, unknown> } {
|
|
228
|
+
const stringPart: Record<string, string> = {};
|
|
229
|
+
const objectPart: Record<string, AliasDiskValue> = {};
|
|
230
|
+
for (const [k, v] of Object.entries(aliasesIn)) {
|
|
231
|
+
if (typeof v === 'string') stringPart[k] = v;
|
|
232
|
+
else objectPart[k] = v;
|
|
233
|
+
}
|
|
234
|
+
// String-valued config entries join the migration input so a migration can
|
|
235
|
+
// rename or relocate them. After migration the bag flows through
|
|
236
|
+
// `splitAliasesAndConfig` which routes KNOWN keys back to config and the
|
|
237
|
+
// rest to aliases — this is what lets a migration *move* a key from the
|
|
238
|
+
// config bucket to the aliases bucket by also removing it from KNOWN.
|
|
239
|
+
// Config wins over an aliases-bucket collision on the same key: the legacy
|
|
240
|
+
// single-bucket → split-bucket move preserved "explicit config field beats
|
|
241
|
+
// legacy alias-bucketed value", and that contract still holds.
|
|
242
|
+
// Non-string config values (rare; reserved for future structured payloads)
|
|
243
|
+
// pass through untouched.
|
|
244
|
+
const configOut: Record<string, unknown> = {};
|
|
245
|
+
for (const [k, v] of Object.entries(rawConfig ?? {})) {
|
|
246
|
+
if (typeof v === 'string') stringPart[k] = v;
|
|
247
|
+
else configOut[k] = v;
|
|
248
|
+
}
|
|
249
|
+
if (component === 'sectiondivider') {
|
|
250
|
+
synthesizeSectionDividerGradients(stringPart, objectPart);
|
|
251
|
+
}
|
|
252
|
+
const migratedString = runMigrations('component-config', fileVersion, stringPart, { component });
|
|
253
|
+
const migratedObject = component === 'sectiondivider'
|
|
254
|
+
? renameSectionDividerObjectSlots(objectPart)
|
|
255
|
+
: objectPart;
|
|
256
|
+
return {
|
|
257
|
+
aliases: { ...migratedString, ...migratedObject },
|
|
258
|
+
config: configOut,
|
|
259
|
+
};
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
/**
|
|
263
|
+
* v8→v9 companion to `componentMigration_2026_05_20_sectiondividerSlimVariants`:
|
|
264
|
+
* the structured background payload is reshaped from six color families →
|
|
265
|
+
* three size variants (lg/md/sm). Canvas's gradient is taken as the canonical
|
|
266
|
+
* seed and fanned across all three new variants; other families' gradients
|
|
267
|
+
* are dropped. Idempotent — keys already at the final shape pass through.
|
|
268
|
+
*
|
|
269
|
+
* Sources accepted (in priority order, first-found wins for canvas's slot):
|
|
270
|
+
* --sectiondivider-canvas-background (current/in-progress shape)
|
|
271
|
+
* --sectiondivider-canvas-gradient (v7-era shape)
|
|
272
|
+
* --sectiondivider-color-canvas-background (intermediate shape that landed
|
|
273
|
+
* briefly during the color-prop pivot)
|
|
274
|
+
*
|
|
275
|
+
* The migration runner only sees string keys, so this object-shape rename
|
|
276
|
+
* has to live alongside the runner call.
|
|
277
|
+
*/
|
|
278
|
+
const FAMILIES = ['canvas', 'neutral', 'alternate', 'primary', 'accent', 'special'] as const;
|
|
279
|
+
const SIZE_VARIANTS = ['lg', 'md', 'sm'] as const;
|
|
280
|
+
function renameSectionDividerObjectSlots(
|
|
281
|
+
objectPart: Record<string, AliasDiskValue>,
|
|
282
|
+
): Record<string, AliasDiskValue> {
|
|
283
|
+
// Find canvas's gradient under any historical key shape.
|
|
284
|
+
const canvasSourceKeys = [
|
|
285
|
+
'--sectiondivider-canvas-background',
|
|
286
|
+
'--sectiondivider-canvas-gradient',
|
|
287
|
+
'--sectiondivider-color-canvas-background',
|
|
288
|
+
];
|
|
289
|
+
let canvasGradient: AliasDiskValue | undefined;
|
|
290
|
+
for (const key of canvasSourceKeys) {
|
|
291
|
+
if (objectPart[key] !== undefined) {
|
|
292
|
+
canvasGradient = objectPart[key];
|
|
293
|
+
break;
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
// If we found a canvas gradient (any era), fan it into the three new
|
|
298
|
+
// per-variant background slots and drop every other family's gradient.
|
|
299
|
+
// If no canvas gradient is found, pass through non-family keys verbatim
|
|
300
|
+
// so non-migration data (theme tokens, other components) isn't touched.
|
|
301
|
+
const out: Record<string, AliasDiskValue> = {};
|
|
302
|
+
for (const [key, value] of Object.entries(objectPart)) {
|
|
303
|
+
// Skip any sectiondivider per-family gradient; the canvas fan-out emits
|
|
304
|
+
// the canonical set below.
|
|
305
|
+
let isFamilyGradient = false;
|
|
306
|
+
for (const f of FAMILIES) {
|
|
307
|
+
if (
|
|
308
|
+
key === `--sectiondivider-${f}-background`
|
|
309
|
+
|| key === `--sectiondivider-${f}-gradient`
|
|
310
|
+
|| key === `--sectiondivider-color-${f}-background`
|
|
311
|
+
) {
|
|
312
|
+
isFamilyGradient = true;
|
|
313
|
+
break;
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
// Pass through anything that's already at the final lg/md/sm shape so
|
|
317
|
+
// re-running the migration is idempotent.
|
|
318
|
+
if (isFamilyGradient) continue;
|
|
319
|
+
out[key] = value;
|
|
320
|
+
}
|
|
321
|
+
if (canvasGradient !== undefined) {
|
|
322
|
+
for (const v of SIZE_VARIANTS) {
|
|
323
|
+
out[`--sectiondivider-${v}-background`] = canvasGradient;
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
return out;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
/** SectionDivider variants that ship gradient aliases. */
|
|
330
|
+
const SECTIONDIVIDER_VARIANTS = ['canvas', 'neutral', 'alternate', 'primary', 'accent', 'special'] as const;
|
|
331
|
+
|
|
332
|
+
/**
|
|
333
|
+
* Collapse legacy 7-flat-token gradients (`{angle, stop-{1,2,3}-{color,position}}`)
|
|
334
|
+
* for each sectiondivider variant into one structured gradient alias at
|
|
335
|
+
* `--sectiondivider-{v}-gradient`. The flat tokens stay in `stringPart`
|
|
336
|
+
* for the migration runner to strip; the structured payload joins
|
|
337
|
+
* `objectPart` so the merge produces the new shape.
|
|
338
|
+
*
|
|
339
|
+
* Skips variants that already declare a gradient alias (object form) so
|
|
340
|
+
* round-tripping doesn't overwrite user edits.
|
|
341
|
+
*/
|
|
342
|
+
function synthesizeSectionDividerGradients(
|
|
343
|
+
stringPart: Record<string, string>,
|
|
344
|
+
objectPart: Record<string, AliasDiskValue>,
|
|
345
|
+
): void {
|
|
346
|
+
const GRADIENT_ANGLE_TOKENS: Record<string, number> = {
|
|
347
|
+
'--gradient-angle-horizontal': 90,
|
|
348
|
+
'--gradient-angle-vertical': 180,
|
|
349
|
+
'--gradient-angle-diagonal': 135,
|
|
350
|
+
'--gradient-angle-counter-diagonal': 45,
|
|
351
|
+
};
|
|
352
|
+
const GRADIENT_STOP_POSITIONS: Record<string, number> = {
|
|
353
|
+
'--gradient-stop-start': 0,
|
|
354
|
+
'--gradient-stop-mid': 50,
|
|
355
|
+
'--gradient-stop-end': 100,
|
|
356
|
+
};
|
|
357
|
+
const parseAngle = (raw: string | undefined): number => {
|
|
358
|
+
if (!raw) return 135;
|
|
359
|
+
if (raw.startsWith('--')) return GRADIENT_ANGLE_TOKENS[raw] ?? 135;
|
|
360
|
+
const m = raw.match(/^(-?\d+(?:\.\d+)?)\s*deg$/i);
|
|
361
|
+
return m ? parseFloat(m[1]) : 135;
|
|
362
|
+
};
|
|
363
|
+
const parsePosition = (raw: string | undefined, fallback: number): number => {
|
|
364
|
+
if (!raw) return fallback;
|
|
365
|
+
if (raw.startsWith('--')) return GRADIENT_STOP_POSITIONS[raw] ?? fallback;
|
|
366
|
+
const m = raw.match(/^(-?\d+(?:\.\d+)?)\s*%$/);
|
|
367
|
+
return m ? parseFloat(m[1]) : fallback;
|
|
368
|
+
};
|
|
369
|
+
const parseStopColor = (raw: string | undefined): { color: string; opacity?: number } | null => {
|
|
370
|
+
if (!raw) return null;
|
|
371
|
+
if (raw.startsWith('--')) return { color: raw };
|
|
372
|
+
const mix = raw.match(/^color-mix\(\s*in\s+srgb\s*,\s*var\((--[a-z0-9-]+)\)\s+([\d.]+)%\s*,\s*transparent\s*\)$/i);
|
|
373
|
+
if (mix) return { color: mix[1], opacity: parseFloat(mix[2]) };
|
|
374
|
+
return null;
|
|
375
|
+
};
|
|
376
|
+
for (const v of SECTIONDIVIDER_VARIANTS) {
|
|
377
|
+
const slot = `--sectiondivider-${v}-gradient`;
|
|
378
|
+
if (slot in objectPart) continue;
|
|
379
|
+
const angleKey = `${slot}-angle`;
|
|
380
|
+
const has1 = stringPart[`${slot}-stop-1-color`] !== undefined;
|
|
381
|
+
const has2 = stringPart[`${slot}-stop-2-color`] !== undefined;
|
|
382
|
+
const has3 = stringPart[`${slot}-stop-3-color`] !== undefined;
|
|
383
|
+
if (!has1 && !has2 && !has3) continue;
|
|
384
|
+
const stops: { position: number; color: string; opacity?: number }[] = [];
|
|
385
|
+
const positionDefaults = [0, 50, 100];
|
|
386
|
+
for (let i = 1; i <= 3; i++) {
|
|
387
|
+
const c = parseStopColor(stringPart[`${slot}-stop-${i}-color`]);
|
|
388
|
+
if (!c) continue;
|
|
389
|
+
const pos = parsePosition(stringPart[`${slot}-stop-${i}-position`], positionDefaults[i - 1]);
|
|
390
|
+
stops.push({ position: pos, color: c.color, ...(c.opacity !== undefined ? { opacity: c.opacity } : {}) });
|
|
391
|
+
}
|
|
392
|
+
if (stops.length < 2) continue;
|
|
393
|
+
objectPart[slot] = {
|
|
394
|
+
kind: 'gradient',
|
|
395
|
+
value: {
|
|
396
|
+
type: 'linear',
|
|
397
|
+
angle: parseAngle(stringPart[angleKey]),
|
|
398
|
+
stops,
|
|
399
|
+
},
|
|
400
|
+
};
|
|
401
|
+
}
|
|
214
402
|
}
|
|
215
403
|
|
|
216
404
|
/**
|
|
@@ -219,12 +407,18 @@ function migrateComponentAliases(
|
|
|
219
407
|
* config bucket, and wraps the remainder as `CssVarRef` discriminated unions.
|
|
220
408
|
*/
|
|
221
409
|
function splitAliasesAndConfig(
|
|
222
|
-
rawAliases: Record<string,
|
|
410
|
+
rawAliases: Record<string, AliasDiskValue>,
|
|
223
411
|
rawConfig: Record<string, unknown> | undefined,
|
|
224
412
|
): { aliases: Record<string, CssVarRef>; config: Record<string, unknown> } {
|
|
225
413
|
const aliases: Record<string, CssVarRef> = {};
|
|
226
414
|
const config: Record<string, unknown> = { ...(rawConfig ?? {}) };
|
|
227
415
|
for (const [key, value] of Object.entries(rawAliases)) {
|
|
416
|
+
if (typeof value !== 'string') {
|
|
417
|
+
if (value.kind === 'gradient') {
|
|
418
|
+
aliases[key] = { kind: 'gradient', value: value.value as GradientAliasValue };
|
|
419
|
+
}
|
|
420
|
+
continue;
|
|
421
|
+
}
|
|
228
422
|
if (KNOWN_COMPONENT_CONFIG_KEYS.has(key)) {
|
|
229
423
|
if (config[key] === undefined) config[key] = value;
|
|
230
424
|
continue;
|
|
@@ -249,12 +443,12 @@ function splitAliasesAndConfig(
|
|
|
249
443
|
export function loadComponentActive(
|
|
250
444
|
component: string,
|
|
251
445
|
activeFile: string,
|
|
252
|
-
aliases: Record<string,
|
|
446
|
+
aliases: Record<string, AliasDiskValue>,
|
|
253
447
|
config?: Record<string, unknown>,
|
|
254
448
|
schemaVersion: number = 0,
|
|
255
449
|
): void {
|
|
256
|
-
const migrated = migrateComponentAliases(component, aliases, schemaVersion);
|
|
257
|
-
const split = splitAliasesAndConfig(migrated, config);
|
|
450
|
+
const migrated = migrateComponentAliases(component, aliases, config, schemaVersion);
|
|
451
|
+
const split = splitAliasesAndConfig(migrated.aliases, migrated.config);
|
|
258
452
|
mutate(`load ${component}/${activeFile}`, (s) => {
|
|
259
453
|
s.components[component] = { activeFile, aliases: { ...split.aliases }, config: { ...split.config } };
|
|
260
454
|
});
|
|
@@ -264,7 +458,7 @@ export function loadComponentActive(
|
|
|
264
458
|
|
|
265
459
|
export interface ComponentSeed {
|
|
266
460
|
activeFile: string;
|
|
267
|
-
aliases: Record<string,
|
|
461
|
+
aliases: Record<string, AliasDiskValue>;
|
|
268
462
|
config?: Record<string, unknown>;
|
|
269
463
|
schemaVersion?: number;
|
|
270
464
|
}
|
|
@@ -282,8 +476,8 @@ export function seedComponentsFromApi(
|
|
|
282
476
|
store.update((s) => {
|
|
283
477
|
s.components = {};
|
|
284
478
|
for (const [comp, cfg] of Object.entries(configs)) {
|
|
285
|
-
const migrated = migrateComponentAliases(comp, cfg.aliases, cfg.schemaVersion ?? 0);
|
|
286
|
-
const split = splitAliasesAndConfig(migrated,
|
|
479
|
+
const migrated = migrateComponentAliases(comp, cfg.aliases, cfg.config, cfg.schemaVersion ?? 0);
|
|
480
|
+
const split = splitAliasesAndConfig(migrated.aliases, migrated.config);
|
|
287
481
|
s.components[comp] = { activeFile: cfg.activeFile, aliases: { ...split.aliases }, config: { ...split.config } };
|
|
288
482
|
setSavedComponentBaseline(comp, componentBaseline(split));
|
|
289
483
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { PaletteConfig, FontSource, FontStack } from '
|
|
1
|
+
import type { PaletteConfig, FontSource, FontStack } from '../themes/themeTypes';
|
|
2
2
|
|
|
3
3
|
export interface ShadowGlobals {
|
|
4
4
|
angle: number;
|
|
@@ -43,24 +43,25 @@ export interface ColumnsState {
|
|
|
43
43
|
margin: number;
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
config: Record<string, unknown>;
|
|
54
|
-
unlinked?: string[];
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
export type GradientType = 'linear' | 'radial';
|
|
46
|
+
/** Gradient render mode.
|
|
47
|
+
* - `linear` / `radial`: real gradients with N stops + angle (linear) or radius (radial).
|
|
48
|
+
* - `solid`: collapses to the first stop's color. Angle/radius/extra stops carried in
|
|
49
|
+
* the payload but ignored by the renderer; toggling back restores the prior shape.
|
|
50
|
+
* - `none`: transparent. Same carry-forward semantics — payload retained for
|
|
51
|
+
* round-trip when the user toggles back to a real gradient. */
|
|
52
|
+
export type GradientType = 'linear' | 'radial' | 'solid' | 'none';
|
|
58
53
|
|
|
59
54
|
export interface GradientTokenStop {
|
|
60
55
|
/** 0–100 percentage along the gradient axis. */
|
|
61
56
|
position: number;
|
|
62
57
|
/** CSS variable name the stop resolves through (e.g. '--color-brand-500'). */
|
|
63
58
|
color: string;
|
|
59
|
+
/** When `false`, this stop is an explicit off-palette override: the stop
|
|
60
|
+
* picker opens to any color (not family-filtered), and the stop is skipped
|
|
61
|
+
* by family-swap rewrites so its color survives a variant family change.
|
|
62
|
+
* Defaults to true (follow family) on read; absence is the same as `true`.
|
|
63
|
+
* Only meaningful for gradients rendered inside a family-aware context. */
|
|
64
|
+
monochrome?: boolean;
|
|
64
65
|
/** 0–100 alpha applied to the stop's color. Defaults to 100 (fully opaque). */
|
|
65
66
|
opacity?: number;
|
|
66
67
|
}
|
|
@@ -71,9 +72,51 @@ export interface GradientToken {
|
|
|
71
72
|
type: GradientType;
|
|
72
73
|
/** Degrees, applies to linear only. */
|
|
73
74
|
angle: number;
|
|
75
|
+
/** Pixel radius for radial gradients. When absent or zero, the renderer
|
|
76
|
+
* emits CSS's default ellipse/farthest-corner shape. */
|
|
77
|
+
radius?: number;
|
|
78
|
+
/** Horizontal center position for radial gradients, 0–100. Defaults to 50. */
|
|
79
|
+
centerX?: number;
|
|
80
|
+
/** Horizontal stretch factor for the radial ellipse (1–8). Defaults to 1.
|
|
81
|
+
* With aspectY, the rendered semi-axes are `radius * aspect*`, so both
|
|
82
|
+
* shape (ratio) and size are encoded together. Both = 1 keeps the legacy
|
|
83
|
+
* `circle` render path verbatim. */
|
|
84
|
+
aspectX?: number;
|
|
85
|
+
/** Vertical stretch factor for the radial ellipse (1–8). Defaults to 1. */
|
|
86
|
+
aspectY?: number;
|
|
74
87
|
stops: GradientTokenStop[];
|
|
75
88
|
}
|
|
76
89
|
|
|
90
|
+
/** Structured gradient payload carried inline on a component alias.
|
|
91
|
+
* Mirrors GradientToken minus `variable` (the alias key itself is the
|
|
92
|
+
* binding). Used when a component owns a per-instance gradient that
|
|
93
|
+
* doesn't share the theme-level `--gradient-N` library. */
|
|
94
|
+
export interface GradientAliasValue {
|
|
95
|
+
type: GradientType;
|
|
96
|
+
angle: number;
|
|
97
|
+
/** See GradientToken.radius. */
|
|
98
|
+
radius?: number;
|
|
99
|
+
/** See GradientToken.centerX. */
|
|
100
|
+
centerX?: number;
|
|
101
|
+
/** See GradientToken.aspectX. */
|
|
102
|
+
aspectX?: number;
|
|
103
|
+
/** See GradientToken.aspectY. */
|
|
104
|
+
aspectY?: number;
|
|
105
|
+
stops: GradientTokenStop[];
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export type CssVarRef =
|
|
109
|
+
| { kind: 'token'; name: string }
|
|
110
|
+
| { kind: 'literal'; value: string }
|
|
111
|
+
| { kind: 'gradient'; value: GradientAliasValue };
|
|
112
|
+
|
|
113
|
+
export interface ComponentSlice {
|
|
114
|
+
activeFile: string;
|
|
115
|
+
aliases: Record<string, CssVarRef>;
|
|
116
|
+
config: Record<string, unknown>;
|
|
117
|
+
unlinked?: string[];
|
|
118
|
+
}
|
|
119
|
+
|
|
77
120
|
/**
|
|
78
121
|
* Single source of truth for everything a saved token file depends on, plus
|
|
79
122
|
* the domain state currently scattered across VariablesTab local `let` fields.
|