@motion-proto/live-tokens 0.67.0 → 0.68.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/CHANGELOG.md +54 -0
  2. package/README.md +67 -9
  3. package/bin/generate-theme.mjs +5 -4
  4. package/dist-plugin/adjust/index.d.cts +1 -1
  5. package/dist-plugin/adjust/index.d.ts +1 -1
  6. package/dist-plugin/{chunk-T4PMCFJN.js → chunk-2UX6EVVA.js} +30 -30
  7. package/dist-plugin/{dataPaths-DZUzVv8H.d.cts → dataPaths-bJTCEO4H.d.cts} +1 -1
  8. package/dist-plugin/{dataPaths-DZUzVv8H.d.ts → dataPaths-bJTCEO4H.d.ts} +1 -1
  9. package/dist-plugin/fontPairing/index.d.cts +1 -1
  10. package/dist-plugin/fontPairing/index.d.ts +1 -1
  11. package/dist-plugin/generateColorsAndType/index.d.cts +1 -1
  12. package/dist-plugin/generateColorsAndType/index.d.ts +1 -1
  13. package/dist-plugin/index.cjs +32 -32
  14. package/dist-plugin/index.d.cts +1 -1
  15. package/dist-plugin/index.d.ts +1 -1
  16. package/dist-plugin/index.js +5 -5
  17. package/dist-plugin/migrateData/index.cjs +30 -30
  18. package/dist-plugin/migrateData/index.d.cts +1 -1
  19. package/dist-plugin/migrateData/index.d.ts +1 -1
  20. package/dist-plugin/migrateData/index.js +1 -1
  21. package/dist-plugin/tokensCssMigrations/index.d.cts +1 -1
  22. package/dist-plugin/tokensCssMigrations/index.d.ts +1 -1
  23. package/package.json +4 -4
  24. package/src/editor/bootstrap.ts +6 -6
  25. package/src/editor/component-editor/ImageLightboxEditor.svelte +1 -1
  26. package/src/editor/component-editor/scaffolding/ComponentFileManager.svelte +4 -4
  27. package/src/editor/core/fonts/fontLoader.ts +2 -2
  28. package/src/editor/core/preview/{lookPreview.ts → themePreview.ts} +27 -27
  29. package/src/editor/core/productionPulse.ts +3 -3
  30. package/src/editor/core/sketch/index.ts +52 -44
  31. package/src/editor/core/sketch/maskField.ts +9 -9
  32. package/src/editor/core/sketch/sketchLayer.ts +9 -9
  33. package/src/editor/core/sketch/sketchRegistry.ts +34 -34
  34. package/src/editor/core/sketch/sketchStore.ts +98 -83
  35. package/src/editor/core/sketch/sketchStyleService.ts +4 -4
  36. package/src/editor/core/sketch/sketchStyles.ts +28 -28
  37. package/src/editor/core/themes/colorsAndTypeService.ts +1 -1
  38. package/src/editor/core/themes/loadRows.ts +8 -8
  39. package/src/editor/core/themes/themeDocumentSync.ts +2 -2
  40. package/src/editor/core/themes/themeInit.ts +2 -2
  41. package/src/editor/core/themes/themeService.ts +17 -17
  42. package/src/editor/core/themes/{lookSummary.ts → themeSummary.ts} +9 -9
  43. package/src/editor/core/themes/themeTypes.ts +10 -6
  44. package/src/editor/docs/content/getting-started.md +1 -1
  45. package/src/editor/docs/content/sketch-mode.md +22 -17
  46. package/src/editor/docs/content/themes-workflow.md +11 -11
  47. package/src/editor/docs/content/where-themes-live.md +6 -6
  48. package/src/editor/docs/content.generated.ts +4 -4
  49. package/src/editor/index.ts +2 -2
  50. package/src/editor/ui/ThemePanel.svelte +52 -52
  51. package/src/editor/ui/sketch/SketchPreview.svelte +2 -2
  52. package/src/editor/ui/sketch/SketchTab.svelte +64 -38
  53. package/src/live-tokens/data/sketch-styles/dry.json +5 -5
  54. package/src/live-tokens/data/sketch-styles/hatched.json +9 -9
  55. package/src/live-tokens/data/sketch-styles/napkin.json +4 -4
  56. package/src/live-tokens/data/sketch-styles/pencil.json +2 -2
  57. package/src/live-tokens/data/themes/autumn.json +1 -1
  58. package/src/live-tokens/data/themes/halloween.json +1 -1
  59. package/src/live-tokens/data/themes/midnight-study.json +1 -1
  60. package/src/live-tokens/data/themes/ocean.json +1 -1
  61. package/src/live-tokens/data/themes/royal-velvet.json +1 -1
  62. package/src/live-tokens/data/themes/sketchy.json +1 -1
  63. package/src/live-tokens/data/themes/spring-meadow.json +1 -1
  64. package/src/live-tokens/data/themes/sunset.json +1 -1
  65. package/src/system/backdrop/backdrop.ts +1 -1
  66. package/src/system/components/SectionDivider.svelte +1 -1
