@motion-proto/live-tokens 0.47.0 → 0.48.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 (124) hide show
  1. package/.claude/skills/live-tokens-adjust-shape-space/SKILL.md +68 -0
  2. package/.claude/skills/live-tokens-create-component/SKILL.md +2 -2
  3. package/.claude/skills/live-tokens-generate-theme/SKILL.md +152 -0
  4. package/CHANGELOG.md +292 -0
  5. package/README.md +37 -26
  6. package/bin/adjust.mjs +254 -0
  7. package/bin/cli.mjs +94 -7
  8. package/bin/generate-theme.mjs +251 -0
  9. package/bin/migrate.mjs +95 -6
  10. package/dist-plugin/adjust/index.cjs +259 -0
  11. package/dist-plugin/adjust/index.d.cts +45 -0
  12. package/dist-plugin/adjust/index.d.ts +45 -0
  13. package/dist-plugin/adjust/index.js +176 -0
  14. package/dist-plugin/{chunk-H4TRUINI.js → chunk-44RSTAII.js} +0 -48
  15. package/dist-plugin/chunk-6OZFXIQI.js +316 -0
  16. package/dist-plugin/chunk-76TFDTJO.js +556 -0
  17. package/dist-plugin/chunk-D3ZVKOR4.js +52 -0
  18. package/dist-plugin/dataPaths-DBN0RPuT.d.cts +54 -0
  19. package/dist-plugin/dataPaths-DBN0RPuT.d.ts +54 -0
  20. package/dist-plugin/generateColorsAndType/index.cjs +1781 -0
  21. package/dist-plugin/generateColorsAndType/index.d.cts +81 -0
  22. package/dist-plugin/generateColorsAndType/index.d.ts +81 -0
  23. package/dist-plugin/generateColorsAndType/index.js +1210 -0
  24. package/dist-plugin/index.cjs +901 -533
  25. package/dist-plugin/index.d.cts +3 -2
  26. package/dist-plugin/index.d.ts +3 -2
  27. package/dist-plugin/index.js +658 -1082
  28. package/dist-plugin/migrateData/index.cjs +728 -0
  29. package/dist-plugin/migrateData/index.d.cts +60 -0
  30. package/dist-plugin/migrateData/index.d.ts +60 -0
  31. package/dist-plugin/migrateData/index.js +348 -0
  32. package/dist-plugin/themeTypes-DMHZOnUn.d.cts +211 -0
  33. package/dist-plugin/themeTypes-DMHZOnUn.d.ts +211 -0
  34. package/dist-plugin/tokensCssMigrations/index.cjs +2 -1
  35. package/dist-plugin/tokensCssMigrations/index.d.cts +3 -15
  36. package/dist-plugin/tokensCssMigrations/index.d.ts +3 -15
  37. package/dist-plugin/tokensCssMigrations/index.js +4 -2
  38. package/package.json +18 -4
  39. package/src/editor/component-editor/scaffolding/ComponentFileManager.svelte +183 -158
  40. package/src/editor/component-editor/scaffolding/ComponentFileMenu.svelte +0 -4
  41. package/src/editor/component-editor/scaffolding/SaveAsDialog.svelte +4 -4
  42. package/src/editor/component-editor/scaffolding/TokenLayout.svelte +2 -59
  43. package/src/editor/component-editor/scaffolding/VariantGroup.svelte +1 -1
  44. package/src/editor/core/components/adjustAliases.ts +180 -0
  45. package/src/editor/core/components/aliasKinds.ts +73 -0
  46. package/src/editor/core/components/componentConfigService.ts +26 -38
  47. package/src/editor/core/flashStatus.ts +1 -1
  48. package/src/editor/core/fonts/fontMigration.ts +13 -13
  49. package/src/editor/core/fonts/fontPairing.ts +35 -0
  50. package/src/editor/core/palettes/paletteDerivation.ts +128 -16
  51. package/src/editor/core/preview/lookPreview.ts +141 -0
  52. package/src/editor/core/productionPulse.ts +34 -21
  53. package/src/editor/core/storage/files/versionedFileResourceClient.ts +18 -45
  54. package/src/editor/core/store/editorConfigStore.ts +2 -2
  55. package/src/editor/core/store/editorPersistence.ts +0 -1
  56. package/src/editor/core/store/editorStore.ts +114 -51
  57. package/src/editor/core/store/editorTypes.ts +0 -1
  58. package/src/editor/core/store/gradientSource.ts +2 -2
  59. package/src/editor/core/themes/colorsAndTypeService.ts +95 -0
  60. package/src/editor/core/themes/generateColorsAndType.ts +433 -0
  61. package/src/editor/core/themes/loadRows.ts +64 -0
  62. package/src/editor/core/themes/lookSummary.ts +75 -0
  63. package/src/editor/core/themes/migrations/2026-04-24-legacy-keys-and-bg-to-canvas.ts +3 -3
  64. package/src/editor/core/themes/migrations/2026-05-13-primary-to-brand.ts +2 -2
  65. package/src/editor/core/themes/migrations/2026-05-26-drop-overlay-extra-stops.ts +3 -3
  66. package/src/editor/core/themes/migrations/2026-08-13-drop-legacy-shape-space-keys.ts +38 -0
  67. package/src/editor/core/themes/migrations/2026-08-15-line-height-scale-rename.ts +57 -0
  68. package/src/editor/core/themes/migrations/index.ts +19 -11
  69. package/src/editor/core/themes/slices/components.ts +4 -4
  70. package/src/editor/core/themes/slices/fonts.ts +1 -1
  71. package/src/editor/core/themes/slices/gradients.ts +22 -0
  72. package/src/editor/core/themes/slices/palettes.ts +2 -2
  73. package/src/editor/core/themes/themeInit.ts +21 -29
  74. package/src/editor/core/themes/themeService.ts +218 -78
  75. package/src/editor/core/themes/themeTypes.ts +94 -51
  76. package/src/editor/docs/Docs.svelte +1 -0
  77. package/src/editor/docs/chapters.ts +1 -0
  78. package/src/editor/docs/content/01-overview.md +1 -1
  79. package/src/editor/docs/content/editing-tokens.md +6 -6
  80. package/src/editor/docs/content/getting-started.md +9 -7
  81. package/src/editor/docs/content/themes-workflow.md +74 -34
  82. package/src/editor/docs/content/where-themes-live.md +61 -0
  83. package/src/editor/docs/content.generated.ts +5 -4
  84. package/src/editor/index.ts +27 -27
  85. package/src/editor/pages/ComponentEditorPage.svelte +2 -2
  86. package/src/editor/pages/EditorShell.svelte +4 -30
  87. package/src/editor/ui/BezierCurveEditor.svelte +2 -2
  88. package/src/editor/ui/ColorEditPanel.svelte +1 -1
  89. package/src/editor/ui/FileLoadList.svelte +67 -7
  90. package/src/editor/ui/GradientEditor.svelte +3 -3
  91. package/src/editor/ui/PaletteEditor.svelte +26 -12
  92. package/src/editor/ui/ThemePanel.svelte +1067 -0
  93. package/src/editor/ui/UIDialog.svelte +11 -9
  94. package/src/editor/ui/UIPillButton.svelte +7 -2
  95. package/src/editor/ui/colors/ColorWheel.svelte +34 -1
  96. package/src/editor/ui/curveEngine.ts +48 -0
  97. package/src/editor/ui/index.ts +4 -2
  98. package/src/editor/ui/palette/PaletteBase.svelte +75 -51
  99. package/src/editor/ui/palette/PaletteJumpButton.svelte +3 -8
  100. package/src/live-tokens/data/colors-and-type/autumn.json +2490 -0
  101. package/src/live-tokens/data/{themes → colors-and-type}/default.json +816 -293
  102. package/src/live-tokens/data/colors-and-type/halloween.json +2529 -0
  103. package/src/live-tokens/data/colors-and-type/midnight-study.json +2536 -0
  104. package/src/live-tokens/data/colors-and-type/ocean.json +2489 -0
  105. package/src/live-tokens/data/colors-and-type/royal-velvet.json +2520 -0
  106. package/src/live-tokens/data/colors-and-type/spring-meadow.json +2476 -0
  107. package/src/live-tokens/data/colors-and-type/sunset.json +2528 -0
  108. package/src/live-tokens/data/themes/autumn.json +3918 -0
  109. package/src/live-tokens/data/themes/halloween.json +3992 -0
  110. package/src/live-tokens/data/themes/midnight-study.json +3932 -0
  111. package/src/live-tokens/data/themes/ocean.json +3917 -0
  112. package/src/live-tokens/data/themes/royal-velvet.json +3983 -0
  113. package/src/live-tokens/data/themes/spring-meadow.json +3904 -0
  114. package/src/live-tokens/data/themes/sunset.json +3931 -0
  115. package/src/live-tokens/data/tokens.generated.css +106 -117
  116. package/src/system/styles/CONVENTIONS.md +1 -1
  117. package/src/system/styles/fonts.css +1 -1
  118. package/template/README.md +7 -5
  119. package/template/_gitignore +0 -6
  120. package/src/editor/core/components/componentPersist.ts +0 -62
  121. package/src/editor/core/manifests/manifestService.ts +0 -172
  122. package/src/editor/ui/ManifestFileManager.svelte +0 -446
  123. package/src/editor/ui/ThemeFileManager.svelte +0 -785
  124. package/src/live-tokens/data/manifests/default.json +0 -35
