@motion-proto/live-tokens 0.1.0 → 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 (225) 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 +51 -23
  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 +265 -82
  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 -31
  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 +49 -0
  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 -41
  158. package/src/{showcase → ui}/TextTab.svelte +27 -29
  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/pageSource.ts +0 -6
  195. package/src/lib/tokenInit.ts +0 -29
  196. package/src/lib/tokenService.ts +0 -144
  197. package/src/lib/tokenTypes.ts +0 -45
  198. package/src/pages/Admin.svelte +0 -100
  199. package/src/pages/ShowcasePage.svelte +0 -146
  200. package/src/showcase/BackupBrowser.svelte +0 -617
  201. package/src/showcase/ComponentsTab.svelte +0 -107
  202. package/src/showcase/PaletteEditor.svelte +0 -2579
  203. package/src/showcase/PaletteSelector.svelte +0 -627
  204. package/src/showcase/TokenMap.svelte +0 -54
  205. package/src/showcase/VariablesTab.svelte +0 -2657
  206. package/src/showcase/VisualsTab.svelte +0 -233
  207. package/src/showcase/demos/BadgeDemo.svelte +0 -58
  208. package/src/showcase/demos/CardDemo.svelte +0 -52
  209. package/src/showcase/demos/ChoiceButtonsDemo.svelte +0 -194
  210. package/src/showcase/demos/CollapsibleSectionDemo.svelte +0 -56
  211. package/src/showcase/demos/DialogDemo.svelte +0 -42
  212. package/src/showcase/demos/InlineEditActionsDemo.svelte +0 -27
  213. package/src/showcase/demos/NotificationDemo.svelte +0 -149
  214. package/src/showcase/demos/ProgressBarDemo.svelte +0 -56
  215. package/src/showcase/demos/RadioButtonDemo.svelte +0 -58
  216. package/src/showcase/demos/SectionDividerDemo.svelte +0 -79
  217. package/src/showcase/demos/StandardButtonsDemo.svelte +0 -457
  218. package/src/showcase/demos/TabBarDemo.svelte +0 -60
  219. package/src/showcase/demos/TooltipDemo.svelte +0 -54
  220. package/src/showcase/editor.css +0 -93
  221. package/src/showcase/index.ts +0 -17
  222. package/src/styles/fonts/Domine/Domine-VariableFont_wght.ttf +0 -0
  223. package/src/styles/fonts/Domine/OFL.txt +0 -97
  224. package/src/styles/fonts/Domine/README.txt +0 -66
  225. /package/src/{showcase → ui}/curveEngine.ts +0 -0