@@ -1,70 +1,78 @@
1
1
  import { derived, get, type Readable } from 'svelte/store';
2
2
  import { THEME_SKETCH_ID } from './sketchStyles';
3
- import { lookById, sketchLooks, type SketchLook } from './sketchRegistry';
3
+ import { sketchStyleById, sketchStyles, type SketchStyle } from './sketchRegistry';
4
4
  import {
5
- sameLook,
5
+ sameSketchStyle,
6
6
  selectSketchStyle,
7
- selectThemeSketchStyle,
7
+ selectUnsavedSketchStyle,
8
8
  setSketchEnabled,
9
9
  sketchEnabled,
10
- sketchStyleName,
11
- themeSketchStyle,
10
+ selectedSketchStyleId,
11
+ themeSketchSettings,
12
12
  } from './sketchStore';
13
13
 
14
- export { sketchLooks, registerSketchLook } from './sketchRegistry';
15
- export type { SketchLook, SketchLookSource, RegisterSketchLookInput } from './sketchRegistry';
14
+ export { sketchStyles, registerSketchStyle } from './sketchRegistry';
15
+ export type { SketchStyle, SketchStyleSource, RegisterSketchStyleInput } from './sketchRegistry';
16
16
 
17
- /** A look as one picker row. The theme's own look is offered this way too, and
17
+ /** A style as one picker row. The theme's own style is offered this way too, and
18
18
  it belongs to no pool entry, so the fields only a pool entry has are off. */
19
- export type SketchLookRow = Omit<SketchLook, 'settings' | 'source'>;
19
+ export type SketchStyleRow = Omit<SketchStyle, 'settings' | 'source'>;
20
20
 
21
21
  /**
22
- * The look the open theme carries, as one more row for a picker: same shape as
23
- * a shipped look, and `setSketch` takes its id like any other. Null when the
24
- * theme carries no sketchstyle, and null when what it carries IS one of the
25
- * shipped looks, since that look's own row already names it.
22
+ * Sketch settings the open theme carries that no sketchstyle file holds, as one
23
+ * more row for a picker: same shape as a shipped sketchstyle, and `setSketch`
24
+ * takes its id like any other. Null when the theme carries no settings, and
25
+ * null when what it carries matches a sketchstyle, since that file's own row
26
+ * already names it.
26
27
  *
27
- * Without this row the theme's look is a one-way door: a visitor lands on it,
28
- * picks Pencil, and nothing can take them back. It is also the only thing that
29
- * can name that look, which no shipped label can do honestly. A theme tuned off
30
- * `marker` still carries the label "Marker", so a row built from the style's
31
- * own label would sit beside the shipped Marker claiming to be it.
28
+ * A theme embeds its sketch settings by value, so it can hold a set that
29
+ * belongs to no file: Save As is what turns one into a sketchstyle. Until then
30
+ * this is the only row that can offer it. Without it the settings are a one-way
31
+ * door, a visitor picks Pencil and nothing can take them back.
32
+ *
33
+ * Labelled "Unsaved" rather than by the settings' own label, which lies: a theme
34
+ * tuned off `marker` still carries the label "Marker", so a row built from it
35
+ * would sit beside the shipped Marker claiming to be it.
32
36
  */