@@ -0,0 +1,556 @@
1
+ // src/editor/core/storage/files/versionedFileResourceClient.ts
2
+ function sanitizeFileName(name) {
3
+ return name.toLowerCase().trim().replace(/\s+/g, "-").replace(/[^a-z0-9\-_]/g, "").replace(/-+/g, "-").replace(/^[-_]+|-+$/g, "") || "unnamed";
4
+ }
5
+
6
+ // src/editor/core/palettes/oklch.ts
7
+ function srgbToLinear(c) {
8
+ return c <= 0.04045 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4);
9
+ }
10
+ function linearToSrgb(c) {
11
+ return c <= 31308e-7 ? 12.92 * c : 1.055 * Math.pow(c, 1 / 2.4) - 0.055;
12
+ }
13
+ function hexToLinearRgb(hex) {
14
+ const r = parseInt(hex.slice(1, 3), 16) / 255;
15
+ const g = parseInt(hex.slice(3, 5), 16) / 255;
16
+ const b = parseInt(hex.slice(5, 7), 16) / 255;
17
+ return [srgbToLinear(r), srgbToLinear(g), srgbToLinear(b)];
18
+ }
19
+ function linearRgbToHex(r, g, b) {
20
+ const toHex = (c) => {
21
+ const v = Math.round(Math.max(0, Math.min(1, linearToSrgb(c))) * 255);
22
+ return v.toString(16).padStart(2, "0");
23
+ };
24
+ return `#${toHex(r)}${toHex(g)}${toHex(b)}`;
25
+ }
26
+ function linearRgbToOklab(r, g, b) {
27
+ const l_ = 0.4122214708 * r + 0.5363325363 * g + 0.0514459929 * b;
28
+ const m_ = 0.2119034982 * r + 0.6806995451 * g + 0.1073969566 * b;
29
+ const s_ = 0.0883024619 * r + 0.2817188376 * g + 0.6299787005 * b;
30
+ const l = Math.cbrt(l_);
31
+ const m = Math.cbrt(m_);
32
+ const s = Math.cbrt(s_);
33
+ return [
34
+ 0.2104542553 * l + 0.793617785 * m - 0.0040720468 * s,
35
+ 1.9779984951 * l - 2.428592205 * m + 0.4505937099 * s,
36
+ 0.0259040371 * l + 0.7827717662 * m - 0.808675766 * s
37
+ ];
38
+ }
39
+ function oklabToLinearRgb(L, a, b) {
40
+ const l_ = L + 0.3963377774 * a + 0.2158037573 * b;
41
+ const m_ = L - 0.1055613458 * a - 0.0638541728 * b;
42
+ const s_ = L - 0.0894841775 * a - 1.291485548 * b;
43
+ const l = l_ * l_ * l_;
44
+ const m = m_ * m_ * m_;
45
+ const s = s_ * s_ * s_;
46
+ return [
47
+ 4.0767416621 * l - 3.3077115913 * m + 0.2309699292 * s,
48
+ -1.2684380046 * l + 2.6097574011 * m - 0.3413193965 * s,
49
+ -0.0041960863 * l - 0.7034186147 * m + 1.707614701 * s
50
+ ];
51
+ }
52
+ function oklabToOklch(L, a, b) {
53
+ const c = Math.sqrt(a * a + b * b);
54
+ let h = Math.atan2(b, a) * 180 / Math.PI;
55
+ if (h < 0) h += 360;
56
+ return { l: L, c, h };
57
+ }
58
+ function oklchToOklab(l, c, h) {
59
+ const hRad = h * Math.PI / 180;
60
+ return [l, c * Math.cos(hRad), c * Math.sin(hRad)];
61
+ }
62
+ function hexToOklch(hex) {
63
+ const [r, g, b] = hexToLinearRgb(hex);
64
+ const [L, a, bVal] = linearRgbToOklab(r, g, b);
65
+ return oklabToOklch(L, a, bVal);
66
+ }
67
+ function oklchToHex(l, c, h) {
68
+ const [L, a, b] = oklchToOklab(l, c, h);
69
+ const [r, g, bVal] = oklabToLinearRgb(L, a, b);
70
+ return linearRgbToHex(r, g, bVal);
71
+ }
72
+ function isInGamut(r, g, b) {
73
+ const eps = 1e-4;
74
+ return r >= -eps && r <= 1 + eps && g >= -eps && g <= 1 + eps && b >= -eps && b <= 1 + eps;
75
+ }
76
+ function oklchToHexClamped(l, c, h) {
77
+ const g = gamutClamp(l, c, h);
78
+ return oklchToHex(g.l, g.c, g.h);
79
+ }
80
+ function gamutClamp(l, c, h) {
81
+ if (l <= 0) return { l: 0, c: 0, h };
82
+ if (l >= 1) return { l: 1, c: 0, h };
83
+ const [L, a, b] = oklchToOklab(l, c, h);
84
+ const [r, g, bVal] = oklabToLinearRgb(L, a, b);
85
+ if (isInGamut(r, g, bVal)) return { l, c, h };
86
+ let lo = 0;
87
+ let hi = c;
88
+ for (let i = 0; i < 20; i++) {
89
+ const mid = (lo + hi) / 2;
90
+ const [La, aa, ba] = oklchToOklab(l, mid, h);
91
+ const [rr, gg, bb] = oklabToLinearRgb(La, aa, ba);
92
+ if (isInGamut(rr, gg, bb)) {
93
+ lo = mid;
94
+ } else {
95
+ hi = mid;
96
+ }
97
+ }
98
+ return { l, c: lo, h };
99
+ }
100
+
101
+ // src/editor/ui/curveEngine.ts
102
+ function makeAnchor(x, y, tangentLen = 15) {
103
+ return { x, y, inDx: -tangentLen, inDy: 0, outDx: tangentLen, outDy: 0 };
104
+ }
105
+ var HANDLE_SPAN = 1 / 3;
106
+ function tangentSlope(prev, x, y, next) {
107
+ const hPrev = prev ? x - prev.x : 0;
108
+ const hNext = next ? next.x - x : 0;
109
+ const dPrev = hPrev > 0 ? (y - prev.y) / hPrev : null;
110
+ const dNext = hNext > 0 ? (next.y - y) / hNext : null;
111
+ if (dPrev === null) return dNext ?? 0;
112
+ if (dNext === null) return dPrev;
113
+ if (dPrev * dNext <= 0) return 0;
114
+ const wPrev = 2 * hNext + hPrev;
115
+ const wNext = hNext + 2 * hPrev;
116
+ return (wPrev + wNext) / (wPrev / dPrev + wNext / dNext);
117
+ }
118
+ function tangentAnchor(x, y, prev, next) {
119
+ const m = tangentSlope(prev, x, y, next);
120
+ const inDx = prev ? -(x - prev.x) * HANDLE_SPAN : 0;
121
+ const outDx = next ? (next.x - x) * HANDLE_SPAN : 0;
122
+ return { x, y, inDx, inDy: m * inDx, outDx, outDy: m * outDx };
123
+ }
124
+ function evalBezier(p0x, p0y, c0x, c0y, c1x, c1y, p1x, p1y, t) {
125
+ const u = 1 - t, u2 = u * u, u3 = u2 * u;
126
+ const t2 = t * t, t3 = t2 * t;
127
+ return {
128
+ x: u3 * p0x + 3 * u2 * t * c0x + 3 * u * t2 * c1x + t3 * p1x,
129
+ y: u3 * p0y + 3 * u2 * t * c0y + 3 * u * t2 * c1y + t3 * p1y
130
+ };
131
+ }
132
+ function sampleCurve(anchors, xPos) {
133
+ if (anchors.length === 0) return 0;
134
+ if (anchors.length === 1) return anchors[0].y;
135
+ if (xPos <= anchors[0].x) return anchors[0].y;
136
+ if (xPos >= anchors[anchors.length - 1].x) return anchors[anchors.length - 1].y;
137
+ let seg = 0;
138
+ while (seg < anchors.length - 2 && anchors[seg + 1].x < xPos) seg++;
139
+ const a0 = anchors[seg], a1 = anchors[seg + 1];
140
+ const p0x = a0.x, p0y = a0.y;
141
+ const c0x = a0.x + a0.outDx, c0y = a0.y + a0.outDy;
142
+ const c1x = a1.x + a1.inDx, c1y = a1.y + a1.inDy;
143
+ const p1x = a1.x, p1y = a1.y;
144
+ let lo = 0, hi = 1;
145
+ for (let i = 0; i < 20; i++) {
146
+ const mid = (lo + hi) / 2;
147
+ const pt = evalBezier(p0x, p0y, c0x, c0y, c1x, c1y, p1x, p1y, mid);
148
+ if (pt.x < xPos) lo = mid;
149
+ else hi = mid;
150
+ }
151
+ return evalBezier(p0x, p0y, c0x, c0y, c1x, c1y, p1x, p1y, (lo + hi) / 2).y;
152
+ }
153
+
154
+ // src/editor/core/palettes/paletteDerivation.ts
155
+ var PALETTE_SPECS = [
156
+ { label: "Brand", cssNamespace: "brand", initialColor: { l: 0.5573, c: 0.1841, h: 25.49 } },
157
+ { label: "Accent", cssNamespace: "accent", initialColor: { l: 0.7674, c: 0.164, h: 70.44 } },
158
+ { label: "Special", cssNamespace: "special", initialColor: { l: 0.6056, c: 0.2189, h: 292.72 } },
159
+ { label: "Canvas", cssNamespace: "canvas", emptySelector: true, initialColor: { l: 0.2284, c: 0.0384, h: 282.93 } },
160
+ { label: "Neutral", cssNamespace: "neutral", neutral: true, initialColor: { l: 0.5679, c: 0.0134, h: 240.07 } },
161
+ { label: "Alternate", cssNamespace: "alternate", neutral: true, displayLabel: "Alternate (neutral)", initialColor: { l: 0.5873, c: 87e-4, h: 48.57 } },
162
+ { label: "Info", cssNamespace: "info", initialColor: { l: 0.5871, c: 0.1855, h: 259.56 } },
163
+ { label: "Success", cssNamespace: "success", initialColor: { l: 0.7198, c: 0.1918, h: 149.52 } },
164
+ { label: "Warning", cssNamespace: "warning", initialColor: { l: 0.6704, c: 0.1716, h: 48.75 } },
165
+ { label: "Danger", cssNamespace: "danger", initialColor: { l: 0.6103, c: 0.2165, h: 18.1 } }
166
+ ];
167
+ var PALETTE_STEPS = [
168
+ { label: "100" },
169
+ { label: "200" },
170
+ { label: "300" },
171
+ { label: "400" },
172
+ { label: "500" },
173
+ { label: "600" },
174
+ { label: "700" },
175
+ { label: "800" },
176
+ { label: "850" },
177
+ { label: "900" },
178
+ { label: "950" }
179
+ ];
180
+ var SCALES = [
181
+ {
182
+ title: "Surfaces",
183
+ isText: false,
184
+ steps: [
185
+ { name: "lowest", position: -1 },
186
+ { name: "lower", position: -2 / 3 },
187
+ { name: "low", position: -1 / 3 },
188
+ { name: "default", position: 0 },
189
+ { name: "high", position: 1 / 3 },
190
+ { name: "higher", position: 2 / 3 },
191
+ { name: "highest", position: 1 }
192
+ ]
193
+ },
194
+ {
195
+ title: "Borders",
196
+ isText: false,
197
+ steps: [
198
+ { name: "faint", position: -1 },
199
+ { name: "subtle", position: -0.5 },
200
+ { name: "default", position: 0 },
201
+ { name: "medium", position: 0.5 },
202
+ { name: "strong", position: 1 }
203
+ ]
204
+ },
205
+ {
206
+ title: "Text",
207
+ isText: true,
208
+ steps: [
209
+ { name: "primary", position: 0 },
210
+ { name: "secondary", position: 0 },
211
+ { name: "tertiary", position: 0 },
212
+ { name: "muted", position: 0 },
213
+ { name: "disabled", position: 0 }
214
+ ]
215
+ }
216
+ ];
217
+ var BW_GUARD_MIN_L = 0.17;
218
+ var BW_GUARD_MAX_L = 0.93;
219
+ var DEFAULT_PALETTE_LIGHTNESS = () => [makeAnchor(0, 95, 5), makeAnchor(100, 8, 5)];
220
+ var DEFAULT_PALETTE_SATURATION = () => [makeAnchor(0, 100, 30), makeAnchor(100, 100, 30)];
221
+ function scaleCurveDefaults(scheme = "dark") {
222
+ if (scheme === "light") {
223
+ return {
224
+ Surfaces: {
225
+ lightness: () => [makeAnchor(0, 98, 5), makeAnchor(100, 82, 5)],
226
+ saturation: () => [makeAnchor(0, 100, 30), makeAnchor(100, 100, 30)]
227
+ },
228
+ Borders: {
229
+ lightness: () => [makeAnchor(0, 92, 5), makeAnchor(100, 45, 5)],
230
+ saturation: () => [makeAnchor(0, 100, 30), makeAnchor(100, 100, 30)]
231
+ },
232
+ Text: {
233
+ lightness: () => [makeAnchor(0, 30, 30), makeAnchor(100, 120, 30)],
234
+ saturation: () => [makeAnchor(0, 100, 30), makeAnchor(100, 15, 30)]
235
+ }
236
+ };
237
+ }
238
+ return {
239
+ Surfaces: {
240
+ lightness: () => [makeAnchor(0, 15, 5), makeAnchor(100, 47, 5)],
241
+ saturation: () => [makeAnchor(0, 100, 30), makeAnchor(100, 100, 30)]
242
+ },
243
+ Borders: {
244
+ lightness: () => [makeAnchor(0, 25, 5), makeAnchor(100, 80, 5)],
245
+ saturation: () => [makeAnchor(0, 100, 30), makeAnchor(100, 100, 30)]
246
+ },
247
+ Text: {
248
+ lightness: () => [makeAnchor(0, 120, 30), makeAnchor(100, 55, 30)],
249
+ saturation: () => [makeAnchor(0, 100, 30), makeAnchor(100, 15, 30)]
250
+ }
251
+ };
252
+ }
253
+ var defaultScaleCurves = scaleCurveDefaults("dark");
254
+ function paletteStepKey(label) {
255
+ return `Palette-${label}`;
256
+ }
257
+ function stepKey(scaleTitle, stepName) {
258
+ return `${scaleTitle}-${stepName}`;
259
+ }
260
+ function stepIndexToX(index) {
261
+ return index / (PALETTE_STEPS.length - 1) * 100;
262
+ }
263
+ function scaleStepToX(step, scale) {
264
+ const idx = scale.steps.indexOf(step);
265
+ return scale.steps.length > 1 ? idx / (scale.steps.length - 1) * 100 : 50;
266
+ }
267
+ function serializeDerivedValue(value) {
268
+ return value.kind === "raw" ? value.css : oklchToHexClamped(value.l, value.c, value.h);
269
+ }
270
+ function computePaletteOklch(index, base, lightnessCurve, saturationCurve, curveOffset) {
271
+ const { c: baseC, h } = base;
272
+ const xPos = stepIndexToX(index);
273
+ const targetL = Math.max(0, Math.min(100, sampleCurve(lightnessCurve, xPos) + (curveOffset.lightness ?? 0))) / 100;
274
+ const satMul = Math.max(0, Math.min(2, (sampleCurve(saturationCurve, xPos) + (curveOffset.saturation ?? 0)) / 100));
275
+ const targetC = baseC * satMul;
276
+ return gamutClamp(targetL, targetC, h);
277
+ }
278
+ function nearestPaletteStep(lightnessCurve, baseL) {
279
+ let best = 0;
280
+ let bestD = Infinity;
281
+ for (let i = 0; i < PALETTE_STEPS.length; i++) {
282
+ const d = Math.abs(sampleCurve(lightnessCurve, stepIndexToX(i)) - baseL * 100);
283
+ if (d < bestD) {
284
+ bestD = d;
285
+ best = i;
286
+ }
287
+ }
288
+ return best;
289
+ }
290
+ function setCurveAnchor(curve, x, y, smooth = false) {
291
+ if (smooth && curve.length === 2) {
292
+ const [p0, p2] = curve;
293
+ const mid = { x, y, inDx: 0, inDy: 0, outDx: 0, outDy: 0 };
294
+ if (Math.abs(p0.x - x) < 0.5) {
295
+ return {
296
+ curve: [tangentAnchor(x, y, null, p2), tangentAnchor(p2.x, p2.y, mid, null)],
297
+ displacedY: p0.y,
298
+ priorEndpoints: [p0, p2]
299
+ };
300
+ }
301
+ if (Math.abs(p2.x - x) < 0.5) {
302
+ return {
303
+ curve: [tangentAnchor(p0.x, p0.y, null, mid), tangentAnchor(x, y, p0, null)],
304
+ displacedY: p2.y,
305
+ priorEndpoints: [p0, p2]
306
+ };
307
+ }
308
+ return {
309
+ curve: [
310
+ tangentAnchor(p0.x, p0.y, null, mid),
311
+ tangentAnchor(x, y, p0, p2),
312
+ tangentAnchor(p2.x, p2.y, mid, null)
313
+ ],
314
+ priorEndpoints: [p0, p2]
315
+ };
316
+ }
317
+ const existing = curve.findIndex((a) => Math.abs(a.x - x) < 0.5);
318
+ if (existing >= 0) {
319
+ const displacedY = curve[existing].y;
320
+ return { curve: curve.map((a, i) => i === existing ? { ...a, x, y } : a), displacedY };
321
+ }
322
+ let insertAt = curve.findIndex((a) => a.x > x);
323
+ if (insertAt < 0) insertAt = curve.length;
324
+ const prev = curve[insertAt - 1] ?? null;
325
+ const next = curve[insertAt] ?? null;
326
+ const out = [...curve];
327
+ if (prev && next) {
328
+ const span = next.x - prev.x;
329
+ out[insertAt - 1] = scaleOutHandle(prev, (x - prev.x) / span);
330
+ out[insertAt] = scaleInHandle(next, (next.x - x) / span);
331
+ }
332
+ out.splice(insertAt, 0, fitBetween(tangentAnchor(x, y, prev, next), out[insertAt - 1] ?? null, out[insertAt] ?? null));
333
+ return { curve: out };
334
+ }
335
+ var scaleOutHandle = (a, k) => ({ ...a, outDx: a.outDx * k, outDy: a.outDy * k });
336
+ var scaleInHandle = (a, k) => ({ ...a, inDx: a.inDx * k, inDy: a.inDy * k });
337
+ function fitBetween(a, prev, next) {
338
+ let out = a;
339
+ if (prev) {
340
+ const room = a.x - (prev.x + prev.outDx);
341
+ if (room < -out.inDx) out = scaleInHandle(out, room <= 0 ? 0 : room / -out.inDx);
342
+ }
343
+ if (next) {
344
+ const room = next.x + next.inDx - a.x;
345
+ if (room < out.outDx) out = scaleOutHandle(out, room <= 0 ? 0 : room / out.outDx);
346
+ }
347
+ return out;
348
+ }
349
+ function liftCurveAnchor(curve, x, displacedY, priorEndpoints) {
350
+ if (priorEndpoints) return priorEndpoints;
351
+ const idx = curve.findIndex((a) => Math.abs(a.x - x) < 0.5);
352
+ if (idx < 0) return curve;
353
+ if (displacedY !== void 0) return curve.map((a, i) => i === idx ? { ...a, y: displacedY } : a);
354
+ if (idx === 0 || idx === curve.length - 1) return curve;
355
+ const out = curve.filter((_, i) => i !== idx);
356
+ const prev = curve[idx - 1];
357
+ const next = curve[idx + 1];
358
+ if (prev && next) {
359
+ const span = next.x - prev.x;
360
+ out[idx - 1] = scaleOutHandle(prev, span / (curve[idx].x - prev.x));
361
+ out[idx] = scaleInHandle(next, span / (next.x - curve[idx].x));
362
+ }
363
+ return out;
364
+ }
365
+ function syncBaseAnchor(cfg) {
366
+ if (cfg.anchorToBase === false) return;
367
+ const prev = cfg.anchorPlacement;
368
+ const fresh = prev === void 0;
369
+ let lCurve = cfg.lightnessCurve;
370
+ let sCurve = cfg.saturationCurve;
371
+ if (prev) {
372
+ const prevX = stepIndexToX(prev.step);
373
+ lCurve = liftCurveAnchor(lCurve, prevX, prev.displacedL);
374
+ sCurve = liftCurveAnchor(sCurve, prevX, prev.displacedS);
375
+ }
376
+ const step = nearestPaletteStep(lCurve, cfg.baseColor.l);
377
+ const x = stepIndexToX(step);
378
+ const l = setCurveAnchor(lCurve, x, cfg.baseColor.l * 100, fresh);
379
+ const s = setCurveAnchor(sCurve, x, 100, fresh);
380
+ cfg.lightnessCurve = l.curve;
381
+ cfg.saturationCurve = s.curve;
382
+ cfg.anchorPlacement = {
383
+ step,
384
+ displacedL: l.displacedY,
385
+ displacedS: s.displacedY,
386
+ priorLightnessEndpoints: prev?.priorLightnessEndpoints ?? l.priorEndpoints,
387
+ priorSaturationEndpoints: prev?.priorSaturationEndpoints ?? s.priorEndpoints
388
+ };
389
+ }
390
+ function computeDerivedOklch(step, base, scaleTitle, scaleCurves, curveOffset) {
391
+ const scale = SCALES.find((s) => s.title === scaleTitle);
392
+ const xPos = scaleStepToX(step, scale);
393
+ const defs = defaultScaleCurves[scaleTitle];
394
+ const lCurve = scaleCurves[scaleTitle]?.lightness ?? defs.lightness();
395
+ const sCurve = scaleCurves[scaleTitle]?.saturation ?? defs.saturation();
396
+ const lOff = curveOffset[`${scaleTitle}-lightness`] ?? 0;
397
+ const sOff = curveOffset[`${scaleTitle}-saturation`] ?? 0;
398
+ const { l: baseL, c: baseC, h: baseH } = base;
399
+ let targetL;
400
+ if (scale.isText) {
401
+ const lMul = Math.max(0, Math.min(2, (sampleCurve(lCurve, xPos) + lOff) / 100));
402
+ targetL = Math.max(0, Math.min(1, baseL * lMul));
403
+ } else {
404
+ targetL = Math.max(0, Math.min(100, sampleCurve(lCurve, xPos) + lOff)) / 100;
405
+ }
406
+ const satMul = Math.max(0, Math.min(2, (sampleCurve(sCurve, xPos) + sOff) / 100));
407
+ const targetC = baseC * satMul;
408
+ return gamutClamp(targetL, targetC, baseH);
409
+ }
410
+ function scaleToCssVar(scaleTitle, stepName, cssNamespace) {
411
+ if (cssNamespace === null) return null;
412
+ if (scaleTitle === "Surfaces") {
413
+ const suffix = stepName === "default" ? "" : `-${stepName}`;
414
+ return cssNamespace === "neutral" ? `--surface-neutral${suffix}` : `--surface-${cssNamespace}${suffix}`;
415
+ }
416
+ if (scaleTitle === "Borders") {
417
+ const suffix = stepName === "default" ? "" : `-${stepName}`;
418
+ return cssNamespace === "neutral" ? `--border-neutral${suffix}` : `--border-${cssNamespace}${suffix}`;
419
+ }
420
+ if (scaleTitle === "Text") {
421
+ if (cssNamespace === "neutral") return `--text-${stepName}`;
422
+ return stepName === "primary" ? `--text-${cssNamespace}` : `--text-${cssNamespace}-${stepName}`;
423
+ }
424
+ return null;
425
+ }
426
+ function derivePaletteValues(spec, config) {
427
+ const out = {};
428
+ if (!config) return out;
429
+ const baseColor = config.baseColor ?? spec.initialColor;
430
+ const overrides = config.overrides ?? {};
431
+ const curveOffset = config.curveOffset ?? {};
432
+ const scaleCurves = config.scaleCurves ?? {};
433
+ const lightnessCurve = config.lightnessCurve ?? DEFAULT_PALETTE_LIGHTNESS();
434
+ const saturationCurve = config.saturationCurve ?? DEFAULT_PALETTE_SATURATION();
435
+ PALETTE_STEPS.forEach((ps, index) => {
436
+ const k = paletteStepKey(ps.label);
437
+ const value = k in overrides ? { kind: "color", ...overrides[k] } : { kind: "color", ...computePaletteOklch(index, baseColor, lightnessCurve, saturationCurve, curveOffset) };
438
+ out[`--color-${spec.cssNamespace}-${ps.label}`] = value;
439
+ });
440
+ for (const scale of SCALES) {
441
+ for (const step of scale.steps) {
442
+ const k = stepKey(scale.title, step.name);
443
+ const value = k in overrides ? { kind: "color", ...overrides[k] } : { kind: "color", ...computeDerivedOklch(step, baseColor, scale.title, scaleCurves, curveOffset) };
444
+ const varName = scaleToCssVar(scale.title, step.name, spec.cssNamespace);
445
+ if (varName) out[varName] = value;
446
+ }
447
+ }
448
+ const textPrimary = out["--text-primary"];
449
+ if (textPrimary?.kind === "color") {
450
+ const mirroredL = Math.max(BW_GUARD_MIN_L, Math.min(BW_GUARD_MAX_L, 1 - textPrimary.l));
451
+ out["--text-inverted"] = { kind: "color", ...gamutClamp(mirroredL, textPrimary.c, textPrimary.h) };
452
+ }
453
+ if (spec.emptySelector) {
454
+ const emptyMode = config.emptyMode ?? "solid";
455
+ const gradientStyle = config.gradientStyle ?? "linear";
456
+ const gradientAngle = config.gradientAngle ?? 180;
457
+ const gradientReverse = config.gradientReverse ?? false;
458
+ const gradientSize = config.gradientSize ?? "page";
459
+ const gradientStops = config.gradientStops ?? [
460
+ { position: 0, paletteLabel: "800" },
461
+ { position: 100, paletteLabel: "950" }
462
+ ];
463
+ if (emptyMode === "solid") {
464
+ out["--page-bg"] = { kind: "color", ...baseColor };
465
+ out["--page-bg-attachment"] = { kind: "raw", css: "scroll" };
466
+ } else {
467
+ const sortedStops = [...gradientStops].sort(
468
+ (a, b) => gradientReverse ? b.position - a.position : a.position - b.position
469
+ );
470
+ const stopsCss = sortedStops.map((s) => {
471
+ const stopValue = out[`--color-${spec.cssNamespace}-${s.paletteLabel}`];
472
+ const hex = stopValue ? serializeDerivedValue(stopValue) : "#000000";
473
+ return `${hex} ${s.position}%`;
474
+ }).join(", ");
475
+ let gradient;
476
+ switch (gradientStyle) {
477
+ case "radial":
478
+ gradient = `radial-gradient(circle, ${stopsCss})`;
479
+ break;
480
+ case "conic":
481
+ gradient = `conic-gradient(from ${gradientAngle}deg, ${stopsCss})`;
482
+ break;
483
+ default:
484
+ gradient = `linear-gradient(${gradientAngle}deg, ${stopsCss})`;
485
+ }
486
+ out["--page-bg"] = { kind: "raw", css: gradient };
487
+ out["--page-bg-attachment"] = { kind: "raw", css: gradientSize === "window" ? "fixed" : "scroll" };
488
+ }
489
+ }
490
+ return out;
491
+ }
492
+ function derivePaletteVars(spec, config) {
493
+ const out = {};
494
+ for (const [k, v] of Object.entries(derivePaletteValues(spec, config))) {
495
+ out[k] = serializeDerivedValue(v);
496
+ }
497
+ return out;
498
+ }
499
+ function palettesToValues(palettes) {
500
+ const out = {};
501
+ for (const spec of PALETTE_SPECS) {
502
+ Object.assign(out, derivePaletteValues(spec, palettes[spec.label]));
503
+ }
504
+ return out;
505
+ }
506
+ function palettesToVars(palettes) {
507
+ const out = {};
508
+ for (const [k, v] of Object.entries(palettesToValues(palettes))) {
509
+ out[k] = serializeDerivedValue(v);
510
+ }
511
+ return out;
512
+ }
513
+ var HEX_RE = /^#[0-9a-f]{6}$/i;
514
+ function reconcilePalettesFromCssVars(palettes, cssVars) {
515
+ const next = structuredClone(palettes);
516
+ const consumed = /* @__PURE__ */ new Set();
517
+ const snapped = /* @__PURE__ */ new Set();
518
+ for (const spec of PALETTE_SPECS) {
519
+ const current = next[spec.label];
520
+ if (current === void 0) continue;
521
+ if (current._imported === true) {
522
+ const anchorHex = cssVars[`--color-${spec.cssNamespace}-500`];
523
+ if (anchorHex && HEX_RE.test(anchorHex.trim())) {
524
+ next[spec.label] = { ...current, baseColor: hexToOklch(anchorHex.trim()), _imported: false };
525
+ syncBaseAnchor(next[spec.label]);
526
+ snapped.add(spec.label);
527
+ } else {
528
+ next[spec.label] = { ...current, _imported: false };
529
+ }
530
+ }
531
+ for (const k of Object.keys(derivePaletteVars(spec, next[spec.label]))) {
532
+ consumed.add(k);
533
+ }
534
+ }
535
+ return { palettes: next, consumed, snapped };
536
+ }
537
+
538
+ export {
539
+ sanitizeFileName,
540
+ hexToOklch,
541
+ oklchToHex,
542
+ gamutClamp,
543
+ makeAnchor,
544
+ PALETTE_SPECS,
545
+ PALETTE_STEPS,
546
+ SCALES,
547
+ DEFAULT_PALETTE_LIGHTNESS,
548
+ DEFAULT_PALETTE_SATURATION,
549
+ scaleCurveDefaults,
550
+ scaleStepToX,
551
+ setCurveAnchor,
552
+ syncBaseAnchor,
553
+ scaleToCssVar,
554
+ palettesToVars,
555
+ reconcilePalettesFromCssVars
556
+ };
@@ -0,0 +1,52 @@
1
+ // vite-plugin/files/dataPaths.ts
2
+ import fs from "fs";
3
+ import path from "path";
4
+ var DEFAULT_DATA_DIR = "src/live-tokens/data";
5
+ var KNOWN_CONFIG_KEYS = /* @__PURE__ */ new Set([
6
+ "dataDir",
7
+ "colorsAndTypeDir",
8
+ "componentConfigsDir",
9
+ "themesDir",
10
+ "manifestsDir",
11
+ "tokensCssPath"
12
+ ]);
13
+ var cached = null;
14
+ function readLiveTokensConfig() {
15
+ if (cached) return cached;
16
+ try {
17
+ const configPath = path.resolve("live-tokens.config.json");
18
+ if (!fs.existsSync(configPath)) return cached = {};
19
+ const parsed = JSON.parse(fs.readFileSync(configPath, "utf-8"));
20
+ if (!parsed || typeof parsed !== "object") return cached = {};
21
+ const unknown = Object.keys(parsed).filter(
22
+ (k) => k !== "$schema" && !KNOWN_CONFIG_KEYS.has(k)
23
+ );
24
+ if (unknown.length > 0) {
25
+ console.warn(
26
+ `[live-tokens] Unknown key(s) in live-tokens.config.json: ${unknown.join(", ")}. Known keys: ${Array.from(KNOWN_CONFIG_KEYS).join(", ")}.`
27
+ );
28
+ }
29
+ cached = parsed;
30
+ return cached;
31
+ } catch {
32
+ return cached = {};
33
+ }
34
+ }
35
+ function resolveDataDirs(opts = {}) {
36
+ const fileConfig = readLiveTokensConfig();
37
+ const dataDirRaw = opts.dataDir ?? fileConfig.dataDir ?? DEFAULT_DATA_DIR;
38
+ const dataDir = path.resolve(dataDirRaw);
39
+ const sub = (name) => path.resolve(dataDir, name);
40
+ return {
41
+ dataDir,
42
+ colorsAndTypeDir: opts.colorsAndTypeDir ? path.resolve(opts.colorsAndTypeDir) : fileConfig.colorsAndTypeDir ? path.resolve(fileConfig.colorsAndTypeDir) : sub("colors-and-type"),
43
+ componentConfigsDir: opts.componentConfigsDir ? path.resolve(opts.componentConfigsDir) : fileConfig.componentConfigsDir ? path.resolve(fileConfig.componentConfigsDir) : sub("component-configs"),
44
+ themesDir: opts.themesDir ? path.resolve(opts.themesDir) : fileConfig.themesDir ? path.resolve(fileConfig.themesDir) : sub("themes"),
45
+ legacyManifestsDir: fileConfig.manifestsDir ? path.resolve(fileConfig.manifestsDir) : void 0
46
+ };
47
+ }
48
+
49
+ export {
50
+ readLiveTokensConfig,
51
+ resolveDataDirs
52
+ };
@@ -0,0 +1,54 @@
1
+ interface LiveTokensFileConfig {
2
+ dataDir?: string;
3
+ colorsAndTypeDir?: string;
4
+ componentConfigsDir?: string;
5
+ themesDir?: string;
6
+ /**
7
+ * Retired in 0.48, where `themesDir` took over the meaning. Still recognised
8
+ * so an unmigrated project is not told its key is a typo, and so the
9
+ * migration can find (or refuse to guess at) a whole-look directory the
10
+ * consumer moved.
11
+ */
12
+ manifestsDir?: string;
13
+ /**
14
+ * Path to the developer-authored `tokens.css`. The dev plugin takes this from
15
+ * its `themeFileApi({ tokensCssPath })` option; the standalone `live-tokens
16
+ * migrate` CLI has no plugin options, so it reads this key to locate the file.
17
+ */
18
+ tokensCssPath?: string;
19
+ }
20
+ interface ResolveDataDirsInput {
21
+ dataDir?: string;
22
+ colorsAndTypeDir?: string;
23
+ componentConfigsDir?: string;
24
+ themesDir?: string;
25
+ }
26
+ interface ResolvedDataDirs {
27
+ dataDir: string;
28
+ colorsAndTypeDir: string;
29
+ componentConfigsDir: string;
30
+ themesDir: string;
31
+ /** Absolute path of the retired `manifestsDir` key, when the config sets it.
32
+ * Only the pre-0.48 layout detector and the migration read it. */
33
+ legacyManifestsDir?: string;
34
+ }
35
+ declare function readLiveTokensConfig(): LiveTokensFileConfig;
36
+ /**
37
+ * Resolve the four data directories for a single plugin/preprocessor.
38
+ *
39
+ * Per-folder resolution order (most specific wins):
40
+ * 1. explicit opts (e.g. `opts.colorsAndTypeDir`)
41
+ * 2. `live-tokens.config.json` field (e.g. `fileConfig.colorsAndTypeDir`)
42
+ * 3. `<dataDir>/<sub>` where dataDir comes from opts > config file > the
43
+ * package default (`src/live-tokens/data`)
44
+ *
45
+ * This lets a consumer set `dataDir` once and have all three subfolders move
46
+ * together, while still allowing per-folder overrides for unusual layouts
47
+ * (e.g. a monorepo where colors and type are shared across packages but
48
+ * component-configs aren't).
49
+ *
50
+ * All returned paths are absolute (resolved via `path.resolve` against cwd).
51
+ */
52
+ declare function resolveDataDirs(opts?: ResolveDataDirsInput): ResolvedDataDirs;
53
+
54
+ export { resolveDataDirs as a, readLiveTokensConfig as r };