@weasel-js/labkit 0.8.0 → 1.0.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/README.md +11 -3
- package/dist/_dts/{DrawCommand-DACv9lhe.d.ts → DrawCommand-CitWPxMY.d.ts} +80 -7
- package/dist/_dts/{useExperimentState-eSvpwV_P.d.ts → useExperimentState-CJn2hHzd.d.ts} +6 -4
- package/dist/{chunk-SSMHPMDV.js → chunk-53XSBIUK.js} +12 -11
- package/dist/chunk-53XSBIUK.js.map +1 -0
- package/dist/{chunk-OHGEOTCV.js → chunk-EXBV7A6X.js} +3 -3
- package/dist/{chunk-OHGEOTCV.js.map → chunk-EXBV7A6X.js.map} +1 -1
- package/dist/{chunk-6V7ROR7G.js → chunk-ISEK5LXT.js} +1931 -904
- package/dist/chunk-ISEK5LXT.js.map +1 -0
- package/dist/chunk-NRD3TDNQ.js +5946 -0
- package/dist/chunk-NRD3TDNQ.js.map +1 -0
- package/dist/index.d.ts +37 -13
- package/dist/index.js +776 -27
- package/dist/index.js.map +1 -1
- package/dist/passthrough/weasel-canvas.d.ts +29 -6
- package/dist/passthrough/weasel-canvas.js +1 -1
- package/dist/passthrough/weasel-ui.d.ts +169 -79
- package/dist/passthrough/weasel-ui.js +2 -2
- package/dist/state/index.d.ts +2 -2
- package/dist/state/index.js +2 -2
- package/dist/styles.css +228 -287
- package/dist/ui/layers/index.js +3 -3
- package/package.json +4 -6
- package/src/canvas/CanvasStack.less +1 -1
- package/src/controls/ControlPanel.less +12 -12
- package/src/dragdrop/DragGhost.less +2 -2
- package/src/dragdrop/Palette.less +6 -6
- package/src/index.ts +2 -0
- package/src/lab/Lab.test.tsx +20 -15
- package/src/lab/Lab.tsx +33 -32
- package/src/lab/LabContext.ts +3 -3
- package/src/lab/LabShell.less +14 -14
- package/src/lab/LabShell.test.tsx +7 -20
- package/src/lab/LabShell.tsx +22 -13
- package/src/lab/WorkspaceGrid.less +1 -1
- package/src/lab/WorkspaceGrid.stories.tsx +4 -4
- package/src/lab/index.ts +1 -1
- package/src/lab/useSystemMode.ts +30 -0
- package/src/layers/LayerList.less +9 -9
- package/src/passthrough/weasel-ui.ts +4 -0
- package/src/primitives/FpsMeter.less +5 -5
- package/src/primitives/ScaleIndicator.less +7 -7
- package/src/primitives/Sidebar.less +12 -12
- package/src/primitives/StatusBar.less +10 -10
- package/src/primitives/Toolbar.less +16 -16
- package/src/state/store.test.ts +17 -9
- package/src/state/store.ts +13 -10
- package/src/state/types.ts +5 -2
- package/src/theme/Interstellar.stories.less +20 -20
- package/src/theme/Interstellar.stories.tsx +44 -59
- package/src/theme/base.less +26 -26
- package/src/theme/interstellar.test.ts +30 -0
- package/src/theme/interstellar.tokens.json +57 -0
- package/src/theme/interstellar.ts +9 -0
- package/src/ui/layers/LayerStack.less +21 -21
- package/src/ui/properties/CurveField.less +5 -5
- package/src/ui/properties/EffectCard.tsx +2 -2
- package/src/ui/properties/PropertyGroup.less +6 -6
- package/src/ui/properties/PropertyPanel.less +70 -70
- package/src/ui/properties/PropertyPanel.stories.tsx +0 -1
- package/src/ui/properties/SpeechBalloonPanels.stories.tsx +1 -1
- package/src/ui/properties/storyLayouts.tsx +1 -1
- package/src/workspace/Workspace.less +14 -14
- package/src/workspace/Workspace.stories.tsx +2 -2
- package/src/workspace/Workspace.test.tsx +2 -2
- package/dist/chunk-6V7ROR7G.js.map +0 -1
- package/dist/chunk-FBZCQXI2.js +0 -6037
- package/dist/chunk-FBZCQXI2.js.map +0 -1
- package/dist/chunk-SSMHPMDV.js.map +0 -1
- package/dist/theme-interstellar.css +0 -25
- package/dist/theme-light.css +0 -13
- package/src/theme/interstellar.less +0 -34
- package/src/theme/light.less +0 -14
- package/src/theme/tokens.less +0 -85
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
-
import {
|
|
2
|
+
import type { TokenName } from '@weasel-js/theme';
|
|
3
|
+
import { useTheme } from '@weasel-js/theme/react';
|
|
3
4
|
import {
|
|
4
5
|
CheckboxRow,
|
|
5
6
|
ColorRow,
|
|
@@ -17,7 +18,7 @@ const meta: Meta = {
|
|
|
17
18
|
description: {
|
|
18
19
|
component:
|
|
19
20
|
'The interstellar theme: deep-space cosmic gradient + starscape backdrop, glass surfaces, Oswald display type, purple accent. ' +
|
|
20
|
-
'
|
|
21
|
+
'Authored as DTCG in `src/theme/interstellar.tokens.json` and loaded with `loadDTCG`; it extends the built-in weasel theme, overriding values rather than adding tokens.',
|
|
21
22
|
},
|
|
22
23
|
},
|
|
23
24
|
},
|
|
@@ -34,58 +35,40 @@ interface Swatch {
|
|
|
34
35
|
}
|
|
35
36
|
|
|
36
37
|
const SURFACE_TOKENS: Swatch[] = [
|
|
37
|
-
{ name: 'bg', cssVar: '--
|
|
38
|
-
{ name: 'bg-elevated', cssVar: '--
|
|
39
|
-
{ name: 'bg-canvas', cssVar: '--
|
|
40
|
-
{ name: 'border', cssVar: '--
|
|
41
|
-
{ name: 'divider', cssVar: '--
|
|
38
|
+
{ name: 'bg', cssVar: '--wzl-surface' },
|
|
39
|
+
{ name: 'bg-elevated', cssVar: '--wzl-surface-raised' },
|
|
40
|
+
{ name: 'bg-canvas', cssVar: '--wzl-surface-sunken' },
|
|
41
|
+
{ name: 'border', cssVar: '--wzl-border' },
|
|
42
|
+
{ name: 'divider', cssVar: '--wzl-line-subtle' },
|
|
42
43
|
];
|
|
43
44
|
|
|
44
45
|
const TEXT_TOKENS: Swatch[] = [
|
|
45
|
-
{ name: 'text', cssVar: '--
|
|
46
|
-
{ name: 'text-muted', cssVar: '--
|
|
47
|
-
{ name: 'text-disabled', cssVar: '--
|
|
46
|
+
{ name: 'text', cssVar: '--wzl-fg' },
|
|
47
|
+
{ name: 'text-muted', cssVar: '--wzl-fg-muted' },
|
|
48
|
+
{ name: 'text-disabled', cssVar: '--wzl-fg-subtle' },
|
|
48
49
|
];
|
|
49
50
|
|
|
50
51
|
const ACCENT_TOKENS: Swatch[] = [
|
|
51
|
-
{ name: 'accent', cssVar: '--
|
|
52
|
-
{ name: 'accent-hover', cssVar: '--
|
|
53
|
-
{ name: 'focus-ring', cssVar: '--
|
|
52
|
+
{ name: 'accent', cssVar: '--wzl-accent' },
|
|
53
|
+
{ name: 'accent-hover', cssVar: '--wzl-accent-hover' },
|
|
54
|
+
{ name: 'focus-ring', cssVar: '--wzl-focus-ring' },
|
|
54
55
|
];
|
|
55
56
|
|
|
56
57
|
const PALETTE_TOKENS: Swatch[] = [
|
|
57
|
-
{ name: 'green', cssVar: '--
|
|
58
|
-
{ name: 'pink', cssVar: '--
|
|
59
|
-
{ name: 'cyan', cssVar: '--
|
|
60
|
-
{ name: 'gold', cssVar: '--
|
|
61
|
-
{ name: 'amber', cssVar: '--
|
|
62
|
-
{ name: 'violet', cssVar: '--
|
|
63
|
-
{ name: 'mint', cssVar: '--
|
|
64
|
-
{ name: 'sky', cssVar: '--
|
|
65
|
-
{ name: 'orange', cssVar: '--
|
|
66
|
-
{ name: 'magenta', cssVar: '--
|
|
58
|
+
{ name: 'green', cssVar: '--wzl-swatch-green' },
|
|
59
|
+
{ name: 'pink', cssVar: '--wzl-swatch-pink' },
|
|
60
|
+
{ name: 'cyan', cssVar: '--wzl-swatch-cyan' },
|
|
61
|
+
{ name: 'gold', cssVar: '--wzl-swatch-gold' },
|
|
62
|
+
{ name: 'amber', cssVar: '--wzl-swatch-amber' },
|
|
63
|
+
{ name: 'violet', cssVar: '--wzl-swatch-violet' },
|
|
64
|
+
{ name: 'mint', cssVar: '--wzl-swatch-mint' },
|
|
65
|
+
{ name: 'sky', cssVar: '--wzl-swatch-sky' },
|
|
66
|
+
{ name: 'orange', cssVar: '--wzl-swatch-orange' },
|
|
67
|
+
{ name: 'magenta', cssVar: '--wzl-swatch-magenta' },
|
|
67
68
|
];
|
|
68
69
|
|
|
69
|
-
/**
|
|
70
|
-
* Resolves a CSS custom property's computed value off `document.documentElement`
|
|
71
|
-
* so swatch cards can display the actual color alongside the var name.
|
|
72
|
-
* Returns null until the first effect runs.
|
|
73
|
-
*/
|
|
74
|
-
function useResolvedVars(vars: readonly string[]): Record<string, string> {
|
|
75
|
-
const key = vars.join('|');
|
|
76
|
-
const [resolved, setResolved] = useState<Record<string, string>>({});
|
|
77
|
-
useEffect(() => {
|
|
78
|
-
const root = document.querySelector('.lk-theme-interstellar') ?? document.documentElement;
|
|
79
|
-
const cs = window.getComputedStyle(root);
|
|
80
|
-
const out: Record<string, string> = {};
|
|
81
|
-
for (const v of key.split('|')) out[v] = cs.getPropertyValue(v).trim();
|
|
82
|
-
setResolved(out);
|
|
83
|
-
}, [key]);
|
|
84
|
-
return resolved;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
70
|
function SwatchGrid({ tokens, title }: { tokens: readonly Swatch[]; title: string }) {
|
|
88
|
-
const resolved =
|
|
71
|
+
const { resolved } = useTheme();
|
|
89
72
|
return (
|
|
90
73
|
<div>
|
|
91
74
|
<h3 className="lk-theme-doc__heading">{title}</h3>
|
|
@@ -96,7 +79,7 @@ function SwatchGrid({ tokens, title }: { tokens: readonly Swatch[]; title: strin
|
|
|
96
79
|
<div className="lk-theme-doc__swatch-meta">
|
|
97
80
|
<div className="lk-theme-doc__swatch-name">{t.name}</div>
|
|
98
81
|
<code className="lk-theme-doc__swatch-var">{t.cssVar}</code>
|
|
99
|
-
<code className="lk-theme-doc__swatch-value">{resolved[t.cssVar
|
|
82
|
+
<code className="lk-theme-doc__swatch-value">{resolved[t.cssVar as TokenName]}</code>
|
|
100
83
|
</div>
|
|
101
84
|
</div>
|
|
102
85
|
))}
|
|
@@ -108,8 +91,8 @@ function SwatchGrid({ tokens, title }: { tokens: readonly Swatch[]; title: strin
|
|
|
108
91
|
function NebulaPreview() {
|
|
109
92
|
return (
|
|
110
93
|
<div>
|
|
111
|
-
<h3 className="lk-theme-doc__heading">Cosmic backdrop (`--
|
|
112
|
-
<div className="lk-theme-doc__nebula" style={{ background: 'var(--
|
|
94
|
+
<h3 className="lk-theme-doc__heading">Cosmic backdrop (`--wzl-backdrop`)</h3>
|
|
95
|
+
<div className="lk-theme-doc__nebula" style={{ background: 'var(--wzl-backdrop)' }} />
|
|
113
96
|
<p className="lk-theme-doc__note">
|
|
114
97
|
Default: four radial gradients (purple, pink, blue, then a dark void base). Override per-Lab
|
|
115
98
|
by passing <code>nebula={'{[colors]}'}</code> to the <code><Lab></code> component.
|
|
@@ -123,29 +106,29 @@ function TypographySample() {
|
|
|
123
106
|
<div>
|
|
124
107
|
<h3 className="lk-theme-doc__heading">Typography</h3>
|
|
125
108
|
<div className="lk-theme-doc__type-stack">
|
|
126
|
-
<h1 style={{ font: '300 2.6rem/1 var(--
|
|
109
|
+
<h1 style={{ font: '300 2.6rem/1 var(--wzl-font-display)', color: 'var(--wzl-fg)' }}>
|
|
127
110
|
Heading display 300
|
|
128
111
|
</h1>
|
|
129
|
-
<h2 style={{ font: '300 1.4rem/1.2 var(--
|
|
112
|
+
<h2 style={{ font: '300 1.4rem/1.2 var(--wzl-font-display)', color: 'var(--wzl-fg)' }}>
|
|
130
113
|
Heading 300
|
|
131
114
|
</h2>
|
|
132
115
|
<div
|
|
133
116
|
style={{
|
|
134
|
-
font: '300 0.78rem/1 var(--
|
|
135
|
-
color: 'var(--
|
|
117
|
+
font: '300 0.78rem/1 var(--wzl-font-display)',
|
|
118
|
+
color: 'var(--wzl-fg-muted)',
|
|
136
119
|
textTransform: 'uppercase',
|
|
137
120
|
letterSpacing: '0.05em',
|
|
138
121
|
}}
|
|
139
122
|
>
|
|
140
123
|
Label uppercase 300
|
|
141
124
|
</div>
|
|
142
|
-
<p style={{ font: '400 0.9rem/1.5 var(--
|
|
125
|
+
<p style={{ font: '400 0.9rem/1.5 var(--wzl-font-ui)', color: 'var(--wzl-fg)' }}>
|
|
143
126
|
Body 400. Free-form prose at the default font size and line height.
|
|
144
127
|
</p>
|
|
145
128
|
<code
|
|
146
129
|
style={{
|
|
147
|
-
font: '400 0.85rem/1 var(--
|
|
148
|
-
color: 'var(--
|
|
130
|
+
font: '400 0.85rem/1 var(--wzl-font-mono)',
|
|
131
|
+
color: 'var(--wzl-fg)',
|
|
149
132
|
background: 'rgba(0,0,0,0.35)',
|
|
150
133
|
padding: '4px 8px',
|
|
151
134
|
borderRadius: 3,
|
|
@@ -188,20 +171,21 @@ function LivePanelPreview() {
|
|
|
188
171
|
export const Overview: Story = {
|
|
189
172
|
render: () => (
|
|
190
173
|
<div
|
|
191
|
-
className="lk-theme-
|
|
174
|
+
className="lk-theme-doc"
|
|
192
175
|
style={{
|
|
193
|
-
|
|
176
|
+
backgroundColor: 'var(--wzl-surface)',
|
|
177
|
+
backgroundImage: 'var(--wzl-backdrop)',
|
|
194
178
|
padding: 32,
|
|
195
179
|
minHeight: '100vh',
|
|
196
180
|
}}
|
|
197
181
|
>
|
|
198
|
-
<h1 style={{ font: '300 2.6rem/1 var(--
|
|
182
|
+
<h1 style={{ font: '300 2.6rem/1 var(--wzl-font-display)', color: 'var(--wzl-fg)' }}>
|
|
199
183
|
Interstellar
|
|
200
184
|
</h1>
|
|
201
185
|
<p
|
|
202
186
|
style={{
|
|
203
|
-
font: '300 1.05rem/1.4 var(--
|
|
204
|
-
color: 'var(--
|
|
187
|
+
font: '300 1.05rem/1.4 var(--wzl-font-display)',
|
|
188
|
+
color: 'var(--wzl-fg-muted)',
|
|
205
189
|
maxWidth: 640,
|
|
206
190
|
margin: '12px 0 32px',
|
|
207
191
|
}}
|
|
@@ -225,9 +209,10 @@ export const Overview: Story = {
|
|
|
225
209
|
export const Palette: Story = {
|
|
226
210
|
render: () => (
|
|
227
211
|
<div
|
|
228
|
-
className="lk-theme-
|
|
212
|
+
className="lk-theme-doc"
|
|
229
213
|
style={{
|
|
230
|
-
|
|
214
|
+
backgroundColor: 'var(--wzl-surface)',
|
|
215
|
+
backgroundImage: 'var(--wzl-backdrop)',
|
|
231
216
|
padding: 32,
|
|
232
217
|
minHeight: '100vh',
|
|
233
218
|
}}
|
package/src/theme/base.less
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
@import './tokens.less';
|
|
2
|
-
|
|
3
1
|
// Self-hosted Oswald (variable font, wght axis 200–700) for the headline
|
|
4
2
|
// typeface. Sourced from @weasel-js/theme; build:fonts copies it into dist/fonts.
|
|
5
3
|
@font-face {
|
|
@@ -18,11 +16,11 @@
|
|
|
18
16
|
|
|
19
17
|
// Resets and global element defaults.
|
|
20
18
|
.lk-root {
|
|
21
|
-
font-family: var(--
|
|
22
|
-
font-size: var(--
|
|
23
|
-
font-weight: var(--
|
|
24
|
-
color: var(--
|
|
25
|
-
background: var(--
|
|
19
|
+
font-family: var(--wzl-font-ui);
|
|
20
|
+
font-size: var(--wzl-font-size);
|
|
21
|
+
font-weight: var(--wzl-font-weight-light);
|
|
22
|
+
color: var(--wzl-fg);
|
|
23
|
+
background: var(--wzl-surface);
|
|
26
24
|
line-height: 1.4;
|
|
27
25
|
|
|
28
26
|
*, *::before, *::after {
|
|
@@ -32,33 +30,33 @@
|
|
|
32
30
|
button {
|
|
33
31
|
font: inherit;
|
|
34
32
|
color: inherit;
|
|
35
|
-
background: var(--
|
|
36
|
-
border: 1px solid var(--
|
|
37
|
-
border-radius: var(--
|
|
38
|
-
height: var(--
|
|
39
|
-
padding: 0 var(--
|
|
33
|
+
background: var(--wzl-surface-raised);
|
|
34
|
+
border: 1px solid var(--wzl-border);
|
|
35
|
+
border-radius: var(--wzl-radius-md);
|
|
36
|
+
height: var(--wzl-control-h);
|
|
37
|
+
padding: 0 var(--wzl-space-md);
|
|
40
38
|
cursor: pointer;
|
|
41
|
-
backdrop-filter: blur(var(--
|
|
42
|
-
-webkit-backdrop-filter: blur(var(--
|
|
39
|
+
backdrop-filter: blur(var(--wzl-glass-blur));
|
|
40
|
+
-webkit-backdrop-filter: blur(var(--wzl-glass-blur));
|
|
43
41
|
|
|
44
42
|
&:hover {
|
|
45
|
-
border-color: var(--
|
|
46
|
-
color: var(--
|
|
43
|
+
border-color: var(--wzl-accent);
|
|
44
|
+
color: var(--wzl-accent);
|
|
47
45
|
}
|
|
48
46
|
|
|
49
47
|
&:focus-visible {
|
|
50
|
-
outline: 2px solid var(--
|
|
48
|
+
outline: 2px solid var(--wzl-focus-ring);
|
|
51
49
|
outline-offset: 1px;
|
|
52
50
|
}
|
|
53
51
|
|
|
54
52
|
&:disabled {
|
|
55
|
-
color: var(--
|
|
53
|
+
color: var(--wzl-fg-subtle);
|
|
56
54
|
cursor: not-allowed;
|
|
57
55
|
}
|
|
58
56
|
}
|
|
59
57
|
|
|
60
58
|
input[type="range"] {
|
|
61
|
-
accent-color: var(--
|
|
59
|
+
accent-color: var(--wzl-accent);
|
|
62
60
|
}
|
|
63
61
|
}
|
|
64
62
|
|
|
@@ -67,7 +65,9 @@
|
|
|
67
65
|
.lk-lab {
|
|
68
66
|
position: relative;
|
|
69
67
|
isolation: isolate;
|
|
70
|
-
background: var(--
|
|
68
|
+
background-color: var(--wzl-surface);
|
|
69
|
+
// Not the shorthand: `background: none` paints transparent, not the surface.
|
|
70
|
+
background-image: var(--wzl-backdrop);
|
|
71
71
|
background-attachment: fixed;
|
|
72
72
|
}
|
|
73
73
|
|
|
@@ -102,13 +102,13 @@
|
|
|
102
102
|
background-repeat: no-repeat;
|
|
103
103
|
}
|
|
104
104
|
|
|
105
|
-
//
|
|
106
|
-
.
|
|
107
|
-
|
|
105
|
+
// The backdrop follows the token, but a starfield is structure, not a color —
|
|
106
|
+
// it needs the mode.
|
|
107
|
+
.lk-lab[data-wzl-mode='light'] {
|
|
108
108
|
background-attachment: scroll;
|
|
109
109
|
}
|
|
110
110
|
|
|
111
|
-
.lk-
|
|
111
|
+
.lk-lab[data-wzl-mode='light']::before {
|
|
112
112
|
display: none;
|
|
113
113
|
}
|
|
114
114
|
|
|
@@ -116,8 +116,8 @@
|
|
|
116
116
|
.lk-lab h1,
|
|
117
117
|
.lk-lab h2,
|
|
118
118
|
.lk-lab h3 {
|
|
119
|
-
font-family: var(--
|
|
120
|
-
font-weight: var(--
|
|
119
|
+
font-family: var(--wzl-font-display);
|
|
120
|
+
font-weight: var(--wzl-font-weight-light);
|
|
121
121
|
letter-spacing: 0.01em;
|
|
122
122
|
line-height: 1.2;
|
|
123
123
|
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { resolveTheme } from '@weasel-js/theme';
|
|
2
|
+
import { describe, expect, it } from 'vitest';
|
|
3
|
+
import { interstellarTheme } from './interstellar';
|
|
4
|
+
|
|
5
|
+
describe('interstellarTheme', () => {
|
|
6
|
+
it('extends weasel and resolves both modes', () => {
|
|
7
|
+
const dark = resolveTheme(interstellarTheme, 'dark');
|
|
8
|
+
const light = resolveTheme(interstellarTheme, 'light');
|
|
9
|
+
|
|
10
|
+
// Values carried over verbatim from the retired Less.
|
|
11
|
+
expect(dark['--wzl-surface']).toBe('#0a0a14');
|
|
12
|
+
expect(dark['--wzl-accent']).toBe('#b08adb');
|
|
13
|
+
expect(light['--wzl-surface']).toBe('#fafaf7');
|
|
14
|
+
expect(light['--wzl-accent']).toBe('#a86f3c');
|
|
15
|
+
|
|
16
|
+
// Inherited from weasel — interstellar overrides values, not the token set.
|
|
17
|
+
expect(dark['--wzl-space-md']).toBe('12px');
|
|
18
|
+
expect(dark['--wzl-swatch-cyan']).toBe('#00dfff');
|
|
19
|
+
|
|
20
|
+
// Deliberate divergences from the base.
|
|
21
|
+
expect(dark['--wzl-radius-md']).toBe('6px');
|
|
22
|
+
expect(dark['--wzl-font-weight-light']).toBe('300');
|
|
23
|
+
expect(dark['--wzl-glass-blur']).toBe('12px');
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it('carries the cosmic backdrop in dark and drops it in light', () => {
|
|
27
|
+
expect(resolveTheme(interstellarTheme, 'dark')['--wzl-backdrop']).toContain('radial-gradient');
|
|
28
|
+
expect(resolveTheme(interstellarTheme, 'light')['--wzl-backdrop']).toBe('none');
|
|
29
|
+
});
|
|
30
|
+
});
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "interstellar",
|
|
3
|
+
"defaultMode": "dark",
|
|
4
|
+
"primitives": {
|
|
5
|
+
"dimension": {
|
|
6
|
+
"$type": "dimension",
|
|
7
|
+
"radius-md": { "$value": "6px" },
|
|
8
|
+
"glass-blur": { "$value": "12px" }
|
|
9
|
+
},
|
|
10
|
+
"fontWeight": {
|
|
11
|
+
"$type": "fontWeight",
|
|
12
|
+
"font-weight-light": { "$value": 300 },
|
|
13
|
+
"font-weight-medium": { "$value": 500 },
|
|
14
|
+
"font-weight-bold": { "$value": 700 }
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
"modes": {
|
|
18
|
+
"dark": {
|
|
19
|
+
"color": {
|
|
20
|
+
"$type": "color",
|
|
21
|
+
"surface": { "$value": "#0a0a14" },
|
|
22
|
+
"surface-raised": { "$value": "rgba(20, 20, 36, 0.55)" },
|
|
23
|
+
"surface-sunken": { "$value": "#02020a" },
|
|
24
|
+
"border": { "$value": "rgba(255, 255, 255, 0.14)" },
|
|
25
|
+
"line-subtle": { "$value": "rgba(255, 255, 255, 0.08)" },
|
|
26
|
+
"fg": { "$value": "#e8e8f0" },
|
|
27
|
+
"fg-muted": { "$value": "#a8a8c0" },
|
|
28
|
+
"fg-subtle": { "$value": "#5a5a78" },
|
|
29
|
+
"accent": { "$value": "#b08adb" },
|
|
30
|
+
"accent-hover": { "$value": "#c6a3ee" },
|
|
31
|
+
"focus-ring": { "$value": "rgba(176, 138, 219, 0.45)" }
|
|
32
|
+
},
|
|
33
|
+
"gradient": {
|
|
34
|
+
"$type": "gradient",
|
|
35
|
+
"backdrop": {
|
|
36
|
+
"$value": "radial-gradient(ellipse 60% 80% at 18% 30%, rgba(150, 80, 200, 0.22), transparent 70%), radial-gradient(ellipse 55% 90% at 78% 70%, rgba(220, 100, 140, 0.18), transparent 65%), radial-gradient(ellipse 50% 70% at 50% 50%, rgba(60, 110, 200, 0.18), transparent 75%), radial-gradient(ellipse at center, #0a0a18 0%, #02020a 100%)"
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
"light": {
|
|
41
|
+
"color": {
|
|
42
|
+
"$type": "color",
|
|
43
|
+
"surface": { "$value": "#fafaf7" },
|
|
44
|
+
"surface-raised": { "$value": "#ffffff" },
|
|
45
|
+
"surface-sunken": { "$value": "#f0ebe2" },
|
|
46
|
+
"border": { "$value": "#c9bba5" },
|
|
47
|
+
"line-subtle": { "$value": "rgba(0, 0, 0, 0.08)" },
|
|
48
|
+
"fg": { "$value": "#2a2018" },
|
|
49
|
+
"fg-muted": { "$value": "#6b5c4a" },
|
|
50
|
+
"fg-subtle": { "$value": "#a89b85" },
|
|
51
|
+
"accent": { "$value": "#a86f3c" },
|
|
52
|
+
"accent-hover": { "$value": "#c2854f" },
|
|
53
|
+
"focus-ring": { "$value": "rgba(168, 111, 60, 0.35)" }
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { loadDTCG, type Theme } from '@weasel-js/theme';
|
|
2
|
+
import doc from './interstellar.tokens.json' with { type: 'json' };
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* labkit's theme: a cosmic dark and a warm parchment light, extending the
|
|
6
|
+
* built-in weasel theme. Authored as DTCG and loaded at import time — the
|
|
7
|
+
* interchange path a theme exported from a design tool would take.
|
|
8
|
+
*/
|
|
9
|
+
export const interstellarTheme: Theme = loadDTCG(doc);
|
|
@@ -12,10 +12,10 @@
|
|
|
12
12
|
|
|
13
13
|
.lk-layer-stack__title {
|
|
14
14
|
margin: 0;
|
|
15
|
-
font-family: var(--
|
|
16
|
-
font-weight: var(--
|
|
15
|
+
font-family: var(--wzl-font-display);
|
|
16
|
+
font-weight: var(--wzl-font-weight-light);
|
|
17
17
|
font-size: 1rem;
|
|
18
|
-
color: var(--
|
|
18
|
+
color: var(--wzl-fg);
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
.lk-layer-stack__palette {
|
|
@@ -25,17 +25,17 @@
|
|
|
25
25
|
|
|
26
26
|
.lk-layer-stack__add {
|
|
27
27
|
background: transparent;
|
|
28
|
-
border: 1px dashed var(--
|
|
29
|
-
border-radius: var(--
|
|
28
|
+
border: 1px dashed var(--wzl-border);
|
|
29
|
+
border-radius: var(--wzl-radius-sm);
|
|
30
30
|
padding: 2px 8px;
|
|
31
31
|
font-size: 0.78rem;
|
|
32
|
-
color: var(--
|
|
32
|
+
color: var(--wzl-fg-subtle);
|
|
33
33
|
cursor: pointer;
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
.lk-layer-stack__add:hover {
|
|
37
|
-
background: var(--
|
|
38
|
-
color: var(--
|
|
37
|
+
background: var(--wzl-surface-raised);
|
|
38
|
+
color: var(--wzl-fg);
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
.lk-layer-stack__list {
|
|
@@ -45,29 +45,29 @@
|
|
|
45
45
|
|
|
46
46
|
.lk-layer-stack__drop-hint {
|
|
47
47
|
height: 2px;
|
|
48
|
-
background: var(--
|
|
48
|
+
background: var(--wzl-accent);
|
|
49
49
|
border-radius: 1px;
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
.lk-layer-stack__empty {
|
|
53
|
-
color: var(--
|
|
53
|
+
color: var(--wzl-fg-subtle);
|
|
54
54
|
font-size: 0.85rem;
|
|
55
55
|
padding: 8px;
|
|
56
56
|
text-align: center;
|
|
57
57
|
}
|
|
58
58
|
|
|
59
59
|
.lk-layer-card {
|
|
60
|
-
background: var(--
|
|
61
|
-
border: 1px solid var(--
|
|
62
|
-
border-radius: var(--
|
|
60
|
+
background: var(--wzl-surface-raised);
|
|
61
|
+
border: 1px solid var(--wzl-border);
|
|
62
|
+
border-radius: var(--wzl-radius-md);
|
|
63
63
|
overflow: hidden;
|
|
64
64
|
}
|
|
65
65
|
|
|
66
66
|
.lk-layer-card.has-accent {
|
|
67
|
-
// Re-bind --
|
|
67
|
+
// Re-bind --wzl-accent inside the card so descendant controls (slider tracks
|
|
68
68
|
// and thumbs, readouts, etc.) tint to the per-card accent instead of the
|
|
69
69
|
// global theme accent. Mirrors EffectCard's behavior.
|
|
70
|
-
--
|
|
70
|
+
--wzl-accent: var(--lk-layer-card-accent);
|
|
71
71
|
border-left: 3px solid var(--lk-layer-card-accent);
|
|
72
72
|
}
|
|
73
73
|
|
|
@@ -87,7 +87,7 @@
|
|
|
87
87
|
.lk-root .lk-layer-card__handle {
|
|
88
88
|
background: transparent;
|
|
89
89
|
border: 0;
|
|
90
|
-
color: var(--
|
|
90
|
+
color: var(--wzl-fg-subtle);
|
|
91
91
|
padding: 2px 4px;
|
|
92
92
|
cursor: grab;
|
|
93
93
|
display: inline-flex;
|
|
@@ -95,7 +95,7 @@
|
|
|
95
95
|
justify-content: center;
|
|
96
96
|
min-width: 22px;
|
|
97
97
|
height: 22px;
|
|
98
|
-
border-radius: var(--
|
|
98
|
+
border-radius: var(--wzl-radius-sm);
|
|
99
99
|
font-weight: 600;
|
|
100
100
|
font-size: 0.85rem;
|
|
101
101
|
}
|
|
@@ -118,7 +118,7 @@
|
|
|
118
118
|
.lk-layer-card__primary {
|
|
119
119
|
background: transparent;
|
|
120
120
|
border: 0;
|
|
121
|
-
color: var(--
|
|
121
|
+
color: var(--wzl-fg);
|
|
122
122
|
font: inherit;
|
|
123
123
|
text-transform: uppercase;
|
|
124
124
|
letter-spacing: 0.06em;
|
|
@@ -127,17 +127,17 @@
|
|
|
127
127
|
.lk-root .lk-layer-card__remove {
|
|
128
128
|
background: transparent;
|
|
129
129
|
border: 0;
|
|
130
|
-
color: var(--
|
|
130
|
+
color: var(--wzl-fg-subtle);
|
|
131
131
|
font-size: 1rem;
|
|
132
132
|
cursor: pointer;
|
|
133
133
|
padding: 2px 6px;
|
|
134
134
|
}
|
|
135
135
|
|
|
136
136
|
.lk-layer-card__remove:hover {
|
|
137
|
-
color: var(--
|
|
137
|
+
color: var(--wzl-fg);
|
|
138
138
|
}
|
|
139
139
|
|
|
140
140
|
.lk-layer-card__body {
|
|
141
141
|
padding: 8px;
|
|
142
|
-
border-top: 1px solid var(--
|
|
142
|
+
border-top: 1px solid var(--wzl-border);
|
|
143
143
|
}
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
justify-content: space-between;
|
|
21
21
|
font-variant-numeric: tabular-nums;
|
|
22
22
|
font-size: 0.85rem;
|
|
23
|
-
color: var(--
|
|
23
|
+
color: var(--wzl-fg-subtle);
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
.lk-curve-field__readout {
|
|
@@ -35,14 +35,14 @@
|
|
|
35
35
|
|
|
36
36
|
.lk-curve-field__action {
|
|
37
37
|
background: transparent;
|
|
38
|
-
border: 1px solid var(--
|
|
39
|
-
border-radius: var(--
|
|
40
|
-
color: var(--
|
|
38
|
+
border: 1px solid var(--wzl-border);
|
|
39
|
+
border-radius: var(--wzl-radius-sm);
|
|
40
|
+
color: var(--wzl-fg);
|
|
41
41
|
padding: 4px 10px;
|
|
42
42
|
font-size: 0.78rem;
|
|
43
43
|
cursor: pointer;
|
|
44
44
|
}
|
|
45
45
|
|
|
46
46
|
.lk-curve-field__action:hover {
|
|
47
|
-
background: var(--
|
|
47
|
+
background: var(--wzl-surface-raised);
|
|
48
48
|
}
|
|
@@ -26,7 +26,7 @@ export function Subpanel({ title, children, className }: SubpanelProps) {
|
|
|
26
26
|
|
|
27
27
|
// ── EffectCard ───────────────────────────────────────────────────────
|
|
28
28
|
// Draggable, collapsible card for stacked effect editors. Optional --lk-panel-accent
|
|
29
|
-
// per-instance recolors the title bar, border-left, and (via re-binding --
|
|
29
|
+
// per-instance recolors the title bar, border-left, and (via re-binding --wzl-accent
|
|
30
30
|
// inside the card) every descendant control that reads from the accent token.
|
|
31
31
|
|
|
32
32
|
export interface EffectCardProps {
|
|
@@ -82,7 +82,7 @@ export function EffectCard({
|
|
|
82
82
|
const stateClass = `${expanded ? 'is-expanded' : 'is-collapsed'}${dragging ? ' is-dragging' : ''}${accent ? ' has-accent' : ''}`;
|
|
83
83
|
const cls = `lk-effect-card ${stateClass}${className ? ` ${className}` : ''}`;
|
|
84
84
|
// Per-instance dynamic color → CSS custom property requires inline style.
|
|
85
|
-
// The card's CSS re-binds --
|
|
85
|
+
// The card's CSS re-binds --wzl-accent to --lk-panel-accent so descendants tint.
|
|
86
86
|
const style = accent ? ({ '--lk-panel-accent': accent } as CSSProperties) : undefined;
|
|
87
87
|
|
|
88
88
|
// When a toggle handler is supplied the header acts as a disclosure button:
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
.lk-property-group {
|
|
2
2
|
grid-column: 1 / -1;
|
|
3
|
-
background: var(--
|
|
4
|
-
border-radius: var(--
|
|
3
|
+
background: var(--wzl-surface-sunken);
|
|
4
|
+
border-radius: var(--wzl-radius-md);
|
|
5
5
|
padding: 10px 12px 12px;
|
|
6
6
|
}
|
|
7
7
|
|
|
@@ -11,17 +11,17 @@
|
|
|
11
11
|
align-items: center;
|
|
12
12
|
gap: 10px;
|
|
13
13
|
margin: 0 0 8px;
|
|
14
|
-
font-family: var(--
|
|
15
|
-
font-weight: var(--
|
|
14
|
+
font-family: var(--wzl-font-display);
|
|
15
|
+
font-weight: var(--wzl-font-weight-light);
|
|
16
16
|
font-size: 0.78rem;
|
|
17
17
|
letter-spacing: 0.08em;
|
|
18
18
|
text-transform: uppercase;
|
|
19
|
-
color: var(--
|
|
19
|
+
color: var(--wzl-fg-subtle);
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
.lk-property-group__title hr {
|
|
23
23
|
border: 0;
|
|
24
|
-
border-top: 1px solid var(--
|
|
24
|
+
border-top: 1px solid var(--wzl-border);
|
|
25
25
|
margin: 0;
|
|
26
26
|
}
|
|
27
27
|
|