@motion-proto/live-tokens 0.61.0 → 0.63.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 (83) hide show
  1. package/.claude/skills/live-tokens-adjust-geometry/SKILL.md +4 -4
  2. package/.claude/skills/live-tokens-build-page/SKILL.md +21 -3
  3. package/.claude/skills/live-tokens-create-component/SKILL.md +16 -48
  4. package/.claude/skills/live-tokens-create-component/references/fixed-overlays.md +10 -1
  5. package/.claude/skills/live-tokens-create-component/references/intrinsics.md +7 -5
  6. package/.claude/skills/live-tokens-create-component/references/sketch-mode.md +1 -1
  7. package/.claude/skills/live-tokens-create-component/references/token-naming.md +50 -0
  8. package/.claude/skills/live-tokens-generate-theme/SKILL.md +16 -9
  9. package/.claude/skills/live-tokens-pair-fonts/SKILL.md +8 -6
  10. package/.claude/skills/live-tokens-pick-component/SKILL.md +19 -5
  11. package/CHANGELOG.md +114 -0
  12. package/bin/migrate.mjs +6 -2
  13. package/dist-plugin/adjust/index.cjs +1 -1
  14. package/dist-plugin/adjust/index.d.cts +1 -1
  15. package/dist-plugin/adjust/index.d.ts +1 -1
  16. package/dist-plugin/adjust/index.js +1 -1
  17. package/dist-plugin/{chunk-232GZGQU.js → chunk-NDJJORKJ.js} +342 -5
  18. package/dist-plugin/{chunk-Y5CNFSSV.js → chunk-RVE3MNKM.js} +1 -1
  19. package/dist-plugin/{chunk-OIOXU7FR.js → chunk-ZHPX7ZYQ.js} +83 -25
  20. package/dist-plugin/{dataPaths-CRfD1LdA.d.ts → dataPaths-DZUzVv8H.d.cts} +3 -3
  21. package/dist-plugin/{dataPaths-CRfD1LdA.d.cts → dataPaths-DZUzVv8H.d.ts} +3 -3
  22. package/dist-plugin/fontPairing/index.cjs +1 -1
  23. package/dist-plugin/fontPairing/index.d.cts +1 -1
  24. package/dist-plugin/fontPairing/index.d.ts +1 -1
  25. package/dist-plugin/fontPairing/index.js +1 -1
  26. package/dist-plugin/generateColorsAndType/index.cjs +1 -1
  27. package/dist-plugin/generateColorsAndType/index.d.cts +1 -1
  28. package/dist-plugin/generateColorsAndType/index.d.ts +1 -1
  29. package/dist-plugin/generateColorsAndType/index.js +1 -1
  30. package/dist-plugin/index.cjs +461 -58
  31. package/dist-plugin/index.d.cts +1 -1
  32. package/dist-plugin/index.d.ts +1 -1
  33. package/dist-plugin/index.js +31 -23
  34. package/dist-plugin/migrateData/index.cjs +350 -9
  35. package/dist-plugin/migrateData/index.d.cts +1 -1
  36. package/dist-plugin/migrateData/index.d.ts +1 -1
  37. package/dist-plugin/migrateData/index.js +9 -5
  38. package/dist-plugin/tokensCssMigrations/index.cjs +83 -25
  39. package/dist-plugin/tokensCssMigrations/index.d.cts +1 -1
  40. package/dist-plugin/tokensCssMigrations/index.d.ts +1 -1
  41. package/dist-plugin/tokensCssMigrations/index.js +2 -2
  42. package/package.json +4 -2
  43. package/src/app/site.css +32 -0
  44. package/src/editor/component-editor/CardEditor.svelte +7 -1
  45. package/src/editor/component-editor/scaffolding/VariantGroup.svelte +25 -2
  46. package/src/editor/core/preview/lookPreview.ts +46 -5
  47. package/src/editor/core/productionPulse.ts +6 -2
  48. package/src/editor/core/sketch/maskField.ts +75 -39
  49. package/src/editor/core/sketch/sketchLayer.ts +32 -11
  50. package/src/editor/core/sketch/sketchStore.ts +311 -86
  51. package/src/editor/core/sketch/{sketchPresetService.ts → sketchStyleService.ts} +14 -14
  52. package/src/editor/core/sketch/{sketchPresets.ts → sketchStyles.ts} +27 -28
  53. package/src/editor/core/themes/themeDocumentSync.ts +2 -0
  54. package/src/editor/core/themes/themeInit.ts +19 -1
  55. package/src/editor/core/themes/themeService.ts +7 -2
  56. package/src/editor/core/themes/themeTypes.ts +5 -0
  57. package/src/editor/docs/content/editing-tokens.md +1 -1
  58. package/src/editor/docs/content/sketch-mode.md +34 -18
  59. package/src/editor/docs/content/themes-workflow.md +30 -21
  60. package/src/editor/docs/content/where-themes-live.md +9 -5
  61. package/src/editor/docs/content.generated.ts +4 -4
  62. package/src/editor/overlay/LiveTokensRouter.svelte +8 -0
  63. package/src/editor/ui/EditorViewSwitcher.svelte +3 -3
  64. package/src/editor/ui/ThemePanel.svelte +47 -1
  65. package/src/editor/ui/sections/textStyles.ts +29 -1
  66. package/src/editor/ui/sketch/SketchPreview.svelte +3 -3
  67. package/src/editor/ui/sketch/SketchTab.svelte +120 -134
  68. package/src/live-tokens/data/colors-and-type/midnight-study.json +40 -30
  69. package/src/live-tokens/data/themes/autumn.json +3 -3
  70. package/src/live-tokens/data/themes/halloween.json +3 -3
  71. package/src/live-tokens/data/themes/midnight-study.json +61 -49
  72. package/src/live-tokens/data/themes/ocean.json +3 -3
  73. package/src/live-tokens/data/themes/royal-velvet.json +3 -3
  74. package/src/live-tokens/data/themes/sketchy.json +3 -3
  75. package/src/live-tokens/data/themes/spring-meadow.json +3 -3
  76. package/src/live-tokens/data/themes/sunset.json +3 -3
  77. package/src/system/components/Card.svelte +27 -9
  78. package/src/system/components/FloatingTokenTags.css +10 -8
  79. package/src/system/components/ImageLightbox.svelte +5 -2
  80. package/src/system/components/SectionDivider.svelte +3 -3
  81. package/src/system/components/SegmentedControl.svelte +11 -9
  82. package/src/system/styles/tokens.css +28 -5
  83. package/template/src/pages/Home.svelte +1 -11
