@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
@@ -1,62 +0,0 @@
1
- <script lang="ts">
2
- interface Props {
3
- children?: import('svelte').Snippet;
4
- }
5
-
6
- let { children }: Props = $props();
7
- /** Section that gathers render-time toggles a component accepts as props
8
- (e.g. dismissible, action buttons, hover shimmer, show icons). */
9
- </script>
10
-
11
- <section class="config-block">
12
- <header class="config-header">
13
- <h3 class="config-title">Configuration</h3>
14
- <p class="config-description">Component accepts multiple properties that can change its layout. Use these to preview.</p>
15
- </header>
16
- <div class="config-controls">
17
- {@render children?.()}
18
- </div>
19
- </section>
20
-
21
- <style>
22
- .config-block {
23
- margin-top: var(--ui-space-12);
24
- padding: var(--ui-space-12);
25
- border: 1px solid var(--ui-border-faint);
26
- border-radius: var(--ui-radius-md);
27
- background: var(--ui-surface-low);
28
- }
29
-
30
- .config-header {
31
- margin-bottom: var(--ui-space-12);
32
- }
33
-
34
- .config-title {
35
- margin: 0;
36
- font-size: var(--ui-font-size-md);
37
- font-weight: 500;
38
- color: var(--ui-text-primary);
39
- }
40
-
41
- .config-description {
42
- margin: var(--ui-space-2) 0 0;
43
- font-size: var(--ui-font-size-sm);
44
- color: var(--ui-text-secondary);
45
- }
46
-
47
- .config-controls {
48
- display: flex;
49
- flex-wrap: wrap;
50
- gap: var(--ui-space-16);
51
- align-items: center;
52
- }
53
-
54
- .config-controls :global(label) {
55
- display: inline-flex;
56
- align-items: center;
57
- gap: var(--ui-space-6);
58
- font-size: var(--ui-font-size-sm);
59
- color: var(--ui-text-secondary);
60
- cursor: pointer;
61
- }
62
- </style>
@@ -1,37 +0,0 @@
1
- <script lang="ts">
2
- import newspaperBg from '../../assets/newspaper.webp';
3
-
4
-
5
-
6
- interface Props {
7
- mode?: 'image' | 'color';
8
- /** CSS var name (set by ShadowBackdropControls) the backdrop reads when in color mode. */
9
- colorVariable: string;
10
- /** Padding around the slotted preview. Set to '0' when the slotted component should cover the full backdrop area (e.g. dialog overlay). */
11
- padding?: string;
12
- children?: import('svelte').Snippet;
13
- }
14
-
15
- let {
16
- mode = 'image',
17
- colorVariable,
18
- padding = '128px',
19
- children
20
- }: Props = $props();
21
-
22
- let backgroundStyle =
23
- $derived(mode === 'image'
24
- ? `padding: ${padding}; background-image: url(${newspaperBg}); background-size: cover; background-position: center; background-repeat: no-repeat;`
25
- : `padding: ${padding}; background: var(${colorVariable}, #1a1a1a);`);
26
- </script>
27
-
28
- <div class="shadow-backdrop" style={backgroundStyle}>
29
- {@render children?.()}
30
- </div>
31
-
32
- <style>
33
- .shadow-backdrop {
34
- border-radius: var(--ui-radius-md);
35
- overflow: hidden;
36
- }
37
- </style>
@@ -1,61 +0,0 @@
1
- <script lang="ts">
2
- import { onMount } from 'svelte';
3
- import UIRadioGroup from '../../ui/UIRadioGroup.svelte';
4
- import UIPaletteSelector from '../../ui/UIPaletteSelector.svelte';
5
- import { setCssVar } from '../../lib/cssVarSync';
6
-
7
- type Mode = 'image' | 'color';
8
-
9
- interface Props {
10
- mode?: Mode;
11
- /** Editor-scoped CSS var the picker writes to (must end with `-surface` to allow gradients). */
12
- colorVariable: string;
13
- }
14
-
15
- let { mode = $bindable('image'), colorVariable }: Props = $props();
16
-
17
- const options: ReadonlyArray<{ value: Mode; label: string }> = [
18
- { value: 'image', label: 'Image' },
19
- { value: 'color', label: 'Color' },
20
- ];
21
-
22
- // Editor-only backdrop vars aren't persisted to disk; seed surface-canvas as
23
- // the default selection on first mount so the picker reads as surface-canvas
24
- // and the color-mode preview matches.
25
- onMount(() => {
26
- if (!document.documentElement.style.getPropertyValue(colorVariable)) {
27
- setCssVar(colorVariable, 'var(--surface-canvas)');
28
- }
29
- });
30
- </script>
31
-
32
- <label class="backdrop-config">
33
- <span>Sample background</span>
34
- <div class="backdrop-row">
35
- <UIRadioGroup
36
- bind:value={mode}
37
- name="shadow-backdrop-mode-{Math.random().toString(36).slice(2, 8)}"
38
- {options}
39
- />
40
- <div class="picker-slot">
41
- <UIPaletteSelector variable={colorVariable} disabled={mode !== 'color'} />
42
- </div>
43
- </div>
44
- </label>
45
-
46
- <style>
47
- .backdrop-row {
48
- display: inline-flex;
49
- align-items: center;
50
- gap: var(--ui-space-16);
51
- padding: var(--ui-space-4) var(--ui-space-8);
52
- border: 1px solid var(--ui-border-faint);
53
- border-radius: var(--ui-radius-sm);
54
- }
55
- .picker-slot {
56
- min-width: 8rem;
57
- }
58
- .picker-slot :global(.ui-token-selector) {
59
- width: 100%;
60
- }
61
- </style>
@@ -1,132 +0,0 @@
1
- <script lang="ts">
2
- /**
3
- * Shared inner block rendered inside a single state in VariantGroup.
4
- *
5
- * Both the tabs branch and the list branch of VariantGroup render the same
6
- * `<TypeEditor>` (when a state has type groups) followed by `<TokenLayout>`,
7
- * differing only in the surrounding chrome (preview placement, toggles,
8
- * tab strip). This component owns the duplicated inner block so a per-state
9
- * control change happens in exactly one place.
10
- */
11
- import TokenLayout from './TokenLayout.svelte';
12
- import TypeEditor from './TypeEditor.svelte';
13
- import type { Token, TypeGroupConfig } from './types';
14
-
15
-
16
-
17
-
18
-
19
-
20
- interface Props {
21
- /** Tokens for this state, fed to `<TokenLayout>`. */
22
- tokens: Token[];
23
- /** Type groups for this state; rendered as a row of `<TypeEditor>` blocks. */
24
- typeGroups?: TypeGroupConfig[];
25
- /** Forwarded to TypeEditor and TokenLayout so writes persist through the editor store. */
26
- component?: string | undefined;
27
- /** Per-variable rank passed through to TokenLayout for linked-block alignment. */
28
- linkedOrder?: Map<string, number> | undefined;
29
- /** Render the token grid with N visual columns. >1 spreads a long property
30
- list horizontally; only meaningful for state-blocks without typeGroups
31
- (the two-col flex layout already partitions screen real estate when
32
- typeGroups are present). */
33
- columns?: number;
34
- onchange?: () => void;
35
- }
36
-
37
- let {
38
- tokens,
39
- typeGroups = [],
40
- component = undefined,
41
- linkedOrder = undefined,
42
- columns = 1,
43
- onchange,
44
- }: Props = $props();
45
-
46
- let hasTypeGroups = $derived(typeGroups.length > 0);
47
- </script>
48
-
49
- <div class="state-controls" class:two-col={hasTypeGroups}>
50
- {#if hasTypeGroups}
51
- <div class="state-type-groups">
52
- {#each typeGroups as tg}
53
- <TypeEditor
54
- legend={tg.legend ?? 'type'}
55
- colorVariable={tg.colorVariable}
56
- colorLabel={tg.colorLabel ?? 'text color'}
57
- familyVariable={tg.familyVariable}
58
- familyLabel={tg.familyLabel ?? 'font family'}
59
- sizeVariable={tg.sizeVariable}
60
- sizeLabel={tg.sizeLabel ?? 'font size'}
61
- weightVariable={tg.weightVariable}
62
- weightLabel={tg.weightLabel ?? 'font weight'}
63
- lineHeightVariable={tg.lineHeightVariable}
64
- lineHeightLabel={tg.lineHeightLabel ?? 'line height'}
65
- outlineWidthVariable={tg.outlineWidthVariable}
66
- outlineWidthLabel={tg.outlineWidthLabel ?? 'outline thickness'}
67
- outlineColorVariable={tg.outlineColorVariable}
68
- outlineColorLabel={tg.outlineColorLabel ?? 'outline color'}
69
- {component}
70
- {onchange}
71
- />
72
- {/each}
73
- </div>
74
- {/if}
75
- <TokenLayout
76
- title=""
77
- {tokens}
78
- {component}
79
- {linkedOrder}
80
- {columns}
81
- {onchange}
82
- />
83
- </div>
84
-
85
- <style>
86
- .state-controls {
87
- display: grid;
88
- grid-template-columns: 1fr;
89
- gap: var(--ui-space-12);
90
- align-items: start;
91
- margin-top: var(--ui-space-4);
92
- }
93
-
94
- .state-controls.two-col {
95
- display: flex;
96
- flex-wrap: wrap;
97
- gap: var(--ui-space-16) var(--ui-space-16);
98
- align-items: flex-start;
99
- justify-content: flex-start;
100
- }
101
-
102
- .state-type-groups {
103
- display: flex;
104
- flex-direction: row;
105
- flex-wrap: wrap;
106
- gap: var(--ui-space-16);
107
- align-items: flex-start;
108
- }
109
-
110
- /* Inside a state's two-col layout the fieldset frame is redundant with the
111
- surrounding state card. Flatten the border/padding but keep the legend so
112
- each block ("title", "body text", …) is identifiable. */
113
- .state-controls.two-col .state-type-groups :global(.fieldset-wrapper) {
114
- border: none;
115
- padding: 0;
116
- }
117
-
118
- .state-controls.two-col .state-type-groups :global(.fieldset-wrapper.active) {
119
- outline: none;
120
- }
121
-
122
- .state-controls.two-col .state-type-groups :global(.fieldset-legend) {
123
- padding: 0 var(--ui-space-4) var(--ui-space-4);
124
- }
125
-
126
- /* The general-properties column has no legend of its own; pad it down by
127
- one legend-line so its first row aligns with the first row of the
128
- adjacent type-group. */
129
- .state-controls.two-col > :global(.token-group) {
130
- padding-top: calc(var(--ui-font-size-xs) + var(--ui-space-4));
131
- }
132
- </style>
@@ -1,310 +0,0 @@
1
- <script lang="ts">
2
- import { writable } from 'svelte/store';
3
- import type { Snippet } from 'svelte';
4
- import TokenLayout from './TokenLayout.svelte';
5
- import StateBlock from './StateBlock.svelte';
6
- import CopyFromMenu from './CopyFromMenu.svelte';
7
- import { mutate } from '../../lib/editorStore';
8
- import { getEditorContext } from './editorContext';
9
- import type { Token, TypeGroupConfig } from './types';
10
- import type { Sibling } from './siblings';
11
-
12
- interface Props {
13
- name: string;
14
- title: string;
15
- tokens?: Token[];
16
- states?: Record<string, Token[]> | null;
17
- /** Per-state type groups; rendered as TypeEditor blocks alongside the state's TokenLayout. */
18
- typeGroups?: Record<string, TypeGroupConfig[]>;
19
- /** When set, overrides are read from and cleared through the editor store. */
20
- component?: string | undefined;
21
- /** Sibling variants of this component (excludes self). When non-empty,
22
- a "Copy from" menu is rendered that lets the user pull token values from
23
- a sibling's same-state into the current state. */
24
- siblings?: Sibling[];
25
- /** Forwarded to StateBlock → TokenLayout. >1 lays out the property grid
26
- across multiple visual columns (column-major flow). Useful for
27
- single-text components like Button whose 8-10 properties stretch the
28
- panel vertically when stacked single-column. */
29
- columns?: number;
30
- /** Label rendered above the state-tab selector strip. Defaults to "Element"
31
- because most strips mix structural parts (e.g. bar, frame) with
32
- component states; "States" would mislabel the parts. Editors can override
33
- when every tab on the strip really is a state. */
34
- selectorLabel?: string;
35
- /** Forwarded to StateBlock — fires when a token is mutated. */
36
- onchange?: () => void;
37
- /** Default snippet: receives the active state name; renders the live preview. */
38
- children?: Snippet<[{ activeState: string }]>;
39
- /** Right-aligned controls in the state-tabs strip (e.g. per-state toggles). */
40
- stateActions?: Snippet<[string]>;
41
- /** Rendered above the property grid when a state is active. */
42
- compositeControls?: Snippet<[string]>;
43
- }
44
-
45
- let {
46
- name,
47
- title,
48
- tokens = [],
49
- states = null,
50
- typeGroups = {},
51
- component = undefined,
52
- siblings = [],
53
- columns = 1,
54
- selectorLabel = 'Element',
55
- onchange,
56
- children,
57
- stateActions,
58
- compositeControls,
59
- }: Props = $props();
60
-
61
- const editorCtx = getEditorContext();
62
- const linkedOrderStore = editorCtx?.linkedOrder ?? writable<Map<string, number> | null>(null);
63
- const focusedVariantStore = editorCtx?.focusedVariant ?? writable<string | null>(null);
64
- const focusedStateStore = editorCtx?.focusedState ?? writable<string | null>(null);
65
- let linkedOrder = $derived($linkedOrderStore ?? undefined);
66
-
67
- let activeTab: string = $state('');
68
-
69
- const TYPE_PROPS = ['colorVariable', 'familyVariable', 'sizeVariable', 'weightVariable', 'lineHeightVariable', 'outlineWidthVariable', 'outlineColorVariable'] as const;
70
-
71
- function pickCopySource(toState: string, fromVariant: string, fromState: string) {
72
- if (!component || !states) return;
73
- const isSelfVariant = fromVariant === name;
74
- const sibling = isSelfVariant ? null : siblings.find((s) => s.name === fromVariant);
75
- if (!isSelfVariant && !sibling) return;
76
- const srcTokens = (isSelfVariant ? states[fromState] : sibling!.states[fromState]) ?? [];
77
- const dstTokens = states[toState] ?? [];
78
- const srcTypeGroups = (isSelfVariant ? typeGroups[fromState] : sibling!.typeGroups?.[fromState]) ?? [];
79
- const dstTypeGroups = typeGroups[toState] ?? [];
80
-
81
- mutate(`copy ${fromVariant}/${fromState} → ${name}/${toState}`, (s) => {
82
- const slice = s.components[component!] ?? (s.components[component!] = { activeFile: 'default', aliases: {}, config: {} });
83
- const apply = (srcVar: string, dstVar: string) => {
84
- if (srcVar === dstVar) return;
85
- if (srcVar in slice.aliases) slice.aliases[dstVar] = slice.aliases[srcVar];
86
- else delete slice.aliases[dstVar];
87
- };
88
- const minLen = Math.min(srcTokens.length, dstTokens.length);
89
- for (let i = 0; i < minLen; i++) apply(srcTokens[i].variable, dstTokens[i].variable);
90
- const minTypeGroups = Math.min(srcTypeGroups.length, dstTypeGroups.length);
91
- for (let g = 0; g < minTypeGroups; g++) {
92
- const srcType = srcTypeGroups[g];
93
- const dstType = dstTypeGroups[g];
94
- for (const prop of TYPE_PROPS) {
95
- const srcVar = srcType[prop];
96
- const dstVar = dstType[prop];
97
- if (srcVar && dstVar) apply(srcVar, dstVar);
98
- }
99
- }
100
- });
101
- }
102
-
103
- let copySources = $derived.by(() => {
104
- const fromSiblings = siblings.map((s) => ({
105
- name: s.name,
106
- label: s.label,
107
- states: Object.keys(s.states),
108
- }));
109
- const ownStates = states ? Object.keys(states) : [];
110
- if (ownStates.length >= 2) {
111
- return [{ name, label: title, states: ownStates }, ...fromSiblings];
112
- }
113
- return fromSiblings;
114
- });
115
-
116
- let stateNames = $derived(states ? Object.keys(states) : []);
117
- let tabsStripVisible = $derived(stateNames.length >= 2);
118
- $effect(() => {
119
- if (stateNames.length > 0 && !stateNames.includes(activeTab)) {
120
- activeTab = stateNames[0];
121
- }
122
- });
123
- // Cross-group hint from chart row clicks: adopt it if it names one of our states.
124
- $effect(() => {
125
- if ($focusedStateStore && stateNames.includes($focusedStateStore) && activeTab !== $focusedStateStore) {
126
- activeTab = $focusedStateStore;
127
- }
128
- });
129
-
130
- let inFocusMode = $derived(siblings.length > 0);
131
- let amIFocused = $derived($focusedVariantStore === name);
132
- let shouldRender = $derived(!inFocusMode || amIFocused);
133
- // Mirror this group's active state back to the shared store when this is the
134
- // focused variant, so the linked-block row + chart selection track the user's
135
- // state-tab clicks (not just chart-row clicks).
136
- $effect(() => {
137
- if (amIFocused && activeTab && stateNames.includes(activeTab) && $focusedStateStore !== activeTab) {
138
- focusedStateStore.set(activeTab);
139
- }
140
- });
141
-
142
- </script>
143
-
144
- {#if shouldRender}
145
- <div class="demo-section variant-group">
146
- {#if !inFocusMode}
147
- <div class="variant-header">
148
- <h3 class="demo-subtitle">{title}</h3>
149
- </div>
150
- {/if}
151
-
152
- {#if states}
153
- <!-- Preview at top, then state tabs + Copy from, then properties for active tab. -->
154
- <div class="tabs-preview">
155
- <span class="section-label">Preview</span>
156
- {@render children?.({ activeState: activeTab })}
157
- </div>
158
-
159
- {#if tabsStripVisible || (copySources.length > 0 && activeTab)}
160
- <div class="tabs-states-block">
161
- {#if tabsStripVisible}
162
- <span class="section-label">{selectorLabel}</span>
163
- {/if}
164
- <div class="tabs-selectors">
165
- {#if tabsStripVisible}
166
- <div class="state-tabs" role="tablist">
167
- {#each stateNames as s}
168
- <button
169
- type="button"
170
- class="state-tab-btn"
171
- class:active={activeTab === s}
172
- role="tab"
173
- aria-selected={activeTab === s}
174
- onclick={() => { activeTab = s; focusedStateStore.set(s); }}
175
- >{s}</button>
176
- {/each}
177
- </div>
178
- {/if}
179
- {#if activeTab}
180
- {@render stateActions?.(activeTab)}
181
- {/if}
182
- {#if copySources.length > 0 && activeTab}
183
- <CopyFromMenu
184
- toState={activeTab}
185
- variantName={name}
186
- {copySources}
187
- onselect={(d) => pickCopySource(activeTab, d.fromVariant, d.fromState)}
188
- />
189
- {/if}
190
- </div>
191
- </div>
192
- {/if}
193
-
194
- {#if activeTab && states[activeTab]}
195
- {@const stateName = activeTab}
196
- {@render compositeControls?.(stateName)}
197
- <span class="section-label">Properties</span>
198
- <StateBlock
199
- tokens={states[stateName]}
200
- typeGroups={typeGroups[stateName] ?? []}
201
- {component}
202
- {linkedOrder}
203
- {columns}
204
- {onchange}
205
- />
206
- {/if}
207
- {:else}
208
- {@render children?.({ activeState: '' })}
209
- <TokenLayout
210
- title={name}
211
- tokens={tokens}
212
- {component}
213
- {linkedOrder}
214
- {onchange}
215
- />
216
- {/if}
217
-
218
- </div>
219
- {/if}
220
-
221
- <style>
222
- .variant-group {
223
- padding: var(--ui-space-16);
224
- background: var(--ui-surface-low);
225
- border: 1px solid var(--ui-border-faint);
226
- border-radius: var(--ui-radius-md);
227
- gap: var(--ui-space-12);
228
- }
229
-
230
- .variant-header {
231
- display: flex;
232
- align-items: center;
233
- justify-content: flex-start;
234
- gap: var(--ui-space-12);
235
- }
236
-
237
- .variant-header .demo-subtitle {
238
- margin: 0;
239
- font-size: var(--ui-font-size-2xl);
240
- font-weight: var(--ui-font-weight-semibold);
241
- color: var(--ui-text-primary);
242
- }
243
-
244
- .tabs-preview {
245
- display: flex;
246
- flex-direction: column;
247
- gap: var(--ui-space-8);
248
- }
249
-
250
- .tabs-states-block {
251
- display: flex;
252
- flex-direction: column;
253
- gap: var(--ui-space-8);
254
- }
255
-
256
- .tabs-selectors {
257
- display: flex;
258
- align-items: center;
259
- gap: var(--ui-space-12);
260
- }
261
-
262
- .state-tabs {
263
- display: inline-flex;
264
- flex-wrap: wrap;
265
- gap: var(--ui-space-4);
266
- padding: var(--ui-space-4);
267
- background: var(--ui-surface-lowest);
268
- border: 1px solid var(--ui-border-faint);
269
- border-radius: var(--ui-radius-md);
270
- }
271
-
272
- .state-tab-btn {
273
- padding: var(--ui-space-6) var(--ui-space-12);
274
- background: none;
275
- border: none;
276
- border-radius: var(--ui-radius-sm);
277
- color: var(--ui-text-secondary);
278
- font-size: var(--ui-font-size-sm);
279
- font-weight: var(--ui-font-weight-medium);
280
- text-transform: capitalize;
281
- cursor: pointer;
282
- transition: color var(--ui-transition-fast), background var(--ui-transition-fast);
283
- }
284
-
285
- .state-tab-btn:hover:not(.active) {
286
- color: var(--ui-text-primary);
287
- background: var(--ui-hover);
288
- }
289
-
290
- .state-tab-btn.active {
291
- color: var(--ui-text-primary);
292
- background: var(--ui-surface-high);
293
- box-shadow: 0 0 0 1px var(--ui-border-default);
294
- }
295
-
296
- .section-label {
297
- display: block;
298
- margin: 0;
299
- font-size: var(--ui-font-size-md);
300
- font-weight: 500;
301
- color: var(--ui-text-primary);
302
- }
303
-
304
- /* The Properties label is a direct child of .variant-group (which doesn't
305
- apply a flex gap), so space it from the tabs strip above. */
306
- .variant-group > .section-label {
307
- margin-top: var(--ui-space-8);
308
- }
309
-
310
- </style>