@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.
Files changed (232) hide show
  1. package/README.md +14 -13
  2. package/dist-plugin/index.cjs +854 -226
  3. package/dist-plugin/index.d.cts +2 -1
  4. package/dist-plugin/index.d.ts +2 -1
  5. package/dist-plugin/index.js +852 -225
  6. package/package.json +26 -40
  7. package/src/{styles → app}/site.css +1 -1
  8. package/src/{component-editor → editor/component-editor}/BadgeEditor.svelte +8 -82
  9. package/src/{component-editor → editor/component-editor}/CalloutEditor.svelte +4 -4
  10. package/src/{component-editor → editor/component-editor}/CardEditor.svelte +28 -76
  11. package/src/{component-editor → editor/component-editor}/CollapsibleSectionEditor.svelte +37 -30
  12. package/src/{component-editor → editor/component-editor}/CornerBadgeEditor.svelte +31 -93
  13. package/src/{component-editor → editor/component-editor}/DialogEditor.svelte +60 -57
  14. package/src/editor/component-editor/ImageEditor.svelte +30 -0
  15. package/src/{component-editor → editor/component-editor}/InlineEditActionsEditor.svelte +6 -4
  16. package/src/editor/component-editor/MenuSelectEditor.svelte +160 -0
  17. package/src/{component-editor → editor/component-editor}/NotificationEditor.svelte +67 -38
  18. package/src/{component-editor → editor/component-editor}/ProgressBarEditor.svelte +5 -4
  19. package/src/{component-editor → editor/component-editor}/RadioButtonEditor.svelte +3 -3
  20. package/src/editor/component-editor/SectionDividerEditor.svelte +565 -0
  21. package/src/{component-editor → editor/component-editor}/SegmentedControlEditor.svelte +2 -2
  22. package/src/{component-editor → editor/component-editor}/StandardButtonsEditor.svelte +29 -21
  23. package/src/{component-editor → editor/component-editor}/TabBarEditor.svelte +9 -14
  24. package/src/{component-editor → editor/component-editor}/TableEditor.svelte +9 -18
  25. package/src/{component-editor → editor/component-editor}/TooltipEditor.svelte +11 -47
  26. package/src/editor/component-editor/editors.d.ts +10 -0
  27. package/src/{component-editor → editor/component-editor}/registry.ts +28 -18
  28. package/src/{component-editor → editor/component-editor}/scaffolding/AngleDial.svelte +54 -15
  29. package/src/{component-editor → editor/component-editor}/scaffolding/ComponentEditorBase.svelte +3 -51
  30. package/src/{component-editor → editor/component-editor}/scaffolding/ComponentFileManager.svelte +151 -424
  31. package/src/{component-editor → editor/component-editor}/scaffolding/ComponentFileMenu.svelte +18 -170
  32. package/src/{component-editor → editor/component-editor}/scaffolding/ComponentsTab.svelte +2 -2
  33. package/src/{component-editor → editor/component-editor}/scaffolding/CopyFromMenu.svelte +44 -4
  34. package/src/{component-editor → editor/component-editor}/scaffolding/FieldsetWrapper.svelte +1 -1
  35. package/src/{component-editor → editor/component-editor}/scaffolding/LinkageChart.svelte +6 -6
  36. package/src/{component-editor → editor/component-editor}/scaffolding/LinkedBlock.svelte +6 -12
  37. package/src/editor/component-editor/scaffolding/NonStylableConfig.svelte +38 -0
  38. package/src/editor/component-editor/scaffolding/RadialShapePad.svelte +483 -0
  39. package/src/{component-editor → editor/component-editor}/scaffolding/SaveAsDialog.svelte +66 -12
  40. package/src/editor/component-editor/scaffolding/ShadowBackdrop.svelte +85 -0
  41. package/src/editor/component-editor/scaffolding/ShadowBackdropControls.svelte +132 -0
  42. package/src/editor/component-editor/scaffolding/StateBlock.svelte +345 -0
  43. package/src/{component-editor → editor/component-editor}/scaffolding/TokenLayout.svelte +17 -12
  44. package/src/{component-editor → editor/component-editor}/scaffolding/TypeEditor.svelte +13 -1
  45. package/src/editor/component-editor/scaffolding/VariantGroup.svelte +858 -0
  46. package/src/{component-editor → editor/component-editor}/scaffolding/buildTypeGroupTokens.ts +1 -0
  47. package/src/{component-editor → editor/component-editor}/scaffolding/editorContext.ts +19 -9
  48. package/src/{component-editor → editor/component-editor}/scaffolding/linkedBlock.ts +2 -2
  49. package/src/{component-editor → editor/component-editor}/scaffolding/types.ts +25 -0
  50. package/src/{lib → editor/core/components}/componentConfigKeys.ts +8 -0
  51. package/src/{lib → editor/core/components}/componentConfigService.ts +3 -3
  52. package/src/{lib → editor/core/components}/componentPersist.ts +11 -9
  53. package/src/editor/core/flashStatus.ts +30 -0
  54. package/src/{lib → editor/core/fonts}/fontLoader.ts +2 -2
  55. package/src/{lib → editor/core/fonts}/fontMigration.ts +4 -4
  56. package/src/{lib → editor/core/fonts}/fontParse.ts +1 -1
  57. package/src/editor/core/manifests/manifestService.ts +171 -0
  58. package/src/editor/core/palettes/familySwap.ts +99 -0
  59. package/src/{lib → editor/core/palettes}/paletteDerivation.ts +71 -2
  60. package/src/{lib → editor/core/palettes}/tokenRegistry.ts +9 -6
  61. package/src/editor/core/productionPulse.ts +37 -0
  62. package/src/{lib → editor/core/routing}/router.ts +1 -1
  63. package/src/{lib/files/versionedFileResource.ts → editor/core/storage/files/versionedFileResourceClient.ts} +8 -1
  64. package/src/{lib → editor/core/store}/editorCore.ts +24 -8
  65. package/src/{lib → editor/core/store}/editorPersistence.ts +3 -3
  66. package/src/{lib → editor/core/store}/editorRenderer.ts +2 -2
  67. package/src/{lib → editor/core/store}/editorStore.ts +222 -28
  68. package/src/{lib → editor/core/store}/editorTypes.ts +56 -13
  69. package/src/editor/core/store/gradientSource.ts +192 -0
  70. package/src/editor/core/themes/migrations/2026-05-19-collapsiblesection-drop-frame-surface.ts +28 -0
  71. package/src/editor/core/themes/migrations/2026-05-19-sectiondivider-rich-gradient.ts +35 -0
  72. package/src/editor/core/themes/migrations/2026-05-20-sectiondivider-slim-variants.ts +82 -0
  73. package/src/editor/core/themes/migrations/2026-05-21-sectiondivider-spacing-to-padding.ts +24 -0
  74. package/src/editor/core/themes/migrations/2026-05-22-sectiondivider-intrinsics-to-css.ts +81 -0
  75. package/src/{lib → editor/core/themes}/migrations/index.ts +10 -0
  76. package/src/{lib → editor/core/themes}/slices/columns.ts +2 -2
  77. package/src/{lib → editor/core/themes}/slices/components.ts +20 -6
  78. package/src/{lib → editor/core/themes}/slices/fonts.ts +1 -1
  79. package/src/{lib → editor/core/themes}/slices/gradients.ts +89 -14
  80. package/src/{lib → editor/core/themes}/slices/overlays.ts +1 -1
  81. package/src/{lib → editor/core/themes}/slices/palettes.ts +1 -1
  82. package/src/{lib → editor/core/themes}/slices/shadows.ts +3 -3
  83. package/src/{lib → editor/core/themes}/themeInit.ts +8 -8
  84. package/src/{lib → editor/core/themes}/themeService.ts +6 -6
  85. package/src/{lib → editor/core/themes}/themeTypes.ts +67 -8
  86. package/src/editor/index.ts +69 -0
  87. package/src/{lib → editor/overlay}/ColumnsOverlay.svelte +0 -1
  88. package/src/{lib → editor/overlay}/LiveEditorOverlay.svelte +80 -129
  89. package/src/{lib → editor/overlay}/columnsOverlay.ts +2 -2
  90. package/src/{pages → editor/pages}/ComponentEditorPage.svelte +12 -12
  91. package/src/{pages → editor/pages}/Editor.svelte +4 -4
  92. package/src/{pages → editor/pages}/EditorShell.svelte +18 -36
  93. package/src/{styles → editor/styles}/ui-editor.css +43 -22
  94. package/src/{styles → editor/styles}/ui-form-controls.css +23 -24
  95. package/src/{ui → editor/ui}/BezierCurveEditor.svelte +119 -68
  96. package/src/{ui → editor/ui}/ColorEditPanel.svelte +13 -13
  97. package/src/{ui → editor/ui}/EditorViewSwitcher.svelte +7 -6
  98. package/src/editor/ui/FileLoadList.svelte +367 -0
  99. package/src/editor/ui/FilePill.svelte +80 -0
  100. package/src/editor/ui/FontStackEditor.svelte +499 -0
  101. package/src/editor/ui/GradientEditor.svelte +690 -0
  102. package/src/{ui → editor/ui}/GradientStopPicker.svelte +12 -4
  103. package/src/editor/ui/ManifestFileManager.svelte +438 -0
  104. package/src/{ui → editor/ui}/PaletteEditor.svelte +180 -673
  105. package/src/editor/ui/ProjectFontsSection.svelte +638 -0
  106. package/src/{ui → editor/ui}/SurfacesTab.svelte +3 -3
  107. package/src/{ui → editor/ui}/TextTab.svelte +3 -3
  108. package/src/editor/ui/ThemeFileManager.svelte +783 -0
  109. package/src/{ui → editor/ui}/UICopyPopover.svelte +4 -4
  110. package/src/{ui → editor/ui}/UIFontFamilySelector.svelte +6 -7
  111. package/src/{ui → editor/ui}/UIFontSizeSelector.svelte +4 -1
  112. package/src/editor/ui/UIInfoPopover.svelte +243 -0
  113. package/src/editor/ui/UILetterSpacingSelector.svelte +65 -0
  114. package/src/{ui → editor/ui}/UILineHeightSelector.svelte +5 -5
  115. package/src/{ui → editor/ui}/UILinkToggle.svelte +2 -2
  116. package/src/{ui → editor/ui}/UIPaddingSelector.svelte +6 -6
  117. package/src/{ui → editor/ui}/UIPaletteSelector.svelte +57 -30
  118. package/src/editor/ui/UIPillButton.svelte +168 -0
  119. package/src/{ui → editor/ui}/UIRadio.svelte +2 -2
  120. package/src/{ui → editor/ui}/UIRelinkConfirmPopover.svelte +4 -4
  121. package/src/editor/ui/UISegmentedControl.svelte +114 -0
  122. package/src/editor/ui/UISquareButton.svelte +172 -0
  123. package/src/{ui → editor/ui}/UITokenSelector.svelte +14 -11
  124. package/src/{ui → editor/ui}/UIVariantSelector.svelte +1 -1
  125. package/src/{ui → editor/ui}/VariablesTab.svelte +46 -17
  126. package/src/{ui → editor/ui}/palette/GradientStopEditor.svelte +13 -13
  127. package/src/{ui → editor/ui}/palette/OverridesPanel.svelte +24 -47
  128. package/src/{ui → editor/ui}/palette/PaletteBase.svelte +11 -8
  129. package/src/{ui → editor/ui}/palette/paletteEditorState.ts +1 -1
  130. package/src/editor/ui/palette/paletteMath.ts +275 -0
  131. package/src/{ui → editor/ui}/sections/ColumnsSection.svelte +137 -18
  132. package/src/{ui → editor/ui}/sections/GradientsSection.svelte +8 -8
  133. package/src/{ui → editor/ui}/sections/OverlaysSection.svelte +18 -18
  134. package/src/{ui → editor/ui}/sections/ShadowsSection.svelte +23 -23
  135. package/src/{ui → editor/ui}/sections/TokenScaleTable.svelte +3 -3
  136. package/src/{components → system/components}/Badge.svelte +0 -36
  137. package/src/{components → system/components}/Button.svelte +2 -2
  138. package/src/{components → system/components}/Card.svelte +34 -60
  139. package/src/{components → system/components}/CollapsibleSection.svelte +25 -2
  140. package/src/{components → system/components}/CornerBadge.svelte +8 -24
  141. package/src/{components → system/components}/Dialog.svelte +1 -1
  142. package/src/system/components/FloatingTokenTags.css +275 -0
  143. package/src/system/components/FloatingTokenTags.svelte +543 -0
  144. package/src/{components → system/components}/InlineEditActions.svelte +6 -4
  145. package/src/system/components/MenuSelect.svelte +229 -0
  146. package/src/{components → system/components}/Notification.svelte +8 -1
  147. package/src/{components → system/components}/ProgressBar.svelte +29 -11
  148. package/src/system/components/SectionDivider.svelte +560 -0
  149. package/src/{components → system/components}/SegmentedControl.svelte +49 -43
  150. package/src/{components → system/components}/TabBar.svelte +81 -65
  151. package/src/{components → system/components}/Table.svelte +17 -3
  152. package/src/{components → system/components}/Tooltip.svelte +6 -4
  153. package/src/system/styles/CONVENTIONS.md +178 -0
  154. package/src/system/styles/fonts.css +20 -0
  155. package/src/system/styles/tokens.css +601 -0
  156. package/src/system/styles/tokens.generated.css +544 -0
  157. package/src/component-editor/ImageEditor.svelte +0 -74
  158. package/src/component-editor/SectionDividerEditor.svelte +0 -265
  159. package/src/component-editor/scaffolding/DividerEditor.svelte +0 -94
  160. package/src/component-editor/scaffolding/GradientCard.svelte +0 -296
  161. package/src/component-editor/scaffolding/NonStylableConfig.svelte +0 -62
  162. package/src/component-editor/scaffolding/ShadowBackdrop.svelte +0 -37
  163. package/src/component-editor/scaffolding/ShadowBackdropControls.svelte +0 -61
  164. package/src/component-editor/scaffolding/StateBlock.svelte +0 -132
  165. package/src/component-editor/scaffolding/VariantGroup.svelte +0 -310
  166. package/src/components/SectionDivider.svelte +0 -483
  167. package/src/data/google-fonts.json +0 -75
  168. package/src/lib/index.ts +0 -68
  169. package/src/lib/presetService.ts +0 -214
  170. package/src/lib/productionPulse.ts +0 -32
  171. package/src/styles/fonts.css +0 -30
  172. package/src/styles/tokens.css +0 -1324
  173. package/src/ui/FontStackEditor.svelte +0 -361
  174. package/src/ui/GradientEditor.svelte +0 -470
  175. package/src/ui/PresetFileManager.svelte +0 -1116
  176. package/src/ui/ProjectFontsSection.svelte +0 -645
  177. package/src/ui/ThemeFileManager.svelte +0 -1020
  178. package/src/ui/UnsavedComponentsDialog.svelte +0 -315
  179. /package/src/{component-editor → editor/component-editor}/index.ts +0 -0
  180. /package/src/{component-editor → editor/component-editor}/scaffolding/DemoHeader.svelte +0 -0
  181. /package/src/{component-editor → editor/component-editor}/scaffolding/componentSectionType.ts +0 -0
  182. /package/src/{component-editor → editor/component-editor}/scaffolding/componentSources.ts +0 -0
  183. /package/src/{component-editor → editor/component-editor}/scaffolding/defaultSections.ts +0 -0
  184. /package/src/{component-editor → editor/component-editor}/scaffolding/siblings.ts +0 -0
  185. /package/src/{lib → editor/core}/cssVarSync.ts +0 -0
  186. /package/src/{lib → editor/core/palettes}/oklch.ts +0 -0
  187. /package/src/{lib → editor/core/routing}/navLinkTypes.ts +0 -0
  188. /package/src/{lib → editor/core/routing}/parentRouteStore.ts +0 -0
  189. /package/src/{lib → editor/core/storage}/storage.ts +0 -0
  190. /package/src/{lib → editor/core/store}/editorConfig.ts +0 -0
  191. /package/src/{lib → editor/core/store}/editorConfigStore.ts +0 -0
  192. /package/src/{lib → editor/core/store}/editorKeybindings.ts +0 -0
  193. /package/src/{lib → editor/core/store}/editorViewStore.ts +0 -0
  194. /package/src/{lib → editor/core/themes}/migrations/2026-04-24-component-prefix-and-suffix-renames.ts +0 -0
  195. /package/src/{lib → editor/core/themes}/migrations/2026-04-24-legacy-keys-and-bg-to-canvas.ts +0 -0
  196. /package/src/{lib → editor/core/themes}/migrations/2026-04-27-segmentedcontrol-disabled-flatten.ts +0 -0
  197. /package/src/{lib → editor/core/themes}/migrations/2026-05-08-collapsiblesection-frame-and-cleanup.ts +0 -0
  198. /package/src/{lib → editor/core/themes}/migrations/2026-05-08-collapsiblesection-variant-namespace.ts +0 -0
  199. /package/src/{lib → editor/core/themes}/migrations/2026-05-10-sectiondivider-gradient-stops.ts +0 -0
  200. /package/src/{lib → editor/core/themes}/migrations/2026-05-13-primary-to-brand.ts +0 -0
  201. /package/src/{lib → editor/core/themes}/parsers/globalRootBlock.ts +0 -0
  202. /package/src/{lib → editor/core/themes}/slices/domainVars.ts +0 -0
  203. /package/src/{lib → editor/overlay}/overlayState.ts +0 -0
  204. /package/src/{pages → editor/pages}/ComponentEditorPage.svelte.d.ts +0 -0
  205. /package/src/{pages → editor/pages}/Editor.svelte.d.ts +0 -0
  206. /package/src/{ui → editor/ui}/Toggle.svelte +0 -0
  207. /package/src/{ui → editor/ui}/UIDialog.svelte +0 -0
  208. /package/src/{ui → editor/ui}/UIFontWeightSelector.svelte +0 -0
  209. /package/src/{ui → editor/ui}/UIOptionItem.svelte +0 -0
  210. /package/src/{ui → editor/ui}/UIOptionList.svelte +0 -0
  211. /package/src/{ui → editor/ui}/UIRadioGroup.svelte +0 -0
  212. /package/src/{lib → editor/ui}/copyPopover.ts +0 -0
  213. /package/src/{ui → editor/ui}/curveEngine.ts +0 -0
  214. /package/src/{ui → editor/ui}/index.ts +0 -0
  215. /package/src/{ui → editor/ui}/keepInViewport.ts +0 -0
  216. /package/src/{ui → editor/ui}/palette/ScaleCurveEditor.svelte +0 -0
  217. /package/src/{lib → editor/ui}/scrollSection.ts +0 -0
  218. /package/src/{ui → editor/ui}/sections/tokenScales.ts +0 -0
  219. /package/src/{ui → editor/ui}/variantScales.ts +0 -0
  220. /package/src/{assets → system/assets}/newspaper.webp +0 -0
  221. /package/src/{assets → system/assets}/offering.webp +0 -0
  222. /package/src/{components → system/components}/Callout.svelte +0 -0
  223. /package/src/{components → system/components}/Image.svelte +0 -0
  224. /package/src/{components → system/components}/RadioButton.svelte +0 -0
  225. /package/src/{components → system/components}/types.ts +0 -0
  226. /package/src/{styles → system/styles}/_padding.scss +0 -0
  227. /package/src/{styles → system/styles}/fonts/Fraunces/Fraunces-italic-latin-ext.woff2 +0 -0
  228. /package/src/{styles → system/styles}/fonts/Fraunces/Fraunces-italic-latin.woff2 +0 -0
  229. /package/src/{styles → system/styles}/fonts/Fraunces/Fraunces-roman-latin-ext.woff2 +0 -0
  230. /package/src/{styles → system/styles}/fonts/Fraunces/Fraunces-roman-latin.woff2 +0 -0
  231. /package/src/{styles → system/styles}/fonts/Manrope/Manrope-latin-ext.woff2 +0 -0
  232. /package/src/{styles → system/styles}/fonts/Manrope/Manrope-latin.woff2 +0 -0