@@ -0,0 +1,263 @@
1
+ <script context="module" lang="ts">
2
+ import { buildSiblings } from './scaffolding/siblings';
3
+ import type { Token, TypeGroupConfig } from './scaffolding/types';
4
+
5
+ export const component = 'sectiondivider';
6
+
7
+ type Variant = 'canvas' | 'neutral' | 'alternate' | 'primary' | 'accent' | 'special';
8
+ const variants: { key: Variant; title: string }[] = [
9
+ { key: 'primary', title: 'Primary' },
10
+ { key: 'accent', title: 'Accent' },
11
+ { key: 'neutral', title: 'Neutral' },
12
+ { key: 'special', title: 'Special' },
13
+ { key: 'canvas', title: 'Canvas' },
14
+ { key: 'alternate', title: 'Alternate' },
15
+ ];
16
+
17
+ /** Frame tokens for a variant. Gradient tokens are owned by GradientCard, and
18
+ * outline thickness/color are rendered nested under the title TypeEditor;
19
+ * both are emitted only for `allTokens` (reset/registry) — not for the
20
+ * per-state token grid. */
21
+ function frameTokens(v: Variant): Token[] {
22
+ return [
23
+ { label: 'padding', canBeLinked: true, groupKey: 'padding', variable: `--sectiondivider-${v}-padding` },
24
+ { label: 'corner radius', canBeLinked: true, groupKey: 'radius', variable: `--sectiondivider-${v}-radius` },
25
+ { label: 'border color', canBeLinked: true, groupKey: 'border', variable: `--sectiondivider-${v}-border` },
26
+ { label: 'border width', canBeLinked: true, groupKey: 'border-width', variable: `--sectiondivider-${v}-border-width` },
27
+ { label: 'drop shadow', canBeLinked: true, groupKey: 'shadow', variable: `--sectiondivider-${v}-shadow` },
28
+ ];
29
+ }
30
+ /** Title outline tokens — rendered inside the title TypeEditor (not the
31
+ * property grid) but registered here so reset/linkage still see them. */
32
+ function titleOutlineTokens(v: Variant): Token[] {
33
+ return [
34
+ { label: 'outline thickness', canBeLinked: true, groupKey: 'title-border-width', variable: `--sectiondivider-${v}-title-border-width` },
35
+ { label: 'outline color', canBeLinked: true, groupKey: 'title-stroke-color', variable: `--sectiondivider-${v}-title-stroke-color` },
36
+ ];
37
+ }
38
+ function gradientTokens(v: Variant): Token[] {
39
+ return [
40
+ { label: 'gradient angle', groupKey: 'angle', variable: `--sectiondivider-${v}-gradient-angle` },
41
+ { label: 'gradient stop 1 color', groupKey: 'color', variable: `--sectiondivider-${v}-gradient-stop-1-color` },
42
+ { label: 'gradient stop 1 position', groupKey: 'position', variable: `--sectiondivider-${v}-gradient-stop-1-position` },
43
+ { label: 'gradient stop 2 color', groupKey: 'color', variable: `--sectiondivider-${v}-gradient-stop-2-color` },
44
+ { label: 'gradient stop 2 position', groupKey: 'position', variable: `--sectiondivider-${v}-gradient-stop-2-position` },
45
+ { label: 'gradient stop 3 color', groupKey: 'color', variable: `--sectiondivider-${v}-gradient-stop-3-color` },
46
+ { label: 'gradient stop 3 position', groupKey: 'position', variable: `--sectiondivider-${v}-gradient-stop-3-position` },
47
+ ];
48
+ }
49
+ function variantTokens(v: Variant): Token[] {
50
+ return [...frameTokens(v), ...titleOutlineTokens(v), ...gradientTokens(v)];
51
+ }
52
+
53
+ /** Two type groups per variant: title and description. The TypeEditor
54
+ * fieldset visually groups each color with its font-shape props. The
55
+ * title fieldset also nests the SVG-text outline width + color so those
56
+ * controls sit with the typography that drives them. */
57
+ function variantTypeGroups(v: Variant): TypeGroupConfig[] {
58
+ return [
59
+ {
60
+ legend: 'title',
61
+ colorVariable: `--sectiondivider-${v}-title`,
62
+ familyVariable: `--sectiondivider-${v}-title-font-family`,
63
+ sizeVariable: `--sectiondivider-${v}-title-font-size`,
64
+ weightVariable: `--sectiondivider-${v}-title-font-weight`,
65
+ lineHeightVariable: `--sectiondivider-${v}-title-line-height`,
66
+ outlineWidthVariable: `--sectiondivider-${v}-title-border-width`,
67
+ outlineColorVariable: `--sectiondivider-${v}-title-stroke-color`,
68
+ },
69
+ {
70
+ legend: 'description',
71
+ colorVariable: `--sectiondivider-${v}-description`,
72
+ familyVariable: `--sectiondivider-${v}-description-font-family`,
73
+ sizeVariable: `--sectiondivider-${v}-description-font-size`,
74
+ weightVariable: `--sectiondivider-${v}-description-font-weight`,
75
+ lineHeightVariable: `--sectiondivider-${v}-description-line-height`,
76
+ },
77
+ ];
78
+ }
79
+
80
+ /** Token registry entries for the type-group properties. Colors are emitted
81
+ * with canBeLinked so the LinkedBlock keeps the cross-variant linkage they
82
+ * ship with (title/description colors share the same theme defaults across
83
+ * every variant). */
84
+ function variantTypeGroupTokens(v: Variant): Token[] {
85
+ return [
86
+ { label: 'title color', canBeLinked: true, groupKey: 'title-color', variable: `--sectiondivider-${v}-title` },
87
+ { label: 'title font family', canBeLinked: true, groupKey: 'title-font-family', variable: `--sectiondivider-${v}-title-font-family` },
88
+ { label: 'title font size', canBeLinked: true, groupKey: 'title-font-size', variable: `--sectiondivider-${v}-title-font-size` },
89
+ { label: 'title font weight', canBeLinked: true, groupKey: 'title-font-weight', variable: `--sectiondivider-${v}-title-font-weight` },
90
+ { label: 'title line height', canBeLinked: true, groupKey: 'title-line-height', variable: `--sectiondivider-${v}-title-line-height` },
91
+ { label: 'description color', canBeLinked: true, groupKey: 'description-color', variable: `--sectiondivider-${v}-description` },
92
+ { label: 'description font family', canBeLinked: true, groupKey: 'description-font-family', variable: `--sectiondivider-${v}-description-font-family` },
93
+ { label: 'description font size', canBeLinked: true, groupKey: 'description-font-size', variable: `--sectiondivider-${v}-description-font-size` },
94
+ { label: 'description font weight', canBeLinked: true, groupKey: 'description-font-weight', variable: `--sectiondivider-${v}-description-font-weight` },
95
+ { label: 'description line height', canBeLinked: true, groupKey: 'description-line-height', variable: `--sectiondivider-${v}-description-line-height` },
96
+ ];
97
+ }
98
+
99
+ export const allTokens: Token[] = variants.flatMap((v) => [
100
+ ...variantTokens(v.key),
101
+ ...variantTypeGroupTokens(v.key),
102
+ ]);
103
+
104
+ // Linked block contexts: every linkable token registers under its variant name.
105
+ // Gradient stops are intentionally absent — they're variant-defining and never link.
106
+ const LINKED_GROUP_KEYS = [
107
+ 'padding', 'radius',
108
+ 'border', 'border-width', 'shadow',
109
+ 'title-border-width', 'title-stroke-color',
110
+ 'title-color', 'title-font-family', 'title-font-size', 'title-font-weight', 'title-line-height',
111
+ 'description-color', 'description-font-family', 'description-font-size', 'description-font-weight', 'description-line-height',
112
+ ] as const;
113
+ const linkableContexts = new Map<string, string>(
114
+ variants.flatMap((v) =>
115
+ [...variantTokens(v.key), ...variantTypeGroupTokens(v.key)]
116
+ .filter((t) => t.groupKey && (LINKED_GROUP_KEYS as readonly string[]).includes(t.groupKey))
117
+ .map((t) => [t.variable, v.key] as const),
118
+ ),
119
+ );
120
+
121
+ const variantOptions = variants.map((v) => ({ value: v.key, label: v.title }));
122
+ </script>
123
+
124
+ <script lang="ts">
125
+ import { onMount } from 'svelte';
126
+ import SectionDivider from '../components/SectionDivider.svelte';
127
+ import VariantGroup from './scaffolding/VariantGroup.svelte';
128
+ import ComponentEditorBase from './scaffolding/ComponentEditorBase.svelte';
129
+ import GradientCard from './scaffolding/GradientCard.svelte';
130
+ import ShadowBackdrop from './scaffolding/ShadowBackdrop.svelte';
131
+ import UIPaletteSelector from '../ui/UIPaletteSelector.svelte';
132
+ import { editorState } from '../lib/editorStore';
133
+ import { setCssVar } from '../lib/cssVarSync';
134
+ import { computeLinkedBlock, withLinkedDisabled } from './scaffolding/linkedBlock';
135
+
136
+ let testTitle = 'Section Title';
137
+ let showDescription = true;
138
+ let descriptionText = 'This text is meant to provide additional context or meaning.';
139
+
140
+ const bgVar = '--backdrop-sectiondivider-surface';
141
+
142
+ onMount(() => {
143
+ if (!document.documentElement.style.getPropertyValue(bgVar)) {
144
+ setCssVar(bgVar, 'var(--surface-canvas)');
145
+ }
146
+ });
147
+
148
+ $: linked = computeLinkedBlock(component, linkableContexts, allTokens, $editorState);
149
+ // The gradient tokens are owned by GradientCard, so the property grid only
150
+ // shows the frame tokens (padding/radius/outline). Gradient tokens still
151
+ // live in `allTokens` so they participate in reset and the registry.
152
+ $: visibleVariantTokens = (v: Variant) => withLinkedDisabled(frameTokens(v), linked.varSet);
153
+ </script>
154
+
155
+ <ComponentEditorBase {component} title="Section Divider" description="Full-width section banner with display font and palette variants. Import from <code>components/SectionDivider.svelte</code>" tokens={allTokens} {linked} variants={variantOptions}>
156
+ <svelte:fragment slot="config">
157
+ <label class="text-field">
158
+ <span>Test title</span>
159
+ <input type="text" bind:value={testTitle} placeholder="Section Title" />
160
+ </label>
161
+ <label class="checkbox-field">
162
+ <input type="checkbox" bind:checked={showDescription} />
163
+ <span>Show description</span>
164
+ </label>
165
+ <label class="text-field text-field-wide">
166
+ <span>Description text</span>
167
+ <input type="text" bind:value={descriptionText} placeholder="Description text" />
168
+ </label>
169
+ <label class="backdrop-config">
170
+ <span>Sample background</span>
171
+ <div class="picker-slot">
172
+ <UIPaletteSelector variable={bgVar} />
173
+ </div>
174
+ </label>
175
+ </svelte:fragment>
176
+ {#each variants as v}
177
+ <VariantGroup
178
+ name={v.key}
179
+ title={v.title}
180
+ states={{ [v.key]: visibleVariantTokens(v.key) }}
181
+ typeGroups={{ [v.key]: variantTypeGroups(v.key) }}
182
+ {component}
183
+ siblings={buildSiblings(
184
+ variants.map((x) => x.key),
185
+ v.key,
186
+ (sv) => ({ [sv]: variantTokens(sv) }),
187
+ (sv) => ({ [sv]: variantTypeGroups(sv) }),
188
+ )}
189
+ >
190
+ <ShadowBackdrop mode="color" colorVariable={bgVar} padding="32px">
191
+ <SectionDivider
192
+ title={testTitle || v.title}
193
+ variant={v.key}
194
+ description={showDescription ? descriptionText : undefined}
195
+ />
196
+ </ShadowBackdrop>
197
+ <svelte:fragment slot="composite-controls">
198
+ <span class="gradient-section-label">Gradient</span>
199
+ <GradientCard {component} prefix={`--sectiondivider-${v.key}`} />
200
+ </svelte:fragment>
201
+ </VariantGroup>
202
+ {/each}
203
+ </ComponentEditorBase>
204
+
205
+ <style>
206
+ .text-field,
207
+ .checkbox-field {
208
+ display: inline-flex;
209
+ align-items: center;
210
+ gap: var(--ui-space-8);
211
+ font-size: var(--ui-font-size-xs);
212
+ color: var(--ui-text-secondary);
213
+ }
214
+
215
+ .checkbox-field {
216
+ cursor: pointer;
217
+ user-select: none;
218
+ }
219
+
220
+ .checkbox-field input {
221
+ margin: 0;
222
+ cursor: pointer;
223
+ }
224
+
225
+ .text-field input {
226
+ padding: var(--ui-space-4) var(--ui-space-8);
227
+ background: var(--ui-surface-input);
228
+ color: var(--ui-text-primary);
229
+ border: 1px solid var(--ui-border-subtle);
230
+ border-radius: var(--ui-radius-sm);
231
+ font-family: var(--ui-font-mono);
232
+ font-size: var(--ui-font-size-xs);
233
+ min-width: 16rem;
234
+ }
235
+
236
+ .text-field-wide input {
237
+ min-width: 28rem;
238
+ }
239
+
240
+ .backdrop-config {
241
+ display: inline-flex;
242
+ align-items: center;
243
+ gap: var(--ui-space-8);
244
+ font-size: var(--ui-font-size-xs);
245
+ color: var(--ui-text-secondary);
246
+ }
247
+
248
+ .picker-slot {
249
+ min-width: 8rem;
250
+ }
251
+
252
+ .picker-slot :global(.ui-token-selector) {
253
+ width: 100%;
254
+ }
255
+
256
+ .gradient-section-label {
257
+ display: block;
258
+ margin-top: var(--ui-space-8);
259
+ font-size: var(--ui-font-size-md);
260
+ font-weight: 500;
261
+ color: var(--ui-text-primary);
262
+ }
263
+ </style>
@@ -0,0 +1,154 @@
1
+ <script context="module" lang="ts">
2
+ import { buildTypeGroupTokens, buildTypeGroupShareableContexts } from './scaffolding/buildTypeGroupTokens';
3
+ import type { Token, TypeGroupConfig } from './scaffolding/types';
4
+
5
+ export const component = 'segmentedcontrol';
6
+
7
+ // Non-text tokens per state. Text/font properties live in `typeGroups` below
8
+ // and are rendered via TypeEditor instead of TokenLayout.
9
+ const states: Record<string, Token[]> = {
10
+ 'control bar': [
11
+ { label: 'surface color', groupKey: 'surface', variable: '--segmentedcontrol-bar-surface' },
12
+ { label: 'border color', groupKey: 'border', variable: '--segmentedcontrol-bar-border' },
13
+ { label: 'border width', groupKey: 'width', variable: '--segmentedcontrol-bar-border-width' },
14
+ { label: 'divider color', groupKey: 'color', variable: '--segmentedcontrol-divider-color' },
15
+ { label: 'divider width', groupKey: 'thickness', variable: '--segmentedcontrol-divider-thickness' },
16
+ { label: 'divider height', groupKey: 'height', variable: '--segmentedcontrol-divider-height' },
17
+ { label: 'corner radius', groupKey: 'radius', variable: '--segmentedcontrol-bar-radius' },
18
+ { label: 'option gap', groupKey: 'gap', variable: '--segmentedcontrol-bar-gap' },
19
+ { label: 'padding', variable: '--segmentedcontrol-bar-padding', groupKey: 'bar-padding' },
20
+ { label: 'padding-top', variable: '--segmentedcontrol-bar-padding-top', groupKey: 'bar-padding-top', hidden: true },
21
+ { label: 'padding-right', variable: '--segmentedcontrol-bar-padding-right', groupKey: 'bar-padding-right', hidden: true },
22
+ { label: 'padding-bottom', variable: '--segmentedcontrol-bar-padding-bottom', groupKey: 'bar-padding-bottom', hidden: true },
23
+ { label: 'padding-left', variable: '--segmentedcontrol-bar-padding-left', groupKey: 'bar-padding-left', hidden: true },
24
+ ],
25
+ 'default option': [
26
+ { label: 'icon color', groupKey: 'icon', variable: '--segmentedcontrol-option-icon' },
27
+ { label: 'icon size', canBeLinked: true, groupKey: 'icon-size', variable: '--segmentedcontrol-option-icon-size' },
28
+ ],
29
+ 'selected option': [
30
+ { label: 'surface color', groupKey: 'surface', variable: '--segmentedcontrol-selected-surface' },
31
+ { label: 'icon color', groupKey: 'icon', variable: '--segmentedcontrol-selected-icon' },
32
+ { label: 'icon size', canBeLinked: true, groupKey: 'icon-size', variable: '--segmentedcontrol-selected-icon-size' },
33
+ { label: 'border color', groupKey: 'border', variable: '--segmentedcontrol-selected-border' },
34
+ { label: 'border width', groupKey: 'width', variable: '--segmentedcontrol-selected-border-width' },
35
+ { label: 'corner radius', groupKey: 'radius', variable: '--segmentedcontrol-selected-radius' },
36
+ ],
37
+ 'hover option': [
38
+ { label: 'surface color', groupKey: 'surface', variable: '--segmentedcontrol-option-hover-surface' },
39
+ { label: 'icon color', groupKey: 'icon', variable: '--segmentedcontrol-option-hover-icon' },
40
+ { label: 'icon size', canBeLinked: true, groupKey: 'icon-size', variable: '--segmentedcontrol-option-hover-icon-size' },
41
+ ],
42
+ 'disabled option': [
43
+ { label: 'surface color', groupKey: 'surface', variable: '--segmentedcontrol-disabled-surface' },
44
+ { label: 'icon color', groupKey: 'icon', variable: '--segmentedcontrol-disabled-icon' },
45
+ { label: 'icon size', canBeLinked: true, groupKey: 'icon-size', variable: '--segmentedcontrol-disabled-icon-size' },
46
+ ],
47
+ };
48
+
49
+ // Per-state typography groups for the option text element. All five
50
+ // properties are exposed and individually share-able via groupKey across
51
+ // the four states.
52
+ const typeGroups: Record<string, TypeGroupConfig[]> = {
53
+ 'default option': [{
54
+ legend: 'option text',
55
+ colorVariable: '--segmentedcontrol-option-text',
56
+ familyVariable: '--segmentedcontrol-option-text-font-family',
57
+ sizeVariable: '--segmentedcontrol-option-text-font-size',
58
+ weightVariable: '--segmentedcontrol-option-text-font-weight',
59
+ lineHeightVariable: '--segmentedcontrol-option-text-line-height',
60
+ }],
61
+ 'selected option': [{
62
+ legend: 'option text',
63
+ colorVariable: '--segmentedcontrol-selected-text',
64
+ familyVariable: '--segmentedcontrol-selected-text-font-family',
65
+ sizeVariable: '--segmentedcontrol-selected-text-font-size',
66
+ weightVariable: '--segmentedcontrol-selected-text-font-weight',
67
+ lineHeightVariable: '--segmentedcontrol-selected-text-line-height',
68
+ }],
69
+ 'hover option': [{
70
+ legend: 'option text',
71
+ colorVariable: '--segmentedcontrol-option-hover-text',
72
+ familyVariable: '--segmentedcontrol-option-hover-text-font-family',
73
+ sizeVariable: '--segmentedcontrol-option-hover-text-font-size',
74
+ weightVariable: '--segmentedcontrol-option-hover-text-font-weight',
75
+ lineHeightVariable: '--segmentedcontrol-option-hover-text-line-height',
76
+ }],
77
+ 'disabled option': [{
78
+ legend: 'option text',
79
+ colorVariable: '--segmentedcontrol-disabled-text',
80
+ familyVariable: '--segmentedcontrol-disabled-text-font-family',
81
+ sizeVariable: '--segmentedcontrol-disabled-text-font-size',
82
+ weightVariable: '--segmentedcontrol-disabled-text-font-weight',
83
+ lineHeightVariable: '--segmentedcontrol-disabled-text-line-height',
84
+ }],
85
+ };
86
+
87
+ // Schema entries for the type-group variables — registered for groupKey
88
+ // resolution but not rendered through TokenLayout. Derived from `typeGroups`
89
+ // so the four font props × four states stay in lockstep with the per-state
90
+ // TypeGroupConfig declarations above.
91
+ const typeGroupTokens: Token[] = buildTypeGroupTokens(typeGroups);
92
+ export const allTokens: Token[] = [...Object.values(states).flat(), ...typeGroupTokens];
93
+
94
+ const linkableContexts = new Map<string, string>([
95
+ ...buildTypeGroupShareableContexts(typeGroups),
96
+ ['--segmentedcontrol-option-icon-size', 'default option'],
97
+ ['--segmentedcontrol-selected-icon-size', 'selected option'],
98
+ ['--segmentedcontrol-option-hover-icon-size', 'hover option'],
99
+ ['--segmentedcontrol-disabled-icon-size', 'disabled option'],
100
+ ]);
101
+ </script>
102
+
103
+ <script lang="ts">
104
+ import SegmentedControl from '../components/SegmentedControl.svelte';
105
+ import VariantGroup from './scaffolding/VariantGroup.svelte';
106
+ import ComponentEditorBase from './scaffolding/ComponentEditorBase.svelte';
107
+ import { editorState } from '../lib/editorStore';
108
+ import { computeLinkedBlock, withLinkedDisabled } from './scaffolding/linkedBlock';
109
+
110
+ type Segment = { value: string; label: string; icon?: string; disabled?: boolean };
111
+ const segments: Segment[] = [
112
+ { value: 'option-1', label: 'Option 1', icon: 'fas fa-star' },
113
+ { value: 'option-2', label: 'Option 2', icon: 'fas fa-check' },
114
+ { value: 'option-3', label: 'Option 3', icon: 'fas fa-heart' },
115
+ ];
116
+ let showIcons = true;
117
+ $: previewSegments = showIcons ? segments : segments.map((s) => ({ ...s, icon: undefined }));
118
+
119
+ $: linked = computeLinkedBlock(component, linkableContexts, allTokens, $editorState);
120
+
121
+ $: visibleStates = Object.fromEntries(
122
+ Object.entries(states).map(([name, list]) => [name, withLinkedDisabled(list, linked.varSet)]),
123
+ ) as Record<string, Token[]>;
124
+ </script>
125
+
126
+ <ComponentEditorBase {component} title="Segmented Control" description="A connected set of buttons for toggling between mutually exclusive options." tokens={allTokens} {linked}>
127
+ <svelte:fragment slot="config">
128
+ <label>
129
+ <input type="checkbox" bind:checked={showIcons} />
130
+ <span>Show icons</span>
131
+ </label>
132
+ </svelte:fragment>
133
+ <VariantGroup
134
+ name="segmentedcontrol"
135
+ title="Segmented Control"
136
+ states={visibleStates}
137
+ {typeGroups}
138
+ {component}
139
+ let:activeState
140
+ >
141
+ {@const previewValue = activeState === 'selected option' ? 'option-2' : ''}
142
+ {@const previewForceHover = activeState === 'hover option' ? 'option-1' : null}
143
+ {@const previewDisabled = activeState === 'disabled option'}
144
+ <div>
145
+ <SegmentedControl
146
+ segments={previewSegments}
147
+ value={previewValue}
148
+ forceHoverValue={previewForceHover}
149
+ disabled={previewDisabled}
150
+ />
151
+ </div>
152
+ </VariantGroup>
153
+ </ComponentEditorBase>
154
+
@@ -0,0 +1,178 @@
1
+ <script context="module" lang="ts">
2
+ import { buildSiblings } from './scaffolding/siblings';
3
+ import type { Token } from './scaffolding/types';
4
+
5
+ export const component = 'button';
6
+
7
+ const variants = ['primary', 'secondary', 'outline', 'success', 'danger', 'warning'] as const;
8
+ type Variant = typeof variants[number];
9
+ const stateNames = ['default', 'hover', 'disabled'] as const;
10
+ type StateName = typeof stateNames[number];
11
+ function statePrefix(v: Variant, s: StateName): string {
12
+ return s === 'default' ? `--button-${v}` : `--button-${v}-${s}`;
13
+ }
14
+ /** Buttons have a single text slot, so its typography props live as peer
15
+ * rows in the unified token grid (no TypeEditor fieldset). Default state
16
+ * carries the full font shape (family/weight/size/line-height); hover and
17
+ * disabled only override text color, so they keep just the color row. */
18
+ function variantStateTokens(v: Variant, s: StateName): Token[] {
19
+ const p = statePrefix(v, s);
20
+ const tokens: Token[] = [
21
+ { label: 'surface color', groupKey: 'surface', variable: `${p}-surface` },
22
+ { label: 'border color', groupKey: 'border', variable: `${p}-border` },
23
+ { label: 'border width', canBeLinked: true, groupKey: 'border-width', variable: `${p}-border-width` },
24
+ { label: 'corner radius', canBeLinked: true, groupKey: 'radius', variable: `${p}-radius` },
25
+ { label: 'padding', canBeLinked: true, groupKey: 'padding', variable: `${p}-padding` },
26
+ ];
27
+ if (s === 'default') {
28
+ tokens.push(
29
+ { label: 'text color', groupKey: 'text', variable: `--button-${v}-text` },
30
+ { label: 'font family', canBeLinked: true, groupKey: 'font-family', variable: `--button-${v}-text-font-family` },
31
+ { label: 'font size', canBeLinked: true, groupKey: 'font-size', variable: `--button-${v}-text-font-size` },
32
+ { label: 'font weight', canBeLinked: true, groupKey: 'font-weight', variable: `--button-${v}-text-font-weight` },
33
+ { label: 'line height', canBeLinked: true, groupKey: 'line-height', variable: `--button-${v}-text-line-height` },
34
+ { label: 'icon size', canBeLinked: true, groupKey: 'icon-size', variable: `--button-${v}-icon-size` },
35
+ );
36
+ } else {
37
+ tokens.push({ label: 'text color', groupKey: 'text', variable: `--button-${v}-${s}-text` });
38
+ }
39
+ return tokens;
40
+ }
41
+
42
+ function variantStates(v: Variant): Record<string, Token[]> {
43
+ return Object.fromEntries(stateNames.map((s) => [s, variantStateTokens(v, s)]));
44
+ }
45
+ export const allTokens: Token[] = variants.flatMap((v) =>
46
+ Object.values(variantStates(v)).flat(),
47
+ );
48
+
49
+ // Linked block:
50
+ // - shape props (border-width, radius, padding) link across every variant × state — buttons share one geometry.
51
+ // - typography props link across all six variants.
52
+ const linkableContexts = new Map<string, string>([
53
+ ...variants.flatMap((v) => stateNames.flatMap((s) => [
54
+ [`${statePrefix(v, s)}-border-width`, `${v} ${s}`] as const,
55
+ [`${statePrefix(v, s)}-radius`, `${v} ${s}`] as const,
56
+ [`${statePrefix(v, s)}-padding`, `${v} ${s}`] as const,
57
+ ])),
58
+ ...variants.flatMap((v) => [
59
+ [`--button-${v}-text-font-family`, v] as const,
60
+ [`--button-${v}-text-font-size`, v] as const,
61
+ [`--button-${v}-text-font-weight`, v] as const,
62
+ [`--button-${v}-text-line-height`, v] as const,
63
+ [`--button-${v}-icon-size`, v] as const,
64
+ ]),
65
+ ]);
66
+
67
+ const variantOptions = variants.map((v) => ({ value: v, label: v.charAt(0).toUpperCase() + v.slice(1) }));
68
+ </script>
69
+
70
+ <script lang="ts">
71
+ import Button from '../components/Button.svelte';
72
+ import Toggle from '../ui/Toggle.svelte';
73
+ import VariantGroup from './scaffolding/VariantGroup.svelte';
74
+ import ComponentEditorBase from './scaffolding/ComponentEditorBase.svelte';
75
+ import { editorState, setComponentAlias } from '../lib/editorStore';
76
+ import { computeLinkedBlock, withLinkedDisabled } from './scaffolding/linkedBlock';
77
+
78
+ $: shimmerRef = $editorState.components.button?.aliases['--button-shimmer'];
79
+ $: shimmerEnabled = !(shimmerRef?.kind === 'token' && shimmerRef.name === '--shimmer-off');
80
+
81
+ function handleShimmerChange(e: CustomEvent<boolean>) {
82
+ setComponentAlias('button', '--button-shimmer', { kind: 'token', name: e.detail ? '--shimmer-on' : '--shimmer-off' });
83
+ }
84
+
85
+ $: linked = computeLinkedBlock(component, linkableContexts, allTokens, $editorState);
86
+
87
+ $: visibleVariantStates = (v: Variant) => Object.fromEntries(
88
+ Object.entries(variantStates(v)).map(([name, list]) => [name, withLinkedDisabled(list, linked.varSet)]),
89
+ ) as Record<string, Token[]>;
90
+ </script>
91
+
92
+ <ComponentEditorBase {component} title="Button" description="Reusable button component with multiple variants and sizes. Import from <code>components/Button.svelte</code>" tokens={allTokens} {linked} variants={variantOptions}>
93
+ <svelte:fragment slot="config">
94
+ <label>
95
+ <span>Hover shimmer</span>
96
+ <Toggle checked={shimmerEnabled} on:change={handleShimmerChange} />
97
+ </label>
98
+ </svelte:fragment>
99
+ {#each variants as v}
100
+ <VariantGroup
101
+ name={v}
102
+ title={v.charAt(0).toUpperCase() + v.slice(1)}
103
+ states={visibleVariantStates(v)}
104
+ {component}
105
+ columns={2}
106
+ siblings={buildSiblings(variants, v, variantStates)}
107
+ let:activeState
108
+ >
109
+ {@const forceClass = activeState === 'hover' ? 'force-hover' : ''}
110
+ {@const isDisabled = activeState === 'disabled'}
111
+ <div class="size-row">
112
+ <div class="size-section">
113
+ <span class="size-label">size="default"</span>
114
+ <div class="button-showcase-grid">
115
+ <div class="button-showcase-item">
116
+ <Button variant={v} disabled={isDisabled} class={forceClass}>{v.charAt(0).toUpperCase() + v.slice(1)}</Button>
117
+ </div>
118
+ <div class="button-showcase-item">
119
+ <Button variant={v} icon="fas fa-star" iconPosition="left" disabled={isDisabled} class={forceClass}>With Icon</Button>
120
+ </div>
121
+ </div>
122
+ </div>
123
+ <div class="size-divider"></div>
124
+ <div class="size-section">
125
+ <span class="size-label">size="small"</span>
126
+ <div class="button-showcase-grid">
127
+ <div class="button-showcase-item">
128
+ <Button variant={v} size="small" disabled={isDisabled} class={forceClass}>{v.charAt(0).toUpperCase() + v.slice(1)}</Button>
129
+ </div>
130
+ <div class="button-showcase-item">
131
+ <Button variant={v} size="small" icon="fas fa-star" iconPosition="left" disabled={isDisabled} class={forceClass}>With Icon</Button>
132
+ </div>
133
+ </div>
134
+ </div>
135
+ </div>
136
+ </VariantGroup>
137
+ {/each}
138
+ </ComponentEditorBase>
139
+
140
+ <style>
141
+ .size-row {
142
+ display: flex;
143
+ gap: var(--space-12);
144
+ align-items: flex-start;
145
+ }
146
+
147
+ .size-divider {
148
+ width: 1px;
149
+ background: var(--ui-border-faint);
150
+ align-self: stretch;
151
+ }
152
+
153
+ .size-section {
154
+ display: flex;
155
+ flex-direction: column;
156
+ gap: var(--space-8);
157
+ }
158
+
159
+ .size-label {
160
+ font-size: var(--font-size-xs);
161
+ font-family: var(--ui-font-mono);
162
+ color: var(--ui-text-tertiary);
163
+ }
164
+
165
+ .button-showcase-grid {
166
+ display: flex;
167
+ flex-wrap: wrap;
168
+ gap: var(--space-16);
169
+ align-items: start;
170
+ }
171
+
172
+ .button-showcase-item {
173
+ display: flex;
174
+ flex-direction: column;
175
+ gap: var(--space-8);
176
+ align-items: flex-start;
177
+ }
178
+ </style>