@@ -95,8 +95,8 @@ function formatRadialShape(v) {
95
95
  if (ax === 1 && ay === 1) {
96
96
  return v.radius && v.radius > 0 ? `circle ${v.radius}px` : "circle";
97
97
  }
98
- const base = v.radius && v.radius > 0 ? v.radius : RADIAL_BASE_PX;
99
- return `ellipse ${(base * ax).toFixed(2)}px ${(base * ay).toFixed(2)}px`;
98
+ const base2 = v.radius && v.radius > 0 ? v.radius : RADIAL_BASE_PX;
99
+ return `ellipse ${(base2 * ax).toFixed(2)}px ${(base2 * ay).toFixed(2)}px`;
100
100
  }
101
101
  function formatGradientValue(v) {
102
102
  if (v.type === "none") return "transparent";
@@ -486,14 +486,14 @@ function scaleStepToX(step, scale) {
486
486
  function serializeDerivedValue(value) {
487
487
  return value.kind === "raw" ? value.css : oklchToCss(value.l, value.c, value.h);
488
488
  }
489
- function computePaletteOklch(index, base, lightnessCurve, saturationCurve, curveOffset, hueCurve) {
490
- const { c: baseC } = base;
489
+ function computePaletteOklch(index, base2, lightnessCurve, saturationCurve, curveOffset, hueCurve) {
490
+ const { c: baseC } = base2;
491
491
  const xPos = stepIndexToX(index);
492
492
  const targetL = Math.max(0, Math.min(100, sampleCurve(lightnessCurve, xPos) + (curveOffset.lightness ?? 0))) / 100;
493
493
  const satMul = Math.max(0, Math.min(2, (sampleCurve(saturationCurve, xPos) + (curveOffset.saturation ?? 0)) / 100));
494
494
  const targetC = baseC * satMul;
495
495
  const hueDelta = (hueCurve ? sampleCurve(hueCurve, xPos) : 0) + (curveOffset.hue ?? 0);
496
- const h = hueDelta === 0 ? base.h : wrapHue(base.h + hueDelta);
496
+ const h = hueDelta === 0 ? base2.h : wrapHue(base2.h + hueDelta);
497
497
  return gamutClamp(targetL, targetC, h);
498
498
  }
499
499
  function nearestPaletteStep(lightnessCurve, baseL) {
@@ -617,7 +617,7 @@ function syncBaseAnchor(cfg) {
617
617
  priorHueEndpoints: h ? prev?.priorHueEndpoints ?? h.priorEndpoints : void 0
618
618
  };
619
619
  }
620
- function computeDerivedOklch(step, base, scaleTitle, scaleCurves, curveOffset) {
620
+ function computeDerivedOklch(step, base2, scaleTitle, scaleCurves, curveOffset) {
621
621
  const scale = SCALES.find((s) => s.title === scaleTitle);
622
622
  const xPos = scaleStepToX(step, scale);
623
623
  const defs = defaultScaleCurves[scaleTitle];
@@ -627,7 +627,7 @@ function computeDerivedOklch(step, base, scaleTitle, scaleCurves, curveOffset) {
627
627
  const lOff = curveOffset[`${scaleTitle}-lightness`] ?? 0;
628
628
  const sOff = curveOffset[`${scaleTitle}-saturation`] ?? 0;
629
629
  const hOff = curveOffset[`${scaleTitle}-hue`] ?? 0;
630
- const { l: baseL, c: baseC, h: baseH } = base;
630
+ const { l: baseL, c: baseC, h: baseH } = base2;
631
631
  let targetL;
632
632
  if (scale.isText) {
633
633
  const lMul = Math.max(0, Math.min(2, (sampleCurve(lCurve, xPos) + lOff) / 100));
@@ -1904,6 +1904,340 @@ var KNOWN_COMPONENT_CONFIG_KEYS = /* @__PURE__ */ new Set([
1904
1904
  "--sectiondivider-sm-color-family"
1905
1905
  ]);
1906
1906
 
1907
+ // src/editor/core/sketch/sketchStyles.ts
1908
+ var base = {
1909
+ label: "",
1910
+ blurb: "",
1911
+ fillTravel: 1.5,
1912
+ strokeTravel: 1.5,
1913
+ wobble: 45,
1914
+ roughness: 3,
1915
+ borderWavelength: 1,
1916
+ waveform: 1,
1917
+ strokeWidth: 1.5,
1918
+ doubleStroke: false,
1919
+ retraceOffset: 1.2,
1920
+ retracePass: "copy",
1921
+ fillStyle: "solid",
1922
+ hatchInk: 0.4,
1923
+ strokeStyle: "solid",
1924
+ pressure: 0.25,
1925
+ pressureMod: 0.35,
1926
+ pooling: 1.2,
1927
+ strokeInk: 1,
1928
+ maskOn: true,
1929
+ maskBlob: 100,
1930
+ maskOutputMin: 0.45,
1931
+ maskOutputMax: 1,
1932
+ maskOctaves: 2,
1933
+ maskGrain: "fractal",
1934
+ maskPosterize: 1,
1935
+ maskSoftness: 1.5,
1936
+ jitterX: 2.5,
1937
+ jitterY: 2.5,
1938
+ jitterRot: 0.6,
1939
+ jitterScale: 0.035,
1940
+ cornerSpread: 10,
1941
+ cornerTravel: 8,
1942
+ iconTravel: 1.25,
1943
+ iconWavelength: 0.625,
1944
+ iconMaskOn: true,
1945
+ iconMaskScale: 1
1946
+ };
1947
+ var SKETCH_STYLES = {
1948
+ pencil: {
1949
+ ...base,
1950
+ label: "Pencil",
1951
+ blurb: "Two graphite passes on their own seeds, so the outline disagrees with itself the way a hand coming back round does. Tight grain, little else.",
1952
+ fillTravel: 0.75,
1953
+ strokeTravel: 1.25,
1954
+ wobble: 30,
1955
+ roughness: 3,
1956
+ waveform: 1,
1957
+ strokeWidth: 1.25,
1958
+ doubleStroke: true,
1959
+ retracePass: "reseeded",
1960
+ retraceOffset: 1.5,
1961
+ strokeInk: 0.85,
1962
+ maskBlob: 40,
1963
+ maskOutputMin: 0.62,
1964
+ maskOutputMax: 1,
1965
+ maskOctaves: 3,
1966
+ maskPosterize: 1,
1967
+ maskSoftness: 0,
1968
+ jitterX: 1.5,
1969
+ jitterY: 1.5,
1970
+ jitterRot: 0.35,
1971
+ jitterScale: 0.022,
1972
+ cornerSpread: 6,
1973
+ cornerTravel: 4.5,
1974
+ pressure: 0.15,
1975
+ pressureMod: 0.3,
1976
+ pooling: 0,
1977
+ iconTravel: 0.75
1978
+ },
1979
+ marker: {
1980
+ ...base,
1981
+ label: "Marker",
1982
+ blurb: "Broad translucent nib gone round twice on the same line, so the overlap darkens and the ink pools where it slows.",
1983
+ fillTravel: 2,
1984
+ strokeTravel: 1.5,
1985
+ wobble: 56,
1986
+ waveform: 1.4,
1987
+ borderWavelength: 1.3,
1988
+ strokeWidth: 4,
1989
+ doubleStroke: true,
1990
+ retracePass: "copy",
1991
+ strokeInk: 0.52,
1992
+ retraceOffset: 2.2,
1993
+ maskBlob: 115,
1994
+ maskOutputMin: 0.42,
1995
+ maskOutputMax: 1,
1996
+ maskOctaves: 3,
1997
+ maskPosterize: 4,
1998
+ maskSoftness: 4,
1999
+ jitterX: 3,
2000
+ jitterY: 3,
2001
+ jitterRot: 0.8,
2002
+ jitterScale: 0.045,
2003
+ cornerSpread: 10,
2004
+ cornerTravel: 8,
2005
+ pressure: 0.2,
2006
+ pressureMod: 0.25,
2007
+ pooling: 2,
2008
+ iconTravel: 1.25,
2009
+ iconMaskScale: 4
2010
+ },
2011
+ whiteboard: {
2012
+ ...base,
2013
+ label: "Whiteboard",
2014
+ blurb: "The fattest nib on glass. One long smooth undulation, and a veined mask that streaks the fill like a half-wiped board.",
2015
+ fillTravel: 2.5,
2016
+ strokeTravel: 2.5,
2017
+ wobble: 90,
2018
+ roughness: 1,
2019
+ waveform: 1,
2020
+ borderWavelength: 1.5,
2021
+ strokeWidth: 5.5,
2022
+ doubleStroke: true,
2023
+ retracePass: "copy",
2024
+ strokeInk: 0.66,
2025
+ retraceOffset: 3,
2026
+ maskGrain: "turbulence",
2027
+ maskBlob: 180,
2028
+ maskOutputMin: 0.42,
2029
+ maskOutputMax: 1,
2030
+ maskOctaves: 1,
2031
+ maskPosterize: 3,
2032
+ maskSoftness: 8,
2033
+ jitterX: 4.5,
2034
+ jitterY: 4.5,
2035
+ jitterRot: 1.2,
2036
+ jitterScale: 0.07,
2037
+ cornerSpread: 14,
2038
+ cornerTravel: 11,
2039
+ pressure: 0.15,
2040
+ pressureMod: 0.15,
2041
+ pooling: 3.5,
2042
+ iconTravel: 1.75,
2043
+ iconMaskScale: 1.5
2044
+ },
2045
+ hatched: {
2046
+ ...base,
2047
+ label: "Hatched",
2048
+ blurb: "An etching. The fill is angled shading, the outline a single hard-edged scratch that chatters along its length. No mask: the hatch is the texture.",
2049
+ fillTravel: 1.25,
2050
+ strokeTravel: 1.5,
2051
+ wobble: 24,
2052
+ roughness: 3,
2053
+ waveform: 3,
2054
+ strokeWidth: 1.5,
2055
+ fillStyle: "hatched",
2056
+ hatchInk: 0.5,
2057
+ doubleStroke: false,
2058
+ maskOn: false,
2059
+ iconMaskOn: false,
2060
+ jitterX: 1.5,
2061
+ jitterY: 1.5,
2062
+ jitterRot: 0.4,
2063
+ jitterScale: 0.03,
2064
+ cornerSpread: 6,
2065
+ cornerTravel: 6,
2066
+ pressure: 0.3,
2067
+ pressureMod: 0.45,
2068
+ pooling: 0.8,
2069
+ iconTravel: 1.25,
2070
+ iconWavelength: 0.5
2071
+ },
2072
+ dashed: {
2073
+ ...base,
2074
+ label: "Dashed",
2075
+ blurb: "A drafting outline. One slow drift along the ruler, broken into strokes, with jitter, mask and pressure all off. The clean pole.",
2076
+ strokeStyle: "dashed",
2077
+ strokeTravel: 1,
2078
+ fillTravel: 0.5,
2079
+ wobble: 120,
2080
+ roughness: 1,
2081
+ waveform: 1,
2082
+ strokeWidth: 1.5,
2083
+ doubleStroke: false,
2084
+ maskOn: false,
2085
+ iconMaskOn: false,
2086
+ jitterX: 0,
2087
+ jitterY: 0,
2088
+ jitterRot: 0,
2089
+ jitterScale: 0,
2090
+ cornerSpread: 4,
2091
+ cornerTravel: 3,
2092
+ pressure: 0,
2093
+ pressureMod: 0,
2094
+ pooling: 0,
2095
+ iconTravel: 0
2096
+ },
2097
+ napkin: {
2098
+ ...base,
2099
+ label: "Napkin",
2100
+ blurb: "Ballpoint in a hurry. Everything loose at once: a square wave sends every edge to full travel, and the second pass lands wherever it lands.",
2101
+ fillTravel: 3,
2102
+ strokeTravel: 2.25,
2103
+ wobble: 50,
2104
+ roughness: 3,
2105
+ waveform: 2.5,
2106
+ strokeWidth: 2.25,
2107
+ doubleStroke: true,
2108
+ retracePass: "reseeded",
2109
+ retraceOffset: 4,
2110
+ strokeInk: 1,
2111
+ maskBlob: 150,
2112
+ maskOutputMin: 0.43,
2113
+ maskOutputMax: 0.95,
2114
+ maskOctaves: 2,
2115
+ maskPosterize: 2,
2116
+ maskSoftness: 10,
2117
+ jitterX: 6,
2118
+ jitterY: 6,
2119
+ jitterRot: 1.8,
2120
+ jitterScale: 0.1,
2121
+ cornerSpread: 20,
2122
+ cornerTravel: 17,
2123
+ pressure: 0.45,
2124
+ pressureMod: 0.6,
2125
+ pooling: 2.5,
2126
+ iconTravel: 2.25,
2127
+ iconMaskScale: 3.6
2128
+ },
2129
+ dry: {
2130
+ ...base,
2131
+ label: "Dry marker",
2132
+ blurb: "Ink that ran out. One scratchy pass that breaks up along its length, over a fill the mask has worn nearly through in patches.",
2133
+ fillTravel: 2.25,
2134
+ strokeTravel: 1.75,
2135
+ wobble: 50,
2136
+ waveform: 2,
2137
+ borderWavelength: 0.5,
2138
+ strokeWidth: 3.5,
2139
+ doubleStroke: false,
2140
+ strokeInk: 0.4,
2141
+ maskBlob: 150,
2142
+ maskOutputMin: 0.24,
2143
+ maskOutputMax: 0.91,
2144
+ maskOctaves: 2,
2145
+ maskPosterize: 4,
2146
+ maskSoftness: 1.75,
2147
+ jitterX: 5,
2148
+ jitterY: 5,
2149
+ jitterRot: 1.4,
2150
+ jitterScale: 0.08,
2151
+ cornerSpread: 16,
2152
+ cornerTravel: 13,
2153
+ pressure: 0.4,
2154
+ pressureMod: 0.8,
2155
+ pooling: 1.5,
2156
+ iconTravel: 1.75,
2157
+ iconMaskScale: 3.8
2158
+ }
2159
+ };
2160
+ var DEFAULT_SKETCH_STYLE = "marker";
2161
+ function hydrateSketchStyle(raw) {
2162
+ const base2 = SKETCH_STYLES[DEFAULT_SKETCH_STYLE];
2163
+ const stored = raw ?? {};
2164
+ const out = { ...base2 };
2165
+ for (const key of Object.keys(base2)) {
2166
+ if (stored[key] !== void 0) out[key] = stored[key];
2167
+ }
2168
+ if (out.fillStyle === "none") out.fillStyle = base2.fillStyle;
2169
+ convertTiledMask(stored, out);
2170
+ convertCutToLevels(stored, out);
2171
+ carryLevelsToOutput(stored, out);
2172
+ halveSwingDials(stored, out);
2173
+ convertCyclesToWavelength(stored, out);
2174
+ convertIconTileToScale(stored, out);
2175
+ restoreDerivedRetrace(stored, out);
2176
+ return out;
2177
+ }
2178
+ function restoreDerivedRetrace(stored, out) {
2179
+ if (stored.retraceOffset === void 0) {
2180
+ out.retraceOffset = Number(Math.max(1.2, out.strokeWidth * 0.55).toFixed(2));
2181
+ }
2182
+ }
2183
+ var SWING_DIALS = {
2184
+ fillScale: "fillTravel",
2185
+ strokeScale: "strokeTravel",
2186
+ iconScale: "iconTravel",
2187
+ cornerShift: "cornerTravel"
2188
+ };
2189
+ function convertCyclesToWavelength(stored, out) {
2190
+ const cycles = stored.frequency;
2191
+ if (typeof cycles === "number" && cycles > 0) out.wobble = Math.round(1 / cycles);
2192
+ for (const [legacy, key] of [
2193
+ ["borderFrequency", "borderWavelength"],
2194
+ ["iconFrequency", "iconWavelength"]
2195
+ ]) {
2196
+ const multiple = stored[legacy];
2197
+ if (typeof multiple === "number" && multiple > 0) {
2198
+ out[key] = Number((1 / multiple).toFixed(3));
2199
+ }
2200
+ }
2201
+ const layers = stored.octaves;
2202
+ if (typeof layers === "number") out.roughness = Math.min(3, Math.max(1, layers));
2203
+ }
2204
+ function convertIconTileToScale(stored, out) {
2205
+ const tile = stored.iconMaskTile;
2206
+ if (typeof tile !== "number") return;
2207
+ out.iconMaskScale = Math.min(5, Math.max(0.5, Number((tile / 90).toFixed(2))));
2208
+ }
2209
+ function halveSwingDials(stored, out) {
2210
+ for (const [legacy, key] of Object.entries(SWING_DIALS)) {
2211
+ const value = stored[legacy];
2212
+ if (typeof value === "number") out[key] = value / 2;
2213
+ }
2214
+ }
2215
+ function convertTiledMask(stored, out) {
2216
+ const scale = stored.maskScale;
2217
+ if (typeof scale !== "number") return;
2218
+ const freq = stored.maskFrequency;
2219
+ if (typeof freq === "number") out.maskBlob = Math.round(scale / (freq * LEGACY_TILE));
2220
+ const soft = stored.maskSoftness;
2221
+ if (typeof soft === "number") out.maskSoftness = Number((soft * scale / LEGACY_TILE).toFixed(1));
2222
+ }
2223
+ function convertCutToLevels(stored, out) {
2224
+ const contrast = stored.maskContrast;
2225
+ const coverage = stored.maskCoverage;
2226
+ if (typeof contrast !== "number" || typeof coverage !== "number") return;
2227
+ const veined = out.maskGrain === "turbulence";
2228
+ const [lo, hi] = veined ? LEGACY_RANGE.turbulence : LEGACY_RANGE.fractal;
2229
+ const pivot = veined ? 0.55 - 0.5 * coverage : 0.8 - 0.6 * coverage;
2230
+ const level = (raw) => Math.min(1, Math.max(0, (raw - lo) / (hi - lo)));
2231
+ out.maskOutputMin = Number(level(pivot - 0.5 / contrast).toFixed(2));
2232
+ out.maskOutputMax = Number(Math.max(out.maskOutputMin + 0.02, level(pivot + 0.5 / contrast)).toFixed(2));
2233
+ }
2234
+ function carryLevelsToOutput(stored, out) {
2235
+ if (typeof stored.maskLevelMin === "number") out.maskOutputMin = stored.maskLevelMin;
2236
+ if (typeof stored.maskLevelMax === "number") out.maskOutputMax = stored.maskLevelMax;
2237
+ }
2238
+ var LEGACY_RANGE = { fractal: [0.24, 0.77], turbulence: [0.02, 0.6] };
2239
+ var LEGACY_TILE = 600;
2240
+
1907
2241
  // vite-plugin/themes/normalizeTheme.ts
1908
2242
  function asObject(value) {
1909
2243
  return value && typeof value === "object" && !Array.isArray(value) ? value : null;
@@ -1995,12 +2329,12 @@ function normalizeTheme(raw, resolvers) {
1995
2329
  }
1996
2330
  const filled = { components: [], aliases: 0, orphans: 0 };
1997
2331
  for (const comp of resolvers.listComponentNames()) {
1998
- const base = asObject(resolvers.readComponentConfig(comp, "default"));
1999
- const baseAliases = base ? asObject(base.aliases) : null;
2000
- if (!base || !baseAliases) continue;
2332
+ const base2 = asObject(resolvers.readComponentConfig(comp, "default"));
2333
+ const baseAliases = base2 ? asObject(base2.aliases) : null;
2334
+ if (!base2 || !baseAliases) continue;
2001
2335
  const entry = componentConfigs[comp];
2002
2336
  if (!entry) {
2003
- const { schemaVersion: _standaloneStamp, ...rest } = stripFileMarker(base);
2337
+ const { schemaVersion: _standaloneStamp, ...rest } = stripFileMarker(base2);
2004
2338
  componentConfigs[comp] = structuredClone(rest);
2005
2339
  filled.components.push(comp);
2006
2340
  continue;
@@ -2016,6 +2350,8 @@ function normalizeTheme(raw, resolvers) {
2016
2350
  if (!(key in baseAliases)) filled.orphans++;
2017
2351
  }
2018
2352
  }
2353
+ const embeddedSketchStyle = asObject(src.sketchStyle);
2354
+ const sketchStyle = embeddedSketchStyle ? hydrateSketchStyle(embeddedSketchStyle) : void 0;
2019
2355
  return {
2020
2356
  theme: {
2021
2357
  name: asString(src.name, "Untitled"),
@@ -2024,7 +2360,8 @@ function normalizeTheme(raw, resolvers) {
2024
2360
  schemaVersion: THEME_SCHEMA_VERSION,
2025
2361
  colorsAndType,
2026
2362
  componentConfigs,
2027
- componentSchemaVersion: CURRENT_COMPONENT_SCHEMA_VERSION
2363
+ componentSchemaVersion: CURRENT_COMPONENT_SCHEMA_VERSION,
2364
+ ...sketchStyle ? { sketchStyle } : {}
2028
2365
  },
2029
2366
  dropped,
2030
2367
  migrated,
@@ -2086,7 +2423,7 @@ function resolveDataDirs(opts = {}) {
2086
2423
  colorsAndTypeDir: opts.colorsAndTypeDir ? import_path2.default.resolve(opts.colorsAndTypeDir) : fileConfig.colorsAndTypeDir ? import_path2.default.resolve(fileConfig.colorsAndTypeDir) : sub("colors-and-type"),
2087
2424
  componentConfigsDir: opts.componentConfigsDir ? import_path2.default.resolve(opts.componentConfigsDir) : fileConfig.componentConfigsDir ? import_path2.default.resolve(fileConfig.componentConfigsDir) : sub("component-configs"),
2088
2425
  themesDir: opts.themesDir ? import_path2.default.resolve(opts.themesDir) : fileConfig.themesDir ? import_path2.default.resolve(fileConfig.themesDir) : sub("themes"),
2089
- sketchPresetsDir: sub("sketch-presets"),
2426
+ sketchStylesDir: sub("sketch-styles"),
2090
2427
  legacyManifestsDir: fileConfig.manifestsDir ? import_path2.default.resolve(fileConfig.manifestsDir) : void 0
2091
2428
  };
2092
2429
  }
@@ -2510,37 +2847,15 @@ var tokensCssMigration_2026_08_19_oklchColorValues = {
2510
2847
 
2511
2848
  // vite-plugin/tokensCssMigrations/migrations/2026-08-25-editorial-type-role.ts
2512
2849
  var STACK = [{ name: "--font-editorial", value: "var(--font-sans)" }];
2513
- var BUNDLE2 = [
2514
- { name: "--editorial-font-family", value: "var(--font-editorial)" },
2515
- { name: "--editorial-font-size", value: "var(--font-size-md)" },
2516
- { name: "--editorial-font-weight", value: "var(--font-weight-normal)" },
2517
- { name: "--editorial-line-height", value: "var(--line-height-normal)" },
2518
- { name: "--editorial-letter-spacing", value: "var(--letter-spacing-normal)" }
2519
- ];
2520
2850
  var tokensCssMigration_2026_08_25_editorialTypeRole = {
2521
2851
  id: "2026-08-25-editorial-type-role",
2522
2852
  kind: "additive",
2523
- description: "Add the editorial type role (--font-editorial and the --editorial-* bundle)",
2853
+ description: "Add the editorial type role (--font-editorial)",
2524
2854
  apply(css) {
2525
- const withStack = ensureScale(css, {
2855
+ return ensureScale(css, {
2526
2856
  anchorPrefixes: ["--font-mono", "--font-serif", "--font-sans", "--font-display"],
2527
2857
  entries: STACK
2528
2858
  });
2529
- return ensureScale(withStack, {
2530
- sectionComment: "Editorial \u2014 the long-reading role, body face until repointed",
2531
- anchorPrefixes: [
2532
- "--eyebrow-",
2533
- "--code-",
2534
- "--body-",
2535
- "--heading-",
2536
- "--letter-spacing-",
2537
- "--line-height-",
2538
- "--font-weight-",
2539
- "--font-size-",
2540
- "--font-"
2541
- ],
2542
- entries: BUNDLE2
2543
- });
2544
2859
  }
2545
2860
  };
2546
2861
 
@@ -2593,6 +2908,84 @@ ${css.slice(at)}`;
2593
2908
  }
2594
2909
  };
2595
2910
 
2911
+ // vite-plugin/tokensCssMigrations/migrations/2026-08-27-editorial-size-steps.ts
2912
+ var AXES = ["font-family", "font-size", "font-weight", "line-height", "letter-spacing"];
2913
+ var BUNDLE2 = [
2914
+ { name: "--editorial-md-font-family", value: "var(--font-editorial)" },
2915
+ { name: "--editorial-md-font-size", value: "var(--font-size-md)" },
2916
+ { name: "--editorial-md-font-weight", value: "var(--font-weight-normal)" },
2917
+ { name: "--editorial-md-line-height", value: "var(--line-height-normal)" },
2918
+ { name: "--editorial-md-letter-spacing", value: "var(--letter-spacing-normal)" },
2919
+ { name: "--editorial-sm-font-family", value: "var(--font-editorial)" },
2920
+ { name: "--editorial-sm-font-size", value: "var(--font-size-sm)" },
2921
+ { name: "--editorial-sm-font-weight", value: "var(--font-weight-normal)" },
2922
+ { name: "--editorial-sm-line-height", value: "var(--line-height-tight)" },
2923
+ { name: "--editorial-sm-letter-spacing", value: "var(--letter-spacing-normal)" }
2924
+ ];
2925
+ var tokensCssMigration_2026_08_27_editorialSizeSteps = {
2926
+ id: "2026-08-27-editorial-size-steps",
2927
+ kind: "breaking",
2928
+ description: "Split the editorial bundle into --editorial-md-* and --editorial-sm-* steps",
2929
+ apply(css) {
2930
+ let out = css;
2931
+ for (const axis of AXES) {
2932
+ out = renameToken2(out, `--editorial-${axis}`, `--editorial-md-${axis}`);
2933
+ }
2934
+ return ensureScale(out, {
2935
+ sectionComment: "Editorial \u2014 the long-reading role, body face until repointed",
2936
+ anchorPrefixes: [
2937
+ "--eyebrow-",
2938
+ "--code-",
2939
+ "--body-",
2940
+ "--heading-",
2941
+ "--letter-spacing-",
2942
+ "--line-height-",
2943
+ "--font-weight-",
2944
+ "--font-size-",
2945
+ "--font-"
2946
+ ],
2947
+ entries: BUNDLE2
2948
+ });
2949
+ }
2950
+ };
2951
+
2952
+ // vite-plugin/tokensCssMigrations/migrations/2026-08-27-editorial-large-steps.ts
2953
+ var BUNDLE3 = [
2954
+ { name: "--editorial-xl-font-family", value: "var(--font-editorial)" },
2955
+ { name: "--editorial-xl-font-size", value: "var(--font-size-xl)" },
2956
+ { name: "--editorial-xl-font-weight", value: "var(--font-weight-normal)" },
2957
+ { name: "--editorial-xl-line-height", value: "var(--line-height-tighter)" },
2958
+ { name: "--editorial-xl-letter-spacing", value: "var(--letter-spacing-normal)" },
2959
+ { name: "--editorial-lg-font-family", value: "var(--font-editorial)" },
2960
+ { name: "--editorial-lg-font-size", value: "var(--font-size-lg)" },
2961
+ { name: "--editorial-lg-font-weight", value: "var(--font-weight-normal)" },
2962
+ { name: "--editorial-lg-line-height", value: "var(--line-height-tight)" },
2963
+ { name: "--editorial-lg-letter-spacing", value: "var(--letter-spacing-normal)" }
2964
+ ];
2965
+ var tokensCssMigration_2026_08_27_editorialLargeSteps = {
2966
+ id: "2026-08-27-editorial-large-steps",
2967
+ kind: "additive",
2968
+ description: "Add the --editorial-lg-* and --editorial-xl-* steps above the reading size",
2969
+ apply(css) {
2970
+ return ensureScale(css, {
2971
+ sectionComment: "Editorial \u2014 the steps above the reading size",
2972
+ anchorPrefixes: [
2973
+ "--editorial-",
2974
+ "--eyebrow-",
2975
+ "--code-",
2976
+ "--body-",
2977
+ "--heading-",
2978
+ "--letter-spacing-",
2979
+ "--line-height-",
2980
+ "--font-weight-",
2981
+ "--font-size-",
2982
+ "--font-"
2983
+ ],
2984
+ entries: BUNDLE3
2985
+ });
2986
+ }
2987
+ };
2988
+
2596
2989
  // vite-plugin/tokensCssMigrations/index.ts
2597
2990
  var TOKENS_CSS_MIGRATIONS = [
2598
2991
  tokensCssMigration_2026_05_29_typographyScaleAdditions,
@@ -2605,7 +2998,9 @@ var TOKENS_CSS_MIGRATIONS = [
2605
2998
  tokensCssMigration_2026_08_19_oklchColorValues,
2606
2999
  tokensCssMigration_2026_08_25_editorialTypeRole,
2607
3000
  tokensCssMigration_2026_08_26_gradientStops,
2608
- tokensCssMigration_2026_08_27_backdropPolarity
3001
+ tokensCssMigration_2026_08_27_backdropPolarity,
3002
+ tokensCssMigration_2026_08_27_editorialSizeSteps,
3003
+ tokensCssMigration_2026_08_27_editorialLargeSteps
2609
3004
  ];
2610
3005
  function runTokensCssMigrations(css) {
2611
3006
  return foldMigrations(css, () => true);
@@ -2706,7 +3101,7 @@ function themeFileApi(opts) {
2706
3101
  const COLORS_AND_TYPE_DIR = dataDirs.colorsAndTypeDir;
2707
3102
  const COMPONENT_CONFIGS_DIR = dataDirs.componentConfigsDir;
2708
3103
  const THEMES_DIR = dataDirs.themesDir;
2709
- const SKETCH_PRESETS_DIR = dataDirs.sketchPresetsDir;
3104
+ const SKETCH_STYLES_DIR = dataDirs.sketchStylesDir;
2710
3105
  const CSS_PATH = import_path4.default.resolve(opts.tokensCssPath);
2711
3106
  const GENERATED_CSS_PATH = opts.tokensGeneratedCssPath ? import_path4.default.resolve(opts.tokensGeneratedCssPath) : import_path4.default.join(dataDirs.dataDir, "tokens.generated.css");
2712
3107
  const FONTS_CSS_PATH = opts.fontsCssPath ? import_path4.default.resolve(opts.fontsCssPath) : import_path4.default.join(import_path4.default.dirname(CSS_PATH), "fonts.css");
@@ -2764,7 +3159,7 @@ function themeFileApi(opts) {
2764
3159
  dir: THEMES_DIR,
2765
3160
  packageDir: packageThemesDir
2766
3161
  });
2767
- const sketchPresetsResource = versionedFileResourceServer({ dir: SKETCH_PRESETS_DIR });
3162
+ const sketchStylesResource = versionedFileResourceServer({ dir: SKETCH_STYLES_DIR });
2768
3163
  function ensureColorsAndTypeDir() {
2769
3164
  colorsAndTypeResource.ensureDir();
2770
3165
  }
@@ -3103,6 +3498,13 @@ ${lines.join("\n")}
3103
3498
  `[live-tokens] This project still uses the data layout from 0.47 and earlier: ${evidence}. Since 0.48 the whole-look theme files live in \`themes/\` and the colors and type live in \`colors-and-type/\`. Nothing in the data directory was written, the editor cannot save, and ${import_path4.default.basename(GENERATED_CSS_PATH)} is left exactly as it is. Run \`npx live-tokens migrate\` to move the directories and heal the tree, then restart the dev server.`
3104
3499
  );
3105
3500
  }
3501
+ function warnOnUnmigratedSketchStyles(warn) {
3502
+ const legacyDir = import_path4.default.join(dataDirs.dataDir, "sketch-presets");
3503
+ if (!import_fs4.default.existsSync(legacyDir)) return;
3504
+ warn(
3505
+ `[live-tokens] Saved sketchstyles still live under the retired ${import_path4.default.basename(legacyDir)}/ directory name. Run \`npx live-tokens migrate\` to rename it to ${import_path4.default.basename(SKETCH_STYLES_DIR)}/; until then they will not show up in the Sketchstyle view.`
3506
+ );
3507
+ }
3106
3508
  const diskThemeResolvers = {
3107
3509
  readColorsAndType: (name) => colorsAndTypeResource.readJson(sanitizeFileName(name)),
3108
3510
  readComponentConfig: (comp, name) => readComponentConfig(comp, sanitizeFileName(name)),
@@ -3342,8 +3744,8 @@ ${lines.join("\n")}
3342
3744
  const THEME_EXPORT_REGEX = new RegExp(`^${escapedBase}/themes/([a-z0-9\\-_]+)/export$`);
3343
3745
  const THEME_IMPORT_ROUTE = `${API_BASE}/themes/import`;
3344
3746
  const THEME_BY_NAME_REGEX = new RegExp(`^${escapedBase}/themes/([a-z0-9\\-_]+)$`);
3345
- const SKETCH_PRESETS_ROUTE = `${API_BASE}/sketch-presets`;
3346
- const SKETCH_PRESET_BY_NAME_REGEX = new RegExp(`^${escapedBase}/sketch-presets/([a-z0-9\\-_]+)$`);
3747
+ const SKETCH_STYLES_ROUTE = `${API_BASE}/sketch-styles`;
3748
+ const SKETCH_STYLE_BY_NAME_REGEX = new RegExp(`^${escapedBase}/sketch-styles/([a-z0-9\\-_]+)$`);
3347
3749
  const PRODUCTION_ROUTE = `${API_BASE}/production`;
3348
3750
  async function handleListColorsAndType(_ctx) {
3349
3751
  const files = colorsAndTypeResource.listNames().map((fileName) => {
@@ -3875,11 +4277,11 @@ ${lines.join("\n")}
3875
4277
  }
3876
4278
  });
3877
4279
  }
3878
- async function handleListSketchPresets({ res }) {
3879
- const files = sketchPresetsResource.listNames().map((fileName) => {
4280
+ async function handleListSketchStyles({ res }) {
4281
+ const files = sketchStylesResource.listNames().map((fileName) => {
3880
4282
  let data = null;
3881
4283
  try {
3882
- data = sketchPresetsResource.readJson(fileName);
4284
+ data = sketchStylesResource.readJson(fileName);
3883
4285
  } catch {
3884
4286
  }
3885
4287
  return {
@@ -3890,12 +4292,12 @@ ${lines.join("\n")}
3890
4292
  });
3891
4293
  jsonResponse(res, 200, { files });
3892
4294
  }
3893
- async function handleSketchPresetByName({ params, req, res }) {
4295
+ async function handleSketchStyleByName({ params, req, res }) {
3894
4296
  const [fileName] = params;
3895
4297
  if (rejectReservedName(res, fileName)) return;
3896
- const filePath = sketchPresetsResource.filePath(fileName);
4298
+ const filePath = sketchStylesResource.filePath(fileName);
3897
4299
  if (req.method === "GET") {
3898
- const raw = sketchPresetsResource.readJson(fileName);
4300
+ const raw = sketchStylesResource.readJson(fileName);
3899
4301
  if (!raw) {
3900
4302
  jsonResponse(res, 404, { error: "Not found" });
3901
4303
  return;
@@ -3906,7 +4308,7 @@ ${lines.join("\n")}
3906
4308
  if (req.method === "PUT") {
3907
4309
  const body = JSON.parse(await readBody(req));
3908
4310
  if (!body || typeof body !== "object" || !body.settings || typeof body.settings !== "object") {
3909
- jsonResponse(res, 400, { error: "A sketch preset needs a settings object" });
4311
+ jsonResponse(res, 400, { error: "A sketchstyle needs a settings object" });
3910
4312
  return;
3911
4313
  }
3912
4314
  body.name = String(body.name || fileName);
@@ -3919,7 +4321,7 @@ ${lines.join("\n")}
3919
4321
  }
3920
4322
  }
3921
4323
  if (!body.createdAt) body.createdAt = body.updatedAt;
3922
- sketchPresetsResource.ensureDir();
4324
+ sketchStylesResource.ensureDir();
3923
4325
  import_fs4.default.writeFileSync(filePath, JSON.stringify(body, null, 2));
3924
4326
  jsonResponse(res, 200, { ok: true, fileName });
3925
4327
  return;
@@ -4006,14 +4408,14 @@ ${lines.join("\n")}
4006
4408
  { method: "PUT", pattern: THEME_BY_NAME_REGEX, handler: handleThemeByName },
4007
4409
  { method: "DELETE", pattern: THEME_BY_NAME_REGEX, handler: handleThemeByName },
4008
4410
  // Production — the whole-look adopt door
4009
- { method: "GET", pattern: SKETCH_PRESETS_ROUTE, handler: handleListSketchPresets },
4010
- { method: "PUT", pattern: SKETCH_PRESETS_ROUTE, handler: methodNotAllowed },
4011
- { method: "POST", pattern: SKETCH_PRESETS_ROUTE, handler: methodNotAllowed },
4012
- { method: "DELETE", pattern: SKETCH_PRESETS_ROUTE, handler: methodNotAllowed },
4013
- { method: "GET", pattern: SKETCH_PRESET_BY_NAME_REGEX, handler: handleSketchPresetByName },
4014
- { method: "PUT", pattern: SKETCH_PRESET_BY_NAME_REGEX, handler: handleSketchPresetByName },
4015
- { method: "DELETE", pattern: SKETCH_PRESET_BY_NAME_REGEX, handler: handleSketchPresetByName },
4016
- { method: "POST", pattern: SKETCH_PRESET_BY_NAME_REGEX, handler: methodNotAllowed },
4411
+ { method: "GET", pattern: SKETCH_STYLES_ROUTE, handler: handleListSketchStyles },
4412
+ { method: "PUT", pattern: SKETCH_STYLES_ROUTE, handler: methodNotAllowed },
4413
+ { method: "POST", pattern: SKETCH_STYLES_ROUTE, handler: methodNotAllowed },
4414
+ { method: "DELETE", pattern: SKETCH_STYLES_ROUTE, handler: methodNotAllowed },
4415
+ { method: "GET", pattern: SKETCH_STYLE_BY_NAME_REGEX, handler: handleSketchStyleByName },
4416
+ { method: "PUT", pattern: SKETCH_STYLE_BY_NAME_REGEX, handler: handleSketchStyleByName },
4417
+ { method: "DELETE", pattern: SKETCH_STYLE_BY_NAME_REGEX, handler: handleSketchStyleByName },
4418
+ { method: "POST", pattern: SKETCH_STYLE_BY_NAME_REGEX, handler: methodNotAllowed },
4017
4419
  { method: "PUT", pattern: PRODUCTION_ROUTE, handler: handleAdoptLook },
4018
4420
  { method: "GET", pattern: PRODUCTION_ROUTE, handler: methodNotAllowed },
4019
4421
  { method: "POST", pattern: PRODUCTION_ROUTE, handler: methodNotAllowed },
@@ -4053,6 +4455,7 @@ ${lines.join("\n")}
4053
4455
  productionPointerHeld,
4054
4456
  (msg) => server.config.logger.warn(msg)
4055
4457
  );
4458
+ warnOnUnmigratedSketchStyles((msg) => server.config.logger.warn(msg));
4056
4459
  }
4057
4460
  server.middlewares.use(async (req, res, next) => {
4058
4461
  if (legacyLayout && req.method !== "GET" && (req.url ?? "").startsWith(API_BASE)) {
@@ -1,6 +1,6 @@
1
1
  import { Plugin } from 'vite';
2
2
  export { ComponentSource, MissingToken, RunResult, TOKENS_CSS_MIGRATIONS, TokensCssMigration, ValidateInput, runTokensCssMigrations, validateTokensCss } from './tokensCssMigrations/index.cjs';
3
- import './dataPaths-CRfD1LdA.cjs';
3
+ import './dataPaths-DZUzVv8H.cjs';
4
4
 
5
5
  interface ThemeFileApiOptions {
6
6
  tokensCssPath: string;