@motion-proto/live-tokens 0.1.1 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (224) hide show
  1. package/README.md +160 -21
  2. package/dist-plugin/index.cjs +823 -336
  3. package/dist-plugin/index.d.cts +9 -7
  4. package/dist-plugin/index.d.ts +9 -7
  5. package/dist-plugin/index.js +822 -335
  6. package/package.json +46 -20
  7. package/src/assets/newspaper.webp +0 -0
  8. package/src/assets/offering.webp +0 -0
  9. package/src/component-editor/BadgeEditor.svelte +170 -0
  10. package/src/component-editor/CalloutEditor.svelte +103 -0
  11. package/src/component-editor/CardEditor.svelte +184 -0
  12. package/src/component-editor/CollapsibleSectionEditor.svelte +167 -0
  13. package/src/component-editor/CornerBadgeEditor.svelte +207 -0
  14. package/src/component-editor/DialogEditor.svelte +172 -0
  15. package/src/component-editor/ImageEditor.svelte +72 -0
  16. package/src/component-editor/InlineEditActionsEditor.svelte +83 -0
  17. package/src/component-editor/NotificationEditor.svelte +160 -0
  18. package/src/component-editor/ProgressBarEditor.svelte +124 -0
  19. package/src/component-editor/RadioButtonEditor.svelte +140 -0
  20. package/src/component-editor/SectionDividerEditor.svelte +263 -0
  21. package/src/component-editor/SegmentedControlEditor.svelte +154 -0
  22. package/src/component-editor/StandardButtonsEditor.svelte +178 -0
  23. package/src/component-editor/TabBarEditor.svelte +137 -0
  24. package/src/component-editor/TableEditor.svelte +128 -0
  25. package/src/component-editor/TooltipEditor.svelte +122 -0
  26. package/src/component-editor/editorTokens.test.ts +93 -0
  27. package/src/component-editor/groupKeySlots.test.ts +67 -0
  28. package/src/component-editor/groupKeySnapshot.test.ts +52 -0
  29. package/src/component-editor/index.ts +5 -0
  30. package/src/component-editor/registry.ts +246 -0
  31. package/src/component-editor/scaffolding/AngleDial.svelte +185 -0
  32. package/src/component-editor/scaffolding/ComponentEditorBase.svelte +96 -0
  33. package/src/component-editor/scaffolding/ComponentFileManager.svelte +682 -0
  34. package/src/component-editor/scaffolding/ComponentFileMenu.svelte +312 -0
  35. package/src/component-editor/scaffolding/ComponentsTab.svelte +69 -0
  36. package/src/component-editor/scaffolding/CopyFromMenu.svelte +246 -0
  37. package/src/component-editor/scaffolding/DemoHeader.svelte +21 -0
  38. package/src/component-editor/scaffolding/DividerEditor.svelte +81 -0
  39. package/src/component-editor/scaffolding/FieldsetWrapper.svelte +46 -0
  40. package/src/component-editor/scaffolding/GradientCard.svelte +291 -0
  41. package/src/component-editor/scaffolding/LinkageChart.svelte +297 -0
  42. package/src/component-editor/scaffolding/LinkedBlock.svelte +418 -0
  43. package/src/component-editor/scaffolding/NonStylableConfig.svelte +57 -0
  44. package/src/component-editor/scaffolding/SaveAsDialog.svelte +177 -0
  45. package/src/component-editor/scaffolding/ShadowBackdrop.svelte +25 -0
  46. package/src/component-editor/scaffolding/ShadowBackdropControls.svelte +56 -0
  47. package/src/component-editor/scaffolding/StateBlock.svelte +115 -0
  48. package/src/component-editor/scaffolding/TokenLayout.svelte +511 -0
  49. package/src/component-editor/scaffolding/TypeEditor.svelte +82 -0
  50. package/src/component-editor/scaffolding/VariantGroup.svelte +277 -0
  51. package/src/component-editor/scaffolding/buildTypeGroupTokens.ts +97 -0
  52. package/src/component-editor/scaffolding/componentSectionType.ts +8 -0
  53. package/src/component-editor/scaffolding/componentSources.ts +9 -0
  54. package/src/component-editor/scaffolding/defaultSections.ts +16 -0
  55. package/src/component-editor/scaffolding/editorContext.ts +44 -0
  56. package/src/component-editor/scaffolding/linkedBlock.ts +226 -0
  57. package/src/component-editor/scaffolding/siblings.ts +33 -0
  58. package/src/component-editor/scaffolding/types.ts +39 -0
  59. package/src/components/Badge.svelte +231 -42
  60. package/src/components/Button.svelte +324 -124
  61. package/src/components/Callout.svelte +145 -0
  62. package/src/components/Card.svelte +123 -25
  63. package/src/components/CollapsibleSection.svelte +213 -35
  64. package/src/components/CornerBadge.svelte +224 -0
  65. package/src/components/Dialog.svelte +137 -114
  66. package/src/components/Image.svelte +43 -0
  67. package/src/components/InlineEditActions.svelte +74 -14
  68. package/src/components/Notification.svelte +184 -163
  69. package/src/components/ProgressBar.svelte +216 -22
  70. package/src/components/RadioButton.svelte +110 -40
  71. package/src/components/SectionDivider.svelte +428 -74
  72. package/src/components/SegmentedControl.svelte +203 -0
  73. package/src/components/TabBar.svelte +146 -21
  74. package/src/components/Table.svelte +102 -0
  75. package/src/components/Tooltip.svelte +45 -19
  76. package/src/components/types.ts +51 -0
  77. package/src/data/google-fonts.json +75 -0
  78. package/src/lib/ColumnsOverlay.svelte +20 -7
  79. package/src/lib/LiveEditorOverlay.svelte +257 -78
  80. package/src/lib/columnsOverlay.ts +21 -17
  81. package/src/lib/componentConfig.test.ts +204 -0
  82. package/src/lib/componentConfigKeys.ts +19 -0
  83. package/src/lib/componentConfigService.ts +88 -0
  84. package/src/lib/copyPopover.ts +30 -0
  85. package/src/lib/cssVarSync.ts +59 -7
  86. package/src/lib/editorConfigStore.ts +0 -10
  87. package/src/lib/editorCore.ts +402 -0
  88. package/src/lib/editorKeybindings.ts +52 -0
  89. package/src/lib/editorPersistence.ts +106 -0
  90. package/src/lib/editorRenderer.ts +74 -0
  91. package/src/lib/editorStore.test.ts +328 -0
  92. package/src/lib/editorStore.ts +412 -0
  93. package/src/lib/editorTypes.ts +100 -0
  94. package/src/lib/editorViewStore.ts +55 -0
  95. package/src/lib/files/versionedFileResource.ts +140 -0
  96. package/src/lib/fontLoader.ts +130 -0
  97. package/src/lib/fontMigration.ts +140 -0
  98. package/src/lib/fontParse.ts +168 -0
  99. package/src/lib/index.ts +48 -30
  100. package/src/lib/lazyConfig.test.ts +54 -0
  101. package/src/lib/migrations/2026-04-24-component-prefix-and-suffix-renames.ts +64 -0
  102. package/src/lib/migrations/2026-04-24-legacy-keys-and-bg-to-canvas.ts +71 -0
  103. package/src/lib/migrations/2026-04-27-segmentedcontrol-disabled-flatten.ts +43 -0
  104. package/src/lib/migrations/2026-05-08-collapsiblesection-frame-and-cleanup.ts +68 -0
  105. package/src/lib/migrations/2026-05-08-collapsiblesection-variant-namespace.ts +35 -0
  106. package/src/lib/migrations/2026-05-10-sectiondivider-gradient-stops.ts +50 -0
  107. package/src/lib/migrations/2026-05-13-primary-to-brand.ts +90 -0
  108. package/src/lib/migrations/index.ts +93 -0
  109. package/src/lib/migrations/migrations.test.ts +341 -0
  110. package/src/lib/navLinkTypes.ts +1 -0
  111. package/src/lib/overlayState.ts +3 -0
  112. package/src/lib/paletteDerivation.ts +300 -0
  113. package/src/lib/parentRouteStore.ts +42 -0
  114. package/src/lib/parsers/globalRootBlock.ts +32 -0
  115. package/src/lib/presetService.ts +94 -0
  116. package/src/lib/router.ts +42 -10
  117. package/src/lib/scrollSection.ts +45 -0
  118. package/src/lib/slices/columns.ts +59 -0
  119. package/src/lib/slices/components.ts +362 -0
  120. package/src/lib/slices/domainVars.ts +15 -0
  121. package/src/lib/slices/fonts.ts +30 -0
  122. package/src/lib/slices/gradients.ts +153 -0
  123. package/src/lib/slices/overlays.ts +132 -0
  124. package/src/lib/slices/palettes.ts +26 -0
  125. package/src/lib/slices/shadows.ts +123 -0
  126. package/src/lib/storage.ts +88 -0
  127. package/src/lib/themeInit.ts +74 -0
  128. package/src/lib/themeService.ts +101 -0
  129. package/src/lib/themeTypes.ts +146 -0
  130. package/src/lib/tokenRegistry.ts +148 -0
  131. package/src/pages/ComponentEditorPage.svelte +384 -0
  132. package/src/pages/ComponentEditorPage.svelte.d.ts +2 -0
  133. package/src/pages/Editor.svelte +98 -0
  134. package/src/pages/Editor.svelte.d.ts +2 -0
  135. package/src/pages/EditorShell.svelte +348 -0
  136. package/src/styles/_padding.scss +34 -0
  137. package/src/styles/fonts/Fraunces/Fraunces-italic-latin-ext.woff2 +0 -0
  138. package/src/styles/fonts/Fraunces/Fraunces-italic-latin.woff2 +0 -0
  139. package/src/styles/fonts/Fraunces/Fraunces-roman-latin-ext.woff2 +0 -0
  140. package/src/styles/fonts/Fraunces/Fraunces-roman-latin.woff2 +0 -0
  141. package/src/styles/fonts/Manrope/Manrope-latin-ext.woff2 +0 -0
  142. package/src/styles/fonts/Manrope/Manrope-latin.woff2 +0 -0
  143. package/src/styles/fonts.css +22 -10
  144. package/src/styles/form-controls.css +14 -16
  145. package/src/styles/tokens.css +1322 -0
  146. package/src/styles/ui-editor.css +126 -0
  147. package/src/{showcase → ui}/BezierCurveEditor.svelte +14 -14
  148. package/src/{showcase → ui}/ColorEditPanel.svelte +42 -36
  149. package/src/ui/EditorViewSwitcher.svelte +180 -0
  150. package/src/ui/FontStackEditor.svelte +360 -0
  151. package/src/ui/GradientEditor.svelte +461 -0
  152. package/src/ui/GradientStopPicker.svelte +74 -0
  153. package/src/ui/PaletteEditor.svelte +1590 -0
  154. package/src/ui/PaletteEditor.test.ts +108 -0
  155. package/src/ui/PresetFileManager.svelte +567 -0
  156. package/src/ui/ProjectFontsSection.svelte +645 -0
  157. package/src/{showcase → ui}/SurfacesTab.svelte +39 -39
  158. package/src/{showcase → ui}/TextTab.svelte +27 -27
  159. package/src/{showcase/TokenFileManager.svelte → ui/ThemeFileManager.svelte} +196 -112
  160. package/src/ui/Toggle.svelte +108 -0
  161. package/src/ui/UICopyPopover.svelte +78 -0
  162. package/src/{showcase/EditorDialog.svelte → ui/UIDialog.svelte} +66 -25
  163. package/src/ui/UIFontFamilySelector.svelte +309 -0
  164. package/src/ui/UIFontSizeSelector.svelte +165 -0
  165. package/src/ui/UIFontWeightSelector.svelte +52 -0
  166. package/src/ui/UILineHeightSelector.svelte +47 -0
  167. package/src/ui/UILinkToggle.svelte +60 -0
  168. package/src/ui/UIOptionItem.svelte +74 -0
  169. package/src/ui/UIOptionList.svelte +27 -0
  170. package/src/ui/UIPaddingSelector.svelte +661 -0
  171. package/src/ui/UIPaletteSelector.svelte +1084 -0
  172. package/src/ui/UIRadio.svelte +72 -0
  173. package/src/ui/UIRadioGroup.svelte +59 -0
  174. package/src/ui/UIRelinkConfirmPopover.svelte +235 -0
  175. package/src/ui/UITokenSelector.svelte +509 -0
  176. package/src/ui/UIVariantSelector.svelte +145 -0
  177. package/src/ui/VariablesTab.svelte +252 -0
  178. package/src/ui/index.ts +31 -0
  179. package/src/ui/keepInViewport.ts +84 -0
  180. package/src/ui/palette/GradientStopEditor.svelte +482 -0
  181. package/src/ui/palette/OverridesPanel.svelte +526 -0
  182. package/src/ui/palette/PaletteBase.svelte +165 -0
  183. package/src/ui/palette/ScaleCurveEditor.svelte +38 -0
  184. package/src/ui/palette/paletteEditorState.ts +89 -0
  185. package/src/ui/sections/ColumnsSection.svelte +273 -0
  186. package/src/ui/sections/GradientsSection.svelte +147 -0
  187. package/src/ui/sections/OverlaysSection.svelte +670 -0
  188. package/src/ui/sections/ShadowsSection.svelte +1250 -0
  189. package/src/ui/sections/TokenScaleTable.svelte +332 -0
  190. package/src/ui/sections/tokenScales.ts +81 -0
  191. package/src/ui/variantScales.ts +108 -0
  192. package/src/components/DetailNav.svelte +0 -78
  193. package/src/components/Toggle.svelte +0 -86
  194. package/src/lib/tokenInit.ts +0 -29
  195. package/src/lib/tokenService.ts +0 -144
  196. package/src/lib/tokenTypes.ts +0 -45
  197. package/src/pages/Admin.svelte +0 -100
  198. package/src/pages/ShowcasePage.svelte +0 -144
  199. package/src/showcase/BackupBrowser.svelte +0 -617
  200. package/src/showcase/ComponentsTab.svelte +0 -105
  201. package/src/showcase/PaletteEditor.svelte +0 -2579
  202. package/src/showcase/PaletteSelector.svelte +0 -627
  203. package/src/showcase/TokenMap.svelte +0 -54
  204. package/src/showcase/VariablesTab.svelte +0 -2655
  205. package/src/showcase/VisualsTab.svelte +0 -231
  206. package/src/showcase/demos/BadgeDemo.svelte +0 -56
  207. package/src/showcase/demos/CardDemo.svelte +0 -50
  208. package/src/showcase/demos/ChoiceButtonsDemo.svelte +0 -192
  209. package/src/showcase/demos/CollapsibleSectionDemo.svelte +0 -54
  210. package/src/showcase/demos/DialogDemo.svelte +0 -42
  211. package/src/showcase/demos/InlineEditActionsDemo.svelte +0 -25
  212. package/src/showcase/demos/NotificationDemo.svelte +0 -147
  213. package/src/showcase/demos/ProgressBarDemo.svelte +0 -54
  214. package/src/showcase/demos/RadioButtonDemo.svelte +0 -56
  215. package/src/showcase/demos/SectionDividerDemo.svelte +0 -77
  216. package/src/showcase/demos/StandardButtonsDemo.svelte +0 -455
  217. package/src/showcase/demos/TabBarDemo.svelte +0 -58
  218. package/src/showcase/demos/TooltipDemo.svelte +0 -52
  219. package/src/showcase/editor.css +0 -93
  220. package/src/showcase/index.ts +0 -17
  221. package/src/styles/fonts/Domine/Domine-VariableFont_wght.ttf +0 -0
  222. package/src/styles/fonts/Domine/OFL.txt +0 -97
  223. package/src/styles/fonts/Domine/README.txt +0 -66
  224. /package/src/{showcase → ui}/curveEngine.ts +0 -0