@@ -0,0 +1,565 @@
1
+ <script 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
+ /** Variant axis = full presets. Each variant owns its size/typography +
8
+ * colors/background, AND its intrinsic display properties (align,
9
+ * hairline, eyebrow + description visibility). */
10
+ type Variant = 'lg' | 'md' | 'sm';
11
+ const variants: { key: Variant; title: string; family: string }[] = [
12
+ { key: 'lg', title: 'Large', family: 'canvas' },
13
+ { key: 'md', title: 'Medium', family: 'canvas' },
14
+ { key: 'sm', title: 'Small', family: 'canvas' },
15
+ ];
16
+
17
+ function containerTokens(v: Variant): Token[] {
18
+ return [
19
+ { label: 'corner radius', canBeLinked: true, groupKey: 'radius', variable: `--sectiondivider-${v}-radius`, element: 'Container' },
20
+ { label: 'drop shadow', canBeLinked: true, groupKey: 'shadow', variable: `--sectiondivider-${v}-shadow`, element: 'Container' },
21
+ { label: 'padding', canBeLinked: true, groupKey: 'container-padding', variable: `--sectiondivider-${v}-padding`, element: 'Container' },
22
+ { label: 'border width', canBeLinked: true, groupKey: 'border-width', variable: `--sectiondivider-${v}-border-width`, element: 'Container' },
23
+ { label: 'border color', canBeLinked: true, groupKey: 'border', variable: `--sectiondivider-${v}-border`, element: 'Container' },
24
+ ];
25
+ }
26
+ function typePaddingTokens(v: Variant): Token[] {
27
+ return [
28
+ { label: 'padding', canBeLinked: true, groupKey: 'title-padding', variable: `--sectiondivider-${v}-title-padding`, element: 'title' },
29
+ { label: 'padding', canBeLinked: true, groupKey: 'description-padding', variable: `--sectiondivider-${v}-description-padding`, element: 'description' },
30
+ { label: 'padding', canBeLinked: true, groupKey: 'eyebrow-padding', variable: `--sectiondivider-${v}-eyebrow-padding`, element: 'eyebrow' },
31
+ ];
32
+ }
33
+ function hairlineTokens(v: Variant): Token[] {
34
+ return [
35
+ { label: 'hairline color', canBeLinked: true, groupKey: 'hairline-color', variable: `--sectiondivider-${v}-hairline-color`, element: 'hairline' },
36
+ { label: 'hairline thickness', canBeLinked: true, groupKey: 'hairline-thickness', variable: `--sectiondivider-${v}-hairline-thickness`, element: 'hairline' },
37
+ ];
38
+ }
39
+ function titleOutlineTokens(v: Variant): Token[] {
40
+ return [
41
+ { label: 'outline thickness', canBeLinked: true, groupKey: 'title-outline-width', variable: `--sectiondivider-${v}-title-outline-width`, element: 'title' },
42
+ { label: 'outline color', canBeLinked: true, groupKey: 'title-outline-color', variable: `--sectiondivider-${v}-title-outline-color`, element: 'title' },
43
+ ];
44
+ }
45
+ function backgroundTokens(v: Variant): Token[] {
46
+ return [
47
+ { label: 'background', groupKey: 'background', variable: `--sectiondivider-${v}-background`, kind: 'gradient', family: variants.find((x) => x.key === v)!.family },
48
+ ];
49
+ }
50
+ function variantTokens(v: Variant): Token[] {
51
+ return [...containerTokens(v), ...hairlineTokens(v), ...titleOutlineTokens(v), ...backgroundTokens(v), ...typePaddingTokens(v)];
52
+ }
53
+ function stateTokens(v: Variant): Token[] {
54
+ return [
55
+ ...containerTokens(v),
56
+ ...hairlineTokens(v),
57
+ ...titleOutlineTokens(v).map((t) => ({ ...t, hidden: true })),
58
+ ...backgroundTokens(v).map((t) => ({ ...t, hidden: true })),
59
+ ...typePaddingTokens(v),
60
+ ];
61
+ }
62
+
63
+ function variantTypeGroups(v: Variant): TypeGroupConfig[] {
64
+ return [
65
+ {
66
+ legend: '',
67
+ element: 'title',
68
+ colorVariable: `--sectiondivider-${v}-title`,
69
+ familyVariable: `--sectiondivider-${v}-title-font-family`,
70
+ sizeVariable: `--sectiondivider-${v}-title-font-size`,
71
+ weightVariable: `--sectiondivider-${v}-title-font-weight`,
72
+ lineHeightVariable: `--sectiondivider-${v}-title-line-height`,
73
+ letterSpacingVariable: `--sectiondivider-${v}-title-letter-spacing`,
74
+ outlineWidthVariable: `--sectiondivider-${v}-title-outline-width`,
75
+ outlineColorVariable: `--sectiondivider-${v}-title-outline-color`,
76
+ },
77
+ {
78
+ legend: '',
79
+ element: 'description',
80
+ colorVariable: `--sectiondivider-${v}-description`,
81
+ familyVariable: `--sectiondivider-${v}-description-font-family`,
82
+ sizeVariable: `--sectiondivider-${v}-description-font-size`,
83
+ weightVariable: `--sectiondivider-${v}-description-font-weight`,
84
+ lineHeightVariable: `--sectiondivider-${v}-description-line-height`,
85
+ },
86
+ {
87
+ legend: '',
88
+ element: 'eyebrow',
89
+ colorVariable: `--sectiondivider-${v}-eyebrow`,
90
+ familyVariable: `--sectiondivider-${v}-eyebrow-font-family`,
91
+ sizeVariable: `--sectiondivider-${v}-eyebrow-font-size`,
92
+ weightVariable: `--sectiondivider-${v}-eyebrow-font-weight`,
93
+ letterSpacingVariable: `--sectiondivider-${v}-eyebrow-letter-spacing`,
94
+ },
95
+ ];
96
+ }
97
+
98
+ function variantTypeGroupTokens(v: Variant): Token[] {
99
+ return [
100
+ { label: 'title color', canBeLinked: true, groupKey: 'title-color', variable: `--sectiondivider-${v}-title` },
101
+ { label: 'title font family', canBeLinked: true, groupKey: 'title-font-family', variable: `--sectiondivider-${v}-title-font-family` },
102
+ { label: 'title font weight', canBeLinked: true, groupKey: 'title-font-weight', variable: `--sectiondivider-${v}-title-font-weight` },
103
+ { label: 'title font size', variable: `--sectiondivider-${v}-title-font-size` },
104
+ { label: 'title line height', canBeLinked: true, groupKey: 'title-line-height', variable: `--sectiondivider-${v}-title-line-height` },
105
+ { label: 'title letter spacing', canBeLinked: true, groupKey: 'title-letter-spacing', variable: `--sectiondivider-${v}-title-letter-spacing` },
106
+ { label: 'description color', canBeLinked: true, groupKey: 'description-color', variable: `--sectiondivider-${v}-description` },
107
+ { label: 'description font family', canBeLinked: true, groupKey: 'description-font-family', variable: `--sectiondivider-${v}-description-font-family` },
108
+ { label: 'description font weight', canBeLinked: true, groupKey: 'description-font-weight', variable: `--sectiondivider-${v}-description-font-weight` },
109
+ { label: 'description font size', variable: `--sectiondivider-${v}-description-font-size` },
110
+ { label: 'description line height', canBeLinked: true, groupKey: 'description-line-height', variable: `--sectiondivider-${v}-description-line-height` },
111
+ { label: 'eyebrow color', canBeLinked: true, groupKey: 'eyebrow-color', variable: `--sectiondivider-${v}-eyebrow` },
112
+ { label: 'eyebrow font family', canBeLinked: true, groupKey: 'eyebrow-font-family', variable: `--sectiondivider-${v}-eyebrow-font-family` },
113
+ { label: 'eyebrow font weight', canBeLinked: true, groupKey: 'eyebrow-font-weight', variable: `--sectiondivider-${v}-eyebrow-font-weight` },
114
+ { label: 'eyebrow font size', variable: `--sectiondivider-${v}-eyebrow-font-size` },
115
+ { label: 'eyebrow letter spacing', canBeLinked: true, groupKey: 'eyebrow-letter-spacing', variable: `--sectiondivider-${v}-eyebrow-letter-spacing` },
116
+ ];
117
+ }
118
+
119
+ export const allTokens: Token[] = variants.flatMap((v) => [
120
+ ...variantTokens(v.key),
121
+ ...variantTypeGroupTokens(v.key),
122
+ ]);
123
+
124
+ const LINKED_GROUP_KEYS = [
125
+ 'container-padding', 'radius', 'border', 'border-width', 'shadow',
126
+ 'hairline-color', 'hairline-thickness',
127
+ 'title-outline-width', 'title-outline-color',
128
+ 'title-color', 'description-color', 'eyebrow-color',
129
+ 'title-padding', 'description-padding', 'eyebrow-padding',
130
+ 'title-font-family', 'title-font-weight', 'title-line-height', 'title-letter-spacing',
131
+ 'description-font-family', 'description-font-weight', 'description-line-height',
132
+ 'eyebrow-font-family', 'eyebrow-font-weight', 'eyebrow-letter-spacing',
133
+ ] as const;
134
+ const linkableContexts = new Map<string, string>(
135
+ variants.flatMap((v) =>
136
+ [...variantTokens(v.key), ...variantTypeGroupTokens(v.key)]
137
+ .filter((t) => t.groupKey && (LINKED_GROUP_KEYS as readonly string[]).includes(t.groupKey))
138
+ .map((t) => [t.variable, v.key] as const),
139
+ ),
140
+ );
141
+
142
+ const variantOptions = variants.map((v) => ({ value: v.key, label: v.title }));
143
+
144
+ type Align = 'start' | 'center';
145
+ type HairlinePosition =
146
+ | 'above-label'
147
+ | 'through-label'
148
+ | 'below-label'
149
+ | 'above-description'
150
+ | 'through-description'
151
+ | 'below-description';
152
+ </script>
153
+
154
+ <script lang="ts">
155
+ import SectionDivider from '../../system/components/SectionDivider.svelte';
156
+ import VariantGroup from './scaffolding/VariantGroup.svelte';
157
+ import ComponentEditorBase from './scaffolding/ComponentEditorBase.svelte';
158
+ import GradientEditor from '../ui/GradientEditor.svelte';
159
+ import { editorState, mutate, setComponentAlias, setComponentConfig } from '../core/store/editorStore';
160
+ import { componentGradientSource } from '../core/store/gradientSource';
161
+ import { computeLinkedBlock, withLinkedDisabled } from './scaffolding/linkedBlock';
162
+ import { KNOWN_FAMILIES, swapTokenFamily } from '../core/palettes/familySwap';
163
+
164
+ // Variants list above carries a default family ('canvas') used as the starting
165
+ // value for new presets. Live family is per-variant config so the user can
166
+ // swap a divider's color world without touching the variants array.
167
+ const FAMILY_OPTIONS: { value: string; label: string }[] = KNOWN_FAMILIES.map((f) => ({
168
+ value: f,
169
+ label: f.charAt(0).toUpperCase() + f.slice(1),
170
+ }));
171
+
172
+ const SAMPLE_TITLE: Record<Variant, string> = {
173
+ lg: 'Large Section',
174
+ md: 'Medium Section',
175
+ sm: 'Small Section',
176
+ };
177
+ const SAMPLE_EYEBROW = 'Section Eyebrow';
178
+ const SAMPLE_DESCRIPTION = 'This text is meant to provide additional context or meaning.';
179
+
180
+ // Intrinsic per-variant properties live in the aliases bucket as literal
181
+ // CssVarRefs, so they cascade to `:root` via cssVarSync and reach every
182
+ // live consumer instance. `color-family` is editor metadata (drives the
183
+ // family-swap rewrite, not a runtime CSS value) and stays in the config
184
+ // bucket.
185
+ let aliases = $derived(($editorState.components[component]?.aliases ?? {}) as Record<string, import('../core/store/editorTypes').CssVarRef>);
186
+ let cfg = $derived(($editorState.components[component]?.config ?? {}) as Record<string, unknown>);
187
+
188
+ function readLiteral(key: string): string | undefined {
189
+ const ref = aliases[key];
190
+ if (!ref || ref.kind !== 'literal') return undefined;
191
+ return ref.value;
192
+ }
193
+
194
+ function getAlign(v: Variant): Align {
195
+ return readLiteral(`--sectiondivider-${v}-align`) === 'start' ? 'start' : 'center';
196
+ }
197
+ function getColorFamily(v: Variant): string {
198
+ const raw = cfg[`--sectiondivider-${v}-color-family`];
199
+ if (typeof raw === 'string' && (KNOWN_FAMILIES as readonly string[]).includes(raw)) return raw;
200
+ return variants.find((x) => x.key === v)!.family;
201
+ }
202
+ /** Active hairline position OR `'none'` (= hidden). */
203
+ function getHairlineValue(v: Variant): HairlinePosition | 'none' {
204
+ const raw = readLiteral(`--sectiondivider-${v}-hairline`);
205
+ if (raw === undefined || raw === 'none') return 'none';
206
+ // 'above-description' renders identically to 'below-label' — coerce on read
207
+ // so the dropdown's option list (which omits 'above-description') stays valid.
208
+ if (raw === 'above-description') return 'below-label';
209
+ const positions: HairlinePosition[] = ['above-label', 'through-label', 'below-label', 'through-description', 'below-description'];
210
+ return (positions as string[]).includes(raw) ? (raw as HairlinePosition) : 'none';
211
+ }
212
+ function getShowHairline(v: Variant): boolean {
213
+ return getHairlineValue(v) !== 'none';
214
+ }
215
+ /** Position bound to the position select. Falls back to 'above-label' when
216
+ * hairline is hidden, so the dropdown displays a sensible value while
217
+ * toggled off. */
218
+ function getHairlinePosition(v: Variant): HairlinePosition {
219
+ const val = getHairlineValue(v);
220
+ return val === 'none' ? 'above-label' : val;
221
+ }
222
+ function getShowEyebrow(v: Variant): boolean {
223
+ return readLiteral(`--sectiondivider-${v}-eyebrow-display`) === 'block';
224
+ }
225
+ function getEyebrowUppercase(v: Variant): boolean {
226
+ return readLiteral(`--sectiondivider-${v}-eyebrow-text-transform`) === 'uppercase';
227
+ }
228
+ function getShowDescription(v: Variant): boolean {
229
+ const raw = readLiteral(`--sectiondivider-${v}-description-display`);
230
+ // Default: shown (flex) when unset. Matches the :root default and the
231
+ // legacy `getShowDescription` semantics for files that never set the key.
232
+ if (raw === undefined) return true;
233
+ return raw === 'flex';
234
+ }
235
+ /** Write an intrinsic to the aliases bucket as a literal so it cascades
236
+ * through cssVarSync to `:root` on both the editor iframe and host page. */
237
+ function setIntrinsic(v: Variant, prop: string, value: string) {
238
+ setComponentAlias(component, `--sectiondivider-${v}-${prop}`, { kind: 'literal', value });
239
+ }
240
+ function setCfg(v: Variant, prop: string, value: string) {
241
+ setComponentConfig(component, `--sectiondivider-${v}-${prop}`, value);
242
+ }
243
+
244
+ let linked = $derived(computeLinkedBlock(component, linkableContexts, allTokens, $editorState));
245
+ let visibleVariantTokens = $derived((v: Variant) => withLinkedDisabled(stateTokens(v), linked.varSet));
246
+
247
+ const gradientSources = Object.fromEntries(
248
+ variants.map((v) => [v.key, componentGradientSource(component, `--sectiondivider-${v.key}-background`)]),
249
+ ) as Record<Variant, ReturnType<typeof componentGradientSource>>;
250
+
251
+ // Family swap on color-family change: for every alias under this variant
252
+ // that currently references `oldFamily`, rewrite the reference to
253
+ // `newFamily`. Aliases targeting other families are left alone so an
254
+ // intentionally-cross-family border doesn't get swept along. Gradient stops
255
+ // flagged `monochrome: false` are off-palette overrides — those skip the
256
+ // rewrite so the user's deliberate non-family stop survives the swap.
257
+ function remapFamily(v: Variant, oldFamily: string, newFamily: string) {
258
+ if (oldFamily === newFamily) return;
259
+ const prefix = `--sectiondivider-${v}-`;
260
+ mutate(`color-family remap ${v} ${oldFamily}->${newFamily}`, (s) => {
261
+ const slice = s.components[component];
262
+ if (!slice) return;
263
+ for (const [key, ref] of Object.entries(slice.aliases)) {
264
+ if (!key.startsWith(prefix)) continue;
265
+ if (ref.kind === 'token') {
266
+ const swapped = swapTokenFamily(ref.name, oldFamily, newFamily);
267
+ if (swapped !== ref.name) {
268
+ slice.aliases[key] = { kind: 'token', name: swapped };
269
+ }
270
+ } else if (ref.kind === 'gradient') {
271
+ let changed = false;
272
+ const stops = ref.value.stops.map((stop) => {
273
+ if (stop.monochrome === false) return stop;
274
+ const swapped = swapTokenFamily(stop.color, oldFamily, newFamily);
275
+ if (swapped === stop.color) return stop;
276
+ changed = true;
277
+ return { ...stop, color: swapped };
278
+ });
279
+ if (changed) {
280
+ slice.aliases[key] = {
281
+ kind: 'gradient',
282
+ value: {
283
+ type: ref.value.type,
284
+ angle: ref.value.angle,
285
+ ...(ref.value.radius !== undefined ? { radius: ref.value.radius } : {}),
286
+ ...(ref.value.centerX !== undefined ? { centerX: ref.value.centerX } : {}),
287
+ ...(ref.value.aspectX !== undefined ? { aspectX: ref.value.aspectX } : {}),
288
+ ...(ref.value.aspectY !== undefined ? { aspectY: ref.value.aspectY } : {}),
289
+ stops,
290
+ },
291
+ };
292
+ }
293
+ }
294
+ }
295
+ });
296
+ }
297
+
298
+ // "None" on the background segmented control clears the container outright:
299
+ // the gradient flips to `type: 'none'` (handled inside GradientEditor) and
300
+ // we follow through here by clearing the border color too — a convenience
301
+ // so the user doesn't have to chase the residual outline. The user can
302
+ // re-set the border independently afterwards; changing border alone never
303
+ // bounces the background back to solid.
304
+ function clearContainerBorder(v: Variant) {
305
+ setComponentAlias(component, `--sectiondivider-${v}-border`, { kind: 'literal', value: 'transparent' });
306
+ }
307
+
308
+ function hairlineOptions(v: Variant): { value: HairlinePosition; label: string }[] {
309
+ const base: { value: HairlinePosition; label: string }[] = [
310
+ { value: 'above-label', label: 'Above title' },
311
+ { value: 'through-label', label: 'Through title' },
312
+ { value: 'below-label', label: 'Below title' },
313
+ ];
314
+ if (!getShowDescription(v)) return base;
315
+ return [
316
+ ...base,
317
+ { value: 'through-description', label: 'Through description' },
318
+ { value: 'below-description', label: 'Below description' },
319
+ ];
320
+ }
321
+
322
+ // Hairline show + position are now one var. Toggle off → 'none'; toggle on
323
+ // → restore the position currently displayed in the dropdown (or
324
+ // 'above-label' default). Description-targeted hairlines are suppressed by
325
+ // a container style query when description-display is 'none', so no
326
+ // editor-side snap is needed at runtime.
327
+ function elementTogglesFor(v: Variant) {
328
+ return {
329
+ description: {
330
+ checked: getShowDescription(v),
331
+ label: 'Show description',
332
+ onchange: (c: boolean) => setIntrinsic(v, 'description-display', c ? 'flex' : 'none'),
333
+ },
334
+ eyebrow: {
335
+ checked: getShowEyebrow(v),
336
+ label: 'Show eyebrow',
337
+ onchange: (c: boolean) => setIntrinsic(v, 'eyebrow-display', c ? 'block' : 'none'),
338
+ },
339
+ hairline: {
340
+ checked: getShowHairline(v),
341
+ label: 'Show',
342
+ onchange: (c: boolean) => setIntrinsic(v, 'hairline', c ? getHairlinePosition(v) : 'none'),
343
+ },
344
+ };
345
+ }
346
+ </script>
347
+
348
+ <ComponentEditorBase {component} title="Section Divider" description="Full-width section banner. Each variant (lg/md/sm) is a full preset: its own size, typography, colors, AND intrinsic properties (alignment, hairline, eyebrow/description visibility)." tokens={allTokens} {linked} variants={variantOptions}>
349
+ {#each variants as v}
350
+ <VariantGroup
351
+ name={v.key}
352
+ title={v.title}
353
+ states={{ [v.key]: visibleVariantTokens(v.key) }}
354
+ typeGroups={{ [v.key]: variantTypeGroups(v.key) }}
355
+ {component}
356
+ siblings={buildSiblings(
357
+ variants.map((x) => x.key),
358
+ v.key,
359
+ (sv) => ({ [sv]: stateTokens(sv) }),
360
+ (sv) => ({ [sv]: variantTypeGroups(sv) }),
361
+ )}
362
+ backdropPadding="20px"
363
+ elementToggles={elementTogglesFor(v.key)}
364
+ elementOrder={['Container', 'title', 'description', 'eyebrow', 'hairline']}
365
+ >
366
+ <div class="section-divider-stage">
367
+ <SectionDivider
368
+ title={SAMPLE_TITLE[v.key]}
369
+ variant={v.key}
370
+ description={SAMPLE_DESCRIPTION}
371
+ eyebrow={SAMPLE_EYEBROW}
372
+ />
373
+ </div>
374
+ {#snippet compositeControls(_stateName)}
375
+ <div class="gradient-bg-section">
376
+ <GradientEditor
377
+ sectionLabel="Background"
378
+ source={gradientSources[v.key]}
379
+ stopIdPrefix={`sectiondivider-${v.key}`}
380
+ familyFilter={getColorFamily(v.key)}
381
+ showNone
382
+ onNone={() => clearContainerBorder(v.key)}
383
+ />
384
+ </div>
385
+ {/snippet}
386
+ {#snippet extraPropertyRowsTop(_stateName)}
387
+ <div class="property-row sd-intrinsic-row">
388
+ <span class="property-label">alignment</span>
389
+ <select
390
+ class="sd-intrinsic-select"
391
+ value={getAlign(v.key)}
392
+ onchange={(e) => setIntrinsic(v.key, 'align', (e.currentTarget as HTMLSelectElement).value)}
393
+ >
394
+ <option value="center">Center</option>
395
+ <option value="start">Start</option>
396
+ </select>
397
+ </div>
398
+ <div class="property-row sd-intrinsic-row">
399
+ <span class="property-label">color family</span>
400
+ <select
401
+ class="sd-intrinsic-select"
402
+ value={getColorFamily(v.key)}
403
+ onchange={(e) => {
404
+ const next = (e.currentTarget as HTMLSelectElement).value;
405
+ const prev = getColorFamily(v.key);
406
+ setCfg(v.key, 'color-family', next);
407
+ remapFamily(v.key, prev, next);
408
+ }}
409
+ >
410
+ {#each FAMILY_OPTIONS as opt (opt.value)}
411
+ <option value={opt.value}>{opt.label}</option>
412
+ {/each}
413
+ </select>
414
+ </div>
415
+ {/snippet}
416
+ {#snippet elementExtras(elementName)}
417
+ {#if elementName === 'eyebrow'}
418
+ <label class="sd-element-check">
419
+ <input
420
+ type="checkbox"
421
+ checked={getEyebrowUppercase(v.key)}
422
+ onchange={(e) => setIntrinsic(v.key, 'eyebrow-text-transform', (e.currentTarget as HTMLInputElement).checked ? 'uppercase' : 'none')}
423
+ />
424
+ <span>All caps</span>
425
+ </label>
426
+ {/if}
427
+ {#if elementName === 'hairline'}
428
+ <div class="property-row sd-intrinsic-row sd-hairline-position-row">
429
+ <span class="property-label">position</span>
430
+ <select
431
+ class="sd-intrinsic-select"
432
+ value={getHairlinePosition(v.key)}
433
+ onchange={(e) => setIntrinsic(v.key, 'hairline', (e.currentTarget as HTMLSelectElement).value)}
434
+ >
435
+ {#each hairlineOptions(v.key) as opt (opt.value)}
436
+ <option value={opt.value}>{opt.label}</option>
437
+ {/each}
438
+ </select>
439
+ </div>
440
+ {/if}
441
+ {/snippet}
442
+ </VariantGroup>
443
+ {/each}
444
+ </ComponentEditorBase>
445
+
446
+ <style>
447
+ .section-divider-stage {
448
+ width: 100%;
449
+ min-width: 32rem;
450
+ }
451
+ /* The shipped SectionDivider carries a 24px block margin so it breathes
452
+ inside a real page. In the editor preview the backdrop already supplies
453
+ framing space, so collapse the margin here to keep the stage tight. */
454
+ .section-divider-stage :global(.section-divider) {
455
+ margin-block: 0;
456
+ }
457
+
458
+
459
+ /* Mirror ShadowBackdrop's preview/controls grid so the ribbon's left/right
460
+ edges land on the preview-stage edges above AND the radial pad lands in
461
+ the same column as the canvas-toolbar above.
462
+ - col 1 (1fr) = preview-stage area; its content sits at left = 1.5rem
463
+ and right edge = parent right - 11rem - 48px
464
+ - col 2 (11rem) = canvas-toolbar area; left edge = parent right - 11rem - 8px
465
+ - gap = 40px (32px backdrop-content right padding + 8px controls-cell left padding)
466
+ - parent padding-right = 8px (matches the controls-cell's right inset)
467
+ For non-radial gradients the editor occupies col 1 only; col 2 stays
468
+ empty. For radial (has-pad), the editor uses subgrid so its inner ribbon
469
+ and pad align with the outer columns. */
470
+ .gradient-bg-section {
471
+ display: grid;
472
+ grid-template-columns: minmax(0, 1fr) 11rem;
473
+ column-gap: 40px;
474
+ padding-left: 1.5rem;
475
+ padding-right: 8px;
476
+ margin-top: var(--ui-space-16);
477
+ box-sizing: border-box;
478
+ }
479
+ .gradient-bg-section > :global(.gradient-editor) {
480
+ grid-column: 1;
481
+ }
482
+ .gradient-bg-section > :global(.gradient-editor.has-pad) {
483
+ grid-column: 1 / -1;
484
+ grid-template-columns: subgrid;
485
+ column-gap: 40px;
486
+ }
487
+ @container variant-group (max-width: 32rem) {
488
+ .gradient-bg-section {
489
+ grid-template-columns: minmax(0, 1fr);
490
+ padding-right: 32px;
491
+ }
492
+ /* Collapsed: parent is 1-col. Drop subgrid and let the editor fall back to
493
+ its native 2-col (ribbon | pad) layout within the single column. */
494
+ .gradient-bg-section > :global(.gradient-editor.has-pad) {
495
+ grid-column: 1;
496
+ grid-template-columns: minmax(0, 1fr) max-content;
497
+ column-gap: var(--ui-space-16);
498
+ }
499
+ }
500
+
501
+ /* Intrinsic-property rows. Sit in the Properties section under the token
502
+ grid (via VariantGroup.extraPropertyRows). The grid columns are inherited
503
+ from the parent so labels line up with token labels above. */
504
+ /* Inline boolean control inside an element-section (e.g. "All caps" under
505
+ the eyebrow heading). Sits flush-left so it reads as a section property
506
+ rather than aligning with the token grid below. */
507
+ :global(.sd-element-check) {
508
+ display: inline-flex;
509
+ align-items: center;
510
+ gap: var(--ui-space-6);
511
+ font-size: var(--ui-font-size-sm);
512
+ color: var(--ui-text-secondary);
513
+ cursor: pointer;
514
+ user-select: none;
515
+ margin-bottom: var(--ui-space-4);
516
+ }
517
+ :global(.sd-element-check:hover) { color: var(--ui-text-primary); }
518
+ :global(.sd-element-check input) { margin: 0; cursor: pointer; }
519
+
520
+ /* Property-row inside an element-section (e.g. hairline position) — the
521
+ extra-property-rows grid lives in VariantGroup and only applies above
522
+ the token list. Mirror its column layout here so the position row's
523
+ label/select reads consistent with the alignment + color family rows. */
524
+ :global(.sd-hairline-position-row.property-row) {
525
+ display: grid;
526
+ grid-template-columns: minmax(8rem, max-content) 1fr;
527
+ column-gap: var(--ui-space-16);
528
+ align-items: center;
529
+ min-height: 1.75rem;
530
+ margin-bottom: var(--ui-space-4);
531
+ }
532
+ :global(.sd-hairline-position-row .property-label) {
533
+ font-size: var(--ui-font-size-sm);
534
+ color: var(--ui-text-secondary);
535
+ }
536
+
537
+ :global(.sd-intrinsic-select) {
538
+ appearance: none;
539
+ -webkit-appearance: none;
540
+ justify-self: start;
541
+ width: max-content;
542
+ min-width: 8rem;
543
+ padding: 0 var(--ui-space-24) 0 var(--ui-space-8);
544
+ min-height: 1.75rem;
545
+ background-color: var(--ui-surface-lowest);
546
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='10' viewBox='0 0 12 12'%3E%3Cpath fill='none' stroke='%23999' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round' d='M3 5l3 3 3-3'/%3E%3C/svg%3E");
547
+ background-repeat: no-repeat;
548
+ background-position: right var(--ui-space-8) center;
549
+ border: 1px solid var(--ui-border-low);
550
+ border-radius: var(--ui-radius-sm);
551
+ color: var(--ui-text-primary);
552
+ font-family: var(--ui-font-sans);
553
+ font-size: var(--ui-font-size-sm);
554
+ cursor: pointer;
555
+ }
556
+ :global(.sd-intrinsic-select:hover) {
557
+ background-color: var(--ui-surface-low);
558
+ border-color: var(--ui-border);
559
+ }
560
+ :global(.sd-intrinsic-select:focus-visible) {
561
+ outline: 2px solid var(--ui-highlight);
562
+ outline-offset: 2px;
563
+ }
564
+
565
+ </style>
@@ -101,10 +101,10 @@
101
101
  </script>
102
102
 
103
103
  <script lang="ts">
104
- import SegmentedControl from '../components/SegmentedControl.svelte';
104
+ import SegmentedControl from '../../system/components/SegmentedControl.svelte';
105
105
  import VariantGroup from './scaffolding/VariantGroup.svelte';
106
106
  import ComponentEditorBase from './scaffolding/ComponentEditorBase.svelte';
107
- import { editorState } from '../lib/editorStore';
107
+ import { editorState } from '../core/store/editorStore';
108
108
  import { computeLinkedBlock, withLinkedDisabled } from './scaffolding/linkedBlock';
109
109
 
110
110
  type Segment = { value: string; label: string; icon?: string; disabled?: boolean };