33
- export const themeSketchLook: Readable<SketchLookRow | null> = derived(
34
- [themeSketchStyle, sketchLooks],
35
- ([style, looks]) => {
36
- if (!style) return null;
37
- if (looks.some((look) => sameLook(look.settings, style))) return null;
38
- return { id: THEME_SKETCH_ID, label: 'Theme', blurb: 'The look this theme carries.' };
37
+ export const unsavedSketchStyle: Readable<SketchStyleRow | null> = derived(
38
+ [themeSketchSettings, sketchStyles],
39
+ ([settings, styles]) => {
40
+ if (!settings) return null;
41
+ if (styles.some((style) => sameSketchStyle(style.settings, settings))) return null;
42
+ return {
43
+ id: THEME_SKETCH_ID,
44
+ label: 'Unsaved',
45
+ blurb: 'Sketch settings this theme carries that no sketchstyle holds.',
46
+ };
39
47
  },
40
48
  );
41
49
 
42
50
  /**
43
51
  * What the page is drawing with. Three states, not two: the effect can be on
44
- * under a look no shipped sketchstyle names — one saved to a file, or one a
52
+ * under a style no shipped sketchstyle names — one saved to a file, or one a
45
53
  * theme carried — and a picker that collapses that into `off` tells the
46
54
  * visitor the page is crisp while it is visibly drawn.
47
55
  *
48
- * A dial moved off a shipped look keeps naming it, which is `selectSketchStyle`'s
49
- * own rule: the pick says where the look came from, and `sketchDirty` says it
56
+ * A dial moved off a shipped style keeps naming it, which is `selectSketchStyle`'s
57
+ * own rule: the pick says where the style came from, and `sketchDirty` says it
50
58
  * has since drifted.
51
59
  */
52
60
  export type SketchPick =
53
61
  | { state: 'off' }
54
- | { state: 'look'; look: SketchLookRow }
62
+ | { state: 'style'; style: SketchStyleRow }
55
63
  | { state: 'adjusted' };
56
64
 
57
65
  export const sketchPick: Readable<SketchPick> = derived(
58
- [sketchEnabled, sketchStyleName, sketchLooks, themeSketchLook],
59
- ([on, name, looks, themeLook]): SketchPick => {
66
+ [sketchEnabled, selectedSketchStyleId, sketchStyles, unsavedSketchStyle],
67
+ ([on, name, styles, unsaved]): SketchPick => {
60
68
  if (!on) return { state: 'off' };
61
- const look = looks.find((l) => l.id === name) ?? (themeLook?.id === name ? themeLook : undefined);
62
- return look ? { state: 'look', look: { id: look.id, label: look.label, blurb: look.blurb } } : { state: 'adjusted' };
69
+ const style = styles.find((s) => s.id === name) ?? (unsaved?.id === name ? unsaved : undefined);
70
+ return style ? { state: 'style', style: { id: style.id, label: style.label, blurb: style.blurb } } : { state: 'adjusted' };
63
71
  },
64
72
  );
65
73
 
66
74
  /**
67
- * Draw the page with one of the looks in the pool, or `null` for none.
75
+ * Draw the page with one of the styles in the pool, or `null` for none.
68
76
  *
69
77
  * The only supported way for a consumer to drive the effect. Reaching for
70
78
  * `applySketchLayer` instead paints a stylesheet the store does not know it
@@ -77,15 +85,15 @@ export function setSketch(id: string | null): void {
77
85
  return;
78
86
  }
79
87
  if (id === THEME_SKETCH_ID) {
80
- if (!get(themeSketchStyle)) {
81
- throw new Error('No theme sketchstyle to draw with. `themeSketchLook` is null unless a theme carries one.');
88
+ if (!get(themeSketchSettings)) {
89
+ throw new Error('No theme sketchstyle to draw with. `unsavedSketchStyle` is null unless a theme carries one.');
82
90
  }
83
- selectThemeSketchStyle();
91
+ selectUnsavedSketchStyle();
84
92
  setSketchEnabled(true);
85
93
  return;
86
94
  }
87
- if (!lookById(id)) {
88
- throw new Error(`Unknown sketchstyle "${id}". Ids come from sketchLooks and themeSketchLook.`);
95
+ if (!sketchStyleById(id)) {
96
+ throw new Error(`Unknown sketchstyle "${id}". Ids come from sketchStyles and unsavedSketchStyle.`);
89
97
  }
90
98
  selectSketchStyle(id);
91
99
  setSketchEnabled(true);
@@ -106,22 +114,22 @@ export { hasPersistedSketchState } from './sketchStore';
106
114
  * already decided for itself.
107
115
  *
108
116
  * The route from a saved theme to a built page. Hand it the theme's
109
- * `sketchStyle` field, raw: a built site has no theme API, so it reads its own
117
+ * `sketchSettings` field, raw: a built site has no theme API, so it reads its own
110
118
  * theme JSON and this hydrates what it finds. Absent, `null`, or anything that
111
119
  * is not an object all mean the same thing, which is no sketch.
112
120
  *
113
121
  * Call it before mounting, the way dev boot does (`bootstrap.ts` awaits
114
- * `initializeTheme` first), so the look is up on the first frame rather than
122
+ * `initializeTheme` first), so the style is up on the first frame rather than
115
123
  * arriving over a crisp page.
116
124
  *
117
125
  * A visitor who has recorded a pick of their own keeps it, None included: this
118
126
  * seeds an undecided browser and never overwrites a decided one, so it is safe
119
- * to call on every boot. `themeSketchLook` is populated either way, so a picker
120
- * can offer the theme's look as a row whether or not this painted it.
127
+ * to call on every boot. `unsavedSketchStyle` is populated either way, so a picker
128
+ * can offer the theme's style as a row whether or not this painted it.
121
129
  */
122
130
  export { seedSketchFromTheme } from './sketchStore';
123
131
 
124
- /** The dial set a theme's `sketchStyle` field holds, for a consumer typing the
132
+ /** The dial set a theme's `sketchSettings` field holds, for a consumer typing the
125
133
  value it pulled out of its own theme JSON. `seedSketchFromTheme` takes it
126
134
  raw, so nothing has to be cast to hand it over. */
127
- export type { SketchStyle } from './sketchStyles';
135
+ export type { SketchStyleSettings } from './sketchStyles';
@@ -19,7 +19,7 @@
19
19
  * Everything is integer maths on a Float32Array with no DOM, so what a test
20
20
  * asserts is what the browser paints.
21
21
  */
22
- import type { SketchStyle } from './sketchStyles';
22
+ import type { SketchStyleSettings } from './sketchStyles';
23
23
 
24
24
  /** Samples across the tile, on both axes. Fixed, whatever the blobs measure:
25
25
  the field is blobs and gradients, so the browser stretching the tile back to
@@ -69,7 +69,7 @@ export interface MaskLattice {
69
69
  angle: number;
70
70
  }
71
71
 
72
- export function maskLattice(s: SketchStyle): MaskLattice {
72
+ export function maskLattice(s: SketchStyleSettings): MaskLattice {
73
73
  const ask = s.maskBlobX === s.maskBlobY ? 0 : s.maskAngle;
74
74
  const rad = ask * (Math.PI / 180);
75
75
  const cos = Math.cos(rad), sin = Math.sin(rad);
@@ -78,7 +78,7 @@ export function maskLattice(s: SketchStyle): MaskLattice {
78
78
  const vx = fit(dx, ask, (v) => turnOf(-v[1] * s.maskBlobY, v[0] * s.maskBlobX));
79
79
  let vy = fit(dy, ask, (v) => turnOf(v[0] * s.maskBlobX, v[1] * s.maskBlobY));
80
80
  // Two vectors along one line describe no tile at all. The turn of the first
81
- // is the whole look, so the second is the one that gives way.
81
+ // fixes the tile, so the second is the one that gives way.
82
82
  if (vx[0] * vy[1] - vx[1] * vy[0] === 0) vy = [-vx[1], vx[0]];
83
83
  return {
84
84
  vx,
@@ -131,7 +131,7 @@ function fit(d: Vec, ask: number, turn: (v: Vec) => number): Vec {
131
131
  * fitted to it, which meant the dial could only reach the sizes that divide
132
132
  * 600: it said 250px and painted 300px, and there was nothing above that.
133
133
  */
134
- export function maskTile(s: SketchStyle): { w: number; h: number } {
134
+ export function maskTile(s: SketchStyleSettings): { w: number; h: number } {
135
135
  const { w, h } = maskLattice(s);
136
136
  return { w, h };
137
137
  }
@@ -228,11 +228,11 @@ function makePerlin(seed: number): (x: number, y: number, w: Wrap) => number {
228
228
  * the one before, stretched onto its own measured range.
229
229
  *
230
230
  * `veined` folds each octave at zero before summing. The fold puts a crease
231
- * wherever the octave crossed zero, which is the marbled look; plain sum is
231
+ * wherever the octave crossed zero, which is the marbled effect; plain sum is
232
232
  * cloud.
233
233
  */
234
234
  function rawField(
235
- s: SketchStyle, seed: number, raster: number, lattice: MaskLattice,
235
+ s: SketchStyleSettings, seed: number, raster: number, lattice: MaskLattice,
236
236
  ): Float32Array {
237
237
  const noise = makePerlin(seed);
238
238
  const veined = s.maskGrain === 'turbulence';
@@ -388,7 +388,7 @@ function boxPass(f: Float32Array, n: number, radius: number, stride: number): Fl
388
388
  all four; the levels, the posterising and the blur are one pass each. */
389
389
  let rawCache: { key: string; field: Float32Array } | null = null;
390
390
 
391
- function cachedRaw(s: SketchStyle, seed: number): Float32Array {
391
+ function cachedRaw(s: SketchStyleSettings, seed: number): Float32Array {
392
392
  const lattice = maskLattice(s);
393
393
  // Keyed on the tile vectors rather than the blob sizes: most of the Scale
394
394
  // dial's travel paints the same lattice at another size, and the field is
@@ -407,7 +407,7 @@ function cachedRaw(s: SketchStyle, seed: number): Float32Array {
407
407
  * pass did.
408
408
  */
409
409
  export function buildMaskField(
410
- s: SketchStyle, seed = 9, through?: MaskStage,
410
+ s: SketchStyleSettings, seed = 9, through?: MaskStage,
411
411
  ): { field: Float32Array; raster: number } {
412
412
  const raw = cachedRaw(s, seed);
413
413
  if (through === 'noise') return { field: raw, raster: RASTER };
@@ -544,7 +544,7 @@ const CACHE_MAX = 6;
544
544
  const cache = new Map<string, string>();
545
545
 
546
546
  /** The field as a `url(...)` for `mask-image`. */
547
- export function buildMaskUri(s: SketchStyle, seed = 9, through?: MaskStage): string {
547
+ export function buildMaskUri(s: SketchStyleSettings, seed = 9, through?: MaskStage): string {
548
548
  const key = [...KEYS.map((k) => s[k]), seed, through ?? 'all'].join('|');
549
549
  const hit = cache.get(key);
550
550
  if (hit) return hit;
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Sketch effect layer.
3
3
  *
4
- * Builds an SVG filter bank and a stylesheet from one SketchStyle and
4
+ * Builds an SVG filter bank and a stylesheet from one SketchStyleSettings and
5
5
  * injects both into every document cssVarSync tracks, so the host page behind
6
6
  * the overlay iframe gets the same effect the editor's preview shows.
7
7
  *
@@ -16,7 +16,7 @@
16
16
  */
17
17
  import { getSyncedDocuments } from '../cssVarSync';
18
18
  import { buildMaskUri, maskTile } from './maskField';
19
- import type { SketchStyle } from './sketchStyles';
19
+ import type { SketchStyleSettings } from './sketchStyles';
20
20
 
21
21
  const DEFS_ATTR = 'data-sketch-defs';
22
22
  const STYLE_ATTR = 'data-sketch-style';
@@ -325,7 +325,7 @@ const UNCLIPPED = PART_SPECS.filter((p) => !p.clips).map((p) => p.sel).join(', '
325
325
  const CLIPPED = PART_SPECS.filter((p) => p.clips).map((p) => p.sel).join(', ');
326
326
  const UNMASKED = PART_SPECS.filter((p) => p.unmasked).map((p) => p.sel).join(', ');
327
327
 
328
- export function buildDefsMarkup(s: SketchStyle): string {
328
+ export function buildDefsMarkup(s: SketchStyleSettings): string {
329
329
  /**
330
330
  * `warp` is the shape stage: one wave of noise whose wavelength spans a whole
331
331
  * component, so the four corners sample different parts of the field and the
@@ -559,7 +559,7 @@ const MASK_POS = ['0 0', '-137px -211px', '-311px -97px', '-73px -389px', '-419p
559
559
  * A hand holds a rough size and misses it by a bit each time, so half to full
560
560
  * is the shape of the error. The four land in a different order row to row.
561
561
  *
562
- * Added, never subtracted, because a hand-drawn look tends to sit on a theme
562
+ * Added, never subtracted, because a hand-drawn line tends to sit on a theme
563
563
  * whose corners are already tight: a coefficient set that swung both ways
564
564
  * spent half its range clamped at zero.
565
565
  */
@@ -584,7 +584,7 @@ const swing = (travel: number) => String(Number((travel * 2).toFixed(4)));
584
584
  /** Squares the displacement wave off around 0.5, its zero, so full amplitude is
585
585
  spent along the whole edge rather than only where the wave peaks. Both
586
586
  channels take it: the map reads x from R and y from G. */
587
- function squareOff(s: SketchStyle, from: string, to: string): string {
587
+ function squareOff(s: SketchStyleSettings, from: string, to: string): string {
588
588
  if (s.waveform <= 1) return '';
589
589
  const slope = s.waveform.toFixed(2);
590
590
  const intercept = ((1 - s.waveform) / 2).toFixed(3);
@@ -594,7 +594,7 @@ function squareOff(s: SketchStyle, from: string, to: string): string {
594
594
  `</feComponentTransfer>`;
595
595
  }
596
596
 
597
- const squaredResult = (s: SketchStyle, from: string, to: string) =>
597
+ const squaredResult = (s: SketchStyleSettings, from: string, to: string) =>
598
598
  (s.waveform > 1 ? to : from);
599
599
 
600
600
  /** Along-stroke pressure wavelength. Low, with a high floor in the transfer
@@ -650,7 +650,7 @@ const RETRACE_SEED = 53;
650
650
  const WARP_FREQUENCY = 0.08;
651
651
 
652
652
 
653
- export function buildStylesheet(s: SketchStyle): string {
653
+ export function buildStylesheet(s: SketchStyleSettings): string {
654
654
  const on = '[data-sketch]';
655
655
  const parts = `:is(${PARTS})`;
656
656
  const el = `${on} ${parts}`;
@@ -1089,7 +1089,7 @@ function defsNode(doc: Document): SVGSVGElement {
1089
1089
  * This only makes the effect *available*. An element opts in by carrying
1090
1090
  * data-sketch, which is what `setSketchScope` writes.
1091
1091
  */
1092
- export function applySketchLayer(settings: SketchStyle): void {
1092
+ export function applySketchLayer(settings: SketchStyleSettings): void {
1093
1093
  const defs = buildDefsMarkup(settings);
1094
1094
  const css = buildStylesheet(settings);
1095
1095
  for (const doc of getSyncedDocuments()) {
@@ -1132,7 +1132,7 @@ export function removeSketchLayer(): void {
1132
1132
  * The host page's root and the editor's own preview container are both scopes,
1133
1133
  * which is why this takes an element rather than assuming documentElement.
1134
1134
  */
1135
- export function setSketchScope(el: HTMLElement | null, settings: SketchStyle | null): void {
1135
+ export function setSketchScope(el: HTMLElement | null, settings: SketchStyleSettings | null): void {
1136
1136
  if (!el) return;
1137
1137
  if (!settings) {
1138
1138
  el.removeAttribute('data-sketch');
@@ -1,97 +1,97 @@
1
1
  import { derived, get, writable, type Readable } from 'svelte/store';
2
- import { SKETCH_STYLES, hydrateSketchStyle, type SketchStyle } from './sketchStyles';
2
+ import { SHIPPED_SKETCH_SETTINGS, hydrateSketchSettings, type SketchStyleSettings } from './sketchStyles';
3
3
 
4
- /** Where a look came from, which is what decides the affordances on offer.
4
+ /** Where a style came from, which is what decides the affordances on offer.
5
5
  `shipped` is served by the package: it has a file, but not one in this
6
6
  project, so there is nothing here to save over or delete until the editor
7
7
  writes a copy. `file` lives in this project's data tree, so the editor can
8
8
  save over it and delete it. `registered` was handed to `bootLiveTokens`, so
9
9
  it is real on a built site but owns no file the editor could touch. */
10
- export type SketchLookSource = 'shipped' | 'file' | 'registered';
10
+ export type SketchStyleSource = 'shipped' | 'file' | 'registered';
11
11
 
12
- export interface SketchLook {
12
+ export interface SketchStyle {
13
13
  /** What `setSketch` takes. A saved sketchstyle's file slug is its id, so a
14
- look picked in dev keeps working once the site is built. */
14
+ style picked in dev keeps working once the site is built. */
15
15
  id: string;
16
16
  label: string;
17
17
  blurb: string;
18
- settings: SketchStyle;
19
- source: SketchLookSource;
18
+ settings: SketchStyleSettings;
19
+ source: SketchStyleSource;
20
20
  }
21
21
 
22
- export interface RegisterSketchLookInput {
22
+ export interface RegisterSketchStyleInput {
23
23
  id: string;
24
24
  label: string;
25
25
  blurb?: string;
26
26
  settings: unknown;
27
- /** Only `replaceRegisteredLooks` sets this. A listing carries the package's
27
+ /** Only `replaceRegisteredSketchStyles` sets this. A listing carries the package's
28
28
  own sketchstyles as well as the project's, and the two differ in what the
29
29
  editor may do to them, so the row's origin has to survive the trip. */
30
- source?: SketchLookSource;
30
+ source?: SketchStyleSource;
31
31
  }
32
32
 
33
- const SHIPPED: ReadonlyMap<string, SketchLook> = new Map(
34
- Object.entries(SKETCH_STYLES).map(([id, style]) => [
33
+ const SHIPPED: ReadonlyMap<string, SketchStyle> = new Map(
34
+ Object.entries(SHIPPED_SKETCH_SETTINGS).map(([id, settings]) => [
35
35
  id,
36
- { id, label: style.label, blurb: style.blurb, settings: style, source: 'shipped' as const },
36
+ { id, label: settings.label, blurb: settings.blurb, settings, source: 'shipped' as const },
37
37
  ]),
38
38
  );
39
39
 
40
- /** Seeded with the shipped looks, then written by `registerSketchLook`. A Map
40
+ /** Seeded with the shipped styles, then written by `registerSketchStyle`. A Map
41
41
  because re-setting an existing key keeps its position, so a project's own
42
42
  `pencil` lands where the shipped Pencil sat rather than at the end of the
43
43
  grid. */
44
- const looks = writable(new Map(SHIPPED));
44
+ const styles = writable(new Map(SHIPPED));
45
45
 
46
46
  /**
47
- * Every sketchstyle on offer: the shipped looks, plus whatever this project
47
+ * Every sketchstyle on offer: the shipped styles, plus whatever this project
48
48
  * registered over and beside them. A store rather than a constant, because
49
49
  * registration happens after this module is imported.
50
50
  *
51
51
  * A picker adds its own "None" row, since off is a state of the effect rather
52
- * than one of the looks. A theme's own look is not here either; `themeSketchLook`
52
+ * than one of the styles. A theme's own style is not here either; `unsavedSketchStyle`
53
53
  * carries that one row.
54
54
  */
55
- export const sketchLooks: Readable<SketchLook[]> = derived(looks, (m) => [...m.values()]);
55
+ export const sketchStyles: Readable<SketchStyle[]> = derived(styles, (m) => [...m.values()]);
56
56
 
57
- export function lookById(id: string): SketchLook | undefined {
58
- return get(looks).get(id);
57
+ export function sketchStyleById(id: string): SketchStyle | undefined {
58
+ return get(styles).get(id);
59
59
  }
60
60
 
61
- function put(m: Map<string, SketchLook>, look: RegisterSketchLookInput, source: SketchLookSource) {
61
+ function put(m: Map<string, SketchStyle>, style: RegisterSketchStyleInput, source: SketchStyleSource) {
62
62
  // Hydrated on the way in: a consumer hands over raw JSON it imported, so this
63
- // is the only place a look stored under a retired dial name gets carried
63
+ // is the only place a style stored under a retired dial name gets carried
64
64
  // forward, the same job `seedSketchFromTheme` does for a theme.
65
- const settings = hydrateSketchStyle(look.settings);
66
- return m.set(look.id, {
67
- id: look.id,
68
- label: look.label,
69
- blurb: look.blurb ?? settings.blurb ?? '',
65
+ const settings = hydrateSketchSettings(style.settings);
66
+ return m.set(style.id, {
67
+ id: style.id,
68
+ label: style.label,
69
+ blurb: style.blurb ?? settings.blurb ?? '',
70
70
  settings,
71
71
  source,
72
72
  });
73
73
  }
74
74
 
75
- export function registerSketchLook(look: RegisterSketchLookInput): void {
76
- looks.update((m) => put(new Map(m), look, 'registered'));
75
+ export function registerSketchStyle(style: RegisterSketchStyleInput): void {
76
+ styles.update((m) => put(new Map(m), style, 'registered'));
77
77
  }
78
78
 
79
79
  /** Ids the last file listing claimed. The sweep below removes these and nothing
80
- else, so a look handed to `bootLiveTokens` survives the editor opening. */
80
+ else, so a style handed to `bootLiveTokens` survives the editor opening. */
81
81
  let fromFiles: string[] = [];
82
82
 
83
83
  /** The editor re-lists its files after every save and delete, so a file removed
84
- on disk has to leave the pool too. A file that had shadowed a shipped look
84
+ on disk has to leave the pool too. A file that had shadowed a shipped style
85
85
  hands the id back on its way out. */
86
- export function replaceRegisteredLooks(next: RegisterSketchLookInput[]): void {
87
- looks.update((m) => {
86
+ export function replaceRegisteredSketchStyles(next: RegisterSketchStyleInput[]): void {
87
+ styles.update((m) => {
88
88
  const out = new Map(m);
89
89
  for (const id of fromFiles) {
90
90
  const shipped = SHIPPED.get(id);
91
91
  if (shipped) out.set(id, shipped);
92
92
  else out.delete(id);
93
93
  }
94
- for (const look of next) put(out, look, look.source ?? 'file');
94
+ for (const style of next) put(out, style, style.source ?? 'file');
95
95
  return out;
96
96
  });
97
97
  fromFiles = next.map((l) => l.id);