@@ -0,0 +1,224 @@
1
+ <script context="module" lang="ts">
2
+ export type CornerAnchor = 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left';
3
+ </script>
4
+
5
+ <script lang="ts">
6
+ import Badge, { type BadgeVariant } from './Badge.svelte';
7
+
8
+ export let variant: BadgeVariant = 'accent';
9
+ export let anchor: CornerAnchor = 'bottom-right';
10
+ export let size: 'default' | 'small' = 'default';
11
+ export let icon: string | undefined = undefined;
12
+ </script>
13
+
14
+ <span class="corner-badge corner-badge-{anchor} corner-badge-{variant}">
15
+ <Badge {variant} {size} {icon}>
16
+ <slot name="icon" slot="icon" />
17
+ <slot />
18
+ </Badge>
19
+ </span>
20
+
21
+ <style lang="scss">
22
+ @use '../styles/padding' as *;
23
+
24
+ $variants: primary, accent, neutral, alternate, canvas, special, success, warning, danger, info;
25
+
26
+ // Per-variant token block kept flat (not collapsed via SCSS @each) so the
27
+ // Layer-2 token-discovery parser (`extractGlobalRootBody` in
28
+ // src/lib/parsers/globalRootBlock.ts) can read the .svelte source verbatim;
29
+ // @each interpolation would make the parser see zero tokens here, even though
30
+ // the rendered DOM would be identical. Same pattern as Badge.svelte / Notification.svelte.
31
+ //
32
+ // Role-based radii: each variable follows the badge's geometry regardless of anchor.
33
+ // - outer: the corner flush with the parent's anchored corner
34
+ // - inner: the diagonally opposite corner (deepest into the parent)
35
+ // - h-axis: the on-axis corner along the horizontal edge shared with `outer`
36
+ // - v-axis: the on-axis corner along the vertical edge shared with `outer`
37
+ //
38
+ // Padding + font props are corner-badge-specific (not inherited from the
39
+ // sibling Badge variant), so corner-badge instances can carry their own
40
+ // typography and sizing without dragging the inline Badge along. They default
41
+ // to the same underlying global tokens Badge uses, so an unconfigured corner
42
+ // badge still matches its inline badge counterpart visually.
43
+ :global(:root) {
44
+ /* Primary */
45
+ --corner-badge-primary-margin: var(--space-0);
46
+ --corner-badge-primary-outer-radius: var(--radius-none);
47
+ --corner-badge-primary-inner-radius: var(--radius-none);
48
+ --corner-badge-primary-h-axis-radius: var(--radius-none);
49
+ --corner-badge-primary-v-axis-radius: var(--radius-none);
50
+ --corner-badge-primary-padding: var(--space-6);
51
+ --corner-badge-primary-text-font-family: var(--font-sans);
52
+ --corner-badge-primary-text-font-size: var(--font-size-sm);
53
+ --corner-badge-primary-text-font-weight: var(--font-weight-light);
54
+ --corner-badge-primary-text-line-height: var(--line-height-tight);
55
+
56
+ /* Accent */
57
+ --corner-badge-accent-margin: var(--space-0);
58
+ --corner-badge-accent-outer-radius: var(--radius-none);
59
+ --corner-badge-accent-inner-radius: var(--radius-none);
60
+ --corner-badge-accent-h-axis-radius: var(--radius-none);
61
+ --corner-badge-accent-v-axis-radius: var(--radius-none);
62
+ --corner-badge-accent-padding: var(--space-6);
63
+ --corner-badge-accent-text-font-family: var(--font-sans);
64
+ --corner-badge-accent-text-font-size: var(--font-size-sm);
65
+ --corner-badge-accent-text-font-weight: var(--font-weight-light);
66
+ --corner-badge-accent-text-line-height: var(--line-height-tight);
67
+
68
+ /* Neutral */
69
+ --corner-badge-neutral-margin: var(--space-0);
70
+ --corner-badge-neutral-outer-radius: var(--radius-none);
71
+ --corner-badge-neutral-inner-radius: var(--radius-none);
72
+ --corner-badge-neutral-h-axis-radius: var(--radius-none);
73
+ --corner-badge-neutral-v-axis-radius: var(--radius-none);
74
+ --corner-badge-neutral-padding: var(--space-6);
75
+ --corner-badge-neutral-text-font-family: var(--font-sans);
76
+ --corner-badge-neutral-text-font-size: var(--font-size-sm);
77
+ --corner-badge-neutral-text-font-weight: var(--font-weight-light);
78
+ --corner-badge-neutral-text-line-height: var(--line-height-tight);
79
+
80
+ /* Alternate */
81
+ --corner-badge-alternate-margin: var(--space-0);
82
+ --corner-badge-alternate-outer-radius: var(--radius-none);
83
+ --corner-badge-alternate-inner-radius: var(--radius-none);
84
+ --corner-badge-alternate-h-axis-radius: var(--radius-none);
85
+ --corner-badge-alternate-v-axis-radius: var(--radius-none);
86
+ --corner-badge-alternate-padding: var(--space-6);
87
+ --corner-badge-alternate-text-font-family: var(--font-sans);
88
+ --corner-badge-alternate-text-font-size: var(--font-size-sm);
89
+ --corner-badge-alternate-text-font-weight: var(--font-weight-light);
90
+ --corner-badge-alternate-text-line-height: var(--line-height-tight);
91
+
92
+ /* Canvas */
93
+ --corner-badge-canvas-margin: var(--space-0);
94
+ --corner-badge-canvas-outer-radius: var(--radius-none);
95
+ --corner-badge-canvas-inner-radius: var(--radius-none);
96
+ --corner-badge-canvas-h-axis-radius: var(--radius-none);
97
+ --corner-badge-canvas-v-axis-radius: var(--radius-none);
98
+ --corner-badge-canvas-padding: var(--space-6);
99
+ --corner-badge-canvas-text-font-family: var(--font-sans);
100
+ --corner-badge-canvas-text-font-size: var(--font-size-sm);
101
+ --corner-badge-canvas-text-font-weight: var(--font-weight-light);
102
+ --corner-badge-canvas-text-line-height: var(--line-height-tight);
103
+
104
+ /* Special */
105
+ --corner-badge-special-margin: var(--space-0);
106
+ --corner-badge-special-outer-radius: var(--radius-none);
107
+ --corner-badge-special-inner-radius: var(--radius-none);
108
+ --corner-badge-special-h-axis-radius: var(--radius-none);
109
+ --corner-badge-special-v-axis-radius: var(--radius-none);
110
+ --corner-badge-special-padding: var(--space-6);
111
+ --corner-badge-special-text-font-family: var(--font-sans);
112
+ --corner-badge-special-text-font-size: var(--font-size-sm);
113
+ --corner-badge-special-text-font-weight: var(--font-weight-light);
114
+ --corner-badge-special-text-line-height: var(--line-height-tight);
115
+
116
+ /* Success */
117
+ --corner-badge-success-margin: var(--space-0);
118
+ --corner-badge-success-outer-radius: var(--radius-none);
119
+ --corner-badge-success-inner-radius: var(--radius-none);
120
+ --corner-badge-success-h-axis-radius: var(--radius-none);
121
+ --corner-badge-success-v-axis-radius: var(--radius-none);
122
+ --corner-badge-success-padding: var(--space-6);
123
+ --corner-badge-success-text-font-family: var(--font-sans);
124
+ --corner-badge-success-text-font-size: var(--font-size-sm);
125
+ --corner-badge-success-text-font-weight: var(--font-weight-light);
126
+ --corner-badge-success-text-line-height: var(--line-height-tight);
127
+
128
+ /* Warning */
129
+ --corner-badge-warning-margin: var(--space-0);
130
+ --corner-badge-warning-outer-radius: var(--radius-none);
131
+ --corner-badge-warning-inner-radius: var(--radius-none);
132
+ --corner-badge-warning-h-axis-radius: var(--radius-none);
133
+ --corner-badge-warning-v-axis-radius: var(--radius-none);
134
+ --corner-badge-warning-padding: var(--space-6);
135
+ --corner-badge-warning-text-font-family: var(--font-sans);
136
+ --corner-badge-warning-text-font-size: var(--font-size-sm);
137
+ --corner-badge-warning-text-font-weight: var(--font-weight-light);
138
+ --corner-badge-warning-text-line-height: var(--line-height-tight);
139
+
140
+ /* Danger */
141
+ --corner-badge-danger-margin: var(--space-0);
142
+ --corner-badge-danger-outer-radius: var(--radius-none);
143
+ --corner-badge-danger-inner-radius: var(--radius-none);
144
+ --corner-badge-danger-h-axis-radius: var(--radius-none);
145
+ --corner-badge-danger-v-axis-radius: var(--radius-none);
146
+ --corner-badge-danger-padding: var(--space-6);
147
+ --corner-badge-danger-text-font-family: var(--font-sans);
148
+ --corner-badge-danger-text-font-size: var(--font-size-sm);
149
+ --corner-badge-danger-text-font-weight: var(--font-weight-light);
150
+ --corner-badge-danger-text-line-height: var(--line-height-tight);
151
+
152
+ /* Info */
153
+ --corner-badge-info-margin: var(--space-0);
154
+ --corner-badge-info-outer-radius: var(--radius-none);
155
+ --corner-badge-info-inner-radius: var(--radius-none);
156
+ --corner-badge-info-h-axis-radius: var(--radius-none);
157
+ --corner-badge-info-v-axis-radius: var(--radius-none);
158
+ --corner-badge-info-padding: var(--space-6);
159
+ --corner-badge-info-text-font-family: var(--font-sans);
160
+ --corner-badge-info-text-font-size: var(--font-size-sm);
161
+ --corner-badge-info-text-font-weight: var(--font-weight-light);
162
+ --corner-badge-info-text-line-height: var(--line-height-tight);
163
+ }
164
+
165
+ .corner-badge {
166
+ position: absolute;
167
+ z-index: 1;
168
+ pointer-events: none;
169
+ }
170
+
171
+ // Per-variant: pull the variant's public tokens into private vars so the
172
+ // anchor-based mappings below can read them without 4 × 10 explicit rules.
173
+ // Padding + font props are forwarded directly onto the inner Badge so the
174
+ // corner-badge tokens fully replace Badge's per-variant declarations
175
+ // (otherwise Badge's own `.badge-#{$v}` rule wins by source order).
176
+ @each $v in $variants {
177
+ .corner-badge-#{$v} {
178
+ --_margin: var(--corner-badge-#{$v}-margin);
179
+ --_outer-radius: var(--corner-badge-#{$v}-outer-radius);
180
+ --_inner-radius: var(--corner-badge-#{$v}-inner-radius);
181
+ --_h-axis-radius: var(--corner-badge-#{$v}-h-axis-radius);
182
+ --_v-axis-radius: var(--corner-badge-#{$v}-v-axis-radius);
183
+
184
+ :global(.badge-#{$v}) {
185
+ @include themed-padding(--corner-badge-#{$v}-padding, $h: 2);
186
+ font-family: var(--corner-badge-#{$v}-text-font-family);
187
+ font-size: var(--corner-badge-#{$v}-text-font-size);
188
+ font-weight: var(--corner-badge-#{$v}-text-font-weight);
189
+ line-height: var(--corner-badge-#{$v}-text-line-height);
190
+ }
191
+ }
192
+ }
193
+
194
+ .corner-badge-bottom-right { bottom: var(--_margin); right: var(--_margin); }
195
+ .corner-badge-bottom-left { bottom: var(--_margin); left: var(--_margin); }
196
+ .corner-badge-top-right { top: var(--_margin); right: var(--_margin); }
197
+ .corner-badge-top-left { top: var(--_margin); left: var(--_margin); }
198
+
199
+ /* Map logical corner roles → physical corners per anchor. */
200
+ .corner-badge-bottom-right :global(.badge) {
201
+ border-top-left-radius: var(--_inner-radius);
202
+ border-top-right-radius: var(--_v-axis-radius);
203
+ border-bottom-right-radius: var(--_outer-radius);
204
+ border-bottom-left-radius: var(--_h-axis-radius);
205
+ }
206
+ .corner-badge-bottom-left :global(.badge) {
207
+ border-top-left-radius: var(--_v-axis-radius);
208
+ border-top-right-radius: var(--_inner-radius);
209
+ border-bottom-right-radius: var(--_h-axis-radius);
210
+ border-bottom-left-radius: var(--_outer-radius);
211
+ }
212
+ .corner-badge-top-right :global(.badge) {
213
+ border-top-left-radius: var(--_h-axis-radius);
214
+ border-top-right-radius: var(--_outer-radius);
215
+ border-bottom-right-radius: var(--_v-axis-radius);
216
+ border-bottom-left-radius: var(--_inner-radius);
217
+ }
218
+ .corner-badge-top-left :global(.badge) {
219
+ border-top-left-radius: var(--_outer-radius);
220
+ border-top-right-radius: var(--_h-axis-radius);
221
+ border-bottom-right-radius: var(--_inner-radius);
222
+ border-bottom-left-radius: var(--_v-axis-radius);
223
+ }
224
+ </style>
@@ -1,37 +1,42 @@
1
1
  <script lang="ts">
2
2
  import { createEventDispatcher, tick } from 'svelte';
3
+ import Button from './Button.svelte';
4
+ import { editorState } from '../lib/editorStore';
5
+ import type { ButtonVariant, DialogButtonSpec } from './types';
6
+
7
+ const BUTTON_VARIANTS: readonly ButtonVariant[] = ['primary', 'secondary', 'outline', 'success', 'danger', 'warning'];
8
+ function asVariant(v: string | undefined, fallback: ButtonVariant): ButtonVariant {
9
+ return v && (BUTTON_VARIANTS as readonly string[]).includes(v) ? (v as ButtonVariant) : fallback;
10
+ }
3
11
 
4
12
  export let show: boolean = false;
5
13
  export let title: string = '';
6
- export let confirmLabel: string = 'Confirm';
7
- export let cancelLabel: string = 'Cancel';
8
- export let showConfirm: boolean = true;
9
- export let showCancel: boolean = true;
10
- export let confirmDisabled: boolean = false;
11
14
  export let width: string = '500px';
15
+ /** When true, the dialog renders inline within its parent rather than as a fixed-position overlay. Used by the editor preview. */
16
+ export let inline: boolean = false;
17
+ /** Right footer button. Undefined hides it. `--dialog-confirm-variant` config drives the variant when `confirm.variant` is unset. */
18
+ export let confirm: DialogButtonSpec | undefined = undefined;
19
+ /** Left footer button. Undefined hides it. `--dialog-cancel-variant` config drives the variant when `cancel.variant` is unset. */
20
+ export let cancel: DialogButtonSpec | undefined = undefined;
12
21
 
13
- // Optional callbacks for parent dialogs to control behavior
14
- export let onConfirm: (() => void) | undefined = undefined;
15
- export let onCancel: (() => void) | undefined = undefined;
22
+ $: configuredConfig = $editorState.components.dialog?.config ?? {};
23
+ $: effectiveConfirmVariant = confirm?.variant ?? asVariant(configuredConfig['--dialog-confirm-variant'] as string | undefined, 'primary');
24
+ $: effectiveCancelVariant = cancel?.variant ?? asVariant(configuredConfig['--dialog-cancel-variant'] as string | undefined, 'outline');
16
25
 
17
26
  const dispatch = createEventDispatcher<{
18
- confirm: void;
19
- cancel: void;
20
27
  close: void;
21
28
  }>();
22
29
 
23
- // Reference to the primary (confirm) button for focus management
24
30
  let confirmButtonRef: HTMLButtonElement;
25
31
  let cancelButtonRef: HTMLButtonElement;
26
32
  let closeButtonRef: HTMLButtonElement;
27
33
 
28
- // Focus the primary button when dialog opens
29
- $: if (show) {
34
+ // Focus the primary button when dialog opens (skip in inline mode so the editor doesn't steal focus).
35
+ $: if (show && !inline) {
30
36
  tick().then(() => {
31
- // Focus the primary (confirm) button first, then fall back to cancel, then close
32
- if (showConfirm && confirmButtonRef && !confirmDisabled) {
37
+ if (confirm && confirmButtonRef && !confirm.disabled) {
33
38
  confirmButtonRef.focus();
34
- } else if (showCancel && cancelButtonRef) {
39
+ } else if (cancel && cancelButtonRef) {
35
40
  cancelButtonRef.focus();
36
41
  } else if (closeButtonRef) {
37
42
  closeButtonRef.focus();
@@ -40,35 +45,23 @@
40
45
  }
41
46
 
42
47
  function handleConfirm() {
43
- if (!confirmDisabled) {
44
- if (onConfirm) {
45
- // Parent dialog controls the flow
46
- onConfirm();
47
- } else {
48
- // Default behavior for backward compatibility
49
- dispatch('confirm');
50
- }
48
+ if (confirm && !confirm.disabled) {
49
+ confirm.onClick();
51
50
  }
52
51
  }
53
52
 
54
53
  function handleCancel() {
55
- if (onCancel) {
56
- // Parent dialog controls the flow
57
- onCancel();
54
+ if (cancel) {
55
+ cancel.onClick();
58
56
  } else {
59
- // Default behavior for backward compatibility
60
- dispatch('cancel');
61
57
  dispatch('close');
62
58
  show = false;
63
59
  }
64
60
  }
65
-
66
- // No implicit keyboard or backdrop close handlers
67
- // Dialog only closes via explicit button clicks (X, Cancel, or Confirm)
68
61
  </script>
69
62
 
70
63
  {#if show}
71
- <div class="dialog-backdrop">
64
+ <div class="dialog-backdrop" class:inline>
72
65
  <div class="dialog" style="width: {width}; max-width: {width};">
73
66
  <div class="dialog-content">
74
67
  {#if title}
@@ -90,32 +83,31 @@
90
83
  <slot />
91
84
  </div>
92
85
 
93
- {#if showConfirm || showCancel}
86
+ {#if confirm || cancel}
94
87
  <div class="dialog-footer">
95
88
  <div class="dialog-footer-left">
96
89
  <slot name="footer-left" />
97
90
  </div>
98
91
  <div class="dialog-footer-buttons">
99
- {#if showCancel}
100
- <button
101
- bind:this={cancelButtonRef}
102
- class="dialog-button dialog-button-secondary"
92
+ {#if cancel}
93
+ <Button
94
+ variant={effectiveCancelVariant}
95
+ disabled={cancel.disabled}
103
96
  on:click={handleCancel}
104
- tabindex="0"
97
+ bind:buttonRef={cancelButtonRef}
105
98
  >
106
- {cancelLabel}
107
- </button>
99
+ {cancel.label}
100
+ </Button>
108
101
  {/if}
109
- {#if showConfirm}
110
- <button
111
- bind:this={confirmButtonRef}
112
- class="dialog-button dialog-button-primary"
102
+ {#if confirm}
103
+ <Button
104
+ variant={effectiveConfirmVariant}
105
+ disabled={confirm.disabled}
113
106
  on:click={handleConfirm}
114
- disabled={confirmDisabled}
115
- tabindex="0"
107
+ bind:buttonRef={confirmButtonRef}
116
108
  >
117
- {confirmLabel}
118
- </button>
109
+ {confirm.label}
110
+ </Button>
119
111
  {/if}
120
112
  </div>
121
113
  </div>
@@ -126,13 +118,56 @@
126
118
  {/if}
127
119
 
128
120
  <style>
121
+ :global(:root) {
122
+ /* Overlay */
123
+ --dialog-overlay-surface: var(--overlay-high);
124
+
125
+ /* Dialog frame */
126
+ --dialog-surface: var(--surface-neutral-lowest);
127
+ --dialog-border: var(--border-neutral-strong);
128
+ --dialog-border-width: var(--border-width-2);
129
+ --dialog-radius: var(--radius-lg);
130
+ --dialog-shadow: var(--shadow-2xl);
131
+ --dialog-blur: var(--blur-none);
132
+
133
+ /* Header */
134
+ --dialog-header-surface: var(--surface-neutral-lower);
135
+ --dialog-header-border: var(--border-neutral-subtle);
136
+ --dialog-header-border-width: var(--border-width-1);
137
+ --dialog-header-padding: var(--space-8);
138
+
139
+ /* Title */
140
+ --dialog-title: var(--text-primary);
141
+ --dialog-title-font-family: var(--font-sans);
142
+ --dialog-title-font-size: var(--font-size-2xl);
143
+ --dialog-title-font-weight: var(--font-weight-normal);
144
+ --dialog-title-line-height: var(--line-height-snug);
145
+
146
+ /* Close icon */
147
+ --dialog-close-icon: var(--text-secondary);
148
+ --dialog-close-icon-size: var(--icon-size-xl);
149
+
150
+ /* Body */
151
+ --dialog-body-padding: var(--space-16);
152
+ --dialog-body: var(--text-secondary);
153
+ --dialog-body-font-family: var(--font-sans);
154
+ --dialog-body-font-size: var(--font-size-md);
155
+ --dialog-body-font-weight: var(--font-weight-normal);
156
+ --dialog-body-line-height: var(--line-height-normal);
157
+
158
+ /* Footer */
159
+ --dialog-footer-border: var(--border-neutral-subtle);
160
+ --dialog-footer-border-width: var(--border-width-1);
161
+ --dialog-footer-padding: var(--space-16);
162
+ }
163
+
129
164
  .dialog-backdrop {
130
165
  position: fixed;
131
166
  top: 0;
132
167
  left: 0;
133
168
  width: 100%;
134
169
  height: 100%;
135
- background-color: var(--overlay-high);
170
+ background: var(--dialog-overlay-surface);
136
171
  display: flex;
137
172
  justify-content: center;
138
173
  align-items: center;
@@ -140,12 +175,24 @@
140
175
  pointer-events: auto;
141
176
  }
142
177
 
178
+ .dialog-backdrop.inline {
179
+ position: relative;
180
+ top: auto;
181
+ left: auto;
182
+ width: 100%;
183
+ height: auto;
184
+ padding: var(--space-32);
185
+ border-radius: var(--radius-md);
186
+ z-index: auto;
187
+ }
188
+
143
189
  .dialog {
144
- background: var(--surface-neutral-lowest);
145
- border: 2px solid var(--border-neutral-strong);
146
- border-radius: var(--radius-lg);
147
- box-shadow: var(--shadow-overlay);
148
- animation: dialogSlideIn var(--transition-base);
190
+ background: var(--dialog-surface);
191
+ border: var(--dialog-border-width) solid var(--dialog-border);
192
+ border-radius: var(--dialog-radius);
193
+ box-shadow: var(--dialog-shadow);
194
+ backdrop-filter: blur(var(--dialog-blur));
195
+ animation: dialogSlideIn var(--duration-200);
149
196
  pointer-events: auto;
150
197
  }
151
198
 
@@ -165,9 +212,13 @@
165
212
  }
166
213
 
167
214
  .dialog-header {
168
- padding: .5rem var(--space-24);
169
- border-bottom: 1px solid var(--border-neutral-subtle);
170
- background: var(--empty);
215
+ padding:
216
+ var(--dialog-header-padding-top, var(--dialog-header-padding))
217
+ var(--dialog-header-padding-right, calc(var(--dialog-header-padding) * 3))
218
+ var(--dialog-header-padding-bottom, var(--dialog-header-padding))
219
+ var(--dialog-header-padding-left, calc(var(--dialog-header-padding) * 3));
220
+ border-bottom: var(--dialog-header-border-width) solid var(--dialog-header-border);
221
+ background: var(--dialog-header-surface);
171
222
  display: flex;
172
223
  justify-content: space-between;
173
224
  align-items: center;
@@ -175,39 +226,54 @@
175
226
 
176
227
  .dialog-title {
177
228
  margin: 0;
178
- font-size: var(--font-2xl);
179
- font-weight: var(--font-weight-semibold);
180
- color: var(--text-primary);
229
+ color: var(--dialog-title);
230
+ font-family: var(--dialog-title-font-family);
231
+ font-size: var(--dialog-title-font-size);
232
+ font-weight: var(--dialog-title-font-weight);
233
+ line-height: var(--dialog-title-line-height);
181
234
  }
182
235
 
183
236
  .dialog-close {
184
237
  background: none;
185
238
  border: none;
186
- color: var(--text-secondary);
187
- font-size: var(--font-xl);
239
+ color: var(--dialog-close-icon);
240
+ font-size: var(--dialog-close-icon-size);
188
241
  cursor: pointer;
189
- margin-right: -var(--space-16);
190
- width: 2rem;
191
- height: 2rem;
242
+ margin-right: -1rem;
243
+ width: 2.25rem;
244
+ height: 2.25rem;
192
245
  display: flex;
193
246
  align-items: center;
194
247
  justify-content: center;
195
248
  border-radius: var(--radius-md);
196
- transition: all var(--transition-base);
249
+ transition: all var(--duration-200);
197
250
  }
198
251
 
199
252
  .dialog-close:hover {
200
- background: var(--hover);
253
+ background: var(--surface-neutral-low);
201
254
  color: var(--text-primary);
202
255
  }
203
256
 
204
257
  .dialog-body {
205
- padding: var(--space-16) var(--space-24);
258
+ padding:
259
+ var(--dialog-body-padding-top, var(--dialog-body-padding))
260
+ var(--dialog-body-padding-right, calc(var(--dialog-body-padding) * 1.5))
261
+ var(--dialog-body-padding-bottom, var(--dialog-body-padding))
262
+ var(--dialog-body-padding-left, calc(var(--dialog-body-padding) * 1.5));
263
+ color: var(--dialog-body);
264
+ font-family: var(--dialog-body-font-family);
265
+ font-size: var(--dialog-body-font-size);
266
+ font-weight: var(--dialog-body-font-weight);
267
+ line-height: var(--dialog-body-line-height);
206
268
  }
207
269
 
208
270
  .dialog-footer {
209
- padding: var(--space-16);
210
- border-top: 1px solid var(--border-neutral-subtle);
271
+ padding:
272
+ var(--dialog-footer-padding-top, var(--dialog-footer-padding))
273
+ var(--dialog-footer-padding-right, var(--dialog-footer-padding))
274
+ var(--dialog-footer-padding-bottom, var(--dialog-footer-padding))
275
+ var(--dialog-footer-padding-left, var(--dialog-footer-padding));
276
+ border-top: var(--dialog-footer-border-width) solid var(--dialog-footer-border);
211
277
  display: flex;
212
278
  justify-content: space-between;
213
279
  align-items: center;
@@ -223,47 +289,4 @@
223
289
  display: flex;
224
290
  gap: var(--space-8);
225
291
  }
226
-
227
- .dialog-button {
228
- padding: var(--space-8) var(--space-16);
229
- border: 1px solid var(--border-neutral-subtle);
230
- border-radius: var(--radius-md);
231
- font-size: var(--font-md);
232
- font-weight: var(--font-weight-medium);
233
- cursor: pointer;
234
- transition: all var(--transition-base);
235
- min-width: 5rem;
236
- }
237
-
238
- .dialog-button:disabled {
239
- opacity: var(--opacity-disabled);
240
- cursor: not-allowed;
241
- }
242
-
243
- .dialog-button-primary {
244
- background: var(--btn-secondary-bg);
245
- color: var(--text-primary);
246
- border-color: var(--border-neutral-medium);
247
- }
248
-
249
- .dialog-button-primary:hover:not(:disabled) {
250
- background: var(--btn-secondary-hover);
251
- border-color: var(--border-neutral-strong);
252
- }
253
-
254
- .dialog-button-primary:focus {
255
- outline: 2px solid var(--border-neutral-strong);
256
- outline-offset: 0.125rem;
257
- }
258
-
259
- .dialog-button-secondary {
260
- background: transparent;
261
- color: var(--text-primary);
262
- border-color: var(--border-neutral-medium);
263
- }
264
-
265
- .dialog-button-secondary:hover:not(:disabled) {
266
- background: var(--hover-low);
267
- border-color: var(--border-neutral-strong);
268
- }
269
292
  </style>
@@ -0,0 +1,43 @@
1
+ <script lang="ts">
2
+ export let src: string;
3
+ export let alt: string;
4
+ export let variant: 'default' | 'banner' | 'medium' | 'compact' = 'default';
5
+ export let height: string | undefined = undefined;
6
+
7
+ const variantHeights: Record<string, string | undefined> = {
8
+ default: undefined,
9
+ banner: '360px',
10
+ medium: '240px',
11
+ compact: '180px',
12
+ };
13
+
14
+ $: resolvedHeight = height ?? variantHeights[variant];
15
+ </script>
16
+
17
+ <div class="image" style:height={resolvedHeight}>
18
+ <img {src} {alt} />
19
+ </div>
20
+
21
+ <style>
22
+ :global(:root) {
23
+ --image-default-radius: var(--radius-xl);
24
+ --image-default-border: var(--border-neutral);
25
+ --image-default-border-width: var(--border-width-1);
26
+ --image-default-shadow: var(--shadow-md);
27
+ }
28
+
29
+ .image {
30
+ border-radius: var(--image-default-radius);
31
+ overflow: hidden;
32
+ border: var(--image-default-border-width) solid var(--image-default-border);
33
+ box-shadow: var(--image-default-shadow);
34
+ }
35
+
36
+ img {
37
+ width: 100%;
38
+ height: 100%;
39
+ display: block;
40
+ object-fit: cover;
41
+ object-position: center;
42
+ }
43
+ </style>