@motion-proto/live-tokens 0.67.1 → 0.69.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-build-page/SKILL.md +16 -5
- package/.claude/skills/live-tokens-create-component/SKILL.md +43 -8
- package/.claude/skills/live-tokens-create-component/references/token-naming.md +30 -1
- package/.claude/skills/live-tokens-fix-findings/SKILL.md +131 -0
- package/.claude/skills/live-tokens-pick-component/SKILL.md +2 -1
- package/CHANGELOG.md +239 -0
- package/README.md +11 -4
- package/bin/check-component.mjs +367 -63
- package/bin/check-page.mjs +409 -0
- package/bin/cli.mjs +57 -8
- package/bin/generate-theme.mjs +5 -4
- package/bin/lib/cssValues.mjs +50 -0
- package/bin/lib/findings.mjs +106 -0
- package/bin/lib/tokenVocabulary.mjs +213 -0
- package/dist-plugin/adjust/index.cjs +174 -23
- package/dist-plugin/adjust/index.d.cts +1 -1
- package/dist-plugin/adjust/index.d.ts +1 -1
- package/dist-plugin/adjust/index.js +68 -23
- package/dist-plugin/{chunk-J2JT4UEA.js → chunk-2YNERPXY.js} +26 -26
- package/dist-plugin/{chunk-NE6N66EE.js → chunk-GPIBU44G.js} +107 -1
- package/dist-plugin/{chunk-ZHPX7ZYQ.js → chunk-RFVYPNRO.js} +39 -1
- package/dist-plugin/{dataPaths-DZUzVv8H.d.ts → dataPaths-bJTCEO4H.d.cts} +1 -1
- package/dist-plugin/{dataPaths-DZUzVv8H.d.cts → 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.cjs +107 -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 +173 -29
- package/dist-plugin/index.d.cts +1 -1
- package/dist-plugin/index.d.ts +1 -1
- package/dist-plugin/index.js +7 -7
- package/dist-plugin/migrateData/index.cjs +132 -26
- package/dist-plugin/migrateData/index.d.cts +1 -1
- package/dist-plugin/migrateData/index.d.ts +1 -1
- package/dist-plugin/migrateData/index.js +2 -2
- package/dist-plugin/tokensCssMigrations/index.cjs +39 -1
- package/dist-plugin/tokensCssMigrations/index.d.cts +1 -1
- package/dist-plugin/tokensCssMigrations/index.d.ts +1 -1
- package/dist-plugin/tokensCssMigrations/index.js +1 -1
- package/package.json +6 -5
- package/src/app/site.css +4 -4
- package/src/editor/bootstrap.ts +6 -6
- package/src/editor/component-editor/ButtonEditor.svelte +71 -4
- package/src/editor/component-editor/CardEditor.svelte +6 -6
- package/src/editor/component-editor/DialogEditor.svelte +3 -3
- package/src/editor/component-editor/IconButtonEditor.svelte +68 -3
- package/src/editor/component-editor/ImageEditor.svelte +8 -8
- package/src/editor/component-editor/ImageLightboxEditor.svelte +13 -2
- package/src/editor/component-editor/MenuSelectEditor.svelte +63 -3
- package/src/editor/component-editor/SegmentedControlEditor.svelte +63 -3
- package/src/editor/component-editor/SideNavigationEditor.svelte +67 -3
- package/src/editor/component-editor/SliderEditor.svelte +186 -0
- package/src/editor/component-editor/TabBarEditor.svelte +63 -3
- package/src/editor/component-editor/registry.ts +10 -0
- package/src/editor/component-editor/scaffolding/ComponentFileManager.svelte +4 -4
- package/src/editor/core/components/aliasKinds.ts +51 -28
- 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 +25 -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/store/editorPersistence.ts +44 -1
- package/src/editor/core/store/editorRenderer.ts +2 -2
- package/src/editor/core/store/editorStore.ts +18 -18
- package/src/editor/core/store/editorTypes.ts +7 -6
- package/src/editor/core/themes/colorsAndTypeService.ts +1 -1
- package/src/editor/core/themes/loadRows.ts +8 -8
- package/src/editor/core/themes/migrations/2026-09-01-gate-suffix-enabled.ts +31 -0
- package/src/editor/core/themes/migrations/2026-09-01-scrim-rename.ts +52 -0
- package/src/editor/core/themes/migrations/2026-09-01-tabbar-active-tint.ts +27 -0
- package/src/editor/core/themes/migrations/2026-09-01-tint-rename.ts +42 -0
- package/src/editor/core/themes/migrations/index.ts +16 -0
- package/src/editor/core/themes/slices/domainVars.ts +2 -2
- package/src/editor/core/themes/slices/washes.ts +107 -0
- 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/editing-tokens.md +5 -3
- 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 +5 -5
- package/src/editor/index.ts +2 -2
- package/src/editor/pages/EditorShell.svelte +1 -1
- package/src/editor/ui/SurfacesTab.svelte +3 -3
- package/src/editor/ui/ThemePanel.svelte +52 -52
- package/src/editor/ui/UITokenSelector.svelte +1 -0
- package/src/editor/ui/VariablesTab.svelte +2 -2
- package/src/editor/ui/sections/{OverlaysSection.svelte → WashesSection.svelte} +44 -43
- package/src/editor/ui/sketch/SketchPreview.svelte +2 -2
- package/src/editor/ui/sketch/SketchTab.svelte +64 -38
- package/src/live-tokens/data/colors-and-type/autumn.json +6 -6
- package/src/live-tokens/data/colors-and-type/default.json +6 -6
- package/src/live-tokens/data/colors-and-type/halloween.json +6 -6
- package/src/live-tokens/data/colors-and-type/midnight-study.json +6 -6
- package/src/live-tokens/data/colors-and-type/ocean.json +6 -6
- package/src/live-tokens/data/colors-and-type/royal-velvet.json +6 -6
- package/src/live-tokens/data/colors-and-type/sketchy.json +6 -6
- package/src/live-tokens/data/colors-and-type/spring-meadow.json +6 -6
- package/src/live-tokens/data/colors-and-type/sunset.json +6 -6
- 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/themes/autumn.json +82 -14
- package/src/live-tokens/data/themes/halloween.json +82 -14
- package/src/live-tokens/data/themes/midnight-study.json +82 -14
- package/src/live-tokens/data/themes/ocean.json +82 -14
- package/src/live-tokens/data/themes/royal-velvet.json +82 -14
- package/src/live-tokens/data/themes/sketchy.json +82 -14
- package/src/live-tokens/data/themes/spring-meadow.json +82 -14
- package/src/live-tokens/data/themes/sunset.json +82 -14
- package/src/live-tokens/data/tokens.generated.css +6 -6
- package/src/system/backdrop/backdrop.ts +1 -1
- package/src/system/components/Button.svelte +28 -10
- package/src/system/components/Card.svelte +6 -6
- package/src/system/components/Dialog.svelte +3 -3
- package/src/system/components/IconButton.svelte +23 -7
- package/src/system/components/Image.svelte +6 -6
- package/src/system/components/MenuSelect.svelte +17 -1
- package/src/system/components/SectionDivider.svelte +1 -1
- package/src/system/components/SegmentedControl.svelte +20 -2
- package/src/system/components/SideNavigation.svelte +22 -2
- package/src/system/components/Slider.svelte +348 -0
- package/src/system/components/TabBar.svelte +20 -2
- package/src/system/styles/CONVENTIONS.md +2 -2
- package/src/system/styles/tokens.css +12 -4
- package/template/package.json +3 -2
- package/template/src/pages/Home.svelte +1 -1
- package/src/editor/core/themes/slices/overlays.ts +0 -101
|
@@ -1,18 +1,19 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
3
|
+
* Scrim + tint stops. A scrim dims what sits behind it; a tint shades the
|
|
4
|
+
* surface it sits on. Each stop binds an existing color token through
|
|
5
|
+
* `UIPaletteSelector`; the picker handles family/step selection and opacity,
|
|
6
|
+
* and writes route through `onwrite` into the washes slice
|
|
7
|
+
* (see editorStore.makeDefaultWashesState). The slice fans the resulting
|
|
8
|
+
* color-mix expressions out to :root.
|
|
8
9
|
*/
|
|
9
10
|
import { editorState, mutate } from '../../core/store/editorStore';
|
|
10
|
-
import type {
|
|
11
|
+
import type { WashToken } from '../../core/store/editorTypes';
|
|
11
12
|
import {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
} from '../../core/themes/slices/
|
|
13
|
+
makeDefaultScrimTokens,
|
|
14
|
+
makeDefaultTintTokens,
|
|
15
|
+
parseWashCss,
|
|
16
|
+
} from '../../core/themes/slices/washes';
|
|
16
17
|
import UIPaletteSelector from '../UIPaletteSelector.svelte';
|
|
17
18
|
|
|
18
19
|
interface Props {
|
|
@@ -22,7 +23,7 @@
|
|
|
22
23
|
|
|
23
24
|
let { copiedVar = null, oncopy }: Props = $props();
|
|
24
25
|
|
|
25
|
-
type Channel = '
|
|
26
|
+
type Channel = 'scrim' | 'tint';
|
|
26
27
|
|
|
27
28
|
function copy(v: string) { oncopy?.(v); }
|
|
28
29
|
|
|
@@ -31,41 +32,41 @@
|
|
|
31
32
|
* - bare `--name` → 100% opacity on that alias.
|
|
32
33
|
* - `color-mix(in srgb, var(--name) N%, transparent)` → alias + N%.
|
|
33
34
|
* - other (incl. `transparent`) → ignored; the picker's "None" option
|
|
34
|
-
* doesn't apply to
|
|
35
|
+
* doesn't apply to a wash. */
|
|
35
36
|
function handleWrite(channel: Channel, idx: number, value: string | null) {
|
|
36
37
|
mutate(`${channel} ${idx} edit`, (s) => {
|
|
37
|
-
const arr = channel === '
|
|
38
|
+
const arr = channel === 'scrim' ? s.washes.scrims : s.washes.tints;
|
|
38
39
|
const t = arr[idx];
|
|
39
40
|
if (!t) return;
|
|
40
41
|
if (value === null) {
|
|
41
|
-
const defaults = channel === '
|
|
42
|
+
const defaults = channel === 'scrim' ? makeDefaultScrimTokens() : makeDefaultTintTokens();
|
|
42
43
|
const d = defaults[idx];
|
|
43
44
|
if (d) { t.alias = d.alias; t.opacity = d.opacity; }
|
|
44
45
|
return;
|
|
45
46
|
}
|
|
46
47
|
if (value.startsWith('--')) { t.alias = value; t.opacity = 1; return; }
|
|
47
|
-
const parsed =
|
|
48
|
+
const parsed = parseWashCss(value);
|
|
48
49
|
if (parsed) { t.alias = parsed.alias; t.opacity = parsed.opacity; }
|
|
49
50
|
});
|
|
50
51
|
}
|
|
51
52
|
|
|
52
|
-
function copyCss(t:
|
|
53
|
+
function copyCss(t: WashToken): string {
|
|
53
54
|
const pct = Math.round(t.opacity * 100);
|
|
54
55
|
return pct >= 100 ? `var(${t.alias})` : `color-mix(in srgb, var(${t.alias}) ${pct}%, transparent)`;
|
|
55
56
|
}
|
|
56
57
|
</script>
|
|
57
58
|
|
|
58
|
-
<section class="section" id="
|
|
59
|
-
<h2 class="section-title">
|
|
59
|
+
<section class="section" id="washes">
|
|
60
|
+
<h2 class="section-title">Washes</h2>
|
|
60
61
|
|
|
61
|
-
<h3 class="group-title">
|
|
62
|
-
<div class="
|
|
63
|
-
{#each $editorState.
|
|
64
|
-
<div class="
|
|
65
|
-
<div class="
|
|
66
|
-
<div class="
|
|
62
|
+
<h3 class="group-title">Scrims</h3>
|
|
63
|
+
<div class="washes-grid">
|
|
64
|
+
{#each $editorState.washes.scrims as token, i (token.variable)}
|
|
65
|
+
<div class="wash-row">
|
|
66
|
+
<div class="wash-swatch-wrap">
|
|
67
|
+
<div class="wash-swatch" style="background: var({token.variable});"></div>
|
|
67
68
|
</div>
|
|
68
|
-
<div class="
|
|
69
|
+
<div class="wash-meta">
|
|
69
70
|
<button
|
|
70
71
|
class="token-variable copyable"
|
|
71
72
|
class:copied={copiedVar === token.variable}
|
|
@@ -73,11 +74,11 @@
|
|
|
73
74
|
>{copiedVar === token.variable ? 'copied!' : token.variable}</button>
|
|
74
75
|
<span class="token-value">{token.label} — {Math.round(token.opacity * 100)}%</span>
|
|
75
76
|
</div>
|
|
76
|
-
<div class="
|
|
77
|
+
<div class="wash-picker">
|
|
77
78
|
<UIPaletteSelector
|
|
78
79
|
variable={token.variable}
|
|
79
80
|
showNone={false}
|
|
80
|
-
onwrite={(v) => handleWrite('
|
|
81
|
+
onwrite={(v) => handleWrite('scrim', i, v)}
|
|
81
82
|
/>
|
|
82
83
|
</div>
|
|
83
84
|
<button
|
|
@@ -91,14 +92,14 @@
|
|
|
91
92
|
{/each}
|
|
92
93
|
</div>
|
|
93
94
|
|
|
94
|
-
<h3 class="group-title">
|
|
95
|
-
<div class="
|
|
96
|
-
{#each $editorState.
|
|
97
|
-
<div class="
|
|
98
|
-
<div class="
|
|
99
|
-
<div class="
|
|
95
|
+
<h3 class="group-title">Tints</h3>
|
|
96
|
+
<div class="washes-grid">
|
|
97
|
+
{#each $editorState.washes.tints as token, i (token.variable)}
|
|
98
|
+
<div class="wash-row">
|
|
99
|
+
<div class="wash-swatch-wrap wash-swatch-wrap--dark">
|
|
100
|
+
<div class="wash-swatch" style="background: var({token.variable});"></div>
|
|
100
101
|
</div>
|
|
101
|
-
<div class="
|
|
102
|
+
<div class="wash-meta">
|
|
102
103
|
<button
|
|
103
104
|
class="token-variable copyable"
|
|
104
105
|
class:copied={copiedVar === token.variable}
|
|
@@ -106,11 +107,11 @@
|
|
|
106
107
|
>{copiedVar === token.variable ? 'copied!' : token.variable}</button>
|
|
107
108
|
<span class="token-value">{token.label} — {Math.round(token.opacity * 100)}%</span>
|
|
108
109
|
</div>
|
|
109
|
-
<div class="
|
|
110
|
+
<div class="wash-picker">
|
|
110
111
|
<UIPaletteSelector
|
|
111
112
|
variable={token.variable}
|
|
112
113
|
showNone={false}
|
|
113
|
-
onwrite={(v) => handleWrite('
|
|
114
|
+
onwrite={(v) => handleWrite('tint', i, v)}
|
|
114
115
|
/>
|
|
115
116
|
</div>
|
|
116
117
|
<button
|
|
@@ -148,13 +149,13 @@
|
|
|
148
149
|
margin: 0;
|
|
149
150
|
}
|
|
150
151
|
|
|
151
|
-
.
|
|
152
|
+
.washes-grid {
|
|
152
153
|
display: flex;
|
|
153
154
|
flex-direction: column;
|
|
154
155
|
gap: var(--ui-space-8);
|
|
155
156
|
}
|
|
156
157
|
|
|
157
|
-
.
|
|
158
|
+
.wash-row {
|
|
158
159
|
display: grid;
|
|
159
160
|
grid-template-columns: 3.5rem minmax(10rem, 1fr) minmax(14rem, 1.5fr) auto;
|
|
160
161
|
gap: var(--ui-space-12);
|
|
@@ -165,7 +166,7 @@
|
|
|
165
166
|
border-radius: var(--ui-radius-md);
|
|
166
167
|
}
|
|
167
168
|
|
|
168
|
-
.
|
|
169
|
+
.wash-swatch-wrap {
|
|
169
170
|
width: 3.5rem;
|
|
170
171
|
height: 3.5rem;
|
|
171
172
|
border-radius: var(--ui-radius-sm);
|
|
@@ -182,7 +183,7 @@
|
|
|
182
183
|
background-color: #fff;
|
|
183
184
|
}
|
|
184
185
|
|
|
185
|
-
.
|
|
186
|
+
.wash-swatch-wrap--dark {
|
|
186
187
|
background-color: #222;
|
|
187
188
|
background-image:
|
|
188
189
|
linear-gradient(45deg, #333 25%, transparent 25%),
|
|
@@ -191,12 +192,12 @@
|
|
|
191
192
|
linear-gradient(-45deg, transparent 75%, #333 75%);
|
|
192
193
|
}
|
|
193
194
|
|
|
194
|
-
.
|
|
195
|
+
.wash-swatch {
|
|
195
196
|
position: absolute;
|
|
196
197
|
inset: 0;
|
|
197
198
|
}
|
|
198
199
|
|
|
199
|
-
.
|
|
200
|
+
.wash-meta {
|
|
200
201
|
display: flex;
|
|
201
202
|
flex-direction: column;
|
|
202
203
|
gap: var(--ui-space-2);
|
|
@@ -220,7 +221,7 @@
|
|
|
220
221
|
color: var(--ui-text-muted);
|
|
221
222
|
}
|
|
222
223
|
|
|
223
|
-
.
|
|
224
|
+
.wash-picker { min-width: 0; }
|
|
224
225
|
|
|
225
226
|
.copy-css-btn {
|
|
226
227
|
all: unset;
|
|
@@ -6,10 +6,10 @@
|
|
|
6
6
|
import Callout from '../../../system/components/Callout.svelte';
|
|
7
7
|
import Toggle from '../../../system/components/Toggle.svelte';
|
|
8
8
|
import { setSketchScope } from '../../core/sketch/sketchLayer';
|
|
9
|
-
import type {
|
|
9
|
+
import type { SketchStyleSettings } from '../../core/sketch/sketchStyles';
|
|
10
10
|
|
|
11
11
|
interface Props {
|
|
12
|
-
settings:
|
|
12
|
+
settings: SketchStyleSettings;
|
|
13
13
|
enabled: boolean;
|
|
14
14
|
}
|
|
15
15
|
|
|
@@ -14,18 +14,19 @@
|
|
|
14
14
|
import {
|
|
15
15
|
sketchEnabled,
|
|
16
16
|
setSketchEnabled,
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
sketchOffTheme,
|
|
18
|
+
selectedSketchStyleId,
|
|
19
19
|
sketchDirty,
|
|
20
20
|
sketchSettings,
|
|
21
|
-
selectSketchStyle,
|
|
22
21
|
updateSketchSettings,
|
|
23
22
|
refreshSavedSketchStyles,
|
|
24
23
|
saveCurrentSketchStyle,
|
|
25
24
|
saveSelectedSketchStyle,
|
|
26
25
|
deleteSavedSketchStyle,
|
|
27
26
|
} from '../../core/sketch/sketchStore';
|
|
28
|
-
import {
|
|
27
|
+
import { sketchStyles } from '../../core/sketch/sketchRegistry';
|
|
28
|
+
import { setSketch, unsavedSketchStyle } from '../../core/sketch';
|
|
29
|
+
import { THEME_SKETCH_ID } from '../../core/sketch/sketchStyles';
|
|
29
30
|
|
|
30
31
|
interface Props {
|
|
31
32
|
/** The rail's last jump. A fresh object per click, not a bare id, so
|
|
@@ -38,8 +39,13 @@
|
|
|
38
39
|
|
|
39
40
|
let s = $derived($sketchSettings);
|
|
40
41
|
|
|
42
|
+
/** The theme's own style sits in the grid like any other row, but it is the
|
|
43
|
+
one row with no file behind it, so Save has nothing to write over. Save As
|
|
44
|
+
is what gives it one, after which it is an ordinary sketchstyle. */
|
|
45
|
+
let onUnsavedSketchStyle = $derived($selectedSketchStyleId === THEME_SKETCH_ID);
|
|
46
|
+
|
|
41
47
|
// Save is disabled for the protected Default theme (ThemePanel.svelte);
|
|
42
|
-
// Save As is the gesture actually on offer there, so the off-
|
|
48
|
+
// Save As is the gesture actually on offer there, so the off-style copy has
|
|
43
49
|
// to name it instead.
|
|
44
50
|
let activeIsProtected = $derived($openThemeSlug === 'default');
|
|
45
51
|
|
|
@@ -50,7 +56,7 @@
|
|
|
50
56
|
|
|
51
57
|
/** All closed to start: twenty-odd dials in one scroll is a wall, and the
|
|
52
58
|
summary on each trigger row answers most questions without opening
|
|
53
|
-
anything. Each section then stands alone, because shaping a
|
|
59
|
+
anything. Each section then stands alone, because shaping a style means
|
|
54
60
|
reaching between them — the border's detail against the noise it
|
|
55
61
|
multiplies, the fill's travel against the border's.
|
|
56
62
|
|
|
@@ -124,43 +130,49 @@
|
|
|
124
130
|
});
|
|
125
131
|
|
|
126
132
|
/** Shipped and saved sketchstyles are one choice, so they share one radio
|
|
127
|
-
group: picking a saved one clears the shipped selection natively.
|
|
133
|
+
group: picking a saved one clears the shipped selection natively.
|
|
134
|
+
|
|
135
|
+
Picks go through `setSketch`, the same door a page picker uses, so one is
|
|
136
|
+
the whole gesture: the style is applied, the effect comes on, and the
|
|
137
|
+
page's own picker follows. Selecting without applying would leave the two
|
|
138
|
+
pickers disagreeing about what the page is drawn with. */
|
|
128
139
|
const STYLE_RADIO_GROUP = 'sketchstyle';
|
|
129
140
|
|
|
130
141
|
/** What the readout under the grid says. The selection survives a dial move,
|
|
131
142
|
so the base keeps its name here and the blurb reports the drift instead. */
|
|
132
143
|
let active = $derived(
|
|
133
144
|
$sketchDirty
|
|
134
|
-
? {
|
|
145
|
+
? {
|
|
146
|
+
name: s.label,
|
|
147
|
+
blurb: onUnsavedSketchStyle
|
|
148
|
+
? 'Modified from settings this theme carries. Save As keeps them as a sketchstyle.'
|
|
149
|
+
: `Modified from ${s.label}. Save it to keep it.`,
|
|
150
|
+
}
|
|
135
151
|
: { name: s.label, blurb: s.blurb || 'Your saved sketchstyle.' },
|
|
136
152
|
);
|
|
137
153
|
|
|
138
|
-
let
|
|
154
|
+
let selectedSketchStyle = $derived($sketchStyles.find((l) => l.id === $selectedSketchStyleId));
|
|
139
155
|
/** Offered whenever the dials have moved off the sketchstyle they name. A
|
|
140
|
-
|
|
156
|
+
style backed by a project file is written over. A shipped one's file lives
|
|
141
157
|
in the package, so saving it writes this project's own under the same
|
|
142
158
|
name, which is how a project comes to own its Pencil: the id is the same,
|
|
143
159
|
so the new file takes the shipped one's place in the grid rather than
|
|
144
160
|
sitting beside it. Nothing is lost either way, since deleting that file
|
|
145
161
|
uncovers the packaged one again. */
|
|
146
|
-
let canSave = $derived(!!
|
|
162
|
+
let canSave = $derived(!!selectedSketchStyle && $sketchDirty);
|
|
147
163
|
let saveTitle = $derived(
|
|
148
|
-
|
|
149
|
-
? '
|
|
150
|
-
:
|
|
151
|
-
? '
|
|
152
|
-
:
|
|
153
|
-
?
|
|
154
|
-
: `
|
|
164
|
+
onUnsavedSketchStyle
|
|
165
|
+
? 'These settings belong to no sketchstyle file. Save As keeps them as one.'
|
|
166
|
+
: !selectedSketchStyle
|
|
167
|
+
? 'Pick a sketchstyle to save over'
|
|
168
|
+
: !$sketchDirty
|
|
169
|
+
? 'No changes to save'
|
|
170
|
+
: `Save over ${selectedSketchStyle.label}`,
|
|
155
171
|
);
|
|
156
172
|
|
|
157
173
|
function saveInPlace() {
|
|
158
|
-
if (!
|
|
159
|
-
runStyleAction(
|
|
160
|
-
selectedLook.source === 'file'
|
|
161
|
-
? saveSelectedSketchStyle()
|
|
162
|
-
: saveCurrentSketchStyle(selectedLook.label),
|
|
163
|
-
);
|
|
174
|
+
if (!selectedSketchStyle) return;
|
|
175
|
+
runStyleAction(saveSelectedSketchStyle());
|
|
164
176
|
}
|
|
165
177
|
|
|
166
178
|
let naming = $state(false);
|
|
@@ -324,9 +336,9 @@
|
|
|
324
336
|
<div class="readout" aria-live="polite">
|
|
325
337
|
<span class="readout-name">{active.name}</span>
|
|
326
338
|
<p class="readout-blurb">{active.blurb}</p>
|
|
327
|
-
{#if $
|
|
339
|
+
{#if $sketchOffTheme}
|
|
328
340
|
{#if $sketchEnabled}
|
|
329
|
-
<p class="readout-off-
|
|
341
|
+
<p class="readout-off-style">
|
|
330
342
|
{#if activeIsProtected}
|
|
331
343
|
Motion Proto is read-only, and these dials are ahead of it. Use Save As in the
|
|
332
344
|
Theme panel to keep them in a new theme.
|
|
@@ -336,7 +348,7 @@
|
|
|
336
348
|
{/if}
|
|
337
349
|
</p>
|
|
338
350
|
{:else}
|
|
339
|
-
<p class="readout-off-
|
|
351
|
+
<p class="readout-off-style">
|
|
340
352
|
The theme carries a sketchstyle this page is not painting. Saving now would drop
|
|
341
353
|
it.
|
|
342
354
|
</p>
|
|
@@ -345,25 +357,39 @@
|
|
|
345
357
|
</div>
|
|
346
358
|
|
|
347
359
|
<div class="presets">
|
|
348
|
-
{#
|
|
360
|
+
{#if $unsavedSketchStyle}
|
|
361
|
+
<div class="saved-item">
|
|
362
|
+
<label class="preset">
|
|
363
|
+
<input
|
|
364
|
+
type="radio"
|
|
365
|
+
name={STYLE_RADIO_GROUP}
|
|
366
|
+
value={$unsavedSketchStyle.id}
|
|
367
|
+
checked={onUnsavedSketchStyle}
|
|
368
|
+
onchange={() => setSketch(THEME_SKETCH_ID)}
|
|
369
|
+
/>
|
|
370
|
+
<span class="preset-name">{$unsavedSketchStyle.label}</span>
|
|
371
|
+
</label>
|
|
372
|
+
</div>
|
|
373
|
+
{/if}
|
|
374
|
+
{#each $sketchStyles as style (style.id)}
|
|
349
375
|
<div class="saved-item">
|
|
350
376
|
<label class="preset">
|
|
351
377
|
<input
|
|
352
378
|
type="radio"
|
|
353
379
|
name={STYLE_RADIO_GROUP}
|
|
354
|
-
value={
|
|
355
|
-
checked={$
|
|
356
|
-
onchange={() =>
|
|
380
|
+
value={style.id}
|
|
381
|
+
checked={$selectedSketchStyleId === style.id}
|
|
382
|
+
onchange={() => setSketch(style.id)}
|
|
357
383
|
/>
|
|
358
|
-
<span class="preset-name">{
|
|
384
|
+
<span class="preset-name">{style.label}</span>
|
|
359
385
|
</label>
|
|
360
|
-
{#if
|
|
386
|
+
{#if style.source === 'file'}
|
|
361
387
|
<button
|
|
362
388
|
type="button"
|
|
363
389
|
class="saved-delete"
|
|
364
|
-
title="Delete {
|
|
365
|
-
aria-label="Delete {
|
|
366
|
-
onclick={() => runStyleAction(deleteSavedSketchStyle(
|
|
390
|
+
title="Delete {style.label}"
|
|
391
|
+
aria-label="Delete {style.label}"
|
|
392
|
+
onclick={() => runStyleAction(deleteSavedSketchStyle(style.id))}
|
|
367
393
|
><i class="fas fa-xmark"></i></button>
|
|
368
394
|
{/if}
|
|
369
395
|
</div>
|
|
@@ -665,7 +691,7 @@
|
|
|
665
691
|
/>
|
|
666
692
|
</div>
|
|
667
693
|
</div>
|
|
668
|
-
{#if
|
|
694
|
+
{#if s.maskBlobX !== s.maskBlobY}
|
|
669
695
|
<SketchDial
|
|
670
696
|
label="Rotation" value={s.maskAngle} min={0} max={180} step={1}
|
|
671
697
|
readout={`${blobAngle}°`}
|
|
@@ -1097,7 +1123,7 @@
|
|
|
1097
1123
|
color: var(--ui-text-secondary);
|
|
1098
1124
|
}
|
|
1099
1125
|
|
|
1100
|
-
.readout-off-
|
|
1126
|
+
.readout-off-style {
|
|
1101
1127
|
margin: var(--ui-space-2) 0 0;
|
|
1102
1128
|
font-size: var(--ui-font-size-sm);
|
|
1103
1129
|
font-weight: var(--ui-font-weight-medium);
|
|
@@ -2259,12 +2259,12 @@
|
|
|
2259
2259
|
"--columns-max-width": "1440px",
|
|
2260
2260
|
"--columns-gutter": "32px",
|
|
2261
2261
|
"--columns-margin": "0px",
|
|
2262
|
-
"--
|
|
2263
|
-
"--
|
|
2264
|
-
"--
|
|
2265
|
-
"--
|
|
2266
|
-
"--
|
|
2267
|
-
"--
|
|
2262
|
+
"--scrim-low": "color-mix(in srgb, var(--surface-neutral-lowest) 38%, transparent)",
|
|
2263
|
+
"--scrim": "color-mix(in srgb, var(--surface-neutral-lowest) 51%, transparent)",
|
|
2264
|
+
"--scrim-high": "color-mix(in srgb, var(--surface-neutral-lowest) 64%, transparent)",
|
|
2265
|
+
"--tint-low": "color-mix(in srgb, var(--text-primary) 5%, transparent)",
|
|
2266
|
+
"--tint": "color-mix(in srgb, var(--text-primary) 10%, transparent)",
|
|
2267
|
+
"--tint-high": "color-mix(in srgb, var(--text-primary) 15%, transparent)",
|
|
2268
2268
|
"--shadow-sm": "1px 1px 2px hsla(237, 18%, 3%, 0.25)",
|
|
2269
2269
|
"--shadow-md": "3px 3px 6px hsla(237, 18%, 3%, 0.25)",
|
|
2270
2270
|
"--shadow-lg": "5px 5px 9px hsla(237, 18%, 3%, 0.25)",
|
|
@@ -2290,12 +2290,12 @@
|
|
|
2290
2290
|
"--columns-max-width": "1440px",
|
|
2291
2291
|
"--columns-gutter": "32px",
|
|
2292
2292
|
"--columns-margin": "0px",
|
|
2293
|
-
"--
|
|
2294
|
-
"--
|
|
2295
|
-
"--
|
|
2296
|
-
"--
|
|
2297
|
-
"--
|
|
2298
|
-
"--
|
|
2293
|
+
"--scrim-low": "color-mix(in srgb, var(--surface-neutral-lowest) 38%, transparent)",
|
|
2294
|
+
"--scrim": "color-mix(in srgb, var(--surface-neutral-lowest) 51%, transparent)",
|
|
2295
|
+
"--scrim-high": "color-mix(in srgb, var(--surface-neutral-lowest) 64%, transparent)",
|
|
2296
|
+
"--tint-low": "color-mix(in srgb, var(--text-primary) 5%, transparent)",
|
|
2297
|
+
"--tint": "color-mix(in srgb, var(--text-primary) 10%, transparent)",
|
|
2298
|
+
"--tint-high": "color-mix(in srgb, var(--text-primary) 15%, transparent)",
|
|
2299
2299
|
"--shadow-sm": "1px 1px 2px hsla(237, 18%, 3%, 0.9)",
|
|
2300
2300
|
"--shadow-md": "3px 3px 6px hsla(237, 18%, 3%, 0.9)",
|
|
2301
2301
|
"--shadow-lg": "5px 5px 9px hsla(237, 18%, 3%, 0.9)",
|
|
@@ -2306,12 +2306,12 @@
|
|
|
2306
2306
|
"--columns-max-width": "1440px",
|
|
2307
2307
|
"--columns-gutter": "32px",
|
|
2308
2308
|
"--columns-margin": "0px",
|
|
2309
|
-
"--
|
|
2310
|
-
"--
|
|
2311
|
-
"--
|
|
2312
|
-
"--
|
|
2313
|
-
"--
|
|
2314
|
-
"--
|
|
2309
|
+
"--scrim-low": "color-mix(in srgb, var(--surface-neutral-lowest) 38%, transparent)",
|
|
2310
|
+
"--scrim": "color-mix(in srgb, var(--surface-neutral-lowest) 51%, transparent)",
|
|
2311
|
+
"--scrim-high": "color-mix(in srgb, var(--surface-neutral-lowest) 64%, transparent)",
|
|
2312
|
+
"--tint-low": "color-mix(in srgb, var(--text-primary) 5%, transparent)",
|
|
2313
|
+
"--tint": "color-mix(in srgb, var(--text-primary) 10%, transparent)",
|
|
2314
|
+
"--tint-high": "color-mix(in srgb, var(--text-primary) 15%, transparent)",
|
|
2315
2315
|
"--shadow-sm": "1px 1px 2px hsla(237, 18%, 3%, 0.9)",
|
|
2316
2316
|
"--shadow-md": "3px 3px 6px hsla(237, 18%, 3%, 0.9)",
|
|
2317
2317
|
"--shadow-lg": "5px 5px 9px hsla(237, 18%, 3%, 0.9)",
|
|
@@ -2302,12 +2302,12 @@
|
|
|
2302
2302
|
"--columns-max-width": "1440px",
|
|
2303
2303
|
"--columns-gutter": "32px",
|
|
2304
2304
|
"--columns-margin": "0px",
|
|
2305
|
-
"--
|
|
2306
|
-
"--
|
|
2307
|
-
"--
|
|
2308
|
-
"--
|
|
2309
|
-
"--
|
|
2310
|
-
"--
|
|
2305
|
+
"--scrim-low": "color-mix(in srgb, var(--surface-neutral-lowest) 38%, transparent)",
|
|
2306
|
+
"--scrim": "color-mix(in srgb, var(--surface-neutral-lowest) 51%, transparent)",
|
|
2307
|
+
"--scrim-high": "color-mix(in srgb, var(--surface-neutral-lowest) 64%, transparent)",
|
|
2308
|
+
"--tint-low": "color-mix(in srgb, var(--text-primary) 5%, transparent)",
|
|
2309
|
+
"--tint": "color-mix(in srgb, var(--text-primary) 10%, transparent)",
|
|
2310
|
+
"--tint-high": "color-mix(in srgb, var(--text-primary) 15%, transparent)",
|
|
2311
2311
|
"--shadow-sm": "1px 1px 2px hsla(237, 18%, 3%, 0.9)",
|
|
2312
2312
|
"--shadow-md": "3px 3px 6px hsla(237, 18%, 3%, 0.9)",
|
|
2313
2313
|
"--shadow-lg": "5px 5px 9px hsla(237, 18%, 3%, 0.9)",
|
|
@@ -2259,12 +2259,12 @@
|
|
|
2259
2259
|
"--columns-max-width": "1440px",
|
|
2260
2260
|
"--columns-gutter": "32px",
|
|
2261
2261
|
"--columns-margin": "0px",
|
|
2262
|
-
"--
|
|
2263
|
-
"--
|
|
2264
|
-
"--
|
|
2265
|
-
"--
|
|
2266
|
-
"--
|
|
2267
|
-
"--
|
|
2262
|
+
"--scrim-low": "color-mix(in srgb, var(--surface-neutral-lowest) 38%, transparent)",
|
|
2263
|
+
"--scrim": "color-mix(in srgb, var(--surface-neutral-lowest) 51%, transparent)",
|
|
2264
|
+
"--scrim-high": "color-mix(in srgb, var(--surface-neutral-lowest) 64%, transparent)",
|
|
2265
|
+
"--tint-low": "color-mix(in srgb, var(--text-primary) 5%, transparent)",
|
|
2266
|
+
"--tint": "color-mix(in srgb, var(--text-primary) 10%, transparent)",
|
|
2267
|
+
"--tint-high": "color-mix(in srgb, var(--text-primary) 15%, transparent)",
|
|
2268
2268
|
"--shadow-sm": "1px 1px 2px hsla(237, 18%, 3%, 0.2)",
|
|
2269
2269
|
"--shadow-md": "3px 3px 6px hsla(237, 18%, 3%, 0.2)",
|
|
2270
2270
|
"--shadow-lg": "5px 5px 9px hsla(237, 18%, 3%, 0.2)",
|
|
@@ -2291,12 +2291,12 @@
|
|
|
2291
2291
|
"--columns-max-width": "1440px",
|
|
2292
2292
|
"--columns-gutter": "32px",
|
|
2293
2293
|
"--columns-margin": "0px",
|
|
2294
|
-
"--
|
|
2295
|
-
"--
|
|
2296
|
-
"--
|
|
2297
|
-
"--
|
|
2298
|
-
"--
|
|
2299
|
-
"--
|
|
2294
|
+
"--scrim-low": "color-mix(in srgb, var(--surface-neutral-lowest) 38%, transparent)",
|
|
2295
|
+
"--scrim": "color-mix(in srgb, var(--surface-neutral-lowest) 51%, transparent)",
|
|
2296
|
+
"--scrim-high": "color-mix(in srgb, var(--surface-neutral-lowest) 64%, transparent)",
|
|
2297
|
+
"--tint-low": "color-mix(in srgb, var(--text-primary) 5%, transparent)",
|
|
2298
|
+
"--tint": "color-mix(in srgb, var(--text-primary) 10%, transparent)",
|
|
2299
|
+
"--tint-high": "color-mix(in srgb, var(--text-primary) 15%, transparent)",
|
|
2300
2300
|
"--shadow-sm": "1px 1px 2px hsla(237, 18%, 3%, 0.9)",
|
|
2301
2301
|
"--shadow-md": "3px 3px 6px hsla(237, 18%, 3%, 0.9)",
|
|
2302
2302
|
"--shadow-lg": "5px 5px 9px hsla(237, 18%, 3%, 0.9)",
|
|
@@ -2245,12 +2245,12 @@
|
|
|
2245
2245
|
"--columns-max-width": "1440px",
|
|
2246
2246
|
"--columns-gutter": "32px",
|
|
2247
2247
|
"--columns-margin": "0px",
|
|
2248
|
-
"--
|
|
2249
|
-
"--
|
|
2250
|
-
"--
|
|
2251
|
-
"--
|
|
2252
|
-
"--
|
|
2253
|
-
"--
|
|
2248
|
+
"--scrim-low": "color-mix(in srgb, var(--surface-neutral-lowest) 38%, transparent)",
|
|
2249
|
+
"--scrim": "color-mix(in srgb, var(--surface-neutral-lowest) 51%, transparent)",
|
|
2250
|
+
"--scrim-high": "color-mix(in srgb, var(--surface-neutral-lowest) 64%, transparent)",
|
|
2251
|
+
"--tint-low": "color-mix(in srgb, var(--text-primary) 5%, transparent)",
|
|
2252
|
+
"--tint": "color-mix(in srgb, var(--text-primary) 10%, transparent)",
|
|
2253
|
+
"--tint-high": "color-mix(in srgb, var(--text-primary) 15%, transparent)",
|
|
2254
2254
|
"--shadow-sm": "1px 1px 2px hsla(237, 18%, 3%, 0.2)",
|
|
2255
2255
|
"--shadow-md": "3px 3px 6px hsla(237, 18%, 3%, 0.2)",
|
|
2256
2256
|
"--shadow-lg": "5px 5px 9px hsla(237, 18%, 3%, 0.2)",
|
|
@@ -2245,12 +2245,12 @@
|
|
|
2245
2245
|
"--columns-max-width": "1440px",
|
|
2246
2246
|
"--columns-gutter": "32px",
|
|
2247
2247
|
"--columns-margin": "0px",
|
|
2248
|
-
"--
|
|
2249
|
-
"--
|
|
2250
|
-
"--
|
|
2251
|
-
"--
|
|
2252
|
-
"--
|
|
2253
|
-
"--
|
|
2248
|
+
"--scrim-low": "color-mix(in srgb, var(--surface-neutral-lowest) 38%, transparent)",
|
|
2249
|
+
"--scrim": "color-mix(in srgb, var(--surface-neutral-lowest) 51%, transparent)",
|
|
2250
|
+
"--scrim-high": "color-mix(in srgb, var(--surface-neutral-lowest) 64%, transparent)",
|
|
2251
|
+
"--tint-low": "color-mix(in srgb, var(--text-primary) 5%, transparent)",
|
|
2252
|
+
"--tint": "color-mix(in srgb, var(--text-primary) 10%, transparent)",
|
|
2253
|
+
"--tint-high": "color-mix(in srgb, var(--text-primary) 15%, transparent)",
|
|
2254
2254
|
"--shadow-sm": "1px 1px 2px hsla(237, 18%, 3%, 0.2)",
|
|
2255
2255
|
"--shadow-md": "3px 3px 6px hsla(237, 18%, 3%, 0.2)",
|
|
2256
2256
|
"--shadow-lg": "5px 5px 9px hsla(237, 18%, 3%, 0.2)",
|
|
@@ -2306,12 +2306,12 @@
|
|
|
2306
2306
|
"--columns-max-width": "1440px",
|
|
2307
2307
|
"--columns-gutter": "32px",
|
|
2308
2308
|
"--columns-margin": "0px",
|
|
2309
|
-
"--
|
|
2310
|
-
"--
|
|
2311
|
-
"--
|
|
2312
|
-
"--
|
|
2313
|
-
"--
|
|
2314
|
-
"--
|
|
2309
|
+
"--scrim-low": "color-mix(in srgb, var(--surface-neutral-lowest) 38%, transparent)",
|
|
2310
|
+
"--scrim": "color-mix(in srgb, var(--surface-neutral-lowest) 51%, transparent)",
|
|
2311
|
+
"--scrim-high": "color-mix(in srgb, var(--surface-neutral-lowest) 64%, transparent)",
|
|
2312
|
+
"--tint-low": "color-mix(in srgb, var(--text-primary) 5%, transparent)",
|
|
2313
|
+
"--tint": "color-mix(in srgb, var(--text-primary) 10%, transparent)",
|
|
2314
|
+
"--tint-high": "color-mix(in srgb, var(--text-primary) 15%, transparent)",
|
|
2315
2315
|
"--shadow-sm": "1px 1px 2px hsla(237, 18%, 3%, 0.9)",
|
|
2316
2316
|
"--shadow-md": "3px 3px 6px hsla(237, 18%, 3%, 0.9)",
|
|
2317
2317
|
"--shadow-lg": "5px 5px 9px hsla(237, 18%, 3%, 0.9)",
|
|
@@ -21,11 +21,11 @@
|
|
|
21
21
|
"pooling": 1.5,
|
|
22
22
|
"strokeInk": 0.4,
|
|
23
23
|
"maskOn": true,
|
|
24
|
-
"maskBlobX":
|
|
25
|
-
"maskBlobY":
|
|
24
|
+
"maskBlobX": 170,
|
|
25
|
+
"maskBlobY": 170,
|
|
26
26
|
"maskBlobLinked": true,
|
|
27
27
|
"maskAngle": 0,
|
|
28
|
-
"maskOutputMin": 0.
|
|
28
|
+
"maskOutputMin": 0.57,
|
|
29
29
|
"maskOutputMax": 0.91,
|
|
30
30
|
"maskOctaves": 2,
|
|
31
31
|
"maskGrain": "fractal",
|
|
@@ -42,6 +42,6 @@
|
|
|
42
42
|
"iconMaskOn": true,
|
|
43
43
|
"iconMaskScale": 3.8
|
|
44
44
|
},
|
|
45
|
-
"updatedAt": "2026-08-
|
|
45
|
+
"updatedAt": "2026-08-28T21:19:51.383Z",
|
|
46
46
|
"createdAt": "2026-08-28T15:47:36.934Z"
|
|
47
|
-
}
|
|
47
|
+
}
|