@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.
- package/CHANGELOG.md +54 -0
- package/README.md +67 -9
- package/bin/generate-theme.mjs +5 -4
- package/dist-plugin/adjust/index.d.cts +1 -1
- package/dist-plugin/adjust/index.d.ts +1 -1
- package/dist-plugin/{chunk-T4PMCFJN.js → chunk-2UX6EVVA.js} +30 -30
- package/dist-plugin/{dataPaths-DZUzVv8H.d.cts → dataPaths-bJTCEO4H.d.cts} +1 -1
- package/dist-plugin/{dataPaths-DZUzVv8H.d.ts → dataPaths-bJTCEO4H.d.ts} +1 -1
- package/dist-plugin/fontPairing/index.d.cts +1 -1
- package/dist-plugin/fontPairing/index.d.ts +1 -1
- package/dist-plugin/generateColorsAndType/index.d.cts +1 -1
- package/dist-plugin/generateColorsAndType/index.d.ts +1 -1
- package/dist-plugin/index.cjs +32 -32
- package/dist-plugin/index.d.cts +1 -1
- package/dist-plugin/index.d.ts +1 -1
- package/dist-plugin/index.js +5 -5
- package/dist-plugin/migrateData/index.cjs +30 -30
- package/dist-plugin/migrateData/index.d.cts +1 -1
- package/dist-plugin/migrateData/index.d.ts +1 -1
- package/dist-plugin/migrateData/index.js +1 -1
- package/dist-plugin/tokensCssMigrations/index.d.cts +1 -1
- package/dist-plugin/tokensCssMigrations/index.d.ts +1 -1
- package/package.json +4 -4
- package/src/editor/bootstrap.ts +6 -6
- package/src/editor/component-editor/ImageLightboxEditor.svelte +1 -1
- package/src/editor/component-editor/scaffolding/ComponentFileManager.svelte +4 -4
- package/src/editor/core/fonts/fontLoader.ts +2 -2
- package/src/editor/core/preview/{lookPreview.ts → themePreview.ts} +27 -27
- package/src/editor/core/productionPulse.ts +3 -3
- package/src/editor/core/sketch/index.ts +52 -44
- package/src/editor/core/sketch/maskField.ts +9 -9
- package/src/editor/core/sketch/sketchLayer.ts +9 -9
- package/src/editor/core/sketch/sketchRegistry.ts +34 -34
- package/src/editor/core/sketch/sketchStore.ts +98 -83
- package/src/editor/core/sketch/sketchStyleService.ts +4 -4
- package/src/editor/core/sketch/sketchStyles.ts +28 -28
- package/src/editor/core/themes/colorsAndTypeService.ts +1 -1
- package/src/editor/core/themes/loadRows.ts +8 -8
- package/src/editor/core/themes/themeDocumentSync.ts +2 -2
- package/src/editor/core/themes/themeInit.ts +2 -2
- package/src/editor/core/themes/themeService.ts +17 -17
- package/src/editor/core/themes/{lookSummary.ts → themeSummary.ts} +9 -9
- package/src/editor/core/themes/themeTypes.ts +10 -6
- package/src/editor/docs/content/getting-started.md +1 -1
- package/src/editor/docs/content/sketch-mode.md +22 -17
- package/src/editor/docs/content/themes-workflow.md +11 -11
- package/src/editor/docs/content/where-themes-live.md +6 -6
- package/src/editor/docs/content.generated.ts +4 -4
- package/src/editor/index.ts +2 -2
- package/src/editor/ui/ThemePanel.svelte +52 -52
- package/src/editor/ui/sketch/SketchPreview.svelte +2 -2
- package/src/editor/ui/sketch/SketchTab.svelte +64 -38
- package/src/live-tokens/data/sketch-styles/dry.json +5 -5
- package/src/live-tokens/data/sketch-styles/hatched.json +9 -9
- package/src/live-tokens/data/sketch-styles/napkin.json +4 -4
- package/src/live-tokens/data/sketch-styles/pencil.json +2 -2
- package/src/live-tokens/data/themes/autumn.json +1 -1
- package/src/live-tokens/data/themes/halloween.json +1 -1
- package/src/live-tokens/data/themes/midnight-study.json +1 -1
- package/src/live-tokens/data/themes/ocean.json +1 -1
- package/src/live-tokens/data/themes/royal-velvet.json +1 -1
- package/src/live-tokens/data/themes/sketchy.json +1 -1
- package/src/live-tokens/data/themes/spring-meadow.json +1 -1
- package/src/live-tokens/data/themes/sunset.json +1 -1
- package/src/system/backdrop/backdrop.ts +1 -1
- package/src/system/components/SectionDivider.svelte +1 -1
|
@@ -2,7 +2,7 @@ import { liveMovedSinceBake } from '../productionPulse';
|
|
|
2
2
|
import { openThemeSlug } from '../store/editorConfigStore';
|
|
3
3
|
import { loadThemeFromApi } from '../store/editorStore';
|
|
4
4
|
import { migrateColorsAndTypeFonts } from '../fonts/fontMigration';
|
|
5
|
-
import {
|
|
5
|
+
import { openThemeSketchSettings } from '../sketch/sketchStore';
|
|
6
6
|
import type { ApplyThemeResult } from './themeService';
|
|
7
7
|
|
|
8
8
|
const CHANNEL_NAME = 'live-tokens:active-theme:v1';
|
|
@@ -43,7 +43,7 @@ export function hydrateAppliedTheme(fileName: string, result: ApplyThemeResult):
|
|
|
43
43
|
migrateColorsAndTypeFonts(colorsAndType);
|
|
44
44
|
loadThemeFromApi(colorsAndType, structuredClone(result.componentConfigs));
|
|
45
45
|
openThemeSlug.set(fileName);
|
|
46
|
-
|
|
46
|
+
openThemeSketchSettings(result.theme.sketchSettings);
|
|
47
47
|
liveMovedSinceBake.set(false);
|
|
48
48
|
if (typeof document !== 'undefined') {
|
|
49
49
|
document.dispatchEvent(new CustomEvent<AppliedThemeDetail>(THEME_APPLIED_EVENT, {
|
|
@@ -65,9 +65,9 @@ export async function initializeTheme(): Promise<void> {
|
|
|
65
65
|
|
|
66
66
|
const active = await safeFetch<Theme>(`${API_BASE}/themes/active`);
|
|
67
67
|
// A failed fetch is not "the theme carries no sketchstyle": treating null as
|
|
68
|
-
// absent would tell the panel the
|
|
68
|
+
// absent would tell the panel the sketchstyle is off the theme, or hand a fresh
|
|
69
69
|
// browser a blank buffer, over a fetch that will likely succeed next time.
|
|
70
70
|
// The same call a built site makes (`@motion-proto/live-tokens/sketch`), so
|
|
71
71
|
// one rule decides what a theme's sketchstyle means at boot in both.
|
|
72
|
-
if (active) seedSketchFromTheme(active.
|
|
72
|
+
if (active) seedSketchFromTheme(active.sketchSettings);
|
|
73
73
|
}
|
|
@@ -7,15 +7,15 @@ import { getActiveColorsAndType } from './colorsAndTypeService';
|
|
|
7
7
|
import { broadcastAppliedTheme, hydrateAppliedTheme } from './themeDocumentSync';
|
|
8
8
|
import { CURRENT_COMPONENT_SCHEMA_VERSION } from './migrations';
|
|
9
9
|
import { THEME_SCHEMA_VERSION } from './themeTypes';
|
|
10
|
-
import {
|
|
10
|
+
import { liveSketchSettings, themeSketchSettings } from '../sketch/sketchStore';
|
|
11
11
|
|
|
12
12
|
export type { ThemeFillReport };
|
|
13
13
|
|
|
14
14
|
/**
|
|
15
15
|
* REST client for theme files, the documents of the editor. A theme carries a
|
|
16
|
-
* whole
|
|
16
|
+
* whole content by value: the colors and type plus a config for every component
|
|
17
17
|
* this install has. One theme is open (`themes/_active.json`) and one is
|
|
18
|
-
* published (`themes/_production.json`); the live
|
|
18
|
+
* published (`themes/_production.json`); the live content is the open theme plus
|
|
19
19
|
* whatever the `_working` buffers hold over it.
|
|
20
20
|
*
|
|
21
21
|
* `default` is the protected baseline — cannot be overwritten or deleted, and
|
|
@@ -75,7 +75,7 @@ export interface ApplyThemeResult {
|
|
|
75
75
|
* Open a theme: the server clears the `_working` buffers, points
|
|
76
76
|
* `themes/_active.json` at it, and returns the resolved state in one payload.
|
|
77
77
|
* Live reads then fall through to the theme's embedded layers.
|
|
78
|
-
* Production is untouched, so trying a
|
|
78
|
+
* Production is untouched, so trying a content cannot change what the site ships.
|
|
79
79
|
* The resolved response hydrates the caller immediately, then broadcasts the
|
|
80
80
|
* same typed state to every already-open same-origin host/editor document.
|
|
81
81
|
* Each store renderer projects that state into its own document, so a theme
|
|
@@ -96,7 +96,7 @@ export async function applyTheme(fileName: string): Promise<ApplyThemeResult> {
|
|
|
96
96
|
return result;
|
|
97
97
|
}
|
|
98
98
|
|
|
99
|
-
export interface
|
|
99
|
+
export interface AdoptThemeResult {
|
|
100
100
|
ok: boolean;
|
|
101
101
|
/** The theme production now ships. */
|
|
102
102
|
productionTheme: { fileName: string; name: string; updatedAt: string };
|
|
@@ -111,7 +111,7 @@ export interface AdoptLookResult {
|
|
|
111
111
|
* Answers 409 `ACTIVE_IS_PROTECTED` while the Default theme is open, which the
|
|
112
112
|
* caller recovers from by forking it under a name of the user's own.
|
|
113
113
|
*/
|
|
114
|
-
export async function
|
|
114
|
+
export async function adoptTheme(): Promise<AdoptThemeResult> {
|
|
115
115
|
const res = await fetch(`${API_BASE}/production`, { method: 'PUT' });
|
|
116
116
|
if (!res.ok) {
|
|
117
117
|
const body = await res.json().catch(() => ({}));
|
|
@@ -135,7 +135,7 @@ function withoutLiveMarkers<T extends { _fileName?: string; _source?: unknown }>
|
|
|
135
135
|
}
|
|
136
136
|
|
|
137
137
|
/**
|
|
138
|
-
* The
|
|
138
|
+
* The content as it stands: the live colors and type plus the live config of
|
|
139
139
|
* every component this install has, all by value. A theme is a complete
|
|
140
140
|
* document (`docs/plans/theme-completeness.md`), so the capture carries every
|
|
141
141
|
* component, not just the ones off their default.
|
|
@@ -145,7 +145,7 @@ function withoutLiveMarkers<T extends { _fileName?: string; _source?: unknown }>
|
|
|
145
145
|
* way out of `GET /colors-and-type/active`, which matters: the server trusts an
|
|
146
146
|
* already-embedded copy and runs no migrations over it on write.
|
|
147
147
|
*/
|
|
148
|
-
async function
|
|
148
|
+
async function captureThemeContent(): Promise<Pick<Theme, 'colorsAndType' | 'componentConfigs' | 'sketchSettings'>> {
|
|
149
149
|
const liveColorsAndType = await getActiveColorsAndType();
|
|
150
150
|
if (!liveColorsAndType) {
|
|
151
151
|
throw new Error('No live colors and type to capture');
|
|
@@ -159,11 +159,11 @@ async function captureLook(): Promise<Pick<Theme, 'colorsAndType' | 'componentCo
|
|
|
159
159
|
});
|
|
160
160
|
// Sketchstyle has no server door of its own (RJC 8): the live buffer, not a
|
|
161
161
|
// fetch, is the source of truth for what the dials currently say.
|
|
162
|
-
return { colorsAndType: withoutLiveMarkers(liveColorsAndType), componentConfigs,
|
|
162
|
+
return { colorsAndType: withoutLiveMarkers(liveColorsAndType), componentConfigs, sketchSettings: liveSketchSettings() };
|
|
163
163
|
}
|
|
164
164
|
|
|
165
165
|
/**
|
|
166
|
-
* Capture the current
|
|
166
|
+
* Capture the current content into a new theme file and open it. Used by the
|
|
167
167
|
* theme panel's Save As action and by the fork-then-Adopt flow the protected
|
|
168
168
|
* Default theme forces.
|
|
169
169
|
*/
|
|
@@ -171,7 +171,7 @@ export async function saveAsTheme(
|
|
|
171
171
|
fileName: string,
|
|
172
172
|
displayName: string,
|
|
173
173
|
): Promise<void> {
|
|
174
|
-
const
|
|
174
|
+
const content = await captureThemeContent();
|
|
175
175
|
const now = new Date().toISOString();
|
|
176
176
|
await saveTheme(fileName, {
|
|
177
177
|
name: displayName,
|
|
@@ -179,15 +179,15 @@ export async function saveAsTheme(
|
|
|
179
179
|
updatedAt: now,
|
|
180
180
|
schemaVersion: THEME_SCHEMA_VERSION,
|
|
181
181
|
componentSchemaVersion: CURRENT_COMPONENT_SCHEMA_VERSION,
|
|
182
|
-
...
|
|
182
|
+
...content,
|
|
183
183
|
});
|
|
184
|
-
|
|
184
|
+
themeSketchSettings.set(content.sketchSettings);
|
|
185
185
|
liveMovedSinceBake.set(true);
|
|
186
186
|
await setActiveTheme(fileName);
|
|
187
187
|
}
|
|
188
188
|
|
|
189
189
|
/**
|
|
190
|
-
* Re-capture the current
|
|
190
|
+
* Re-capture the current content into the open theme file. Used by the theme
|
|
191
191
|
* panel's Save action and by both Adopt paths, which publish what is saved.
|
|
192
192
|
* The server rejects with 403 while the protected `default` theme is open.
|
|
193
193
|
*/
|
|
@@ -196,16 +196,16 @@ export async function saveActiveTheme(displayName?: string): Promise<void> {
|
|
|
196
196
|
if (!active || !active._fileName) {
|
|
197
197
|
throw new Error('No active theme');
|
|
198
198
|
}
|
|
199
|
-
const
|
|
199
|
+
const content = await captureThemeContent();
|
|
200
200
|
await saveTheme(active._fileName, {
|
|
201
201
|
name: displayName ?? active.name,
|
|
202
202
|
createdAt: active.createdAt,
|
|
203
203
|
updatedAt: new Date().toISOString(),
|
|
204
204
|
schemaVersion: THEME_SCHEMA_VERSION,
|
|
205
205
|
componentSchemaVersion: CURRENT_COMPONENT_SCHEMA_VERSION,
|
|
206
|
-
...
|
|
206
|
+
...content,
|
|
207
207
|
});
|
|
208
|
-
|
|
208
|
+
themeSketchSettings.set(content.sketchSettings);
|
|
209
209
|
liveMovedSinceBake.set(true);
|
|
210
210
|
}
|
|
211
211
|
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import type { ComponentSummary } from '../components/componentConfigService';
|
|
2
2
|
|
|
3
|
-
export interface
|
|
3
|
+
export interface ThemeProductionInput {
|
|
4
4
|
/** Slug of the theme the editor has open. */
|
|
5
5
|
openTheme: string;
|
|
6
6
|
/** Slug of the published theme, or null while the read has not landed. */
|
|
7
7
|
productionTheme: string | null;
|
|
8
|
-
/** Live
|
|
8
|
+
/** Live theme moved past what the published theme holds: unsaved edits, or a
|
|
9
9
|
* save since the last Adopt. */
|
|
10
10
|
unpublished: boolean;
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
-
export interface
|
|
14
|
-
/** True when production is known to ship the
|
|
13
|
+
export interface ThemeProductionState {
|
|
14
|
+
/** True when production is known to ship the theme on screen. */
|
|
15
15
|
inProduction: boolean;
|
|
16
16
|
/** True while the production theme is unread: neither claim can be made. */
|
|
17
17
|
unknown: boolean;
|
|
@@ -22,9 +22,9 @@ export interface LookProductionState {
|
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
/**
|
|
25
|
-
* Whether production is running the
|
|
25
|
+
* Whether production is running the theme on screen. Production is one saved
|
|
26
26
|
* theme, so the first half is an identity check against the open one; the
|
|
27
|
-
* second half is the live
|
|
27
|
+
* second half is the live theme sitting ahead of what was published, which
|
|
28
28
|
* `unpublished` carries.
|
|
29
29
|
*
|
|
30
30
|
* A null production read is not an answer, so it is neither state: `unknown`
|
|
@@ -32,11 +32,11 @@ export interface LookProductionState {
|
|
|
32
32
|
* neutral state, which keeps a mount from flashing the alarm without letting a
|
|
33
33
|
* read that never lands read as shipped forever.
|
|
34
34
|
*/
|
|
35
|
-
export function
|
|
35
|
+
export function themeProductionState({
|
|
36
36
|
openTheme,
|
|
37
37
|
productionTheme,
|
|
38
38
|
unpublished,
|
|
39
|
-
}:
|
|
39
|
+
}: ThemeProductionInput): ThemeProductionState {
|
|
40
40
|
const unknown = productionTheme === null;
|
|
41
41
|
const themeOff = !unknown && productionTheme !== openTheme;
|
|
42
42
|
return {
|
|
@@ -48,6 +48,6 @@ export function lookProductionState({
|
|
|
48
48
|
}
|
|
49
49
|
|
|
50
50
|
/** How many components run an unsaved buffer, diverging from what the open theme carries. */
|
|
51
|
-
export function
|
|
51
|
+
export function countComponentsOffTheme(components: ComponentSummary[]): number {
|
|
52
52
|
return components.filter((c) => c.source === 'working').length;
|
|
53
53
|
}
|
|
@@ -2,13 +2,17 @@ import type { CurveAnchor } from '../../ui/curveEngine';
|
|
|
2
2
|
import type { GradientValue } from './parsers/gradient';
|
|
3
3
|
import type { Oklch } from '../palettes/oklch';
|
|
4
4
|
import type { HarmonyAxis } from '../palettes/colorHarmony';
|
|
5
|
-
import type {
|
|
5
|
+
import type { SketchStyleSettings } from '../sketch/sketchStyles';
|
|
6
6
|
/** Single source of truth for the theme schema version
|
|
7
7
|
* (docs/plans/theme-completeness.md, Wave 2 step 5). It lives here, on the
|
|
8
8
|
* shipped side: `vite-plugin/` is build tooling and is not in the tarball, so
|
|
9
9
|
* anything under `src/` that reaches into it resolves in this repo and
|
|
10
10
|
* nowhere else. `normalizeTheme.ts` re-exports this. */
|
|
11
|
-
|
|
11
|
+
/** 5 renamed the sketch field from `sketchStyle` to `sketchSettings`. The bump
|
|
12
|
+
* is what makes the boot pass rewrite a theme still on the old key: the read
|
|
13
|
+
* accepts both, but a built site reads its theme JSON raw and would see
|
|
14
|
+
* `undefined` until the file itself was converted. */
|
|
15
|
+
export const THEME_SCHEMA_VERSION = 5;
|
|
12
16
|
|
|
13
17
|
/** What the completeness fill had to add to reach a whole theme. `components`
|
|
14
18
|
* names each component the input carried no entry for; `aliases` counts keys
|
|
@@ -240,7 +244,7 @@ export interface ComponentConfigMeta {
|
|
|
240
244
|
}
|
|
241
245
|
|
|
242
246
|
/**
|
|
243
|
-
* A saved
|
|
247
|
+
* A saved theme, encapsulated: the colors and type plus a config for every
|
|
244
248
|
* component this install has, all carried by value. Themes are the documents
|
|
245
249
|
* of the editor. Applying one opens it by clearing the reserved `_working`
|
|
246
250
|
* buffers and updating `themes/_active.json`; live reads fall through to its
|
|
@@ -267,7 +271,7 @@ export interface Theme {
|
|
|
267
271
|
* component schema and then fills any gap from the local default, on every
|
|
268
272
|
* read (Waves 1 and 2 of `docs/plans/theme-completeness.md`); both the
|
|
269
273
|
* migration and the fill are persisted on the next write, so a theme is a
|
|
270
|
-
* whole-
|
|
274
|
+
* whole-theme document rather than a diff against a moving baseline.
|
|
271
275
|
* `component-configs/<id>/default.json` is the derivation product of that
|
|
272
276
|
* component's `:global(:root)`, not a resolution layer this map defers to
|
|
273
277
|
* — a config for a component this install does not have, or an alias key
|
|
@@ -280,10 +284,10 @@ export interface Theme {
|
|
|
280
284
|
* buy no isolation. `normalizeTheme` sets this on every read; an embedded
|
|
281
285
|
* config's own `schemaVersion` (if hand-authored) is ignored and stripped. */
|
|
282
286
|
componentSchemaVersion: number;
|
|
283
|
-
/** The sketchstyle this
|
|
287
|
+
/** The sketchstyle this theme paints, by value. Absent means the theme is
|
|
284
288
|
* crisp: presence is the on state, so there is no separate flag that can
|
|
285
289
|
* disagree with the dials beside it (RJC 1). */
|
|
286
|
-
|
|
290
|
+
sketchSettings?: SketchStyleSettings;
|
|
287
291
|
/** Server-attached file-name marker. Same role as `ColorsAndType._fileName`. */
|
|
288
292
|
_fileName?: string;
|
|
289
293
|
}
|
|
@@ -54,7 +54,7 @@ the editor swaps live.
|
|
|
54
54
|
To ship, click **Adopt** in the Theme panel. That saves the open theme and bakes
|
|
55
55
|
it into `src/live-tokens/data/tokens.generated.css`, which your build bundles
|
|
56
56
|
alongside `tokens.css`. Adopt is the only action that changes what your site
|
|
57
|
-
ships, so try any
|
|
57
|
+
ships, so try any theme you like first. The editor itself never reaches
|
|
58
58
|
production.
|
|
59
59
|
|
|
60
60
|
Already have a Svelte 5 + Vite app? The
|
|
@@ -22,7 +22,7 @@ separately wobbled boxes.
|
|
|
22
22
|
|
|
23
23
|
## The sketchstyles
|
|
24
24
|
|
|
25
|
-
Seven
|
|
25
|
+
Seven sketchstyles ship with the package, and each is a complete set of dials rather
|
|
26
26
|
than just a name:
|
|
27
27
|
|
|
28
28
|
- **Pencil.** Two graphite passes on their own seeds, so the outline disagrees
|
|
@@ -38,8 +38,8 @@ than just a name:
|
|
|
38
38
|
- **Napkin.** Ballpoint in a hurry. Everything loose at once.
|
|
39
39
|
- **Dry marker.** Ink that ran out. One scratchy pass over a mostly eaten fill.
|
|
40
40
|
|
|
41
|
-
All seven ship as files, one per
|
|
42
|
-
`src/live-tokens/data/sketch-styles/` in the package. There is no
|
|
41
|
+
All seven ship as files, one per sketchstyle, under
|
|
42
|
+
`src/live-tokens/data/sketch-styles/` in the package. There is no sketchstyle that
|
|
43
43
|
exists only as code, so every one of them can be read, copied and edited.
|
|
44
44
|
|
|
45
45
|
Pick one, then move whatever you like. **Save As** keeps your dials under a name
|
|
@@ -51,6 +51,11 @@ project's own copy under the same name, which takes its place in the list;
|
|
|
51
51
|
delete that copy and the shipped file behind it comes back. Both are a
|
|
52
52
|
different gesture from saving a theme; see "Where the settings live" below.
|
|
53
53
|
|
|
54
|
+
A theme carries its sketch settings by value, so it can hold a set that belongs
|
|
55
|
+
to no file. The list shows that set as **Unsaved**. It owns no file, so there is
|
|
56
|
+
nothing for Save to write over; **Save As** turns it into a sketchstyle like any
|
|
57
|
+
other, which you can then save over and delete.
|
|
58
|
+
|
|
54
59
|
Your sketchstyles and the shipped ones are one list. A sketchstyle named after
|
|
55
60
|
a shipped one replaces it, keeping its place in the list, so a project that
|
|
56
61
|
wants its own Pencil saves one and every picker shows that one instead.
|
|
@@ -97,9 +102,9 @@ is disabled there; use **Save As** to fold the dials into a theme of your
|
|
|
97
102
|
own.
|
|
98
103
|
|
|
99
104
|
**Save** and **Save As** in the **Sketchstyle** view are a different gesture.
|
|
100
|
-
They write a named sketchstyle to `src/live-tokens/data/sketch-styles/`, a
|
|
105
|
+
They write a named sketchstyle to `src/live-tokens/data/sketch-styles/`, a sketchstyle
|
|
101
106
|
you can pick from any theme. Neither touches the open theme, and neither marks
|
|
102
|
-
the
|
|
107
|
+
the theme as changed.
|
|
103
108
|
|
|
104
109
|
## Shipping the layer
|
|
105
110
|
|
|
@@ -110,11 +115,11 @@ has no server to ask, so it hands the field over itself:
|
|
|
110
115
|
import { seedSketchFromTheme } from '@motion-proto/live-tokens/sketch';
|
|
111
116
|
import theme from './live-tokens/data/themes/sketchy.json';
|
|
112
117
|
|
|
113
|
-
seedSketchFromTheme(theme.
|
|
118
|
+
seedSketchFromTheme(theme.sketchSettings);
|
|
114
119
|
await bootLiveTokens(App, '#app');
|
|
115
120
|
```
|
|
116
121
|
|
|
117
|
-
Call it before mounting, so the
|
|
122
|
+
Call it before mounting, so the sketch layer is up on the first frame. Pass the field
|
|
118
123
|
raw. A theme written against older dial names is carried forward on the way in,
|
|
119
124
|
the same reconciliation the dev server runs on every theme it reads.
|
|
120
125
|
|
|
@@ -122,7 +127,7 @@ Nothing is baked. `tokens.generated.css` still holds token values only, and the
|
|
|
122
127
|
layer stays JavaScript the page runs, because it builds an SVG filter bank
|
|
123
128
|
rather than a set of custom properties.
|
|
124
129
|
|
|
125
|
-
A visitor who has picked a
|
|
130
|
+
A visitor who has picked a sketchstyle of their own keeps it, None included. The theme
|
|
126
131
|
seeds a browser that has decided nothing and never overwrites one that has, so
|
|
127
132
|
calling this on every boot is safe.
|
|
128
133
|
|
|
@@ -138,26 +143,26 @@ const files = import.meta.glob<{ name?: string; settings: unknown }>(
|
|
|
138
143
|
);
|
|
139
144
|
|
|
140
145
|
await bootLiveTokens(App, '#app', {
|
|
141
|
-
|
|
146
|
+
sketchStyles: Object.entries(files).map(([path, file]) => {
|
|
142
147
|
const id = path.split('/').pop()!.replace('.json', '');
|
|
143
148
|
return { id, label: file.name || id, settings: file.settings };
|
|
144
149
|
}),
|
|
145
150
|
});
|
|
146
151
|
```
|
|
147
152
|
|
|
148
|
-
Projects made with `create` ship this already. The file's slug is the
|
|
153
|
+
Projects made with `create` ship this already. The file's slug is the sketchstyle's
|
|
149
154
|
id, so a sketchstyle picked in the editor keeps working once the site is built.
|
|
150
155
|
|
|
151
156
|
### Building a picker
|
|
152
157
|
|
|
153
|
-
`
|
|
154
|
-
each row `setSketch(
|
|
155
|
-
the effect rather than one of the
|
|
158
|
+
`sketchStyles` is every sketchstyle on offer, shipped and your own, as a store. Give
|
|
159
|
+
each row `setSketch(style.id)`, and add your own **None** row: off is a state of
|
|
160
|
+
the effect rather than one of the sketchstyles.
|
|
156
161
|
|
|
157
|
-
`
|
|
158
|
-
theme carries none, and null when what it carries
|
|
159
|
-
`
|
|
160
|
-
other, so a visitor who wanders off the theme's
|
|
162
|
+
`unsavedSketchStyle` is the settings the theme carries as one more row. It is null when the
|
|
163
|
+
theme carries none, and null when what it carries matches a sketchstyle already in
|
|
164
|
+
`sketchStyles`, since that row names it. Its id goes to `setSketch` like any
|
|
165
|
+
other, so a visitor who wanders off the theme's own settings can come back to it.
|
|
161
166
|
|
|
162
167
|
## Drawing your own elements
|
|
163
168
|
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
# Themes
|
|
2
2
|
|
|
3
|
-
Save your work, switch between
|
|
3
|
+
Save your work, switch between themes, and ship one to production.
|
|
4
4
|
|
|
5
5
|
## The Theme panel
|
|
6
6
|
|
|
7
|
-
The **Theme** panel at the foot of the editor sidebar holds the whole
|
|
7
|
+
The **Theme** panel at the foot of the editor sidebar holds the whole theme:
|
|
8
8
|
colors, type, a setting for every component, and the sketch layer, in one
|
|
9
|
-
file. It carries the name the
|
|
9
|
+
file. It carries the name the theme ships under, whether production is running
|
|
10
10
|
it, and **Adopt**. Three parts sit under it, each a read-out rather than a
|
|
11
11
|
file to manage.
|
|
12
12
|
|
|
@@ -14,7 +14,7 @@ file to manage.
|
|
|
14
14
|
define their appearance. It names the two faces the page is showing.
|
|
15
15
|
- **Components** counts how many components have an unsaved edit that has not
|
|
16
16
|
been saved into the theme, and opens the component editors.
|
|
17
|
-
- **Sketchstyle** names the
|
|
17
|
+
- **Sketchstyle** names the sketchstyle the theme's sketch layer carries: its label, or
|
|
18
18
|
off the theme when what's on screen no longer matches what was saved, or
|
|
19
19
|
none when the theme carries no sketch layer. It travels with the theme
|
|
20
20
|
like colors and type do, but never reaches a production build.
|
|
@@ -26,7 +26,7 @@ A theme holds its own copy of every part, so one theme can never break another.
|
|
|
26
26
|
A theme is a document, and the editor works the way any editor does.
|
|
27
27
|
|
|
28
28
|
- **A theme** is a named JSON file in `src/live-tokens/data/themes/`. It carries
|
|
29
|
-
the whole
|
|
29
|
+
the whole theme: the colors and type, a setting for every component, and the
|
|
30
30
|
sketch layer.
|
|
31
31
|
- **The open theme** is the one the editor is working on, named in
|
|
32
32
|
`themes/_active.json`. One at a time.
|
|
@@ -40,11 +40,11 @@ A theme is a document, and the editor works the way any editor does.
|
|
|
40
40
|
Picker performs that Adopt for you.
|
|
41
41
|
|
|
42
42
|
Absence is the answer for anything untouched: a buffer exists only where the
|
|
43
|
-
live
|
|
43
|
+
live theme diverges from the active theme, so a newly opened theme has none.
|
|
44
44
|
|
|
45
45
|
## Fonts
|
|
46
46
|
|
|
47
|
-
Type is part of the
|
|
47
|
+
Type is part of the theme, so it saves, loads and ships with the theme rather
|
|
48
48
|
than on its own. Four named stacks carry it:
|
|
49
49
|
|
|
50
50
|
| Stack | Used by |
|
|
@@ -85,7 +85,7 @@ what writes the font imports your site ships, into `fonts.css`.
|
|
|
85
85
|
|
|
86
86
|
In the Theme panel:
|
|
87
87
|
|
|
88
|
-
- **Save** captures the
|
|
88
|
+
- **Save** captures the theme on screen into the open theme. Your colors and type
|
|
89
89
|
go in as part of it, so there is nothing to save first.
|
|
90
90
|
- **Save As** names a new theme. Use it for your first save and for forking.
|
|
91
91
|
|
|
@@ -104,7 +104,7 @@ to it, and the editor never overwrites it, so start your own with **Save As**.
|
|
|
104
104
|
|
|
105
105
|
**Load**—or clicking the active theme's name—opens the Theme Picker. Picking a
|
|
106
106
|
theme shows it on the page as a preview with nothing written to disk, sketch
|
|
107
|
-
layer included, so you can try each
|
|
107
|
+
layer included, so you can try each theme and compare. **Save** in that window
|
|
108
108
|
opens and adopts the previewed theme in one step: the active pointer changes,
|
|
109
109
|
the buffers clear, the editor works on it, and production ships it. **Cancel**
|
|
110
110
|
returns you to where you were, unsaved sketch dials included. Previewing alone
|
|
@@ -125,10 +125,10 @@ then bakes the colors and type plus every component the theme carries into
|
|
|
125
125
|
it stays a preview. Fonts regenerate to match. The line under the theme name
|
|
126
126
|
says whether production is running this theme.
|
|
127
127
|
|
|
128
|
-
Production is one saved theme, so nothing else publishes. Trying a
|
|
128
|
+
Production is one saved theme, so nothing else publishes. Trying a theme, moving
|
|
129
129
|
a token, saving a theme: all of it leaves the generated CSS alone until you
|
|
130
130
|
Adopt. A component editor's Adopt runs the same save-then-bake step, because a
|
|
131
|
-
component never ships alone. Adopting while Motion Proto is open saves your
|
|
131
|
+
component never ships alone. Adopting while Motion Proto is open saves your theme
|
|
132
132
|
as a theme of your own first, since the built-in one is read-only.
|
|
133
133
|
|
|
134
134
|
Production builds (`npm run build`) ship only that plain CSS and your
|
|
@@ -11,8 +11,8 @@ src/live-tokens/data/
|
|
|
11
11
|
themes/
|
|
12
12
|
_active.json names the theme the editor has open
|
|
13
13
|
_production.json names the theme your site ships
|
|
14
|
-
default.json Motion Proto, the built-in
|
|
15
|
-
my-brand.json a saved theme: the whole
|
|
14
|
+
default.json Motion Proto, the built-in theme, rewritten at boot
|
|
15
|
+
my-brand.json a saved theme: the whole theme in one file
|
|
16
16
|
colors-and-type/
|
|
17
17
|
_working.json unsaved colors and type edits
|
|
18
18
|
component-configs/
|
|
@@ -21,14 +21,14 @@ src/live-tokens/data/
|
|
|
21
21
|
_working.json unsaved Button edits
|
|
22
22
|
my-button.json a preset you saved from the Button editor
|
|
23
23
|
sketch-styles/
|
|
24
|
-
my-
|
|
24
|
+
my-style.json a sketchstyle saved from the Sketchstyle view
|
|
25
25
|
tokens.generated.css the baked CSS your production build ships
|
|
26
26
|
src/system/styles/
|
|
27
27
|
tokens.css your token vocabulary, hand-authored, never written
|
|
28
28
|
fonts.css font imports, rewritten when you Adopt
|
|
29
29
|
```
|
|
30
30
|
|
|
31
|
-
A saved theme carries
|
|
31
|
+
A saved theme carries everything by value: the colors and type, a
|
|
32
32
|
setting for every component, and the sketch layer. It depends on no other
|
|
33
33
|
file, so deleting anything else never breaks it.
|
|
34
34
|
|
|
@@ -40,11 +40,11 @@ file, so deleting anything else never breaks it.
|
|
|
40
40
|
components, **Save all** writes those buffers together.
|
|
41
41
|
- **Save** captures the buffers into the open theme's file, along with the
|
|
42
42
|
sketch layer, which has no buffer of its own and lives only in the browser
|
|
43
|
-
until Save writes it. That file is the durable copy of your
|
|
43
|
+
until Save writes it. That file is the durable copy of your theme; matching
|
|
44
44
|
buffers are then removed.
|
|
45
45
|
- **Load** clears the buffers and points `themes/_active.json` at the theme you
|
|
46
46
|
picked. Live reads fall through to that file. Nothing else changes, so trying
|
|
47
|
-
|
|
47
|
+
themes is free and ordinary switching changes only the pointer.
|
|
48
48
|
- **Adopt** points `themes/_production.json` at the open theme, bakes it into
|
|
49
49
|
`tokens.generated.css`, and rewrites `fonts.css` to match. It is the only
|
|
50
50
|
action that changes what your site ships.
|