@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.
- package/.claude/skills/live-tokens-adjust-geometry/SKILL.md +4 -4
- package/.claude/skills/live-tokens-build-page/SKILL.md +21 -3
- package/.claude/skills/live-tokens-create-component/SKILL.md +16 -48
- package/.claude/skills/live-tokens-create-component/references/fixed-overlays.md +10 -1
- package/.claude/skills/live-tokens-create-component/references/intrinsics.md +7 -5
- package/.claude/skills/live-tokens-create-component/references/sketch-mode.md +1 -1
- package/.claude/skills/live-tokens-create-component/references/token-naming.md +50 -0
- package/.claude/skills/live-tokens-generate-theme/SKILL.md +16 -9
- package/.claude/skills/live-tokens-pair-fonts/SKILL.md +8 -6
- package/.claude/skills/live-tokens-pick-component/SKILL.md +19 -5
- package/CHANGELOG.md +114 -0
- package/bin/migrate.mjs +6 -2
- package/dist-plugin/adjust/index.cjs +1 -1
- package/dist-plugin/adjust/index.d.cts +1 -1
- package/dist-plugin/adjust/index.d.ts +1 -1
- package/dist-plugin/adjust/index.js +1 -1
- package/dist-plugin/{chunk-232GZGQU.js → chunk-NDJJORKJ.js} +342 -5
- package/dist-plugin/{chunk-Y5CNFSSV.js → chunk-RVE3MNKM.js} +1 -1
- package/dist-plugin/{chunk-OIOXU7FR.js → chunk-ZHPX7ZYQ.js} +83 -25
- package/dist-plugin/{dataPaths-CRfD1LdA.d.ts → dataPaths-DZUzVv8H.d.cts} +3 -3
- package/dist-plugin/{dataPaths-CRfD1LdA.d.cts → dataPaths-DZUzVv8H.d.ts} +3 -3
- package/dist-plugin/fontPairing/index.cjs +1 -1
- package/dist-plugin/fontPairing/index.d.cts +1 -1
- package/dist-plugin/fontPairing/index.d.ts +1 -1
- package/dist-plugin/fontPairing/index.js +1 -1
- package/dist-plugin/generateColorsAndType/index.cjs +1 -1
- package/dist-plugin/generateColorsAndType/index.d.cts +1 -1
- package/dist-plugin/generateColorsAndType/index.d.ts +1 -1
- package/dist-plugin/generateColorsAndType/index.js +1 -1
- package/dist-plugin/index.cjs +461 -58
- package/dist-plugin/index.d.cts +1 -1
- package/dist-plugin/index.d.ts +1 -1
- package/dist-plugin/index.js +31 -23
- package/dist-plugin/migrateData/index.cjs +350 -9
- package/dist-plugin/migrateData/index.d.cts +1 -1
- package/dist-plugin/migrateData/index.d.ts +1 -1
- package/dist-plugin/migrateData/index.js +9 -5
- package/dist-plugin/tokensCssMigrations/index.cjs +83 -25
- package/dist-plugin/tokensCssMigrations/index.d.cts +1 -1
- package/dist-plugin/tokensCssMigrations/index.d.ts +1 -1
- package/dist-plugin/tokensCssMigrations/index.js +2 -2
- package/package.json +4 -2
- package/src/app/site.css +32 -0
- package/src/editor/component-editor/CardEditor.svelte +7 -1
- package/src/editor/component-editor/scaffolding/VariantGroup.svelte +25 -2
- package/src/editor/core/preview/lookPreview.ts +46 -5
- package/src/editor/core/productionPulse.ts +6 -2
- package/src/editor/core/sketch/maskField.ts +75 -39
- package/src/editor/core/sketch/sketchLayer.ts +32 -11
- package/src/editor/core/sketch/sketchStore.ts +311 -86
- package/src/editor/core/sketch/{sketchPresetService.ts → sketchStyleService.ts} +14 -14
- package/src/editor/core/sketch/{sketchPresets.ts → sketchStyles.ts} +27 -28
- package/src/editor/core/themes/themeDocumentSync.ts +2 -0
- package/src/editor/core/themes/themeInit.ts +19 -1
- package/src/editor/core/themes/themeService.ts +7 -2
- package/src/editor/core/themes/themeTypes.ts +5 -0
- package/src/editor/docs/content/editing-tokens.md +1 -1
- package/src/editor/docs/content/sketch-mode.md +34 -18
- package/src/editor/docs/content/themes-workflow.md +30 -21
- package/src/editor/docs/content/where-themes-live.md +9 -5
- package/src/editor/docs/content.generated.ts +4 -4
- package/src/editor/overlay/LiveTokensRouter.svelte +8 -0
- package/src/editor/ui/EditorViewSwitcher.svelte +3 -3
- package/src/editor/ui/ThemePanel.svelte +47 -1
- package/src/editor/ui/sections/textStyles.ts +29 -1
- package/src/editor/ui/sketch/SketchPreview.svelte +3 -3
- package/src/editor/ui/sketch/SketchTab.svelte +120 -134
- package/src/live-tokens/data/colors-and-type/midnight-study.json +40 -30
- package/src/live-tokens/data/themes/autumn.json +3 -3
- package/src/live-tokens/data/themes/halloween.json +3 -3
- package/src/live-tokens/data/themes/midnight-study.json +61 -49
- package/src/live-tokens/data/themes/ocean.json +3 -3
- package/src/live-tokens/data/themes/royal-velvet.json +3 -3
- package/src/live-tokens/data/themes/sketchy.json +3 -3
- package/src/live-tokens/data/themes/spring-meadow.json +3 -3
- package/src/live-tokens/data/themes/sunset.json +3 -3
- package/src/system/components/Card.svelte +27 -9
- package/src/system/components/FloatingTokenTags.css +10 -8
- package/src/system/components/ImageLightbox.svelte +5 -2
- package/src/system/components/SectionDivider.svelte +3 -3
- package/src/system/components/SegmentedControl.svelte +11 -9
- package/src/system/styles/tokens.css +28 -5
- package/template/src/pages/Home.svelte +1 -11
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,119 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.63.0 — A theme carries its sketchstyle
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- **The editorial role reaches above the reading size.** It shipped as a pair,
|
|
8
|
+
so a lede, a standfirst or a pull quote had nowhere to go but a heading style:
|
|
9
|
+
the display face, at heading leading. `--editorial-lg-*` and `--editorial-xl-*`
|
|
10
|
+
are the two steps above `md`, set in the same editorial face, editable in the
|
|
11
|
+
editor's Text Styles section and carried by an `.editorial-lg` /
|
|
12
|
+
`.editorial-xl` class in `site.css`. Leading follows the role's own rule: `md`
|
|
13
|
+
is the reading step and takes the most open leading, and every step away from
|
|
14
|
+
it tightens by one. Sizes stay inside the band the responsive scale leaves
|
|
15
|
+
constant, so an article does not resize itself between breakpoints. An
|
|
16
|
+
`additive` tokens.css migration (`2026-08-27-editorial-large-steps`) adds both
|
|
17
|
+
steps to a vendored `tokens.css`.
|
|
18
|
+
|
|
19
|
+
### Changed
|
|
20
|
+
|
|
21
|
+
- **A theme carries its sketchstyle.** Save folds the live dials into the open
|
|
22
|
+
theme's `sketchStyle` field; Load applies whatever the theme carries, or
|
|
23
|
+
turns the effect off for a theme with none. A sketchstyle keeps its old job:
|
|
24
|
+
a reusable look you pick from, saved and loaded independently of the open
|
|
25
|
+
theme. Production is unchanged: Adopt still does not bake the layer, and a
|
|
26
|
+
built site still ships no sketch. No migration runs for the theme field
|
|
27
|
+
itself: a browser that already had sketch dials set reads them as off the
|
|
28
|
+
theme on its first boot after upgrading, and Save folds them into the open
|
|
29
|
+
theme like any other unsaved change.
|
|
30
|
+
- **The Theme Picker previews the sketch layer.** Picking a theme showed its
|
|
31
|
+
colors and type over whatever drawing the previously applied theme had left
|
|
32
|
+
painted, so two themes' looks were on screen at once, which is the one thing a
|
|
33
|
+
preview exists to prevent. A previewed theme now paints its own sketchstyle,
|
|
34
|
+
and one carrying none previews crisp whatever is live. Leaving the picker puts
|
|
35
|
+
back exactly what was there before, an unsaved dial included: the preview
|
|
36
|
+
paints without writing the live buffer, so browsing costs nothing and Cancel
|
|
37
|
+
reverts to the buffer rather than to a snapshot taken before it.
|
|
38
|
+
- **Sketchstyle, named as one thing.** "Sketch preset" is retired: the code,
|
|
39
|
+
the Theme panel row, the editor's fourth view and the on-disk directory all
|
|
40
|
+
say "sketchstyle" now. The saved-look directory moves from
|
|
41
|
+
`data/sketch-presets/` to `data/sketch-styles/`; `npx live-tokens migrate`
|
|
42
|
+
renames it (boot only warns on the old name, it does not refuse the tree).
|
|
43
|
+
|
|
44
|
+
## 0.62.0 — Editorial type reads as a pair
|
|
45
|
+
|
|
46
|
+
### Added
|
|
47
|
+
|
|
48
|
+
- **The editorial role has its own sizes.** The role shipped with a single
|
|
49
|
+
unsized bundle, so an editorial surface could only take the body size. It now
|
|
50
|
+
reads as a pair, matching body: `--editorial-md-*` and `--editorial-sm-*`,
|
|
51
|
+
both editable in the editor's Text Styles section beside the other styles, and
|
|
52
|
+
both carried by an `.editorial-md` / `.editorial-sm` class in `site.css`. Each
|
|
53
|
+
step mirrors its body counterpart apart from the family, so a project that
|
|
54
|
+
never repoints `--font-editorial` renders exactly as it did.
|
|
55
|
+
- **`Card` takes `variant="bare"`.** A card with no icon and no title dropped
|
|
56
|
+
its header silently, which read the same as a card whose title had gone
|
|
57
|
+
missing. `bare` says the headerless card is the intent; the frame and body
|
|
58
|
+
keep every token the default variant uses, so padding, stroke and fill stay
|
|
59
|
+
editable. A default-variant card with nothing to put in its header now warns
|
|
60
|
+
in dev.
|
|
61
|
+
- **Sketch mode reaches the component editor.** A component demo draws itself
|
|
62
|
+
the way the page will, sketch included, while the tab strips and property rows
|
|
63
|
+
around it stay chrome: they run on `--ui-*` tokens the layer knows nothing
|
|
64
|
+
about. The router hands the layer the root to paint, so a sketch style never
|
|
65
|
+
bleeds onto the editor's own routes.
|
|
66
|
+
|
|
67
|
+
### Changed (breaking)
|
|
68
|
+
|
|
69
|
+
- **`--editorial-*` is now `--editorial-md-*`.** The unsized bundle became the
|
|
70
|
+
medium step. A `breaking` tokens.css migration
|
|
71
|
+
(`2026-08-27-editorial-size-steps`) renames it and backfills both steps,
|
|
72
|
+
carrying any value already tuned. It never auto-applies: run
|
|
73
|
+
`npx live-tokens migrate`.
|
|
74
|
+
|
|
75
|
+
### Changed
|
|
76
|
+
|
|
77
|
+
- **Ink coverage is a levels control.** The dials read as a pile of unrelated
|
|
78
|
+
knobs because each one meant something different depending on the grain and
|
|
79
|
+
octave count under it. The field is now normalized to run black to white
|
|
80
|
+
whatever the noise beneath, so **Steps** flattens it into tones and **Output**
|
|
81
|
+
squeezes the whole of it into the range the ink covers, from palest to
|
|
82
|
+
densest. The field is squeezed into that gap, never clipped at it, so both
|
|
83
|
+
ends mean the same thing at every setting. The seven shipped presets are
|
|
84
|
+
retuned against the new response.
|
|
85
|
+
- **Menus and tooltips are drawn solid whatever the coverage dials say.** They
|
|
86
|
+
float over arbitrary page content, so a fill worn through in patches let the
|
|
87
|
+
page show through them and they stopped reading as a surface the pointer can
|
|
88
|
+
land on.
|
|
89
|
+
- **`SectionDivider` titles take no outline by default.** The three sizes each
|
|
90
|
+
carried a themed outline color, which drew a halo around every subsection
|
|
91
|
+
title on a page that never asked for one. All three default to transparent;
|
|
92
|
+
a theme that wants the halo sets the color.
|
|
93
|
+
|
|
94
|
+
### Fixed
|
|
95
|
+
|
|
96
|
+
- **Per-side padding no longer strands the base token.** `themed-padding`
|
|
97
|
+
emits `var(--x-side, <base>)` for each side, so a per-side token is an
|
|
98
|
+
override slot the editor fills when the user splits the padding. `Card` and
|
|
99
|
+
`SegmentedControl` declared sides that named a literal step instead, which
|
|
100
|
+
always beat that fallback and left the base inert: merging split padding back
|
|
101
|
+
to one value cleared the side aliases, the fallback never took over, and the
|
|
102
|
+
padding control moved nothing. Both now track their own base, and
|
|
103
|
+
`paddingBaseStaysLive` holds every component that uses `themed-padding` to
|
|
104
|
+
the same rule. `Card`'s header and body padding are symmetric as a result;
|
|
105
|
+
a theme that wants the asymmetry back sets the per-side aliases.
|
|
106
|
+
- **`ImageLightbox`'s tile fill stays on the closed tile.** The fill also
|
|
107
|
+
painted the opened stage, where it had nothing to do: the stage rides a
|
|
108
|
+
near-opaque overlay that already backs transparent art, so the fill only
|
|
109
|
+
showed as a slab of theme color in the gap the image's aspect left inside the
|
|
110
|
+
stage box. The open stage now takes no fill of its own, matching the tile
|
|
111
|
+
shadow, which already stopped at the same edge.
|
|
112
|
+
- **Sketch settings no longer accumulate a trace on `globalThis`.** Debug
|
|
113
|
+
instrumentation left in `sketchStore` pushed an entry onto an unbounded
|
|
114
|
+
global array on every settings write, every share and every cross-frame
|
|
115
|
+
adopt. It is gone.
|
|
116
|
+
|
|
3
117
|
## 0.61.0 — A surface says which way it leans
|
|
4
118
|
|
|
5
119
|
### Added
|
package/bin/migrate.mjs
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
// resolution, file IO, and reporting.
|
|
13
13
|
|
|
14
14
|
import { existsSync, readFileSync, writeFileSync } from 'node:fs';
|
|
15
|
-
import { dirname, join, relative, resolve } from 'node:path';
|
|
15
|
+
import { basename, dirname, join, relative, resolve } from 'node:path';
|
|
16
16
|
import { fileURLToPath } from 'node:url';
|
|
17
17
|
|
|
18
18
|
const pkgRoot = resolve(dirname(fileURLToPath(import.meta.url)), '..');
|
|
@@ -123,7 +123,11 @@ export function formatMigrateDataResult(result) {
|
|
|
123
123
|
const lines = [planned ? 'Data tree heal (planned):' : 'Data tree healed:'];
|
|
124
124
|
|
|
125
125
|
for (const { from, to } of result.renames) {
|
|
126
|
-
|
|
126
|
+
// Two unrelated renames share this list: the pre-0.48 layout swap, and
|
|
127
|
+
// `sketch-presets/` → `sketch-styles/`. Told apart by the destination
|
|
128
|
+
// name, since `LegacyRename` carries no reason of its own.
|
|
129
|
+
const reason = basename(to) === 'sketch-styles' ? 'sketchstyle rename' : '0.48 layout';
|
|
130
|
+
lines.push(` ${planned ? 'would move' : 'moved'} ${rel(from)} → ${rel(to)} (${reason})`);
|
|
127
131
|
}
|
|
128
132
|
for (const p of result.upgradedThemes) {
|
|
129
133
|
lines.push(` ${planned ? 'would carry' : 'carried'} ${rel(p)} by value (was a pre-v3 theme naming files)`);
|
|
@@ -270,7 +270,7 @@ function resolveDataDirs(opts = {}) {
|
|
|
270
270
|
colorsAndTypeDir: opts.colorsAndTypeDir ? import_path.default.resolve(opts.colorsAndTypeDir) : fileConfig.colorsAndTypeDir ? import_path.default.resolve(fileConfig.colorsAndTypeDir) : sub("colors-and-type"),
|
|
271
271
|
componentConfigsDir: opts.componentConfigsDir ? import_path.default.resolve(opts.componentConfigsDir) : fileConfig.componentConfigsDir ? import_path.default.resolve(fileConfig.componentConfigsDir) : sub("component-configs"),
|
|
272
272
|
themesDir: opts.themesDir ? import_path.default.resolve(opts.themesDir) : fileConfig.themesDir ? import_path.default.resolve(fileConfig.themesDir) : sub("themes"),
|
|
273
|
-
|
|
273
|
+
sketchStylesDir: sub("sketch-styles"),
|
|
274
274
|
legacyManifestsDir: fileConfig.manifestsDir ? import_path.default.resolve(fileConfig.manifestsDir) : void 0
|
|
275
275
|
};
|
|
276
276
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { A as AliasDiskValue, a as ComponentConfig } from '../themeTypes-DSV3Zisf.cjs';
|
|
2
|
-
export { r as readLiveTokensConfig, a as resolveDataDirs } from '../dataPaths-
|
|
2
|
+
export { r as readLiveTokensConfig, a as resolveDataDirs } from '../dataPaths-DZUzVv8H.cjs';
|
|
3
3
|
export { C as CURRENT_COMPONENT_SCHEMA_VERSION } from '../index-4N-Orzzi.cjs';
|
|
4
4
|
|
|
5
5
|
type AdjustKind = 'radius' | 'padding' | 'gap' | 'border-width';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { A as AliasDiskValue, a as ComponentConfig } from '../themeTypes-DSV3Zisf.js';
|
|
2
|
-
export { r as readLiveTokensConfig, a as resolveDataDirs } from '../dataPaths-
|
|
2
|
+
export { r as readLiveTokensConfig, a as resolveDataDirs } from '../dataPaths-DZUzVv8H.js';
|
|
3
3
|
export { C as CURRENT_COMPONENT_SCHEMA_VERSION } from '../index-4N-Orzzi.js';
|
|
4
4
|
|
|
5
5
|
type AdjustKind = 'radius' | 'padding' | 'gap' | 'border-width';
|
|
@@ -268,6 +268,340 @@ var KNOWN_COMPONENT_CONFIG_KEYS = /* @__PURE__ */ new Set([
|
|
|
268
268
|
"--sectiondivider-sm-color-family"
|
|
269
269
|
]);
|
|
270
270
|
|
|
271
|
+
// src/editor/core/sketch/sketchStyles.ts
|
|
272
|
+
var base = {
|
|
273
|
+
label: "",
|
|
274
|
+
blurb: "",
|
|
275
|
+
fillTravel: 1.5,
|
|
276
|
+
strokeTravel: 1.5,
|
|
277
|
+
wobble: 45,
|
|
278
|
+
roughness: 3,
|
|
279
|
+
borderWavelength: 1,
|
|
280
|
+
waveform: 1,
|
|
281
|
+
strokeWidth: 1.5,
|
|
282
|
+
doubleStroke: false,
|
|
283
|
+
retraceOffset: 1.2,
|
|
284
|
+
retracePass: "copy",
|
|
285
|
+
fillStyle: "solid",
|
|
286
|
+
hatchInk: 0.4,
|
|
287
|
+
strokeStyle: "solid",
|
|
288
|
+
pressure: 0.25,
|
|
289
|
+
pressureMod: 0.35,
|
|
290
|
+
pooling: 1.2,
|
|
291
|
+
strokeInk: 1,
|
|
292
|
+
maskOn: true,
|
|
293
|
+
maskBlob: 100,
|
|
294
|
+
maskOutputMin: 0.45,
|
|
295
|
+
maskOutputMax: 1,
|
|
296
|
+
maskOctaves: 2,
|
|
297
|
+
maskGrain: "fractal",
|
|
298
|
+
maskPosterize: 1,
|
|
299
|
+
maskSoftness: 1.5,
|
|
300
|
+
jitterX: 2.5,
|
|
301
|
+
jitterY: 2.5,
|
|
302
|
+
jitterRot: 0.6,
|
|
303
|
+
jitterScale: 0.035,
|
|
304
|
+
cornerSpread: 10,
|
|
305
|
+
cornerTravel: 8,
|
|
306
|
+
iconTravel: 1.25,
|
|
307
|
+
iconWavelength: 0.625,
|
|
308
|
+
iconMaskOn: true,
|
|
309
|
+
iconMaskScale: 1
|
|
310
|
+
};
|
|
311
|
+
var SKETCH_STYLES = {
|
|
312
|
+
pencil: {
|
|
313
|
+
...base,
|
|
314
|
+
label: "Pencil",
|
|
315
|
+
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.",
|
|
316
|
+
fillTravel: 0.75,
|
|
317
|
+
strokeTravel: 1.25,
|
|
318
|
+
wobble: 30,
|
|
319
|
+
roughness: 3,
|
|
320
|
+
waveform: 1,
|
|
321
|
+
strokeWidth: 1.25,
|
|
322
|
+
doubleStroke: true,
|
|
323
|
+
retracePass: "reseeded",
|
|
324
|
+
retraceOffset: 1.5,
|
|
325
|
+
strokeInk: 0.85,
|
|
326
|
+
maskBlob: 40,
|
|
327
|
+
maskOutputMin: 0.62,
|
|
328
|
+
maskOutputMax: 1,
|
|
329
|
+
maskOctaves: 3,
|
|
330
|
+
maskPosterize: 1,
|
|
331
|
+
maskSoftness: 0,
|
|
332
|
+
jitterX: 1.5,
|
|
333
|
+
jitterY: 1.5,
|
|
334
|
+
jitterRot: 0.35,
|
|
335
|
+
jitterScale: 0.022,
|
|
336
|
+
cornerSpread: 6,
|
|
337
|
+
cornerTravel: 4.5,
|
|
338
|
+
pressure: 0.15,
|
|
339
|
+
pressureMod: 0.3,
|
|
340
|
+
pooling: 0,
|
|
341
|
+
iconTravel: 0.75
|
|
342
|
+
},
|
|
343
|
+
marker: {
|
|
344
|
+
...base,
|
|
345
|
+
label: "Marker",
|
|
346
|
+
blurb: "Broad translucent nib gone round twice on the same line, so the overlap darkens and the ink pools where it slows.",
|
|
347
|
+
fillTravel: 2,
|
|
348
|
+
strokeTravel: 1.5,
|
|
349
|
+
wobble: 56,
|
|
350
|
+
waveform: 1.4,
|
|
351
|
+
borderWavelength: 1.3,
|
|
352
|
+
strokeWidth: 4,
|
|
353
|
+
doubleStroke: true,
|
|
354
|
+
retracePass: "copy",
|
|
355
|
+
strokeInk: 0.52,
|
|
356
|
+
retraceOffset: 2.2,
|
|
357
|
+
maskBlob: 115,
|
|
358
|
+
maskOutputMin: 0.42,
|
|
359
|
+
maskOutputMax: 1,
|
|
360
|
+
maskOctaves: 3,
|
|
361
|
+
maskPosterize: 4,
|
|
362
|
+
maskSoftness: 4,
|
|
363
|
+
jitterX: 3,
|
|
364
|
+
jitterY: 3,
|
|
365
|
+
jitterRot: 0.8,
|
|
366
|
+
jitterScale: 0.045,
|
|
367
|
+
cornerSpread: 10,
|
|
368
|
+
cornerTravel: 8,
|
|
369
|
+
pressure: 0.2,
|
|
370
|
+
pressureMod: 0.25,
|
|
371
|
+
pooling: 2,
|
|
372
|
+
iconTravel: 1.25,
|
|
373
|
+
iconMaskScale: 4
|
|
374
|
+
},
|
|
375
|
+
whiteboard: {
|
|
376
|
+
...base,
|
|
377
|
+
label: "Whiteboard",
|
|
378
|
+
blurb: "The fattest nib on glass. One long smooth undulation, and a veined mask that streaks the fill like a half-wiped board.",
|
|
379
|
+
fillTravel: 2.5,
|
|
380
|
+
strokeTravel: 2.5,
|
|
381
|
+
wobble: 90,
|
|
382
|
+
roughness: 1,
|
|
383
|
+
waveform: 1,
|
|
384
|
+
borderWavelength: 1.5,
|
|
385
|
+
strokeWidth: 5.5,
|
|
386
|
+
doubleStroke: true,
|
|
387
|
+
retracePass: "copy",
|
|
388
|
+
strokeInk: 0.66,
|
|
389
|
+
retraceOffset: 3,
|
|
390
|
+
maskGrain: "turbulence",
|
|
391
|
+
maskBlob: 180,
|
|
392
|
+
maskOutputMin: 0.42,
|
|
393
|
+
maskOutputMax: 1,
|
|
394
|
+
maskOctaves: 1,
|
|
395
|
+
maskPosterize: 3,
|
|
396
|
+
maskSoftness: 8,
|
|
397
|
+
jitterX: 4.5,
|
|
398
|
+
jitterY: 4.5,
|
|
399
|
+
jitterRot: 1.2,
|
|
400
|
+
jitterScale: 0.07,
|
|
401
|
+
cornerSpread: 14,
|
|
402
|
+
cornerTravel: 11,
|
|
403
|
+
pressure: 0.15,
|
|
404
|
+
pressureMod: 0.15,
|
|
405
|
+
pooling: 3.5,
|
|
406
|
+
iconTravel: 1.75,
|
|
407
|
+
iconMaskScale: 1.5
|
|
408
|
+
},
|
|
409
|
+
hatched: {
|
|
410
|
+
...base,
|
|
411
|
+
label: "Hatched",
|
|
412
|
+
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.",
|
|
413
|
+
fillTravel: 1.25,
|
|
414
|
+
strokeTravel: 1.5,
|
|
415
|
+
wobble: 24,
|
|
416
|
+
roughness: 3,
|
|
417
|
+
waveform: 3,
|
|
418
|
+
strokeWidth: 1.5,
|
|
419
|
+
fillStyle: "hatched",
|
|
420
|
+
hatchInk: 0.5,
|
|
421
|
+
doubleStroke: false,
|
|
422
|
+
maskOn: false,
|
|
423
|
+
iconMaskOn: false,
|
|
424
|
+
jitterX: 1.5,
|
|
425
|
+
jitterY: 1.5,
|
|
426
|
+
jitterRot: 0.4,
|
|
427
|
+
jitterScale: 0.03,
|
|
428
|
+
cornerSpread: 6,
|
|
429
|
+
cornerTravel: 6,
|
|
430
|
+
pressure: 0.3,
|
|
431
|
+
pressureMod: 0.45,
|
|
432
|
+
pooling: 0.8,
|
|
433
|
+
iconTravel: 1.25,
|
|
434
|
+
iconWavelength: 0.5
|
|
435
|
+
},
|
|
436
|
+
dashed: {
|
|
437
|
+
...base,
|
|
438
|
+
label: "Dashed",
|
|
439
|
+
blurb: "A drafting outline. One slow drift along the ruler, broken into strokes, with jitter, mask and pressure all off. The clean pole.",
|
|
440
|
+
strokeStyle: "dashed",
|
|
441
|
+
strokeTravel: 1,
|
|
442
|
+
fillTravel: 0.5,
|
|
443
|
+
wobble: 120,
|
|
444
|
+
roughness: 1,
|
|
445
|
+
waveform: 1,
|
|
446
|
+
strokeWidth: 1.5,
|
|
447
|
+
doubleStroke: false,
|
|
448
|
+
maskOn: false,
|
|
449
|
+
iconMaskOn: false,
|
|
450
|
+
jitterX: 0,
|
|
451
|
+
jitterY: 0,
|
|
452
|
+
jitterRot: 0,
|
|
453
|
+
jitterScale: 0,
|
|
454
|
+
cornerSpread: 4,
|
|
455
|
+
cornerTravel: 3,
|
|
456
|
+
pressure: 0,
|
|
457
|
+
pressureMod: 0,
|
|
458
|
+
pooling: 0,
|
|
459
|
+
iconTravel: 0
|
|
460
|
+
},
|
|
461
|
+
napkin: {
|
|
462
|
+
...base,
|
|
463
|
+
label: "Napkin",
|
|
464
|
+
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.",
|
|
465
|
+
fillTravel: 3,
|
|
466
|
+
strokeTravel: 2.25,
|
|
467
|
+
wobble: 50,
|
|
468
|
+
roughness: 3,
|
|
469
|
+
waveform: 2.5,
|
|
470
|
+
strokeWidth: 2.25,
|
|
471
|
+
doubleStroke: true,
|
|
472
|
+
retracePass: "reseeded",
|
|
473
|
+
retraceOffset: 4,
|
|
474
|
+
strokeInk: 1,
|
|
475
|
+
maskBlob: 150,
|
|
476
|
+
maskOutputMin: 0.43,
|
|
477
|
+
maskOutputMax: 0.95,
|
|
478
|
+
maskOctaves: 2,
|
|
479
|
+
maskPosterize: 2,
|
|
480
|
+
maskSoftness: 10,
|
|
481
|
+
jitterX: 6,
|
|
482
|
+
jitterY: 6,
|
|
483
|
+
jitterRot: 1.8,
|
|
484
|
+
jitterScale: 0.1,
|
|
485
|
+
cornerSpread: 20,
|
|
486
|
+
cornerTravel: 17,
|
|
487
|
+
pressure: 0.45,
|
|
488
|
+
pressureMod: 0.6,
|
|
489
|
+
pooling: 2.5,
|
|
490
|
+
iconTravel: 2.25,
|
|
491
|
+
iconMaskScale: 3.6
|
|
492
|
+
},
|
|
493
|
+
dry: {
|
|
494
|
+
...base,
|
|
495
|
+
label: "Dry marker",
|
|
496
|
+
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.",
|
|
497
|
+
fillTravel: 2.25,
|
|
498
|
+
strokeTravel: 1.75,
|
|
499
|
+
wobble: 50,
|
|
500
|
+
waveform: 2,
|
|
501
|
+
borderWavelength: 0.5,
|
|
502
|
+
strokeWidth: 3.5,
|
|
503
|
+
doubleStroke: false,
|
|
504
|
+
strokeInk: 0.4,
|
|
505
|
+
maskBlob: 150,
|
|
506
|
+
maskOutputMin: 0.24,
|
|
507
|
+
maskOutputMax: 0.91,
|
|
508
|
+
maskOctaves: 2,
|
|
509
|
+
maskPosterize: 4,
|
|
510
|
+
maskSoftness: 1.75,
|
|
511
|
+
jitterX: 5,
|
|
512
|
+
jitterY: 5,
|
|
513
|
+
jitterRot: 1.4,
|
|
514
|
+
jitterScale: 0.08,
|
|
515
|
+
cornerSpread: 16,
|
|
516
|
+
cornerTravel: 13,
|
|
517
|
+
pressure: 0.4,
|
|
518
|
+
pressureMod: 0.8,
|
|
519
|
+
pooling: 1.5,
|
|
520
|
+
iconTravel: 1.75,
|
|
521
|
+
iconMaskScale: 3.8
|
|
522
|
+
}
|
|
523
|
+
};
|
|
524
|
+
var DEFAULT_SKETCH_STYLE = "marker";
|
|
525
|
+
function hydrateSketchStyle(raw) {
|
|
526
|
+
const base2 = SKETCH_STYLES[DEFAULT_SKETCH_STYLE];
|
|
527
|
+
const stored = raw ?? {};
|
|
528
|
+
const out = { ...base2 };
|
|
529
|
+
for (const key of Object.keys(base2)) {
|
|
530
|
+
if (stored[key] !== void 0) out[key] = stored[key];
|
|
531
|
+
}
|
|
532
|
+
if (out.fillStyle === "none") out.fillStyle = base2.fillStyle;
|
|
533
|
+
convertTiledMask(stored, out);
|
|
534
|
+
convertCutToLevels(stored, out);
|
|
535
|
+
carryLevelsToOutput(stored, out);
|
|
536
|
+
halveSwingDials(stored, out);
|
|
537
|
+
convertCyclesToWavelength(stored, out);
|
|
538
|
+
convertIconTileToScale(stored, out);
|
|
539
|
+
restoreDerivedRetrace(stored, out);
|
|
540
|
+
return out;
|
|
541
|
+
}
|
|
542
|
+
function restoreDerivedRetrace(stored, out) {
|
|
543
|
+
if (stored.retraceOffset === void 0) {
|
|
544
|
+
out.retraceOffset = Number(Math.max(1.2, out.strokeWidth * 0.55).toFixed(2));
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
var SWING_DIALS = {
|
|
548
|
+
fillScale: "fillTravel",
|
|
549
|
+
strokeScale: "strokeTravel",
|
|
550
|
+
iconScale: "iconTravel",
|
|
551
|
+
cornerShift: "cornerTravel"
|
|
552
|
+
};
|
|
553
|
+
function convertCyclesToWavelength(stored, out) {
|
|
554
|
+
const cycles = stored.frequency;
|
|
555
|
+
if (typeof cycles === "number" && cycles > 0) out.wobble = Math.round(1 / cycles);
|
|
556
|
+
for (const [legacy, key] of [
|
|
557
|
+
["borderFrequency", "borderWavelength"],
|
|
558
|
+
["iconFrequency", "iconWavelength"]
|
|
559
|
+
]) {
|
|
560
|
+
const multiple = stored[legacy];
|
|
561
|
+
if (typeof multiple === "number" && multiple > 0) {
|
|
562
|
+
out[key] = Number((1 / multiple).toFixed(3));
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
const layers = stored.octaves;
|
|
566
|
+
if (typeof layers === "number") out.roughness = Math.min(3, Math.max(1, layers));
|
|
567
|
+
}
|
|
568
|
+
function convertIconTileToScale(stored, out) {
|
|
569
|
+
const tile = stored.iconMaskTile;
|
|
570
|
+
if (typeof tile !== "number") return;
|
|
571
|
+
out.iconMaskScale = Math.min(5, Math.max(0.5, Number((tile / 90).toFixed(2))));
|
|
572
|
+
}
|
|
573
|
+
function halveSwingDials(stored, out) {
|
|
574
|
+
for (const [legacy, key] of Object.entries(SWING_DIALS)) {
|
|
575
|
+
const value = stored[legacy];
|
|
576
|
+
if (typeof value === "number") out[key] = value / 2;
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
function convertTiledMask(stored, out) {
|
|
580
|
+
const scale = stored.maskScale;
|
|
581
|
+
if (typeof scale !== "number") return;
|
|
582
|
+
const freq = stored.maskFrequency;
|
|
583
|
+
if (typeof freq === "number") out.maskBlob = Math.round(scale / (freq * LEGACY_TILE));
|
|
584
|
+
const soft = stored.maskSoftness;
|
|
585
|
+
if (typeof soft === "number") out.maskSoftness = Number((soft * scale / LEGACY_TILE).toFixed(1));
|
|
586
|
+
}
|
|
587
|
+
function convertCutToLevels(stored, out) {
|
|
588
|
+
const contrast = stored.maskContrast;
|
|
589
|
+
const coverage = stored.maskCoverage;
|
|
590
|
+
if (typeof contrast !== "number" || typeof coverage !== "number") return;
|
|
591
|
+
const veined = out.maskGrain === "turbulence";
|
|
592
|
+
const [lo, hi] = veined ? LEGACY_RANGE.turbulence : LEGACY_RANGE.fractal;
|
|
593
|
+
const pivot = veined ? 0.55 - 0.5 * coverage : 0.8 - 0.6 * coverage;
|
|
594
|
+
const level = (raw) => Math.min(1, Math.max(0, (raw - lo) / (hi - lo)));
|
|
595
|
+
out.maskOutputMin = Number(level(pivot - 0.5 / contrast).toFixed(2));
|
|
596
|
+
out.maskOutputMax = Number(Math.max(out.maskOutputMin + 0.02, level(pivot + 0.5 / contrast)).toFixed(2));
|
|
597
|
+
}
|
|
598
|
+
function carryLevelsToOutput(stored, out) {
|
|
599
|
+
if (typeof stored.maskLevelMin === "number") out.maskOutputMin = stored.maskLevelMin;
|
|
600
|
+
if (typeof stored.maskLevelMax === "number") out.maskOutputMax = stored.maskLevelMax;
|
|
601
|
+
}
|
|
602
|
+
var LEGACY_RANGE = { fractal: [0.24, 0.77], turbulence: [0.02, 0.6] };
|
|
603
|
+
var LEGACY_TILE = 600;
|
|
604
|
+
|
|
271
605
|
// vite-plugin/themes/normalizeTheme.ts
|
|
272
606
|
function asObject(value) {
|
|
273
607
|
return value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
@@ -359,12 +693,12 @@ function normalizeTheme(raw, resolvers) {
|
|
|
359
693
|
}
|
|
360
694
|
const filled = { components: [], aliases: 0, orphans: 0 };
|
|
361
695
|
for (const comp of resolvers.listComponentNames()) {
|
|
362
|
-
const
|
|
363
|
-
const baseAliases =
|
|
364
|
-
if (!
|
|
696
|
+
const base2 = asObject(resolvers.readComponentConfig(comp, "default"));
|
|
697
|
+
const baseAliases = base2 ? asObject(base2.aliases) : null;
|
|
698
|
+
if (!base2 || !baseAliases) continue;
|
|
365
699
|
const entry = componentConfigs[comp];
|
|
366
700
|
if (!entry) {
|
|
367
|
-
const { schemaVersion: _standaloneStamp, ...rest } = stripFileMarker(
|
|
701
|
+
const { schemaVersion: _standaloneStamp, ...rest } = stripFileMarker(base2);
|
|
368
702
|
componentConfigs[comp] = structuredClone(rest);
|
|
369
703
|
filled.components.push(comp);
|
|
370
704
|
continue;
|
|
@@ -380,6 +714,8 @@ function normalizeTheme(raw, resolvers) {
|
|
|
380
714
|
if (!(key in baseAliases)) filled.orphans++;
|
|
381
715
|
}
|
|
382
716
|
}
|
|
717
|
+
const embeddedSketchStyle = asObject(src.sketchStyle);
|
|
718
|
+
const sketchStyle = embeddedSketchStyle ? hydrateSketchStyle(embeddedSketchStyle) : void 0;
|
|
383
719
|
return {
|
|
384
720
|
theme: {
|
|
385
721
|
name: asString(src.name, "Untitled"),
|
|
@@ -388,7 +724,8 @@ function normalizeTheme(raw, resolvers) {
|
|
|
388
724
|
schemaVersion: THEME_SCHEMA_VERSION,
|
|
389
725
|
colorsAndType,
|
|
390
726
|
componentConfigs,
|
|
391
|
-
componentSchemaVersion: CURRENT_COMPONENT_SCHEMA_VERSION
|
|
727
|
+
componentSchemaVersion: CURRENT_COMPONENT_SCHEMA_VERSION,
|
|
728
|
+
...sketchStyle ? { sketchStyle } : {}
|
|
392
729
|
},
|
|
393
730
|
dropped,
|
|
394
731
|
migrated,
|
|
@@ -42,7 +42,7 @@ function resolveDataDirs(opts = {}) {
|
|
|
42
42
|
colorsAndTypeDir: opts.colorsAndTypeDir ? path.resolve(opts.colorsAndTypeDir) : fileConfig.colorsAndTypeDir ? path.resolve(fileConfig.colorsAndTypeDir) : sub("colors-and-type"),
|
|
43
43
|
componentConfigsDir: opts.componentConfigsDir ? path.resolve(opts.componentConfigsDir) : fileConfig.componentConfigsDir ? path.resolve(fileConfig.componentConfigsDir) : sub("component-configs"),
|
|
44
44
|
themesDir: opts.themesDir ? path.resolve(opts.themesDir) : fileConfig.themesDir ? path.resolve(fileConfig.themesDir) : sub("themes"),
|
|
45
|
-
|
|
45
|
+
sketchStylesDir: sub("sketch-styles"),
|
|
46
46
|
legacyManifestsDir: fileConfig.manifestsDir ? path.resolve(fileConfig.manifestsDir) : void 0
|
|
47
47
|
};
|
|
48
48
|
}
|