@motion-proto/live-tokens 0.1.1 → 0.3.1

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.
Files changed (224) hide show
  1. package/README.md +160 -21
  2. package/dist-plugin/index.cjs +823 -336
  3. package/dist-plugin/index.d.cts +9 -7
  4. package/dist-plugin/index.d.ts +9 -7
  5. package/dist-plugin/index.js +822 -335
  6. package/package.json +46 -20
  7. package/src/assets/newspaper.webp +0 -0
  8. package/src/assets/offering.webp +0 -0
  9. package/src/component-editor/BadgeEditor.svelte +170 -0
  10. package/src/component-editor/CalloutEditor.svelte +103 -0
  11. package/src/component-editor/CardEditor.svelte +184 -0
  12. package/src/component-editor/CollapsibleSectionEditor.svelte +167 -0
  13. package/src/component-editor/CornerBadgeEditor.svelte +207 -0
  14. package/src/component-editor/DialogEditor.svelte +172 -0
  15. package/src/component-editor/ImageEditor.svelte +72 -0
  16. package/src/component-editor/InlineEditActionsEditor.svelte +83 -0
  17. package/src/component-editor/NotificationEditor.svelte +160 -0
  18. package/src/component-editor/ProgressBarEditor.svelte +124 -0
  19. package/src/component-editor/RadioButtonEditor.svelte +140 -0
  20. package/src/component-editor/SectionDividerEditor.svelte +263 -0
  21. package/src/component-editor/SegmentedControlEditor.svelte +154 -0
  22. package/src/component-editor/StandardButtonsEditor.svelte +178 -0
  23. package/src/component-editor/TabBarEditor.svelte +137 -0
  24. package/src/component-editor/TableEditor.svelte +128 -0
  25. package/src/component-editor/TooltipEditor.svelte +122 -0
  26. package/src/component-editor/editorTokens.test.ts +93 -0
  27. package/src/component-editor/groupKeySlots.test.ts +67 -0
  28. package/src/component-editor/groupKeySnapshot.test.ts +52 -0
  29. package/src/component-editor/index.ts +5 -0
  30. package/src/component-editor/registry.ts +246 -0
  31. package/src/component-editor/scaffolding/AngleDial.svelte +185 -0
  32. package/src/component-editor/scaffolding/ComponentEditorBase.svelte +96 -0
  33. package/src/component-editor/scaffolding/ComponentFileManager.svelte +682 -0
  34. package/src/component-editor/scaffolding/ComponentFileMenu.svelte +312 -0
  35. package/src/component-editor/scaffolding/ComponentsTab.svelte +69 -0
  36. package/src/component-editor/scaffolding/CopyFromMenu.svelte +246 -0
  37. package/src/component-editor/scaffolding/DemoHeader.svelte +21 -0
  38. package/src/component-editor/scaffolding/DividerEditor.svelte +81 -0
  39. package/src/component-editor/scaffolding/FieldsetWrapper.svelte +46 -0
  40. package/src/component-editor/scaffolding/GradientCard.svelte +291 -0
  41. package/src/component-editor/scaffolding/LinkageChart.svelte +297 -0
  42. package/src/component-editor/scaffolding/LinkedBlock.svelte +418 -0
  43. package/src/component-editor/scaffolding/NonStylableConfig.svelte +57 -0
  44. package/src/component-editor/scaffolding/SaveAsDialog.svelte +177 -0
  45. package/src/component-editor/scaffolding/ShadowBackdrop.svelte +25 -0
  46. package/src/component-editor/scaffolding/ShadowBackdropControls.svelte +56 -0
  47. package/src/component-editor/scaffolding/StateBlock.svelte +115 -0
  48. package/src/component-editor/scaffolding/TokenLayout.svelte +511 -0
  49. package/src/component-editor/scaffolding/TypeEditor.svelte +82 -0
  50. package/src/component-editor/scaffolding/VariantGroup.svelte +277 -0
  51. package/src/component-editor/scaffolding/buildTypeGroupTokens.ts +97 -0
  52. package/src/component-editor/scaffolding/componentSectionType.ts +8 -0
  53. package/src/component-editor/scaffolding/componentSources.ts +9 -0
  54. package/src/component-editor/scaffolding/defaultSections.ts +16 -0
  55. package/src/component-editor/scaffolding/editorContext.ts +44 -0
  56. package/src/component-editor/scaffolding/linkedBlock.ts +226 -0
  57. package/src/component-editor/scaffolding/siblings.ts +33 -0
  58. package/src/component-editor/scaffolding/types.ts +39 -0
  59. package/src/components/Badge.svelte +231 -42
  60. package/src/components/Button.svelte +324 -124
  61. package/src/components/Callout.svelte +145 -0
  62. package/src/components/Card.svelte +123 -25
  63. package/src/components/CollapsibleSection.svelte +213 -35
  64. package/src/components/CornerBadge.svelte +224 -0
  65. package/src/components/Dialog.svelte +137 -114
  66. package/src/components/Image.svelte +43 -0
  67. package/src/components/InlineEditActions.svelte +74 -14
  68. package/src/components/Notification.svelte +184 -163
  69. package/src/components/ProgressBar.svelte +216 -22
  70. package/src/components/RadioButton.svelte +110 -40
  71. package/src/components/SectionDivider.svelte +428 -74
  72. package/src/components/SegmentedControl.svelte +203 -0
  73. package/src/components/TabBar.svelte +146 -21
  74. package/src/components/Table.svelte +102 -0
  75. package/src/components/Tooltip.svelte +45 -19
  76. package/src/components/types.ts +51 -0
  77. package/src/data/google-fonts.json +75 -0
  78. package/src/lib/ColumnsOverlay.svelte +20 -7
  79. package/src/lib/LiveEditorOverlay.svelte +257 -78
  80. package/src/lib/columnsOverlay.ts +21 -17
  81. package/src/lib/componentConfig.test.ts +204 -0
  82. package/src/lib/componentConfigKeys.ts +19 -0
  83. package/src/lib/componentConfigService.ts +88 -0
  84. package/src/lib/copyPopover.ts +30 -0
  85. package/src/lib/cssVarSync.ts +59 -7
  86. package/src/lib/editorConfigStore.ts +0 -10
  87. package/src/lib/editorCore.ts +402 -0
  88. package/src/lib/editorKeybindings.ts +52 -0
  89. package/src/lib/editorPersistence.ts +106 -0
  90. package/src/lib/editorRenderer.ts +74 -0
  91. package/src/lib/editorStore.test.ts +328 -0
  92. package/src/lib/editorStore.ts +412 -0
  93. package/src/lib/editorTypes.ts +100 -0
  94. package/src/lib/editorViewStore.ts +55 -0
  95. package/src/lib/files/versionedFileResource.ts +140 -0
  96. package/src/lib/fontLoader.ts +130 -0
  97. package/src/lib/fontMigration.ts +140 -0
  98. package/src/lib/fontParse.ts +168 -0
  99. package/src/lib/index.ts +48 -30
  100. package/src/lib/lazyConfig.test.ts +54 -0
  101. package/src/lib/migrations/2026-04-24-component-prefix-and-suffix-renames.ts +64 -0
  102. package/src/lib/migrations/2026-04-24-legacy-keys-and-bg-to-canvas.ts +71 -0
  103. package/src/lib/migrations/2026-04-27-segmentedcontrol-disabled-flatten.ts +43 -0
  104. package/src/lib/migrations/2026-05-08-collapsiblesection-frame-and-cleanup.ts +68 -0
  105. package/src/lib/migrations/2026-05-08-collapsiblesection-variant-namespace.ts +35 -0
  106. package/src/lib/migrations/2026-05-10-sectiondivider-gradient-stops.ts +50 -0
  107. package/src/lib/migrations/2026-05-13-primary-to-brand.ts +90 -0
  108. package/src/lib/migrations/index.ts +93 -0
  109. package/src/lib/migrations/migrations.test.ts +341 -0
  110. package/src/lib/navLinkTypes.ts +1 -0
  111. package/src/lib/overlayState.ts +3 -0
  112. package/src/lib/paletteDerivation.ts +300 -0
  113. package/src/lib/parentRouteStore.ts +42 -0
  114. package/src/lib/parsers/globalRootBlock.ts +32 -0
  115. package/src/lib/presetService.ts +94 -0
  116. package/src/lib/router.ts +42 -10
  117. package/src/lib/scrollSection.ts +45 -0
  118. package/src/lib/slices/columns.ts +59 -0
  119. package/src/lib/slices/components.ts +362 -0
  120. package/src/lib/slices/domainVars.ts +15 -0
  121. package/src/lib/slices/fonts.ts +30 -0
  122. package/src/lib/slices/gradients.ts +153 -0
  123. package/src/lib/slices/overlays.ts +132 -0
  124. package/src/lib/slices/palettes.ts +26 -0
  125. package/src/lib/slices/shadows.ts +123 -0
  126. package/src/lib/storage.ts +88 -0
  127. package/src/lib/themeInit.ts +74 -0
  128. package/src/lib/themeService.ts +101 -0
  129. package/src/lib/themeTypes.ts +146 -0
  130. package/src/lib/tokenRegistry.ts +148 -0
  131. package/src/pages/ComponentEditorPage.svelte +384 -0
  132. package/src/pages/ComponentEditorPage.svelte.d.ts +2 -0
  133. package/src/pages/Editor.svelte +98 -0
  134. package/src/pages/Editor.svelte.d.ts +2 -0
  135. package/src/pages/EditorShell.svelte +348 -0
  136. package/src/styles/_padding.scss +34 -0
  137. package/src/styles/fonts/Fraunces/Fraunces-italic-latin-ext.woff2 +0 -0
  138. package/src/styles/fonts/Fraunces/Fraunces-italic-latin.woff2 +0 -0
  139. package/src/styles/fonts/Fraunces/Fraunces-roman-latin-ext.woff2 +0 -0
  140. package/src/styles/fonts/Fraunces/Fraunces-roman-latin.woff2 +0 -0
  141. package/src/styles/fonts/Manrope/Manrope-latin-ext.woff2 +0 -0
  142. package/src/styles/fonts/Manrope/Manrope-latin.woff2 +0 -0
  143. package/src/styles/fonts.css +22 -10
  144. package/src/styles/form-controls.css +14 -16
  145. package/src/styles/tokens.css +1322 -0
  146. package/src/styles/ui-editor.css +126 -0
  147. package/src/{showcase → ui}/BezierCurveEditor.svelte +14 -14
  148. package/src/{showcase → ui}/ColorEditPanel.svelte +42 -36
  149. package/src/ui/EditorViewSwitcher.svelte +180 -0
  150. package/src/ui/FontStackEditor.svelte +360 -0
  151. package/src/ui/GradientEditor.svelte +461 -0
  152. package/src/ui/GradientStopPicker.svelte +74 -0
  153. package/src/ui/PaletteEditor.svelte +1590 -0
  154. package/src/ui/PaletteEditor.test.ts +108 -0
  155. package/src/ui/PresetFileManager.svelte +567 -0
  156. package/src/ui/ProjectFontsSection.svelte +645 -0
  157. package/src/{showcase → ui}/SurfacesTab.svelte +39 -39
  158. package/src/{showcase → ui}/TextTab.svelte +27 -27
  159. package/src/{showcase/TokenFileManager.svelte → ui/ThemeFileManager.svelte} +196 -112
  160. package/src/ui/Toggle.svelte +108 -0
  161. package/src/ui/UICopyPopover.svelte +78 -0
  162. package/src/{showcase/EditorDialog.svelte → ui/UIDialog.svelte} +66 -25
  163. package/src/ui/UIFontFamilySelector.svelte +309 -0
  164. package/src/ui/UIFontSizeSelector.svelte +165 -0
  165. package/src/ui/UIFontWeightSelector.svelte +52 -0
  166. package/src/ui/UILineHeightSelector.svelte +47 -0
  167. package/src/ui/UILinkToggle.svelte +60 -0
  168. package/src/ui/UIOptionItem.svelte +74 -0
  169. package/src/ui/UIOptionList.svelte +27 -0
  170. package/src/ui/UIPaddingSelector.svelte +661 -0
  171. package/src/ui/UIPaletteSelector.svelte +1084 -0
  172. package/src/ui/UIRadio.svelte +72 -0
  173. package/src/ui/UIRadioGroup.svelte +59 -0
  174. package/src/ui/UIRelinkConfirmPopover.svelte +235 -0
  175. package/src/ui/UITokenSelector.svelte +509 -0
  176. package/src/ui/UIVariantSelector.svelte +145 -0
  177. package/src/ui/VariablesTab.svelte +252 -0
  178. package/src/ui/index.ts +31 -0
  179. package/src/ui/keepInViewport.ts +84 -0
  180. package/src/ui/palette/GradientStopEditor.svelte +482 -0
  181. package/src/ui/palette/OverridesPanel.svelte +526 -0
  182. package/src/ui/palette/PaletteBase.svelte +165 -0
  183. package/src/ui/palette/ScaleCurveEditor.svelte +38 -0
  184. package/src/ui/palette/paletteEditorState.ts +89 -0
  185. package/src/ui/sections/ColumnsSection.svelte +273 -0
  186. package/src/ui/sections/GradientsSection.svelte +147 -0
  187. package/src/ui/sections/OverlaysSection.svelte +670 -0
  188. package/src/ui/sections/ShadowsSection.svelte +1250 -0
  189. package/src/ui/sections/TokenScaleTable.svelte +332 -0
  190. package/src/ui/sections/tokenScales.ts +81 -0
  191. package/src/ui/variantScales.ts +108 -0
  192. package/src/components/DetailNav.svelte +0 -78
  193. package/src/components/Toggle.svelte +0 -86
  194. package/src/lib/tokenInit.ts +0 -29
  195. package/src/lib/tokenService.ts +0 -144
  196. package/src/lib/tokenTypes.ts +0 -45
  197. package/src/pages/Admin.svelte +0 -100
  198. package/src/pages/ShowcasePage.svelte +0 -144
  199. package/src/showcase/BackupBrowser.svelte +0 -617
  200. package/src/showcase/ComponentsTab.svelte +0 -105
  201. package/src/showcase/PaletteEditor.svelte +0 -2579
  202. package/src/showcase/PaletteSelector.svelte +0 -627
  203. package/src/showcase/TokenMap.svelte +0 -54
  204. package/src/showcase/VariablesTab.svelte +0 -2655
  205. package/src/showcase/VisualsTab.svelte +0 -231
  206. package/src/showcase/demos/BadgeDemo.svelte +0 -56
  207. package/src/showcase/demos/CardDemo.svelte +0 -50
  208. package/src/showcase/demos/ChoiceButtonsDemo.svelte +0 -192
  209. package/src/showcase/demos/CollapsibleSectionDemo.svelte +0 -54
  210. package/src/showcase/demos/DialogDemo.svelte +0 -42
  211. package/src/showcase/demos/InlineEditActionsDemo.svelte +0 -25
  212. package/src/showcase/demos/NotificationDemo.svelte +0 -147
  213. package/src/showcase/demos/ProgressBarDemo.svelte +0 -54
  214. package/src/showcase/demos/RadioButtonDemo.svelte +0 -56
  215. package/src/showcase/demos/SectionDividerDemo.svelte +0 -77
  216. package/src/showcase/demos/StandardButtonsDemo.svelte +0 -455
  217. package/src/showcase/demos/TabBarDemo.svelte +0 -58
  218. package/src/showcase/demos/TooltipDemo.svelte +0 -52
  219. package/src/showcase/editor.css +0 -93
  220. package/src/showcase/index.ts +0 -17
  221. package/src/styles/fonts/Domine/Domine-VariableFont_wght.ttf +0 -0
  222. package/src/styles/fonts/Domine/OFL.txt +0 -97
  223. package/src/styles/fonts/Domine/README.txt +0 -66
  224. /package/src/{showcase → ui}/curveEngine.ts +0 -0
