@motion-proto/live-tokens 0.50.0 → 0.52.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.
- package/CHANGELOG.md +45 -0
- package/dist-plugin/adjust/index.d.cts +1 -1
- package/dist-plugin/adjust/index.d.ts +1 -1
- package/dist-plugin/{chunk-76TFDTJO.js → chunk-JIGIIE5P.js} +60 -132
- package/dist-plugin/{chunk-44RSTAII.js → chunk-TKZBVIW5.js} +33 -5
- package/dist-plugin/chunk-YR6GPXW2.js +129 -0
- package/dist-plugin/generateColorsAndType/index.cjs +87 -31
- package/dist-plugin/generateColorsAndType/index.d.cts +1 -1
- package/dist-plugin/generateColorsAndType/index.d.ts +1 -1
- package/dist-plugin/generateColorsAndType/index.js +22 -12
- package/dist-plugin/index.cjs +95 -55
- package/dist-plugin/index.js +5 -3
- package/dist-plugin/{themeTypes-DSwKq-bj.d.cts → themeTypes-Dky03HL9.d.cts} +18 -5
- package/dist-plugin/{themeTypes-DSwKq-bj.d.ts → themeTypes-Dky03HL9.d.ts} +18 -5
- package/dist-plugin/tokensCssMigrations/index.cjs +71 -5
- package/dist-plugin/tokensCssMigrations/index.d.cts +20 -9
- package/dist-plugin/tokensCssMigrations/index.d.ts +20 -9
- package/dist-plugin/tokensCssMigrations/index.js +4 -1
- package/package.json +4 -2
- package/src/editor/component-editor/NotificationEditor.svelte +6 -0
- package/src/editor/core/palettes/oklch.ts +3 -137
- package/src/editor/core/palettes/paletteDerivation.ts +79 -37
- package/src/editor/core/themes/generateColorsAndType.ts +18 -8
- package/src/editor/core/themes/themeTypes.ts +18 -6
- package/src/editor/docs/content/editing-tokens.md +6 -2
- package/src/editor/docs/content.generated.ts +1 -1
- package/src/editor/ui/BezierCurveEditor.svelte +90 -67
- package/src/editor/ui/PaletteEditor.svelte +150 -44
- package/src/editor/ui/Toggle.svelte +14 -2
- package/src/editor/ui/colors/ColorStory.svelte +12 -8
- package/src/editor/ui/curveEngine.ts +101 -21
- package/src/editor/ui/palette/OverridesPanel.svelte +19 -5
- package/src/editor/ui/palette/PaletteBase.svelte +17 -78
- package/src/editor/ui/palette/ScaleCurveEditor.svelte +109 -20
- package/src/editor/ui/palette/curveSummary.ts +20 -0
- package/src/editor/ui/palette/dockMagnify.ts +5 -13
- package/src/editor/ui/palette/paletteMath.ts +7 -4
- package/src/live-tokens/data/colors-and-type/autumn.json +528 -528
- package/src/live-tokens/data/colors-and-type/default.json +247 -247
- package/src/live-tokens/data/colors-and-type/halloween.json +532 -532
- package/src/live-tokens/data/colors-and-type/midnight-study.json +538 -538
- package/src/live-tokens/data/colors-and-type/ocean.json +521 -521
- package/src/live-tokens/data/colors-and-type/royal-velvet.json +532 -532
- package/src/live-tokens/data/colors-and-type/spring-meadow.json +504 -504
- package/src/live-tokens/data/colors-and-type/sunset.json +531 -531
- package/src/live-tokens/data/themes/autumn.json +527 -527
- package/src/live-tokens/data/themes/halloween.json +531 -531
- package/src/live-tokens/data/themes/midnight-study.json +537 -537
- package/src/live-tokens/data/themes/ocean.json +520 -520
- package/src/live-tokens/data/themes/royal-velvet.json +531 -531
- package/src/live-tokens/data/themes/spring-meadow.json +504 -504
- package/src/live-tokens/data/themes/sunset.json +531 -531
- package/src/live-tokens/data/tokens.generated.css +282 -282
- package/src/system/components/FloatingTokenTags.css +0 -1
- package/src/system/internal/backgroundContrast.ts +7 -0
- package/src/system/internal/oklch.ts +189 -0
- package/src/system/styles/tokens.css +283 -283
package/dist-plugin/index.cjs
CHANGED
|
@@ -65,26 +65,16 @@ function sanitizeFileName(name) {
|
|
|
65
65
|
return name.toLowerCase().trim().replace(/\s+/g, "-").replace(/[^a-z0-9\-_]/g, "").replace(/-+/g, "-").replace(/^[-_]+|-+$/g, "") || "unnamed";
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
-
// src/
|
|
68
|
+
// src/system/internal/oklch.ts
|
|
69
69
|
function srgbToLinear(c) {
|
|
70
70
|
return c <= 0.04045 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4);
|
|
71
71
|
}
|
|
72
|
-
function linearToSrgb(c) {
|
|
73
|
-
return c <= 31308e-7 ? 12.92 * c : 1.055 * Math.pow(c, 1 / 2.4) - 0.055;
|
|
74
|
-
}
|
|
75
72
|
function hexToLinearRgb(hex) {
|
|
76
73
|
const r = parseInt(hex.slice(1, 3), 16) / 255;
|
|
77
74
|
const g = parseInt(hex.slice(3, 5), 16) / 255;
|
|
78
75
|
const b = parseInt(hex.slice(5, 7), 16) / 255;
|
|
79
76
|
return [srgbToLinear(r), srgbToLinear(g), srgbToLinear(b)];
|
|
80
77
|
}
|
|
81
|
-
function linearRgbToHex(r, g, b) {
|
|
82
|
-
const toHex = (c) => {
|
|
83
|
-
const v = Math.round(Math.max(0, Math.min(1, linearToSrgb(c))) * 255);
|
|
84
|
-
return v.toString(16).padStart(2, "0");
|
|
85
|
-
};
|
|
86
|
-
return `#${toHex(r)}${toHex(g)}${toHex(b)}`;
|
|
87
|
-
}
|
|
88
78
|
function linearRgbToOklab(r, g, b) {
|
|
89
79
|
const l_ = 0.4122214708 * r + 0.5363325363 * g + 0.0514459929 * b;
|
|
90
80
|
const m_ = 0.2119034982 * r + 0.6806995451 * g + 0.1073969566 * b;
|
|
@@ -126,19 +116,10 @@ function hexToOklch(hex) {
|
|
|
126
116
|
const [L, a, bVal] = linearRgbToOklab(r, g, b);
|
|
127
117
|
return oklabToOklch(L, a, bVal);
|
|
128
118
|
}
|
|
129
|
-
function oklchToHex(l, c, h) {
|
|
130
|
-
const [L, a, b] = oklchToOklab(l, c, h);
|
|
131
|
-
const [r, g, bVal] = oklabToLinearRgb(L, a, b);
|
|
132
|
-
return linearRgbToHex(r, g, bVal);
|
|
133
|
-
}
|
|
134
119
|
function isInGamut(r, g, b) {
|
|
135
120
|
const eps = 1e-4;
|
|
136
121
|
return r >= -eps && r <= 1 + eps && g >= -eps && g <= 1 + eps && b >= -eps && b <= 1 + eps;
|
|
137
122
|
}
|
|
138
|
-
function oklchToHexClamped(l, c, h) {
|
|
139
|
-
const g = gamutClamp(l, c, h);
|
|
140
|
-
return oklchToHex(g.l, g.c, g.h);
|
|
141
|
-
}
|
|
142
123
|
function gamutClamp(l, c, h) {
|
|
143
124
|
if (l <= 0) return { l: 0, c: 0, h };
|
|
144
125
|
if (l >= 1) return { l: 1, c: 0, h };
|
|
@@ -159,6 +140,31 @@ function gamutClamp(l, c, h) {
|
|
|
159
140
|
}
|
|
160
141
|
return { l, c: lo, h };
|
|
161
142
|
}
|
|
143
|
+
function trim(value, decimals) {
|
|
144
|
+
return Number(value.toFixed(decimals)).toString();
|
|
145
|
+
}
|
|
146
|
+
function oklchToCss(l, c, h) {
|
|
147
|
+
const cs = trim(c, 4);
|
|
148
|
+
return `oklch(${trim(l, 4)} ${cs} ${cs === "0" ? "0" : trim(h, 2)})`;
|
|
149
|
+
}
|
|
150
|
+
function oklchToCssClamped(l, c, h) {
|
|
151
|
+
const g = gamutClamp(l, c, h);
|
|
152
|
+
return oklchToCss(g.l, g.c, g.h);
|
|
153
|
+
}
|
|
154
|
+
var OKLCH_RE = /^oklch\(\s*([\d.]+)(%?)\s+([\d.]+)(%?)\s+([\d.]+)(?:deg)?\s*\)$/i;
|
|
155
|
+
var HEX6_RE = /^#[0-9a-f]{6}$/i;
|
|
156
|
+
function parseOklchCss(value) {
|
|
157
|
+
const m = OKLCH_RE.exec(value.trim());
|
|
158
|
+
if (!m) return null;
|
|
159
|
+
const l = Number.parseFloat(m[1]) / (m[2] === "%" ? 100 : 1);
|
|
160
|
+
const c = Number.parseFloat(m[3]) * (m[4] === "%" ? 4e-3 : 1);
|
|
161
|
+
return { l, c, h: Number.parseFloat(m[5]) };
|
|
162
|
+
}
|
|
163
|
+
function cssColorToOklch(value) {
|
|
164
|
+
const raw = value.trim();
|
|
165
|
+
if (HEX6_RE.test(raw)) return hexToOklch(raw);
|
|
166
|
+
return parseOklchCss(raw);
|
|
167
|
+
}
|
|
162
168
|
|
|
163
169
|
// src/editor/ui/curveEngine.ts
|
|
164
170
|
function makeAnchor(x, y, tangentLen = 15) {
|
|
@@ -183,6 +189,15 @@ function tangentAnchor(x, y, prev, next) {
|
|
|
183
189
|
const outDx = next ? (next.x - x) * HANDLE_SPAN : 0;
|
|
184
190
|
return { x, y, inDx, inDy: m * inDx, outDx, outDy: m * outDx };
|
|
185
191
|
}
|
|
192
|
+
function isCornerAnchor(a) {
|
|
193
|
+
return a.inDx === 0 && a.inDy === 0 && a.outDx === 0 && a.outDy === 0;
|
|
194
|
+
}
|
|
195
|
+
function resmoothAutoCurve(anchors) {
|
|
196
|
+
if (anchors.length < 2) return anchors;
|
|
197
|
+
return anchors.map(
|
|
198
|
+
(a, i) => isCornerAnchor(a) ? a : tangentAnchor(a.x, a.y, anchors[i - 1] ?? null, anchors[i + 1] ?? null)
|
|
199
|
+
);
|
|
200
|
+
}
|
|
186
201
|
function evalBezier(p0x, p0y, c0x, c0y, c1x, c1y, p1x, p1y, t) {
|
|
187
202
|
const u = 1 - t, u2 = u * u, u3 = u2 * u;
|
|
188
203
|
const t2 = t * t, t3 = t2 * t;
|
|
@@ -278,37 +293,39 @@ var SCALES = [
|
|
|
278
293
|
];
|
|
279
294
|
var BW_GUARD_MIN_L = 0.17;
|
|
280
295
|
var BW_GUARD_MAX_L = 0.93;
|
|
281
|
-
var
|
|
282
|
-
var
|
|
296
|
+
var autoCurve = (...anchors) => resmoothAutoCurve(anchors);
|
|
297
|
+
var DEFAULT_PALETTE_LIGHTNESS = () => autoCurve(makeAnchor(0, 95), makeAnchor(100, 8));
|
|
298
|
+
var DEFAULT_PALETTE_SATURATION = () => autoCurve(makeAnchor(0, 100), makeAnchor(100, 100));
|
|
299
|
+
var wrapHue = (h) => (h % 360 + 360) % 360;
|
|
283
300
|
function scaleCurveDefaults(scheme = "dark") {
|
|
284
301
|
if (scheme === "light") {
|
|
285
302
|
return {
|
|
286
303
|
Surfaces: {
|
|
287
|
-
lightness: () =>
|
|
288
|
-
saturation: () =>
|
|
304
|
+
lightness: () => autoCurve(makeAnchor(0, 98), makeAnchor(100, 82)),
|
|
305
|
+
saturation: () => autoCurve(makeAnchor(0, 100), makeAnchor(100, 100))
|
|
289
306
|
},
|
|
290
307
|
Borders: {
|
|
291
|
-
lightness: () =>
|
|
292
|
-
saturation: () =>
|
|
308
|
+
lightness: () => autoCurve(makeAnchor(0, 92), makeAnchor(100, 45)),
|
|
309
|
+
saturation: () => autoCurve(makeAnchor(0, 100), makeAnchor(100, 100))
|
|
293
310
|
},
|
|
294
311
|
Text: {
|
|
295
|
-
lightness: () =>
|
|
296
|
-
saturation: () =>
|
|
312
|
+
lightness: () => autoCurve(makeAnchor(0, 30), makeAnchor(100, 120)),
|
|
313
|
+
saturation: () => autoCurve(makeAnchor(0, 100), makeAnchor(100, 15))
|
|
297
314
|
}
|
|
298
315
|
};
|
|
299
316
|
}
|
|
300
317
|
return {
|
|
301
318
|
Surfaces: {
|
|
302
|
-
lightness: () =>
|
|
303
|
-
saturation: () =>
|
|
319
|
+
lightness: () => autoCurve(makeAnchor(0, 15), makeAnchor(100, 47)),
|
|
320
|
+
saturation: () => autoCurve(makeAnchor(0, 100), makeAnchor(100, 100))
|
|
304
321
|
},
|
|
305
322
|
Borders: {
|
|
306
|
-
lightness: () =>
|
|
307
|
-
saturation: () =>
|
|
323
|
+
lightness: () => autoCurve(makeAnchor(0, 25), makeAnchor(100, 80)),
|
|
324
|
+
saturation: () => autoCurve(makeAnchor(0, 100), makeAnchor(100, 100))
|
|
308
325
|
},
|
|
309
326
|
Text: {
|
|
310
|
-
lightness: () =>
|
|
311
|
-
saturation: () =>
|
|
327
|
+
lightness: () => autoCurve(makeAnchor(0, 120), makeAnchor(100, 55)),
|
|
328
|
+
saturation: () => autoCurve(makeAnchor(0, 100), makeAnchor(100, 15))
|
|
312
329
|
}
|
|
313
330
|
};
|
|
314
331
|
}
|
|
@@ -327,14 +344,16 @@ function scaleStepToX(step, scale) {
|
|
|
327
344
|
return scale.steps.length > 1 ? idx / (scale.steps.length - 1) * 100 : 50;
|
|
328
345
|
}
|
|
329
346
|
function serializeDerivedValue(value) {
|
|
330
|
-
return value.kind === "raw" ? value.css :
|
|
347
|
+
return value.kind === "raw" ? value.css : oklchToCssClamped(value.l, value.c, value.h);
|
|
331
348
|
}
|
|
332
|
-
function computePaletteOklch(index, base, lightnessCurve, saturationCurve, curveOffset) {
|
|
333
|
-
const { c: baseC
|
|
349
|
+
function computePaletteOklch(index, base, lightnessCurve, saturationCurve, curveOffset, hueCurve) {
|
|
350
|
+
const { c: baseC } = base;
|
|
334
351
|
const xPos = stepIndexToX(index);
|
|
335
352
|
const targetL = Math.max(0, Math.min(100, sampleCurve(lightnessCurve, xPos) + (curveOffset.lightness ?? 0))) / 100;
|
|
336
353
|
const satMul = Math.max(0, Math.min(2, (sampleCurve(saturationCurve, xPos) + (curveOffset.saturation ?? 0)) / 100));
|
|
337
354
|
const targetC = baseC * satMul;
|
|
355
|
+
const hueDelta = (hueCurve ? sampleCurve(hueCurve, xPos) : 0) + (curveOffset.hue ?? 0);
|
|
356
|
+
const h = hueDelta === 0 ? base.h : wrapHue(base.h + hueDelta);
|
|
338
357
|
return gamutClamp(targetL, targetC, h);
|
|
339
358
|
}
|
|
340
359
|
function nearestPaletteStep(lightnessCurve, baseL) {
|
|
@@ -430,10 +449,12 @@ function syncBaseAnchor(cfg) {
|
|
|
430
449
|
const fresh = prev === void 0;
|
|
431
450
|
let lCurve = cfg.lightnessCurve;
|
|
432
451
|
let sCurve = cfg.saturationCurve;
|
|
452
|
+
let hCurve = cfg.hueCurve;
|
|
433
453
|
if (prev) {
|
|
434
454
|
const prevX = stepIndexToX(prev.step);
|
|
435
455
|
lCurve = liftCurveAnchor(lCurve, prevX, prev.displacedL);
|
|
436
456
|
sCurve = liftCurveAnchor(sCurve, prevX, prev.displacedS);
|
|
457
|
+
if (hCurve) hCurve = liftCurveAnchor(hCurve, prevX, prev.displacedH);
|
|
437
458
|
}
|
|
438
459
|
const step = nearestPaletteStep(lCurve, cfg.baseColor.l);
|
|
439
460
|
const x = stepIndexToX(step);
|
|
@@ -441,12 +462,19 @@ function syncBaseAnchor(cfg) {
|
|
|
441
462
|
const s = setCurveAnchor(sCurve, x, 100, fresh);
|
|
442
463
|
cfg.lightnessCurve = l.curve;
|
|
443
464
|
cfg.saturationCurve = s.curve;
|
|
465
|
+
const h = hCurve ? setCurveAnchor(hCurve, x, 0, fresh) : void 0;
|
|
466
|
+
if (h) cfg.hueCurve = h.curve;
|
|
444
467
|
cfg.anchorPlacement = {
|
|
445
468
|
step,
|
|
446
469
|
displacedL: l.displacedY,
|
|
447
470
|
displacedS: s.displacedY,
|
|
471
|
+
displacedH: h?.displacedY,
|
|
448
472
|
priorLightnessEndpoints: prev?.priorLightnessEndpoints ?? l.priorEndpoints,
|
|
449
|
-
priorSaturationEndpoints: prev?.priorSaturationEndpoints ?? s.priorEndpoints
|
|
473
|
+
priorSaturationEndpoints: prev?.priorSaturationEndpoints ?? s.priorEndpoints,
|
|
474
|
+
// No else-branch reading `prev?.priorHueEndpoints`: that could only fire
|
|
475
|
+
// if a placed hue curve later went absent, which RJC 7 (reset never
|
|
476
|
+
// deletes) never lets happen.
|
|
477
|
+
priorHueEndpoints: h ? prev?.priorHueEndpoints ?? h.priorEndpoints : void 0
|
|
450
478
|
};
|
|
451
479
|
}
|
|
452
480
|
function computeDerivedOklch(step, base, scaleTitle, scaleCurves, curveOffset) {
|
|
@@ -455,8 +483,10 @@ function computeDerivedOklch(step, base, scaleTitle, scaleCurves, curveOffset) {
|
|
|
455
483
|
const defs = defaultScaleCurves[scaleTitle];
|
|
456
484
|
const lCurve = scaleCurves[scaleTitle]?.lightness ?? defs.lightness();
|
|
457
485
|
const sCurve = scaleCurves[scaleTitle]?.saturation ?? defs.saturation();
|
|
486
|
+
const hCurve = scaleCurves[scaleTitle]?.hue;
|
|
458
487
|
const lOff = curveOffset[`${scaleTitle}-lightness`] ?? 0;
|
|
459
488
|
const sOff = curveOffset[`${scaleTitle}-saturation`] ?? 0;
|
|
489
|
+
const hOff = curveOffset[`${scaleTitle}-hue`] ?? 0;
|
|
460
490
|
const { l: baseL, c: baseC, h: baseH } = base;
|
|
461
491
|
let targetL;
|
|
462
492
|
if (scale.isText) {
|
|
@@ -467,7 +497,9 @@ function computeDerivedOklch(step, base, scaleTitle, scaleCurves, curveOffset) {
|
|
|
467
497
|
}
|
|
468
498
|
const satMul = Math.max(0, Math.min(2, (sampleCurve(sCurve, xPos) + sOff) / 100));
|
|
469
499
|
const targetC = baseC * satMul;
|
|
470
|
-
|
|
500
|
+
const hueDelta = (hCurve ? sampleCurve(hCurve, xPos) : 0) + hOff;
|
|
501
|
+
const targetH = hueDelta === 0 ? baseH : wrapHue(baseH + hueDelta);
|
|
502
|
+
return gamutClamp(targetL, targetC, targetH);
|
|
471
503
|
}
|
|
472
504
|
function scaleToCssVar(scaleTitle, stepName, cssNamespace) {
|
|
473
505
|
if (cssNamespace === null) return null;
|
|
@@ -496,7 +528,7 @@ function derivePaletteValues(spec, config) {
|
|
|
496
528
|
const saturationCurve = config.saturationCurve ?? DEFAULT_PALETTE_SATURATION();
|
|
497
529
|
PALETTE_STEPS.forEach((ps, index) => {
|
|
498
530
|
const k = paletteStepKey(ps.label);
|
|
499
|
-
const value = k in overrides ? { kind: "color", ...overrides[k] } : { kind: "color", ...computePaletteOklch(index, baseColor, lightnessCurve, saturationCurve, curveOffset) };
|
|
531
|
+
const value = k in overrides ? { kind: "color", ...overrides[k] } : { kind: "color", ...computePaletteOklch(index, baseColor, lightnessCurve, saturationCurve, curveOffset, config.hueCurve) };
|
|
500
532
|
out[`--color-${spec.cssNamespace}-${ps.label}`] = value;
|
|
501
533
|
});
|
|
502
534
|
for (const scale of SCALES) {
|
|
@@ -531,8 +563,8 @@ function derivePaletteValues(spec, config) {
|
|
|
531
563
|
);
|
|
532
564
|
const stopsCss = sortedStops.map((s) => {
|
|
533
565
|
const stopValue = out[`--color-${spec.cssNamespace}-${s.paletteLabel}`];
|
|
534
|
-
const
|
|
535
|
-
return `${
|
|
566
|
+
const css = stopValue ? serializeDerivedValue(stopValue) : "oklch(0 0 0)";
|
|
567
|
+
return `${css} ${s.position}%`;
|
|
536
568
|
}).join(", ");
|
|
537
569
|
let gradient;
|
|
538
570
|
switch (gradientStyle) {
|
|
@@ -551,13 +583,6 @@ function derivePaletteValues(spec, config) {
|
|
|
551
583
|
}
|
|
552
584
|
return out;
|
|
553
585
|
}
|
|
554
|
-
function derivePaletteVars(spec, config) {
|
|
555
|
-
const out = {};
|
|
556
|
-
for (const [k, v] of Object.entries(derivePaletteValues(spec, config))) {
|
|
557
|
-
out[k] = serializeDerivedValue(v);
|
|
558
|
-
}
|
|
559
|
-
return out;
|
|
560
|
-
}
|
|
561
586
|
function palettesToValues(palettes) {
|
|
562
587
|
const out = {};
|
|
563
588
|
for (const spec of PALETTE_SPECS) {
|
|
@@ -572,7 +597,6 @@ function palettesToVars(palettes) {
|
|
|
572
597
|
}
|
|
573
598
|
return out;
|
|
574
599
|
}
|
|
575
|
-
var HEX_RE = /^#[0-9a-f]{6}$/i;
|
|
576
600
|
function reconcilePalettesFromCssVars(palettes, cssVars) {
|
|
577
601
|
const next = structuredClone(palettes);
|
|
578
602
|
const consumed = /* @__PURE__ */ new Set();
|
|
@@ -581,16 +605,17 @@ function reconcilePalettesFromCssVars(palettes, cssVars) {
|
|
|
581
605
|
const current = next[spec.label];
|
|
582
606
|
if (current === void 0) continue;
|
|
583
607
|
if (current._imported === true) {
|
|
584
|
-
const
|
|
585
|
-
|
|
586
|
-
|
|
608
|
+
const anchor = cssVars[`--color-${spec.cssNamespace}-500`];
|
|
609
|
+
const anchorOklch = anchor ? cssColorToOklch(anchor) : null;
|
|
610
|
+
if (anchorOklch) {
|
|
611
|
+
next[spec.label] = { ...current, baseColor: anchorOklch, _imported: false };
|
|
587
612
|
syncBaseAnchor(next[spec.label]);
|
|
588
613
|
snapped.add(spec.label);
|
|
589
614
|
} else {
|
|
590
615
|
next[spec.label] = { ...current, _imported: false };
|
|
591
616
|
}
|
|
592
617
|
}
|
|
593
|
-
for (const k of Object.keys(
|
|
618
|
+
for (const k of Object.keys(derivePaletteValues(spec, next[spec.label]))) {
|
|
594
619
|
consumed.add(k);
|
|
595
620
|
}
|
|
596
621
|
}
|
|
@@ -1303,6 +1328,20 @@ var tokensCssMigration_2026_07_20_semanticTextStyles = {
|
|
|
1303
1328
|
}
|
|
1304
1329
|
};
|
|
1305
1330
|
|
|
1331
|
+
// vite-plugin/tokensCssMigrations/migrations/2026-08-19-oklch-color-values.ts
|
|
1332
|
+
var HEX_DECLARATION_RE = /(--[a-z0-9-]+:\s*)#([0-9a-f]{6})(?=\s*[;}])/gi;
|
|
1333
|
+
var tokensCssMigration_2026_08_19_oklchColorValues = {
|
|
1334
|
+
id: "2026-08-19-oklch-color-values",
|
|
1335
|
+
kind: "breaking",
|
|
1336
|
+
description: "Rewrite hex token values as oklch()",
|
|
1337
|
+
apply(css) {
|
|
1338
|
+
return css.replace(HEX_DECLARATION_RE, (_match, prefix, hex) => {
|
|
1339
|
+
const { l, c, h } = hexToOklch(`#${hex}`);
|
|
1340
|
+
return `${prefix}${oklchToCss(l, c, h)}`;
|
|
1341
|
+
});
|
|
1342
|
+
}
|
|
1343
|
+
};
|
|
1344
|
+
|
|
1306
1345
|
// vite-plugin/tokensCssMigrations/index.ts
|
|
1307
1346
|
var TOKENS_CSS_MIGRATIONS = [
|
|
1308
1347
|
tokensCssMigration_2026_05_29_typographyScaleAdditions,
|
|
@@ -1311,7 +1350,8 @@ var TOKENS_CSS_MIGRATIONS = [
|
|
|
1311
1350
|
tokensCssMigration_2026_06_04_removeDeadSizeIconScale,
|
|
1312
1351
|
tokensCssMigration_2026_06_04_easingColorAndTypescaleAdditions,
|
|
1313
1352
|
tokensCssMigration_2026_07_20_lineHeightRename,
|
|
1314
|
-
tokensCssMigration_2026_07_20_semanticTextStyles
|
|
1353
|
+
tokensCssMigration_2026_07_20_semanticTextStyles,
|
|
1354
|
+
tokensCssMigration_2026_08_19_oklchColorValues
|
|
1315
1355
|
];
|
|
1316
1356
|
function runTokensCssMigrations(css) {
|
|
1317
1357
|
return foldMigrations(css, () => true);
|
package/dist-plugin/index.js
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import {
|
|
2
|
-
hexToOklch,
|
|
3
2
|
palettesToVars,
|
|
4
3
|
reconcilePalettesFromCssVars,
|
|
5
4
|
sanitizeFileName
|
|
6
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-JIGIIE5P.js";
|
|
7
6
|
import {
|
|
8
7
|
THEME_SCHEMA_VERSION,
|
|
9
8
|
detectLegacyLayout,
|
|
@@ -18,7 +17,10 @@ import {
|
|
|
18
17
|
runAdditiveTokensCssMigrations,
|
|
19
18
|
runTokensCssMigrations,
|
|
20
19
|
validateTokensCss
|
|
21
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-TKZBVIW5.js";
|
|
21
|
+
import {
|
|
22
|
+
hexToOklch
|
|
23
|
+
} from "./chunk-YR6GPXW2.js";
|
|
22
24
|
import {
|
|
23
25
|
resolveDataDirs
|
|
24
26
|
} from "./chunk-D3ZVKOR4.js";
|
|
@@ -33,11 +33,21 @@ interface PaletteConfig {
|
|
|
33
33
|
baseColor: Oklch;
|
|
34
34
|
lightnessCurve: CurveAnchor[];
|
|
35
35
|
saturationCurve: CurveAnchor[];
|
|
36
|
+
/** Signed hue offset in degrees per step, applied on top of the base hue.
|
|
37
|
+
* Absent means flat zero: the palette holds one hue, which is what every
|
|
38
|
+
* theme saved before this field did. */
|
|
39
|
+
hueCurve?: CurveAnchor[];
|
|
36
40
|
scaleCurves: Record<string, {
|
|
37
41
|
lightness: CurveAnchor[];
|
|
38
42
|
saturation: CurveAnchor[];
|
|
43
|
+
hue?: CurveAnchor[];
|
|
39
44
|
}>;
|
|
40
45
|
curveOffset: Record<string, number>;
|
|
46
|
+
/** Per curve key: are the tangents derived from the points, or held by hand?
|
|
47
|
+
* Only an explicit switch-off is recorded. A missing key means the curve's own
|
|
48
|
+
* shape answers (`isAutoSmoothCurve`), which is what every theme saved before
|
|
49
|
+
* the flag existed relies on. */
|
|
50
|
+
curveAutoSmooth?: Record<string, boolean>;
|
|
41
51
|
overrides: Record<string, Oklch>;
|
|
42
52
|
snappedScales: string[];
|
|
43
53
|
emptyMode?: 'solid' | 'gradient';
|
|
@@ -50,11 +60,12 @@ interface PaletteConfig {
|
|
|
50
60
|
/**
|
|
51
61
|
* Where the base color sits in the ramp while `anchorToBase` is on: the
|
|
52
62
|
* PALETTE_STEPS index whose curve anchors are pinned to the base color
|
|
53
|
-
* (lightness = base L, saturation = multiplier 100
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
* placement or toggling off restores it
|
|
57
|
-
* `priorLightnessEndpoints` /
|
|
63
|
+
* (lightness = base L, saturation = multiplier 100, hue delta = 0 when a
|
|
64
|
+
* hue curve exists). `displacedL` / `displacedS` / `displacedH` remember
|
|
65
|
+
* the y of a pre-existing anchor (endpoint or user-authored) the placement
|
|
66
|
+
* overwrote at that x, so moving the placement or toggling off restores it
|
|
67
|
+
* instead of deleting it. `priorLightnessEndpoints` /
|
|
68
|
+
* `priorSaturationEndpoints` / `priorHueEndpoints` remember the two
|
|
58
69
|
* endpoints exactly as they stood before the curve's first-ever placement
|
|
59
70
|
* (a smoothed reshape, not algebraically invertible the way a later
|
|
60
71
|
* scaled-handle re-placement is), so a clear can still restore the true
|
|
@@ -64,8 +75,10 @@ interface PaletteConfig {
|
|
|
64
75
|
step: number;
|
|
65
76
|
displacedL?: number;
|
|
66
77
|
displacedS?: number;
|
|
78
|
+
displacedH?: number;
|
|
67
79
|
priorLightnessEndpoints?: [CurveAnchor, CurveAnchor];
|
|
68
80
|
priorSaturationEndpoints?: [CurveAnchor, CurveAnchor];
|
|
81
|
+
priorHueEndpoints?: [CurveAnchor, CurveAnchor];
|
|
69
82
|
};
|
|
70
83
|
/**
|
|
71
84
|
* Set to true by importers when they overlay `cssVariables[--color-{ns}-*]`
|
|
@@ -33,11 +33,21 @@ interface PaletteConfig {
|
|
|
33
33
|
baseColor: Oklch;
|
|
34
34
|
lightnessCurve: CurveAnchor[];
|
|
35
35
|
saturationCurve: CurveAnchor[];
|
|
36
|
+
/** Signed hue offset in degrees per step, applied on top of the base hue.
|
|
37
|
+
* Absent means flat zero: the palette holds one hue, which is what every
|
|
38
|
+
* theme saved before this field did. */
|
|
39
|
+
hueCurve?: CurveAnchor[];
|
|
36
40
|
scaleCurves: Record<string, {
|
|
37
41
|
lightness: CurveAnchor[];
|
|
38
42
|
saturation: CurveAnchor[];
|
|
43
|
+
hue?: CurveAnchor[];
|
|
39
44
|
}>;
|
|
40
45
|
curveOffset: Record<string, number>;
|
|
46
|
+
/** Per curve key: are the tangents derived from the points, or held by hand?
|
|
47
|
+
* Only an explicit switch-off is recorded. A missing key means the curve's own
|
|
48
|
+
* shape answers (`isAutoSmoothCurve`), which is what every theme saved before
|
|
49
|
+
* the flag existed relies on. */
|
|
50
|
+
curveAutoSmooth?: Record<string, boolean>;
|
|
41
51
|
overrides: Record<string, Oklch>;
|
|
42
52
|
snappedScales: string[];
|
|
43
53
|
emptyMode?: 'solid' | 'gradient';
|
|
@@ -50,11 +60,12 @@ interface PaletteConfig {
|
|
|
50
60
|
/**
|
|
51
61
|
* Where the base color sits in the ramp while `anchorToBase` is on: the
|
|
52
62
|
* PALETTE_STEPS index whose curve anchors are pinned to the base color
|
|
53
|
-
* (lightness = base L, saturation = multiplier 100
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
* placement or toggling off restores it
|
|
57
|
-
* `priorLightnessEndpoints` /
|
|
63
|
+
* (lightness = base L, saturation = multiplier 100, hue delta = 0 when a
|
|
64
|
+
* hue curve exists). `displacedL` / `displacedS` / `displacedH` remember
|
|
65
|
+
* the y of a pre-existing anchor (endpoint or user-authored) the placement
|
|
66
|
+
* overwrote at that x, so moving the placement or toggling off restores it
|
|
67
|
+
* instead of deleting it. `priorLightnessEndpoints` /
|
|
68
|
+
* `priorSaturationEndpoints` / `priorHueEndpoints` remember the two
|
|
58
69
|
* endpoints exactly as they stood before the curve's first-ever placement
|
|
59
70
|
* (a smoothed reshape, not algebraically invertible the way a later
|
|
60
71
|
* scaled-handle re-placement is), so a clear can still restore the true
|
|
@@ -64,8 +75,10 @@ interface PaletteConfig {
|
|
|
64
75
|
step: number;
|
|
65
76
|
displacedL?: number;
|
|
66
77
|
displacedS?: number;
|
|
78
|
+
displacedH?: number;
|
|
67
79
|
priorLightnessEndpoints?: [CurveAnchor, CurveAnchor];
|
|
68
80
|
priorSaturationEndpoints?: [CurveAnchor, CurveAnchor];
|
|
81
|
+
priorHueEndpoints?: [CurveAnchor, CurveAnchor];
|
|
69
82
|
};
|
|
70
83
|
/**
|
|
71
84
|
* Set to true by importers when they overlay `cssVariables[--color-{ns}-*]`
|
|
@@ -33,6 +33,7 @@ __export(tokensCssMigrations_exports, {
|
|
|
33
33
|
TOKENS_CSS_MIGRATIONS: () => TOKENS_CSS_MIGRATIONS,
|
|
34
34
|
collectDefinedTokens: () => collectDefinedTokens,
|
|
35
35
|
collectReferencedTokens: () => collectReferencedTokens,
|
|
36
|
+
collectTokenValues: () => collectTokenValues,
|
|
36
37
|
enforceBreakingRequiresMajor: () => enforceBreakingRequiresMajor,
|
|
37
38
|
ensureScale: () => ensureScale,
|
|
38
39
|
findContractViolations: () => findContractViolations,
|
|
@@ -61,11 +62,17 @@ function extractGlobalRootBody(source) {
|
|
|
61
62
|
// vite-plugin/tokensCssMigrations/cssTokenOps.ts
|
|
62
63
|
var DECL_RE = /(^|[\s;{])(--[a-z0-9-]+)\s*:/gi;
|
|
63
64
|
var REF_RE = /var\(\s*(--[a-z0-9-]+)/gi;
|
|
65
|
+
var DECL_VALUE_RE = /(^|[\s;{])(--[a-z0-9-]+)\s*:([^;}]*)/gi;
|
|
64
66
|
function collectDefinedTokens(css) {
|
|
65
67
|
const out = /* @__PURE__ */ new Set();
|
|
66
68
|
for (const m of css.matchAll(DECL_RE)) out.add(m[2]);
|
|
67
69
|
return out;
|
|
68
70
|
}
|
|
71
|
+
function collectTokenValues(css) {
|
|
72
|
+
const out = /* @__PURE__ */ new Map();
|
|
73
|
+
for (const m of css.matchAll(DECL_VALUE_RE)) out.set(m[2], m[3].trim());
|
|
74
|
+
return out;
|
|
75
|
+
}
|
|
69
76
|
function collectReferencedTokens(css) {
|
|
70
77
|
const out = /* @__PURE__ */ new Set();
|
|
71
78
|
for (const m of css.matchAll(REF_RE)) out.add(m[1]);
|
|
@@ -399,6 +406,62 @@ var tokensCssMigration_2026_07_20_semanticTextStyles = {
|
|
|
399
406
|
}
|
|
400
407
|
};
|
|
401
408
|
|
|
409
|
+
// src/system/internal/oklch.ts
|
|
410
|
+
function srgbToLinear(c) {
|
|
411
|
+
return c <= 0.04045 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4);
|
|
412
|
+
}
|
|
413
|
+
function hexToLinearRgb(hex) {
|
|
414
|
+
const r = parseInt(hex.slice(1, 3), 16) / 255;
|
|
415
|
+
const g = parseInt(hex.slice(3, 5), 16) / 255;
|
|
416
|
+
const b = parseInt(hex.slice(5, 7), 16) / 255;
|
|
417
|
+
return [srgbToLinear(r), srgbToLinear(g), srgbToLinear(b)];
|
|
418
|
+
}
|
|
419
|
+
function linearRgbToOklab(r, g, b) {
|
|
420
|
+
const l_ = 0.4122214708 * r + 0.5363325363 * g + 0.0514459929 * b;
|
|
421
|
+
const m_ = 0.2119034982 * r + 0.6806995451 * g + 0.1073969566 * b;
|
|
422
|
+
const s_ = 0.0883024619 * r + 0.2817188376 * g + 0.6299787005 * b;
|
|
423
|
+
const l = Math.cbrt(l_);
|
|
424
|
+
const m = Math.cbrt(m_);
|
|
425
|
+
const s = Math.cbrt(s_);
|
|
426
|
+
return [
|
|
427
|
+
0.2104542553 * l + 0.793617785 * m - 0.0040720468 * s,
|
|
428
|
+
1.9779984951 * l - 2.428592205 * m + 0.4505937099 * s,
|
|
429
|
+
0.0259040371 * l + 0.7827717662 * m - 0.808675766 * s
|
|
430
|
+
];
|
|
431
|
+
}
|
|
432
|
+
function oklabToOklch(L, a, b) {
|
|
433
|
+
const c = Math.sqrt(a * a + b * b);
|
|
434
|
+
let h = Math.atan2(b, a) * 180 / Math.PI;
|
|
435
|
+
if (h < 0) h += 360;
|
|
436
|
+
return { l: L, c, h };
|
|
437
|
+
}
|
|
438
|
+
function hexToOklch(hex) {
|
|
439
|
+
const [r, g, b] = hexToLinearRgb(hex);
|
|
440
|
+
const [L, a, bVal] = linearRgbToOklab(r, g, b);
|
|
441
|
+
return oklabToOklch(L, a, bVal);
|
|
442
|
+
}
|
|
443
|
+
function trim(value, decimals) {
|
|
444
|
+
return Number(value.toFixed(decimals)).toString();
|
|
445
|
+
}
|
|
446
|
+
function oklchToCss(l, c, h) {
|
|
447
|
+
const cs = trim(c, 4);
|
|
448
|
+
return `oklch(${trim(l, 4)} ${cs} ${cs === "0" ? "0" : trim(h, 2)})`;
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
// vite-plugin/tokensCssMigrations/migrations/2026-08-19-oklch-color-values.ts
|
|
452
|
+
var HEX_DECLARATION_RE = /(--[a-z0-9-]+:\s*)#([0-9a-f]{6})(?=\s*[;}])/gi;
|
|
453
|
+
var tokensCssMigration_2026_08_19_oklchColorValues = {
|
|
454
|
+
id: "2026-08-19-oklch-color-values",
|
|
455
|
+
kind: "breaking",
|
|
456
|
+
description: "Rewrite hex token values as oklch()",
|
|
457
|
+
apply(css) {
|
|
458
|
+
return css.replace(HEX_DECLARATION_RE, (_match, prefix, hex) => {
|
|
459
|
+
const { l, c, h } = hexToOklch(`#${hex}`);
|
|
460
|
+
return `${prefix}${oklchToCss(l, c, h)}`;
|
|
461
|
+
});
|
|
462
|
+
}
|
|
463
|
+
};
|
|
464
|
+
|
|
402
465
|
// vite-plugin/files/dataPaths.ts
|
|
403
466
|
var import_fs = __toESM(require("fs"), 1);
|
|
404
467
|
var import_path = __toESM(require("path"), 1);
|
|
@@ -441,7 +504,8 @@ var TOKENS_CSS_MIGRATIONS = [
|
|
|
441
504
|
tokensCssMigration_2026_06_04_removeDeadSizeIconScale,
|
|
442
505
|
tokensCssMigration_2026_06_04_easingColorAndTypescaleAdditions,
|
|
443
506
|
tokensCssMigration_2026_07_20_lineHeightRename,
|
|
444
|
-
tokensCssMigration_2026_07_20_semanticTextStyles
|
|
507
|
+
tokensCssMigration_2026_07_20_semanticTextStyles,
|
|
508
|
+
tokensCssMigration_2026_08_19_oklchColorValues
|
|
445
509
|
];
|
|
446
510
|
function runTokensCssMigrations(css) {
|
|
447
511
|
return foldMigrations(css, () => true);
|
|
@@ -466,10 +530,11 @@ function findContractViolations(canonicalCss) {
|
|
|
466
530
|
const violations = [];
|
|
467
531
|
for (const m of TOKENS_CSS_MIGRATIONS) {
|
|
468
532
|
if (m.kind !== "additive") continue;
|
|
469
|
-
const before =
|
|
470
|
-
const after =
|
|
471
|
-
const removed = [...before].filter((t) => !after.has(t)).sort();
|
|
472
|
-
|
|
533
|
+
const before = collectTokenValues(canonicalCss);
|
|
534
|
+
const after = collectTokenValues(m.apply(canonicalCss));
|
|
535
|
+
const removed = [...before.keys()].filter((t) => !after.has(t)).sort();
|
|
536
|
+
const changed = [...before.entries()].filter(([t, v]) => after.has(t) && after.get(t) !== v).map(([t]) => t).sort();
|
|
537
|
+
if (removed.length || changed.length) violations.push({ id: m.id, removed, changed });
|
|
473
538
|
}
|
|
474
539
|
return violations;
|
|
475
540
|
}
|
|
@@ -530,6 +595,7 @@ function validateTokensCss(input) {
|
|
|
530
595
|
TOKENS_CSS_MIGRATIONS,
|
|
531
596
|
collectDefinedTokens,
|
|
532
597
|
collectReferencedTokens,
|
|
598
|
+
collectTokenValues,
|
|
533
599
|
enforceBreakingRequiresMajor,
|
|
534
600
|
ensureScale,
|
|
535
601
|
findContractViolations,
|
|
@@ -52,6 +52,8 @@ interface TokensCssMigration {
|
|
|
52
52
|
*/
|
|
53
53
|
/** Names declared as custom properties (`--x: …;`) anywhere in the source. */
|
|
54
54
|
declare function collectDefinedTokens(css: string): Set<string>;
|
|
55
|
+
/** Declared name → value, last declaration winning (as the cascade would). */
|
|
56
|
+
declare function collectTokenValues(css: string): Map<string, string>;
|
|
55
57
|
/** Names referenced via `var(--x)` anywhere in the source. */
|
|
56
58
|
declare function collectReferencedTokens(css: string): Set<string>;
|
|
57
59
|
interface ScaleEntry {
|
|
@@ -123,16 +125,25 @@ interface ContractViolation {
|
|
|
123
125
|
id: string;
|
|
124
126
|
/** Token names the migration removed or renamed away despite declaring `additive`. */
|
|
125
127
|
removed: string[];
|
|
128
|
+
/** Token names whose value the migration rewrote despite declaring `additive`. */
|
|
129
|
+
changed: string[];
|
|
126
130
|
}
|
|
127
131
|
/**
|
|
128
|
-
* Guardrail for the token-as-API contract: an `additive` migration must
|
|
129
|
-
* remove or rename a token
|
|
130
|
-
*
|
|
131
|
-
*
|
|
132
|
-
*
|
|
133
|
-
*
|
|
134
|
-
*
|
|
135
|
-
*
|
|
132
|
+
* Guardrail for the token-as-API contract: an `additive` migration must only
|
|
133
|
+
* ever insert new names — it must never remove or rename a token, and never
|
|
134
|
+
* rewrite the value of one a consumer already references. We verify
|
|
135
|
+
* behaviorally rather than trusting the label: apply each additive migration to
|
|
136
|
+
* the package's own canonical `tokens.css` (which defines the full current
|
|
137
|
+
* vocabulary) and flag any token that disappears or changes value. A rename
|
|
138
|
+
* surfaces as the removal of its old name, so it is caught too.
|
|
139
|
+
*
|
|
140
|
+
* The value half is what makes a value-rewriting migration (hex → `oklch()`)
|
|
141
|
+
* impossible to mislabel: it renames nothing, so a name-only guard would wave
|
|
142
|
+
* it through as additive and the dev plugin would auto-apply a breaking change
|
|
143
|
+
* to a consumer's vendored file.
|
|
144
|
+
*
|
|
145
|
+
* This catches the dangerous direction only. (Over-labeling a no-op as
|
|
146
|
+
* `breaking` is harmless and not checked.)
|
|
136
147
|
*/
|
|
137
148
|
declare function findContractViolations(canonicalCss: string): ContractViolation[];
|
|
138
149
|
type SemverBump = 'major' | 'minor' | 'patch' | 'none';
|
|
@@ -183,4 +194,4 @@ interface ValidateInput {
|
|
|
183
194
|
*/
|
|
184
195
|
declare function validateTokensCss(input: ValidateInput): MissingToken[];
|
|
185
196
|
|
|
186
|
-
export { type BreakingGateResult, type ComponentSource, type ContractViolation, type MissingToken, type RunResult, type SemverBump, TOKENS_CSS_MIGRATIONS, type TokensCssMigration, type ValidateInput, collectDefinedTokens, collectReferencedTokens, enforceBreakingRequiresMajor, ensureScale, findContractViolations, removeToken, removeTokensMatching, renameToken, runAdditiveTokensCssMigrations, runTokensCssMigrations, semverBumpType, validateTokensCss };
|
|
197
|
+
export { type BreakingGateResult, type ComponentSource, type ContractViolation, type MissingToken, type RunResult, type SemverBump, TOKENS_CSS_MIGRATIONS, type TokensCssMigration, type ValidateInput, collectDefinedTokens, collectReferencedTokens, collectTokenValues, enforceBreakingRequiresMajor, ensureScale, findContractViolations, removeToken, removeTokensMatching, renameToken, runAdditiveTokensCssMigrations, runTokensCssMigrations, semverBumpType, validateTokensCss };
|