@@ -0,0 +1,83 @@
1
+ <script context="module" lang="ts">
2
+ import type { Token } from './scaffolding/types';
3
+
4
+ export const component = 'inlineeditactions';
5
+
6
+ // Two objects (save button, cancel button), each with default/hover states.
7
+ // Within each button, link shape props (border-width, radius, padding, icon-size) across states.
8
+ // Save and cancel are different objects, so they don't link to each other by default.
9
+ const buttons = ['save', 'cancel'] as const;
10
+ type Button = typeof buttons[number];
11
+ function buttonStateTokens(btn: Button, state: 'default' | 'hover'): Token[] {
12
+ return [
13
+ { label: 'surface color', groupKey: 'surface', variable: `--inlineeditactions-${btn}-${state}-surface` },
14
+ { label: 'text color', groupKey: 'text', variable: `--inlineeditactions-${btn}-${state}-text` },
15
+ { label: 'border color', groupKey: 'border', variable: `--inlineeditactions-${btn}-${state}-border` },
16
+ { label: 'border width', canBeLinked: true, groupKey: `${btn}-border-width`, variable: `--inlineeditactions-${btn}-${state}-border-width` },
17
+ { label: 'corner radius', canBeLinked: true, groupKey: `${btn}-radius`, variable: `--inlineeditactions-${btn}-${state}-radius` },
18
+ { label: 'padding', canBeLinked: true, groupKey: `${btn}-padding`, variable: `--inlineeditactions-${btn}-${state}-padding` },
19
+ { label: 'icon size', canBeLinked: true, groupKey: `${btn}-icon-size`, variable: `--inlineeditactions-${btn}-${state}-icon-size` },
20
+ ];
21
+ }
22
+
23
+ // Each button gets its own VariantGroup with its own default/hover states.
24
+ function buttonStates(btn: Button): Record<string, Token[]> {
25
+ return {
26
+ default: buttonStateTokens(btn, 'default'),
27
+ hover: buttonStateTokens(btn, 'hover'),
28
+ };
29
+ }
30
+ export const allTokens: Token[] = buttons.flatMap((b) => Object.values(buttonStates(b)).flat());
31
+
32
+ // Linked block surfaces shape props per button (linked across default/hover within same button).
33
+ const linkableContexts = new Map<string, string>(buttons.flatMap((btn) => [
34
+ [`--inlineeditactions-${btn}-default-border-width`, btn] as const,
35
+ [`--inlineeditactions-${btn}-default-radius`, btn] as const,
36
+ [`--inlineeditactions-${btn}-default-padding`, btn] as const,
37
+ [`--inlineeditactions-${btn}-default-icon-size`, btn] as const,
38
+ ]));
39
+ </script>
40
+
41
+ <script lang="ts">
42
+ import InlineEditActions from '../components/InlineEditActions.svelte';
43
+ import VariantGroup from './scaffolding/VariantGroup.svelte';
44
+ import ComponentEditorBase from './scaffolding/ComponentEditorBase.svelte';
45
+ import { editorState } from '../lib/editorStore';
46
+ import { computeLinkedBlock, withLinkedDisabled } from './scaffolding/linkedBlock';
47
+
48
+ $: linked = computeLinkedBlock(component, linkableContexts, allTokens, $editorState);
49
+
50
+ $: visibleStatesByButton = (btn: Button) => Object.fromEntries(
51
+ Object.entries(buttonStates(btn)).map(([name, list]) => [name, withLinkedDisabled(list, linked.varSet)]),
52
+ ) as Record<string, Token[]>;
53
+ </script>
54
+
55
+ <ComponentEditorBase {component} title="Inline Edit Actions" description="Confirm/cancel button pair for inline editing. Import from <code>components/InlineEditActions.svelte</code>" tokens={allTokens} {linked}>
56
+ {#each buttons as btn}
57
+ <VariantGroup
58
+ name={btn}
59
+ title={btn === 'save' ? 'Save button' : 'Cancel button'}
60
+ states={visibleStatesByButton(btn)}
61
+ {component}
62
+ let:activeState
63
+ >
64
+ {@const forceClass = activeState === 'hover' ? 'force-hover' : ''}
65
+ <div class="inline-edit-demo-row">
66
+ <span style="color: var(--text-secondary);">Editing value...</span>
67
+ <InlineEditActions
68
+ onSave={() => {}}
69
+ onCancel={() => {}}
70
+ class={forceClass}
71
+ />
72
+ </div>
73
+ </VariantGroup>
74
+ {/each}
75
+ </ComponentEditorBase>
76
+
77
+ <style>
78
+ .inline-edit-demo-row {
79
+ display: flex;
80
+ align-items: center;
81
+ gap: var(--space-12);
82
+ }
83
+ </style>
@@ -0,0 +1,160 @@
1
+ <script context="module" lang="ts">
2
+ import { buildTypeGroupColorTokens } from './scaffolding/buildTypeGroupTokens';
3
+ import type { Token, TypeGroupConfig } from './scaffolding/types';
4
+
5
+ export const component = 'notification';
6
+ const variants = ['info', 'success', 'warning', 'danger'] as const;
7
+ type Variant = typeof variants[number];
8
+
9
+ // Per variant: notification frame (surface, border, border-width, radius, padding) + icon (color, size).
10
+ function variantTokens(v: Variant): Token[] {
11
+ return [
12
+ { label: 'surface color', groupKey: 'surface', variable: `--notification-${v}-surface` },
13
+ { label: 'border color', groupKey: 'border', variable: `--notification-${v}-border` },
14
+ { label: 'border width', canBeLinked: true, groupKey: 'border-width', variable: `--notification-${v}-border-width` },
15
+ { label: 'corner radius', canBeLinked: true, groupKey: 'radius', variable: `--notification-${v}-radius` },
16
+ { label: 'padding', canBeLinked: true, groupKey: 'padding', variable: `--notification-${v}-padding` },
17
+ { label: 'icon color', groupKey: 'icon', variable: `--notification-${v}-icon` },
18
+ { label: 'icon size', canBeLinked: true, groupKey: 'icon-size', variable: `--notification-${v}-icon-size` },
19
+ ];
20
+ }
21
+
22
+ // Two type groups per variant: title and body text.
23
+ function variantTypeGroups(v: Variant): TypeGroupConfig[] {
24
+ return [
25
+ {
26
+ legend: 'title',
27
+ colorVariable: `--notification-${v}-title`,
28
+ familyVariable: `--notification-${v}-title-font-family`,
29
+ sizeVariable: `--notification-${v}-title-font-size`,
30
+ weightVariable: `--notification-${v}-title-font-weight`,
31
+ lineHeightVariable: `--notification-${v}-title-line-height`,
32
+ },
33
+ {
34
+ legend: 'body text',
35
+ colorVariable: `--notification-${v}-text`,
36
+ familyVariable: `--notification-${v}-text-font-family`,
37
+ sizeVariable: `--notification-${v}-text-font-size`,
38
+ weightVariable: `--notification-${v}-text-font-weight`,
39
+ lineHeightVariable: `--notification-${v}-text-line-height`,
40
+ },
41
+ ];
42
+ }
43
+ function variantTypeGroupTokens(v: Variant): Token[] {
44
+ return [
45
+ { label: 'font family', canBeLinked: true, groupKey: 'title-font-family', variable: `--notification-${v}-title-font-family` },
46
+ { label: 'font size', canBeLinked: true, groupKey: 'title-font-size', variable: `--notification-${v}-title-font-size` },
47
+ { label: 'font weight', canBeLinked: true, groupKey: 'title-font-weight', variable: `--notification-${v}-title-font-weight` },
48
+ { label: 'line height', canBeLinked: true, groupKey: 'title-line-height', variable: `--notification-${v}-title-line-height` },
49
+ { label: 'font family', canBeLinked: true, groupKey: 'text-font-family', variable: `--notification-${v}-text-font-family` },
50
+ { label: 'font size', canBeLinked: true, groupKey: 'text-font-size', variable: `--notification-${v}-text-font-size` },
51
+ { label: 'font weight', canBeLinked: true, groupKey: 'text-font-weight', variable: `--notification-${v}-text-font-weight` },
52
+ { label: 'line height', canBeLinked: true, groupKey: 'text-line-height', variable: `--notification-${v}-text-line-height` },
53
+ ];
54
+ }
55
+ export const allTokens: Token[] = variants.flatMap((v) => [
56
+ ...variantTokens(v),
57
+ ...buildTypeGroupColorTokens(variantTypeGroups(v)),
58
+ ...variantTypeGroupTokens(v),
59
+ ]);
60
+
61
+ // Linked block surfaces shape and font props that may be linked across variants.
62
+ const linkableContexts = new Map<string, string>(variants.flatMap((v) => [
63
+ [`--notification-${v}-border-width`, v] as const,
64
+ [`--notification-${v}-radius`, v] as const,
65
+ [`--notification-${v}-padding`, v] as const,
66
+ [`--notification-${v}-icon-size`, v] as const,
67
+ [`--notification-${v}-title-font-family`, v] as const,
68
+ [`--notification-${v}-title-font-size`, v] as const,
69
+ [`--notification-${v}-title-font-weight`, v] as const,
70
+ [`--notification-${v}-title-line-height`, v] as const,
71
+ [`--notification-${v}-text-font-family`, v] as const,
72
+ [`--notification-${v}-text-font-size`, v] as const,
73
+ [`--notification-${v}-text-font-weight`, v] as const,
74
+ [`--notification-${v}-text-line-height`, v] as const,
75
+ ]));
76
+
77
+ const BUTTON_VARIANT_OPTIONS = ['none', 'primary', 'secondary', 'outline', 'success', 'danger', 'warning'] as const;
78
+ type ButtonVariantOption = typeof BUTTON_VARIANT_OPTIONS[number];
79
+ type ButtonVariant = Exclude<ButtonVariantOption, 'none'>;
80
+ function variantLabel(v: ButtonVariantOption): string {
81
+ return v.charAt(0).toUpperCase() + v.slice(1);
82
+ }
83
+ function toVariant(v: ButtonVariantOption): ButtonVariant | null {
84
+ return v === 'none' ? null : v;
85
+ }
86
+
87
+ const variantOptions = variants.map((v) => ({ value: v, label: v.charAt(0).toUpperCase() + v.slice(1) }));
88
+ </script>
89
+
90
+ <script lang="ts">
91
+ import Notification from '../components/Notification.svelte';
92
+ import VariantGroup from './scaffolding/VariantGroup.svelte';
93
+ import ComponentEditorBase from './scaffolding/ComponentEditorBase.svelte';
94
+ import { editorState } from '../lib/editorStore';
95
+ import { computeLinkedBlock, withLinkedDisabled } from './scaffolding/linkedBlock';
96
+ import { buildSiblings } from './scaffolding/siblings';
97
+
98
+ $: linked = computeLinkedBlock(component, linkableContexts, allTokens, $editorState);
99
+ $: visibleVariantTokens = (v: Variant) => withLinkedDisabled(variantTokens(v), linked.varSet);
100
+
101
+ import type { NotificationActions } from '../components/types';
102
+
103
+ let dismissible = false;
104
+ let rightOption: ButtonVariantOption = 'none';
105
+ let leftOption: ButtonVariantOption = 'none';
106
+ $: actions = ((): NotificationActions => {
107
+ const a: NotificationActions = {};
108
+ const right = toVariant(rightOption);
109
+ const left = toVariant(leftOption);
110
+ if (right) a.right = { label: 'Confirm', variant: right, onClick: () => {} };
111
+ if (left) a.left = { label: 'Cancel', variant: left, onClick: () => {} };
112
+ return a;
113
+ })();
114
+ </script>
115
+
116
+ <ComponentEditorBase {component} title="Notification" description="Contextual feedback notifications with multiple variants. Import from <code>components/Notification.svelte</code>" tokens={allTokens} {linked} variants={variantOptions}>
117
+ <svelte:fragment slot="config">
118
+ <label>
119
+ <input type="checkbox" bind:checked={dismissible} />
120
+ <span>Dismissible</span>
121
+ </label>
122
+ <label>
123
+ <span>Right button</span>
124
+ <select class="form-select" bind:value={rightOption}>
125
+ {#each BUTTON_VARIANT_OPTIONS as v}
126
+ <option value={v}>{variantLabel(v)}</option>
127
+ {/each}
128
+ </select>
129
+ </label>
130
+ <label>
131
+ <span>Left button</span>
132
+ <select class="form-select" bind:value={leftOption}>
133
+ {#each BUTTON_VARIANT_OPTIONS as v}
134
+ <option value={v}>{variantLabel(v)}</option>
135
+ {/each}
136
+ </select>
137
+ </label>
138
+ </svelte:fragment>
139
+ {#each variants as v}
140
+ <VariantGroup
141
+ name={v}
142
+ title={v.charAt(0).toUpperCase() + v.slice(1)}
143
+ states={{ [v]: visibleVariantTokens(v) }}
144
+ typeGroups={{ [v]: variantTypeGroups(v) }}
145
+ {component}
146
+ siblings={buildSiblings(variants, v, (sv) => ({ [sv]: variantTokens(sv) }), (sv) => ({ [sv]: variantTypeGroups(sv) }))}
147
+ >
148
+ {#if v === 'info'}
149
+ <Notification variant="info" title="Information" description="This is an informational message to keep you updated." {dismissible} {actions} />
150
+ {:else if v === 'success'}
151
+ <Notification variant="success" title="Success" description="Your action was completed successfully." {dismissible} {actions} />
152
+ {:else if v === 'warning'}
153
+ <Notification variant="warning" title="Warning" description="Caution: This action may have unintended consequences." {dismissible} {actions} />
154
+ {:else if v === 'danger'}
155
+ <Notification variant="danger" title="Danger" description="Critical error: Please address this issue immediately." {dismissible} {actions} />
156
+ {/if}
157
+ </VariantGroup>
158
+ {/each}
159
+ </ComponentEditorBase>
160
+
@@ -0,0 +1,124 @@
1
+ <script context="module" lang="ts">
2
+ import { buildTypeGroupColorTokens } from './scaffolding/buildTypeGroupTokens';
3
+ import type { Token, TypeGroupConfig } from './scaffolding/types';
4
+
5
+ export const component = 'progressbar';
6
+ const variants = ['primary', 'success', 'warning', 'danger', 'info'] as const;
7
+ type Variant = typeof variants[number];
8
+
9
+ // Per variant: track (surface, border, border-width, radius, height) + fill (color).
10
+ function variantTokens(v: Variant): Token[] {
11
+ return [
12
+ { label: 'fill color', groupKey: 'fill', variable: `--progressbar-${v}-fill` },
13
+ { label: 'track surface color', groupKey: 'surface', variable: `--progressbar-${v}-track-surface` },
14
+ { label: 'track border color', groupKey: 'border', variable: `--progressbar-${v}-track-border` },
15
+ { label: 'track border width', canBeLinked: true, groupKey: 'track-border-width', variable: `--progressbar-${v}-track-border-width` },
16
+ { label: 'corner radius', canBeLinked: true, groupKey: 'radius', variable: `--progressbar-${v}-radius` },
17
+ { label: 'track height', canBeLinked: true, groupKey: 'track-height', variable: `--progressbar-${v}-track-height` },
18
+ ];
19
+ }
20
+
21
+ // Two type groups per variant: label and value.
22
+ function variantTypeGroups(v: Variant): TypeGroupConfig[] {
23
+ return [
24
+ {
25
+ legend: 'label',
26
+ colorVariable: `--progressbar-${v}-label`,
27
+ familyVariable: `--progressbar-${v}-label-font-family`,
28
+ sizeVariable: `--progressbar-${v}-label-font-size`,
29
+ weightVariable: `--progressbar-${v}-label-font-weight`,
30
+ lineHeightVariable: `--progressbar-${v}-label-line-height`,
31
+ },
32
+ {
33
+ legend: 'value',
34
+ colorVariable: `--progressbar-${v}-value`,
35
+ familyVariable: `--progressbar-${v}-value-font-family`,
36
+ sizeVariable: `--progressbar-${v}-value-font-size`,
37
+ weightVariable: `--progressbar-${v}-value-font-weight`,
38
+ lineHeightVariable: `--progressbar-${v}-value-line-height`,
39
+ },
40
+ ];
41
+ }
42
+ function variantTypeGroupTokens(v: Variant): Token[] {
43
+ return [
44
+ { label: 'font family', canBeLinked: true, groupKey: 'label-font-family', variable: `--progressbar-${v}-label-font-family` },
45
+ { label: 'font size', canBeLinked: true, groupKey: 'label-font-size', variable: `--progressbar-${v}-label-font-size` },
46
+ { label: 'font weight', canBeLinked: true, groupKey: 'label-font-weight', variable: `--progressbar-${v}-label-font-weight` },
47
+ { label: 'line height', canBeLinked: true, groupKey: 'label-line-height', variable: `--progressbar-${v}-label-line-height` },
48
+ { label: 'font family', canBeLinked: true, groupKey: 'value-font-family', variable: `--progressbar-${v}-value-font-family` },
49
+ { label: 'font size', canBeLinked: true, groupKey: 'value-font-size', variable: `--progressbar-${v}-value-font-size` },
50
+ { label: 'font weight', canBeLinked: true, groupKey: 'value-font-weight', variable: `--progressbar-${v}-value-font-weight` },
51
+ { label: 'line height', canBeLinked: true, groupKey: 'value-line-height', variable: `--progressbar-${v}-value-line-height` },
52
+ ];
53
+ }
54
+ export const allTokens: Token[] = variants.flatMap((v) => [
55
+ ...variantTokens(v),
56
+ ...buildTypeGroupColorTokens(variantTypeGroups(v)),
57
+ ...variantTypeGroupTokens(v),
58
+ ]);
59
+
60
+ // Cross-variant linked block surfaces shape and font props that may be linked.
61
+ const linkableContexts = new Map<string, string>(variants.flatMap((v) => [
62
+ [`--progressbar-${v}-track-border-width`, v] as const,
63
+ [`--progressbar-${v}-radius`, v] as const,
64
+ [`--progressbar-${v}-track-height`, v] as const,
65
+ [`--progressbar-${v}-label-font-family`, v] as const,
66
+ [`--progressbar-${v}-label-font-size`, v] as const,
67
+ [`--progressbar-${v}-label-font-weight`, v] as const,
68
+ [`--progressbar-${v}-label-line-height`, v] as const,
69
+ [`--progressbar-${v}-value-font-family`, v] as const,
70
+ [`--progressbar-${v}-value-font-size`, v] as const,
71
+ [`--progressbar-${v}-value-font-weight`, v] as const,
72
+ [`--progressbar-${v}-value-line-height`, v] as const,
73
+ ]));
74
+
75
+ const variantOptions = variants.map((v) => ({ value: v, label: v.charAt(0).toUpperCase() + v.slice(1) }));
76
+ </script>
77
+
78
+ <script lang="ts">
79
+ import ProgressBar from '../components/ProgressBar.svelte';
80
+ import VariantGroup from './scaffolding/VariantGroup.svelte';
81
+ import ComponentEditorBase from './scaffolding/ComponentEditorBase.svelte';
82
+ import { editorState } from '../lib/editorStore';
83
+ import { computeLinkedBlock, withLinkedDisabled } from './scaffolding/linkedBlock';
84
+ import { buildSiblings } from './scaffolding/siblings';
85
+
86
+ $: linked = computeLinkedBlock(component, linkableContexts, allTokens, $editorState);
87
+ $: visibleVariantTokens = (v: Variant) => withLinkedDisabled(variantTokens(v), linked.varSet);
88
+ </script>
89
+
90
+ <ComponentEditorBase {component} title="Progress Bar" description="Animated progress bar with variants. Import from <code>components/ProgressBar.svelte</code>" tokens={allTokens} {linked} variants={variantOptions}>
91
+ {#each variants as v}
92
+ <VariantGroup
93
+ name={v}
94
+ title={v.charAt(0).toUpperCase() + v.slice(1)}
95
+ states={{ [v]: visibleVariantTokens(v) }}
96
+ typeGroups={{ [v]: variantTypeGroups(v) }}
97
+ {component}
98
+ siblings={buildSiblings(variants, v, (sv) => ({ [sv]: variantTokens(sv) }), (sv) => ({ [sv]: variantTypeGroups(sv) }))}
99
+ >
100
+ <div class="progress-demo-stack">
101
+ {#if v === 'primary'}
102
+ <ProgressBar value={25} label="Getting Started" variant="primary" />
103
+ <ProgressBar value={60} variant="primary" size="compact" />
104
+ {:else if v === 'success'}
105
+ <ProgressBar value={100} label="Complete" variant="success" />
106
+ {:else if v === 'warning'}
107
+ <ProgressBar value={75} label="Almost Done" variant="warning" />
108
+ {:else if v === 'danger'}
109
+ <ProgressBar value={33} label="Danger Zone" variant="danger" />
110
+ {:else if v === 'info'}
111
+ <ProgressBar value={50} label="Halfway There" variant="info" />
112
+ {/if}
113
+ </div>
114
+ </VariantGroup>
115
+ {/each}
116
+ </ComponentEditorBase>
117
+
118
+ <style>
119
+ .progress-demo-stack {
120
+ display: flex;
121
+ flex-direction: column;
122
+ gap: var(--space-12);
123
+ }
124
+ </style>
@@ -0,0 +1,140 @@
1
+ <script context="module" lang="ts">
2
+ import { buildTypeGroupColorTokens } from './scaffolding/buildTypeGroupTokens';
3
+ import type { Token, TypeGroupConfig } from './scaffolding/types';
4
+
5
+ export const component = 'radiobutton';
6
+
7
+ const states: Record<string, Token[]> = {
8
+ default: [
9
+ { label: 'border color', groupKey: 'color', variable: '--radiobutton-default-dot-border-color' },
10
+ { label: 'border thickness', canBeLinked: true, groupKey: 'border-width', variable: '--radiobutton-default-dot-border-width' },
11
+ { label: 'dot fill', groupKey: 'fill', variable: '--radiobutton-default-dot-fill' },
12
+ { label: 'dot size', groupKey: 'size', variable: '--radiobutton-default-dot-size' },
13
+ ],
14
+ hover: [
15
+ { label: 'border color', groupKey: 'color', variable: '--radiobutton-hover-dot-border-color' },
16
+ { label: 'border thickness', canBeLinked: true, groupKey: 'border-width', variable: '--radiobutton-hover-dot-border-width' },
17
+ { label: 'dot fill', groupKey: 'fill', variable: '--radiobutton-hover-dot-fill' },
18
+ { label: 'dot size', groupKey: 'size', variable: '--radiobutton-hover-dot-size' },
19
+ ],
20
+ active: [
21
+ { label: 'border color', groupKey: 'color', variable: '--radiobutton-active-dot-border-color' },
22
+ { label: 'border thickness', canBeLinked: true, groupKey: 'border-width', variable: '--radiobutton-active-dot-border-width' },
23
+ { label: 'dot fill', groupKey: 'fill', variable: '--radiobutton-active-dot-fill' },
24
+ { label: 'dot size', groupKey: 'size', variable: '--radiobutton-active-dot-size' },
25
+ ],
26
+ };
27
+
28
+ const typeGroups: Record<string, TypeGroupConfig[]> = {
29
+ default: [{
30
+ legend: 'label',
31
+ colorVariable: '--radiobutton-default-label',
32
+ familyVariable: '--radiobutton-default-label-font-family',
33
+ sizeVariable: '--radiobutton-default-label-font-size',
34
+ weightVariable: '--radiobutton-default-label-font-weight',
35
+ lineHeightVariable: '--radiobutton-default-label-line-height',
36
+ }],
37
+ hover: [{
38
+ legend: 'label',
39
+ colorVariable: '--radiobutton-hover-label',
40
+ familyVariable: '--radiobutton-hover-label-font-family',
41
+ sizeVariable: '--radiobutton-hover-label-font-size',
42
+ weightVariable: '--radiobutton-hover-label-font-weight',
43
+ lineHeightVariable: '--radiobutton-hover-label-line-height',
44
+ }],
45
+ active: [{
46
+ legend: 'label',
47
+ colorVariable: '--radiobutton-active-label',
48
+ familyVariable: '--radiobutton-active-label-font-family',
49
+ sizeVariable: '--radiobutton-active-label-font-size',
50
+ weightVariable: '--radiobutton-active-label-font-weight',
51
+ lineHeightVariable: '--radiobutton-active-label-line-height',
52
+ }],
53
+ };
54
+ const typeGroupTokens: Token[] = (['default', 'hover', 'active'] as const).flatMap((s) => [
55
+ { label: 'font family', canBeLinked: true, groupKey: 'font-family', variable: `--radiobutton-${s}-label-font-family` },
56
+ { label: 'font size', canBeLinked: true, groupKey: 'font-size', variable: `--radiobutton-${s}-label-font-size` },
57
+ { label: 'font weight', canBeLinked: true, groupKey: 'font-weight', variable: `--radiobutton-${s}-label-font-weight` },
58
+ { label: 'line height', canBeLinked: true, groupKey: 'line-height', variable: `--radiobutton-${s}-label-line-height` },
59
+ ]);
60
+ const linkableContexts = new Map<string, string>([
61
+ ['--radiobutton-default-dot-border-width', 'default'],
62
+ ['--radiobutton-hover-dot-border-width', 'hover'],
63
+ ['--radiobutton-active-dot-border-width', 'active'],
64
+ ['--radiobutton-default-label-font-family', 'default'],
65
+ ['--radiobutton-hover-label-font-family', 'hover'],
66
+ ['--radiobutton-active-label-font-family', 'active'],
67
+ ['--radiobutton-default-label-font-size', 'default'],
68
+ ['--radiobutton-hover-label-font-size', 'hover'],
69
+ ['--radiobutton-active-label-font-size', 'active'],
70
+ ['--radiobutton-default-label-font-weight', 'default'],
71
+ ['--radiobutton-hover-label-font-weight', 'hover'],
72
+ ['--radiobutton-active-label-font-weight', 'active'],
73
+ ['--radiobutton-default-label-line-height', 'default'],
74
+ ['--radiobutton-hover-label-line-height', 'hover'],
75
+ ['--radiobutton-active-label-line-height', 'active'],
76
+ ]);
77
+ export const allTokens: Token[] = [
78
+ ...Object.values(states).flat(),
79
+ ...buildTypeGroupColorTokens(typeGroups),
80
+ ...typeGroupTokens,
81
+ ];
82
+ </script>
83
+
84
+ <script lang="ts">
85
+ import RadioButton from '../components/RadioButton.svelte';
86
+ import VariantGroup from './scaffolding/VariantGroup.svelte';
87
+ import ComponentEditorBase from './scaffolding/ComponentEditorBase.svelte';
88
+ import { editorState } from '../lib/editorStore';
89
+ import { computeLinkedBlock, withLinkedDisabled } from './scaffolding/linkedBlock';
90
+
91
+ let selectedRadio = 'option-b';
92
+
93
+ $: linked = computeLinkedBlock(component, linkableContexts, allTokens, $editorState);
94
+
95
+ $: visibleStates = Object.fromEntries(
96
+ Object.entries(states).map(([name, list]) => [name, withLinkedDisabled(list, linked.varSet)]),
97
+ ) as Record<string, Token[]>;
98
+ </script>
99
+
100
+ <ComponentEditorBase {component} title="Radio Button" description="Styled radio buttons with icon and color support. Import from <code>components/RadioButton.svelte</code>" tokens={allTokens} {linked}>
101
+ <VariantGroup
102
+ name="radio"
103
+ title="Radio Button"
104
+ states={visibleStates}
105
+ {typeGroups}
106
+ {component}
107
+ let:activeState
108
+ >
109
+ {@const forceClass = activeState === 'hover' ? 'force-hover' : ''}
110
+ {@const forceActive = activeState === 'active'}
111
+ <div class="radio-demo-row">
112
+ <RadioButton
113
+ label="Defense"
114
+ active={forceActive || selectedRadio === 'option-a'}
115
+ class={forceClass}
116
+ on:click={() => (selectedRadio = 'option-a')}
117
+ />
118
+ <RadioButton
119
+ label="Economy"
120
+ active={forceActive || selectedRadio === 'option-b'}
121
+ class={forceClass}
122
+ on:click={() => (selectedRadio = 'option-b')}
123
+ />
124
+ <RadioButton
125
+ label="Loyalty"
126
+ active={forceActive || selectedRadio === 'option-c'}
127
+ class={forceClass}
128
+ on:click={() => (selectedRadio = 'option-c')}
129
+ />
130
+ </div>
131
+ </VariantGroup>
132
+ </ComponentEditorBase>
133
+
134
+ <style>
135
+ .radio-demo-row {
136
+ display: flex;
137
+ gap: var(--space-16);
138
+ flex-wrap: wrap;
139
+ }
140
+ </style>