@kitlangton/knobs 0.4.0-next.0 → 0.4.0-next.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 +288 -43
- package/dist/dev/{chunk-stbcgz1y.js → chunk-1qzffbpa.js} +443 -451
- package/dist/dev/{chunk-7xgkerd2.js → chunk-3ygqgy1x.js} +23 -1
- package/dist/dev/{chunk-pmkvb9ep.js → chunk-8mabjeyk.js} +1920 -507
- package/dist/dev/{chunk-t68smqkc.js → chunk-ayb292zj.js} +13 -11
- package/dist/dev/index.js +10 -5
- package/dist/index.js +25 -1
- package/dist/panel.js +2900 -1320
- package/dist/react.js +294 -6
- package/dist/solid.js +292 -4
- package/dist/themes.js +1509 -7
- package/dist/types/core/adapter.d.ts +6 -2
- package/dist/types/core/appearance.d.ts +44 -0
- package/dist/types/core/glide.d.ts +7 -0
- package/dist/types/core/motion.d.ts +66 -0
- package/dist/types/core/root.d.ts +13 -0
- package/dist/types/core/store.d.ts +18 -5
- package/dist/types/core/theme.d.ts +10 -3
- package/dist/types/index.d.ts +2 -1
- package/dist/types/panel/gpu/color.d.ts +6 -0
- package/dist/types/panel/motion.d.ts +1 -1
- package/dist/types/panel/styles.d.ts +2 -3
- package/dist/types/themes/define.d.ts +104 -0
- package/dist/types/themes/index.d.ts +11 -0
- package/dist/types/themes/knobs.d.ts +5 -0
- package/dist/types/themes/void.d.ts +8 -0
- package/dist/types/tokens/color.d.ts +42 -0
- package/dist/types/tokens/css.d.ts +13 -0
- package/dist/types/tokens/evaluate.d.ts +8 -0
- package/dist/types/tokens/index.d.ts +4 -0
- package/dist/types/tokens/schema.d.ts +1100 -0
- package/dist/types/ui/bento-css.d.ts +1 -1
- package/dist/types/ui/compare-css.d.ts +1 -1
- package/dist/types/ui/index.d.ts +1 -1
- package/dist/types/ui/look.d.ts +18 -13
- package/dist/types/ui/overlay-css.d.ts +1 -1
- package/dist/types/ui/readout-css.d.ts +1 -1
- package/dist/types/ui/readout-model.d.ts +5 -1
- package/dist/types/ui/rgba.d.ts +11 -0
- package/dist/ui-react.js +2320 -676
- package/dist/ui-solid.js +2320 -676
- package/dist/ui.js +2552 -906
- package/package.json +1 -1
package/dist/react.js
CHANGED
|
@@ -22,12 +22,299 @@ import {
|
|
|
22
22
|
useSyncExternalStore as useSyncExternalStore2
|
|
23
23
|
} from "react";
|
|
24
24
|
|
|
25
|
+
// src/core/spring.ts
|
|
26
|
+
class Spring {
|
|
27
|
+
x;
|
|
28
|
+
omega;
|
|
29
|
+
zeta;
|
|
30
|
+
eps;
|
|
31
|
+
v = 0;
|
|
32
|
+
target;
|
|
33
|
+
next;
|
|
34
|
+
constructor(x, omega = 24, zeta = 0.86, eps = 0.005) {
|
|
35
|
+
this.x = x;
|
|
36
|
+
this.omega = omega;
|
|
37
|
+
this.zeta = zeta;
|
|
38
|
+
this.eps = eps;
|
|
39
|
+
this.target = x;
|
|
40
|
+
}
|
|
41
|
+
set(target, delay = 0) {
|
|
42
|
+
if (delay > 0) {
|
|
43
|
+
if (target !== (this.next?.target ?? this.target))
|
|
44
|
+
this.next = { target, at: performance.now() + delay };
|
|
45
|
+
return this;
|
|
46
|
+
}
|
|
47
|
+
this.next = undefined;
|
|
48
|
+
this.target = target;
|
|
49
|
+
return this;
|
|
50
|
+
}
|
|
51
|
+
snap(x) {
|
|
52
|
+
this.next = undefined;
|
|
53
|
+
this.x = this.target = x;
|
|
54
|
+
this.v = 0;
|
|
55
|
+
return this;
|
|
56
|
+
}
|
|
57
|
+
step(dt) {
|
|
58
|
+
if (this.next && performance.now() >= this.next.at) {
|
|
59
|
+
this.target = this.next.target;
|
|
60
|
+
this.next = undefined;
|
|
61
|
+
}
|
|
62
|
+
if (this.x === this.target && this.v === 0)
|
|
63
|
+
return this.x;
|
|
64
|
+
const clampedDt = Math.min(dt, 0.1);
|
|
65
|
+
const h = 1 / 480;
|
|
66
|
+
for (let t = 0;t < clampedDt; t += h) {
|
|
67
|
+
const k = Math.min(h, clampedDt - t);
|
|
68
|
+
const a = -this.omega * this.omega * (this.x - this.target) - 2 * this.zeta * this.omega * this.v;
|
|
69
|
+
this.v += a * k;
|
|
70
|
+
this.x += this.v * k;
|
|
71
|
+
}
|
|
72
|
+
if (this.resting) {
|
|
73
|
+
this.x = this.target;
|
|
74
|
+
this.v = 0;
|
|
75
|
+
}
|
|
76
|
+
return this.x;
|
|
77
|
+
}
|
|
78
|
+
get resting() {
|
|
79
|
+
return !this.next && Math.abs(this.x - this.target) < this.eps && Math.abs(this.v) < this.eps * 4;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
function springMotion({ duration, bounce }) {
|
|
83
|
+
return {
|
|
84
|
+
omega: 2 * Math.PI / Math.max(0.01, duration),
|
|
85
|
+
zeta: bounce >= 0 ? 1 - bounce : 1 / (1 + bounce)
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
function springEasing(omega, zeta) {
|
|
89
|
+
const s = new Spring(0, omega, zeta).set(1);
|
|
90
|
+
const points = ["0"];
|
|
91
|
+
const dt = 1 / 60;
|
|
92
|
+
let t = 0;
|
|
93
|
+
while (t < 4 && !(Math.abs(s.x - 1) < 0.002 && Math.abs(s.v) < 0.05)) {
|
|
94
|
+
s.step(dt);
|
|
95
|
+
t += dt;
|
|
96
|
+
points.push(String(Math.round(s.x * 1000) / 1000));
|
|
97
|
+
}
|
|
98
|
+
points[points.length - 1] = "1";
|
|
99
|
+
return { easing: `linear(${points.join(",")})`, ms: Math.round(t * 1000) };
|
|
100
|
+
}
|
|
101
|
+
function springCss(value) {
|
|
102
|
+
const { omega, zeta } = springMotion(value);
|
|
103
|
+
const { easing, ms } = springEasing(omega, zeta);
|
|
104
|
+
return { easing, duration: ms };
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// src/core/theme.ts
|
|
108
|
+
var property = (k) => k.startsWith("--") ? k : `--k-${k}`;
|
|
109
|
+
function presetCss(preset) {
|
|
110
|
+
if (!/^[\w-]+$/.test(preset.name))
|
|
111
|
+
throw new Error(`Invalid preset name: ${preset.name}`);
|
|
112
|
+
const at = `.knobs-root[data-preset="${preset.name}"]`;
|
|
113
|
+
const light = preset.light ?? {};
|
|
114
|
+
const decls = Object.entries(preset.dark).map(([k, dark]) => {
|
|
115
|
+
const l = light[k];
|
|
116
|
+
return l === undefined || String(l) === String(dark) ? `${property(k)}:${dark}` : `${property(k)}:light-dark(${l},${dark})`;
|
|
117
|
+
});
|
|
118
|
+
for (const [k, l] of Object.entries(light))
|
|
119
|
+
if (!(k in preset.dark) && k !== "color-scheme")
|
|
120
|
+
decls.push(`${property(k)}:${l}`);
|
|
121
|
+
return `${at}{${decls.join(";")}}${(preset.css ?? "").replaceAll("&", at)}`;
|
|
122
|
+
}
|
|
123
|
+
var glide = /* @__PURE__ */ springCss({ duration: 0.185, bounce: 0.14 });
|
|
124
|
+
var problemsPreset = {
|
|
125
|
+
name: "problems",
|
|
126
|
+
dark: {
|
|
127
|
+
bg: "#161618",
|
|
128
|
+
surface: "rgba(255,255,255,.055)",
|
|
129
|
+
"surface-hi": "rgba(255,255,255,.11)",
|
|
130
|
+
line: "rgba(255,255,255,.075)",
|
|
131
|
+
"line-hi": "rgba(255,255,255,.12)",
|
|
132
|
+
text: "#f5f5f7",
|
|
133
|
+
label: "rgba(235,235,245,.62)",
|
|
134
|
+
dim: "rgba(235,235,245,.36)",
|
|
135
|
+
accent: "#0091ff",
|
|
136
|
+
modified: "#0091ff",
|
|
137
|
+
"seg-bg": "rgba(120,120,128,.16)",
|
|
138
|
+
"seg-active": "rgba(120,120,128,.24)",
|
|
139
|
+
"toggle-track": "rgba(120,120,128,.32)",
|
|
140
|
+
"toggle-thumb": "#fff",
|
|
141
|
+
rim: "transparent",
|
|
142
|
+
font: 'system-ui,-apple-system,BlinkMacSystemFont,"Helvetica Neue",sans-serif',
|
|
143
|
+
mono: '"Kit SF Mono",ui-monospace,Menlo,monospace',
|
|
144
|
+
"font-size": "13px",
|
|
145
|
+
"label-weight": 500,
|
|
146
|
+
row: "34px",
|
|
147
|
+
radius: "8px",
|
|
148
|
+
"panel-radius": "12px",
|
|
149
|
+
pad: "0px",
|
|
150
|
+
inset: "10px",
|
|
151
|
+
gap: "4px",
|
|
152
|
+
"row-gap": "4px",
|
|
153
|
+
glass: 0,
|
|
154
|
+
glow: 0,
|
|
155
|
+
blur: 0.6,
|
|
156
|
+
"hover-in": 0,
|
|
157
|
+
"hover-out": 100,
|
|
158
|
+
"handle-rest": 0.55,
|
|
159
|
+
handle: "var(--k-text)",
|
|
160
|
+
"handle-inset": "7.5px",
|
|
161
|
+
"fill-base": "transparent",
|
|
162
|
+
"fill-rest-mix": "24%",
|
|
163
|
+
"fill-hover-mix": "36%",
|
|
164
|
+
"fill-active-mix": "36%",
|
|
165
|
+
chrome: 0,
|
|
166
|
+
"group-transform": "none",
|
|
167
|
+
"value-font": "var(--k-mono)",
|
|
168
|
+
"unit-gap": "0px",
|
|
169
|
+
"unit-color": "currentColor",
|
|
170
|
+
"readout-mark": 1,
|
|
171
|
+
"group-size": "12px",
|
|
172
|
+
"group-color": "rgba(235,235,245,.62)",
|
|
173
|
+
"group-inset": "0px",
|
|
174
|
+
"group-tracking": "-.01em",
|
|
175
|
+
"group-divider": "rgba(255,255,255,.075)",
|
|
176
|
+
"group-divider-gap": "8px",
|
|
177
|
+
"curve-inset": "0px",
|
|
178
|
+
"curve-guide": "dashed",
|
|
179
|
+
"curve-dot": 0,
|
|
180
|
+
spring: "0.185 0.14",
|
|
181
|
+
"fill-ease": glide.easing,
|
|
182
|
+
"fill-ms": glide.duration
|
|
183
|
+
},
|
|
184
|
+
light: {
|
|
185
|
+
bg: "#fff",
|
|
186
|
+
surface: "rgba(0,0,0,.045)",
|
|
187
|
+
"surface-hi": "rgba(0,0,0,.09)",
|
|
188
|
+
line: "rgba(0,0,0,.07)",
|
|
189
|
+
"line-hi": "rgba(0,0,0,.11)",
|
|
190
|
+
text: "#000",
|
|
191
|
+
label: "rgba(60,60,67,.66)",
|
|
192
|
+
dim: "rgba(60,60,67,.38)",
|
|
193
|
+
accent: "#0088ff",
|
|
194
|
+
modified: "#0088ff",
|
|
195
|
+
"seg-bg": "rgba(120,120,128,.11)",
|
|
196
|
+
"seg-active": "#fff",
|
|
197
|
+
"toggle-track": "rgba(120,120,128,.2)",
|
|
198
|
+
"toggle-thumb": "#fff",
|
|
199
|
+
rim: "transparent",
|
|
200
|
+
"group-color": "rgba(60,60,67,.66)",
|
|
201
|
+
"group-divider": "rgba(0,0,0,.07)"
|
|
202
|
+
}
|
|
203
|
+
};
|
|
204
|
+
|
|
205
|
+
// src/core/appearance.ts
|
|
206
|
+
var MODES = {
|
|
207
|
+
dark: "dark",
|
|
208
|
+
light: "light",
|
|
209
|
+
auto: "system"
|
|
210
|
+
};
|
|
211
|
+
function resolveLook(options = {}, base) {
|
|
212
|
+
const t = options.theme;
|
|
213
|
+
const mode = typeof t === "string" ? MODES[t] : undefined;
|
|
214
|
+
const theme = typeof t === "object" ? t : base?.theme;
|
|
215
|
+
const preset = options.preset ?? base?.preset;
|
|
216
|
+
return {
|
|
217
|
+
...theme ? { theme } : {},
|
|
218
|
+
appearance: options.appearance ?? mode ?? base?.appearance ?? "inherit",
|
|
219
|
+
...preset ? { preset } : {}
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
var themes = new Map;
|
|
223
|
+
var themeSelector = (name) => `:where(.knobs-root)[data-knobs-theme="${name}"]`;
|
|
224
|
+
function upsertStyle(doc, key, value, content) {
|
|
225
|
+
const existing = doc.querySelector(`style[${key}="${value}"]`);
|
|
226
|
+
if (existing) {
|
|
227
|
+
if (existing.textContent !== content)
|
|
228
|
+
existing.textContent = content;
|
|
229
|
+
return;
|
|
230
|
+
}
|
|
231
|
+
const style = doc.createElement("style");
|
|
232
|
+
style.setAttribute(key, value);
|
|
233
|
+
style.textContent = content;
|
|
234
|
+
doc.head.append(style);
|
|
235
|
+
}
|
|
236
|
+
function injectTheme(doc, theme) {
|
|
237
|
+
themes.set(theme.name, theme);
|
|
238
|
+
upsertStyle(doc, "data-knobs-theme-css", theme.name, theme.css({ selector: themeSelector(theme.name) }));
|
|
239
|
+
}
|
|
240
|
+
var presets = new Map;
|
|
241
|
+
function injectPreset(doc, preset) {
|
|
242
|
+
presets.set(preset.name, preset);
|
|
243
|
+
upsertStyle(doc, "data-knobs-preset", preset.name, presetCss(preset));
|
|
244
|
+
}
|
|
245
|
+
var setAttr = (el, name, value) => {
|
|
246
|
+
if (value === undefined)
|
|
247
|
+
el.removeAttribute(name);
|
|
248
|
+
else if (el.getAttribute(name) !== value)
|
|
249
|
+
el.setAttribute(name, value);
|
|
250
|
+
};
|
|
251
|
+
function applyLook(el, look) {
|
|
252
|
+
const doc = el.ownerDocument;
|
|
253
|
+
if (look.theme)
|
|
254
|
+
injectTheme(doc, look.theme);
|
|
255
|
+
if (look.preset)
|
|
256
|
+
injectPreset(doc, look.preset);
|
|
257
|
+
setAttr(el, "data-knobs-theme", look.theme?.name);
|
|
258
|
+
setAttr(el, "data-preset", look.preset?.name);
|
|
259
|
+
setAttr(el, "data-appearance", look.appearance === "inherit" ? undefined : look.appearance);
|
|
260
|
+
if (look.appearance === "inherit")
|
|
261
|
+
followPage(el);
|
|
262
|
+
else
|
|
263
|
+
clearInherited(el);
|
|
264
|
+
}
|
|
265
|
+
var clearInherited = (el) => {
|
|
266
|
+
el.style.removeProperty("color-scheme");
|
|
267
|
+
el.style.removeProperty("--_k-light");
|
|
268
|
+
};
|
|
269
|
+
function resolveInherited(el) {
|
|
270
|
+
const parent = el.parentElement;
|
|
271
|
+
const win = el.ownerDocument.defaultView;
|
|
272
|
+
if (!parent || !win || el.hasAttribute("data-appearance"))
|
|
273
|
+
return;
|
|
274
|
+
if (parent.closest(".knobs-root"))
|
|
275
|
+
return clearInherited(el);
|
|
276
|
+
const scheme = win.getComputedStyle(parent).colorScheme.trim();
|
|
277
|
+
const dark = /\bdark\b/.test(scheme);
|
|
278
|
+
const light = /\blight\b/.test(scheme);
|
|
279
|
+
if (!dark && !light)
|
|
280
|
+
return clearInherited(el);
|
|
281
|
+
const isLight = dark && light ? win.matchMedia?.("(prefers-color-scheme: light)").matches ?? false : light;
|
|
282
|
+
el.style.setProperty("color-scheme", "inherit");
|
|
283
|
+
el.style.setProperty("--_k-light", isLight ? "1" : "0");
|
|
284
|
+
}
|
|
285
|
+
var watched = new WeakSet;
|
|
286
|
+
function followPage(el) {
|
|
287
|
+
const doc = el.ownerDocument;
|
|
288
|
+
const win = doc.defaultView;
|
|
289
|
+
if (!win)
|
|
290
|
+
return;
|
|
291
|
+
const run = () => resolveInherited(el);
|
|
292
|
+
if (el.isConnected)
|
|
293
|
+
run();
|
|
294
|
+
queueMicrotask(run);
|
|
295
|
+
win.requestAnimationFrame?.(run);
|
|
296
|
+
if (watched.has(doc))
|
|
297
|
+
return;
|
|
298
|
+
watched.add(doc);
|
|
299
|
+
const all = () => {
|
|
300
|
+
for (const root of doc.querySelectorAll(".knobs-root:not([data-appearance])"))
|
|
301
|
+
resolveInherited(root);
|
|
302
|
+
};
|
|
303
|
+
const observer = new MutationObserver(all);
|
|
304
|
+
const attributeFilter = ["class", "data-theme", "data-appearance"];
|
|
305
|
+
observer.observe(doc.documentElement, { attributes: true, attributeFilter });
|
|
306
|
+
if (doc.body)
|
|
307
|
+
observer.observe(doc.body, { attributes: true, attributeFilter });
|
|
308
|
+
win.matchMedia?.("(prefers-color-scheme: light)").addEventListener?.("change", all);
|
|
309
|
+
}
|
|
310
|
+
|
|
25
311
|
// src/core/adapter.ts
|
|
26
|
-
|
|
312
|
+
var panelLook = (controls, look = {}) => resolveLook(look, resolveLook({ theme: controls.theme, appearance: controls.appearance }));
|
|
313
|
+
function syncPanelLook(host, controls, look = {}, density) {
|
|
27
314
|
const panel = host?.firstElementChild;
|
|
28
315
|
if (!panel)
|
|
29
316
|
return;
|
|
30
|
-
panel
|
|
317
|
+
applyLook(panel, panelLook(controls, look));
|
|
31
318
|
panel.dataset.density = density ?? controls.density;
|
|
32
319
|
}
|
|
33
320
|
function syncPanelValues(controls, descriptors, values, land = false) {
|
|
@@ -43,6 +330,7 @@ function mountPanelAdapter(host, controls, getProps) {
|
|
|
43
330
|
return controls.mount(host, {
|
|
44
331
|
title: p.title,
|
|
45
332
|
theme: p.theme,
|
|
333
|
+
appearance: p.appearance,
|
|
46
334
|
density: p.density,
|
|
47
335
|
renderer: p.renderer,
|
|
48
336
|
variants: p.variants,
|
|
@@ -57,7 +345,7 @@ function mountPanelAdapter(host, controls, getProps) {
|
|
|
57
345
|
onClose: p.onClose ? () => getProps().onClose?.() : undefined,
|
|
58
346
|
onReady(panel) {
|
|
59
347
|
const cur = getProps();
|
|
60
|
-
syncPanelLook(host, controls, cur
|
|
348
|
+
syncPanelLook(host, controls, cur, cur.density);
|
|
61
349
|
cur.onReady?.(panel);
|
|
62
350
|
}
|
|
63
351
|
});
|
|
@@ -89,7 +377,7 @@ function Knobs({
|
|
|
89
377
|
return cloneElement(children, { ref });
|
|
90
378
|
}
|
|
91
379
|
function KnobsPanel(props) {
|
|
92
|
-
const { controls, descriptors, values, land, theme, density } = props;
|
|
380
|
+
const { controls, descriptors, values, land, theme, appearance, preset, density } = props;
|
|
93
381
|
const enabled = useSyncExternalStore2(controls.subscribe, () => controls.enabled, () => false);
|
|
94
382
|
const ref = useRef(null);
|
|
95
383
|
const latest = useRef(props);
|
|
@@ -105,8 +393,8 @@ function KnobsPanel(props) {
|
|
|
105
393
|
syncPanelValues(controls, descriptors, values, Boolean(land));
|
|
106
394
|
}, [enabled, controls, descriptors, values, land]);
|
|
107
395
|
useEffect(() => {
|
|
108
|
-
syncPanelLook(ref.current, controls, theme, density);
|
|
109
|
-
}, [controls, theme, density]);
|
|
396
|
+
syncPanelLook(ref.current, controls, { theme, appearance, preset }, density);
|
|
397
|
+
}, [controls, theme, appearance, preset, density]);
|
|
110
398
|
if (!enabled)
|
|
111
399
|
return null;
|
|
112
400
|
return /* @__PURE__ */ jsx("div", {
|
package/dist/solid.js
CHANGED
|
@@ -179,12 +179,299 @@ import {
|
|
|
179
179
|
untrack
|
|
180
180
|
} from "solid-js";
|
|
181
181
|
|
|
182
|
+
// src/core/spring.ts
|
|
183
|
+
class Spring {
|
|
184
|
+
x;
|
|
185
|
+
omega;
|
|
186
|
+
zeta;
|
|
187
|
+
eps;
|
|
188
|
+
v = 0;
|
|
189
|
+
target;
|
|
190
|
+
next;
|
|
191
|
+
constructor(x, omega = 24, zeta = 0.86, eps = 0.005) {
|
|
192
|
+
this.x = x;
|
|
193
|
+
this.omega = omega;
|
|
194
|
+
this.zeta = zeta;
|
|
195
|
+
this.eps = eps;
|
|
196
|
+
this.target = x;
|
|
197
|
+
}
|
|
198
|
+
set(target, delay = 0) {
|
|
199
|
+
if (delay > 0) {
|
|
200
|
+
if (target !== (this.next?.target ?? this.target))
|
|
201
|
+
this.next = { target, at: performance.now() + delay };
|
|
202
|
+
return this;
|
|
203
|
+
}
|
|
204
|
+
this.next = undefined;
|
|
205
|
+
this.target = target;
|
|
206
|
+
return this;
|
|
207
|
+
}
|
|
208
|
+
snap(x) {
|
|
209
|
+
this.next = undefined;
|
|
210
|
+
this.x = this.target = x;
|
|
211
|
+
this.v = 0;
|
|
212
|
+
return this;
|
|
213
|
+
}
|
|
214
|
+
step(dt) {
|
|
215
|
+
if (this.next && performance.now() >= this.next.at) {
|
|
216
|
+
this.target = this.next.target;
|
|
217
|
+
this.next = undefined;
|
|
218
|
+
}
|
|
219
|
+
if (this.x === this.target && this.v === 0)
|
|
220
|
+
return this.x;
|
|
221
|
+
const clampedDt = Math.min(dt, 0.1);
|
|
222
|
+
const h = 1 / 480;
|
|
223
|
+
for (let t = 0;t < clampedDt; t += h) {
|
|
224
|
+
const k = Math.min(h, clampedDt - t);
|
|
225
|
+
const a = -this.omega * this.omega * (this.x - this.target) - 2 * this.zeta * this.omega * this.v;
|
|
226
|
+
this.v += a * k;
|
|
227
|
+
this.x += this.v * k;
|
|
228
|
+
}
|
|
229
|
+
if (this.resting) {
|
|
230
|
+
this.x = this.target;
|
|
231
|
+
this.v = 0;
|
|
232
|
+
}
|
|
233
|
+
return this.x;
|
|
234
|
+
}
|
|
235
|
+
get resting() {
|
|
236
|
+
return !this.next && Math.abs(this.x - this.target) < this.eps && Math.abs(this.v) < this.eps * 4;
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
function springMotion({ duration, bounce }) {
|
|
240
|
+
return {
|
|
241
|
+
omega: 2 * Math.PI / Math.max(0.01, duration),
|
|
242
|
+
zeta: bounce >= 0 ? 1 - bounce : 1 / (1 + bounce)
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
function springEasing(omega, zeta) {
|
|
246
|
+
const s = new Spring(0, omega, zeta).set(1);
|
|
247
|
+
const points = ["0"];
|
|
248
|
+
const dt = 1 / 60;
|
|
249
|
+
let t = 0;
|
|
250
|
+
while (t < 4 && !(Math.abs(s.x - 1) < 0.002 && Math.abs(s.v) < 0.05)) {
|
|
251
|
+
s.step(dt);
|
|
252
|
+
t += dt;
|
|
253
|
+
points.push(String(Math.round(s.x * 1000) / 1000));
|
|
254
|
+
}
|
|
255
|
+
points[points.length - 1] = "1";
|
|
256
|
+
return { easing: `linear(${points.join(",")})`, ms: Math.round(t * 1000) };
|
|
257
|
+
}
|
|
258
|
+
function springCss(value) {
|
|
259
|
+
const { omega, zeta } = springMotion(value);
|
|
260
|
+
const { easing, ms } = springEasing(omega, zeta);
|
|
261
|
+
return { easing, duration: ms };
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
// src/core/theme.ts
|
|
265
|
+
var property = (k) => k.startsWith("--") ? k : `--k-${k}`;
|
|
266
|
+
function presetCss(preset) {
|
|
267
|
+
if (!/^[\w-]+$/.test(preset.name))
|
|
268
|
+
throw new Error(`Invalid preset name: ${preset.name}`);
|
|
269
|
+
const at = `.knobs-root[data-preset="${preset.name}"]`;
|
|
270
|
+
const light = preset.light ?? {};
|
|
271
|
+
const decls = Object.entries(preset.dark).map(([k, dark]) => {
|
|
272
|
+
const l = light[k];
|
|
273
|
+
return l === undefined || String(l) === String(dark) ? `${property(k)}:${dark}` : `${property(k)}:light-dark(${l},${dark})`;
|
|
274
|
+
});
|
|
275
|
+
for (const [k, l] of Object.entries(light))
|
|
276
|
+
if (!(k in preset.dark) && k !== "color-scheme")
|
|
277
|
+
decls.push(`${property(k)}:${l}`);
|
|
278
|
+
return `${at}{${decls.join(";")}}${(preset.css ?? "").replaceAll("&", at)}`;
|
|
279
|
+
}
|
|
280
|
+
var glide = /* @__PURE__ */ springCss({ duration: 0.185, bounce: 0.14 });
|
|
281
|
+
var problemsPreset = {
|
|
282
|
+
name: "problems",
|
|
283
|
+
dark: {
|
|
284
|
+
bg: "#161618",
|
|
285
|
+
surface: "rgba(255,255,255,.055)",
|
|
286
|
+
"surface-hi": "rgba(255,255,255,.11)",
|
|
287
|
+
line: "rgba(255,255,255,.075)",
|
|
288
|
+
"line-hi": "rgba(255,255,255,.12)",
|
|
289
|
+
text: "#f5f5f7",
|
|
290
|
+
label: "rgba(235,235,245,.62)",
|
|
291
|
+
dim: "rgba(235,235,245,.36)",
|
|
292
|
+
accent: "#0091ff",
|
|
293
|
+
modified: "#0091ff",
|
|
294
|
+
"seg-bg": "rgba(120,120,128,.16)",
|
|
295
|
+
"seg-active": "rgba(120,120,128,.24)",
|
|
296
|
+
"toggle-track": "rgba(120,120,128,.32)",
|
|
297
|
+
"toggle-thumb": "#fff",
|
|
298
|
+
rim: "transparent",
|
|
299
|
+
font: 'system-ui,-apple-system,BlinkMacSystemFont,"Helvetica Neue",sans-serif',
|
|
300
|
+
mono: '"Kit SF Mono",ui-monospace,Menlo,monospace',
|
|
301
|
+
"font-size": "13px",
|
|
302
|
+
"label-weight": 500,
|
|
303
|
+
row: "34px",
|
|
304
|
+
radius: "8px",
|
|
305
|
+
"panel-radius": "12px",
|
|
306
|
+
pad: "0px",
|
|
307
|
+
inset: "10px",
|
|
308
|
+
gap: "4px",
|
|
309
|
+
"row-gap": "4px",
|
|
310
|
+
glass: 0,
|
|
311
|
+
glow: 0,
|
|
312
|
+
blur: 0.6,
|
|
313
|
+
"hover-in": 0,
|
|
314
|
+
"hover-out": 100,
|
|
315
|
+
"handle-rest": 0.55,
|
|
316
|
+
handle: "var(--k-text)",
|
|
317
|
+
"handle-inset": "7.5px",
|
|
318
|
+
"fill-base": "transparent",
|
|
319
|
+
"fill-rest-mix": "24%",
|
|
320
|
+
"fill-hover-mix": "36%",
|
|
321
|
+
"fill-active-mix": "36%",
|
|
322
|
+
chrome: 0,
|
|
323
|
+
"group-transform": "none",
|
|
324
|
+
"value-font": "var(--k-mono)",
|
|
325
|
+
"unit-gap": "0px",
|
|
326
|
+
"unit-color": "currentColor",
|
|
327
|
+
"readout-mark": 1,
|
|
328
|
+
"group-size": "12px",
|
|
329
|
+
"group-color": "rgba(235,235,245,.62)",
|
|
330
|
+
"group-inset": "0px",
|
|
331
|
+
"group-tracking": "-.01em",
|
|
332
|
+
"group-divider": "rgba(255,255,255,.075)",
|
|
333
|
+
"group-divider-gap": "8px",
|
|
334
|
+
"curve-inset": "0px",
|
|
335
|
+
"curve-guide": "dashed",
|
|
336
|
+
"curve-dot": 0,
|
|
337
|
+
spring: "0.185 0.14",
|
|
338
|
+
"fill-ease": glide.easing,
|
|
339
|
+
"fill-ms": glide.duration
|
|
340
|
+
},
|
|
341
|
+
light: {
|
|
342
|
+
bg: "#fff",
|
|
343
|
+
surface: "rgba(0,0,0,.045)",
|
|
344
|
+
"surface-hi": "rgba(0,0,0,.09)",
|
|
345
|
+
line: "rgba(0,0,0,.07)",
|
|
346
|
+
"line-hi": "rgba(0,0,0,.11)",
|
|
347
|
+
text: "#000",
|
|
348
|
+
label: "rgba(60,60,67,.66)",
|
|
349
|
+
dim: "rgba(60,60,67,.38)",
|
|
350
|
+
accent: "#0088ff",
|
|
351
|
+
modified: "#0088ff",
|
|
352
|
+
"seg-bg": "rgba(120,120,128,.11)",
|
|
353
|
+
"seg-active": "#fff",
|
|
354
|
+
"toggle-track": "rgba(120,120,128,.2)",
|
|
355
|
+
"toggle-thumb": "#fff",
|
|
356
|
+
rim: "transparent",
|
|
357
|
+
"group-color": "rgba(60,60,67,.66)",
|
|
358
|
+
"group-divider": "rgba(0,0,0,.07)"
|
|
359
|
+
}
|
|
360
|
+
};
|
|
361
|
+
|
|
362
|
+
// src/core/appearance.ts
|
|
363
|
+
var MODES = {
|
|
364
|
+
dark: "dark",
|
|
365
|
+
light: "light",
|
|
366
|
+
auto: "system"
|
|
367
|
+
};
|
|
368
|
+
function resolveLook(options = {}, base) {
|
|
369
|
+
const t = options.theme;
|
|
370
|
+
const mode = typeof t === "string" ? MODES[t] : undefined;
|
|
371
|
+
const theme = typeof t === "object" ? t : base?.theme;
|
|
372
|
+
const preset = options.preset ?? base?.preset;
|
|
373
|
+
return {
|
|
374
|
+
...theme ? { theme } : {},
|
|
375
|
+
appearance: options.appearance ?? mode ?? base?.appearance ?? "inherit",
|
|
376
|
+
...preset ? { preset } : {}
|
|
377
|
+
};
|
|
378
|
+
}
|
|
379
|
+
var themes = new Map;
|
|
380
|
+
var themeSelector = (name) => `:where(.knobs-root)[data-knobs-theme="${name}"]`;
|
|
381
|
+
function upsertStyle(doc, key, value, content) {
|
|
382
|
+
const existing = doc.querySelector(`style[${key}="${value}"]`);
|
|
383
|
+
if (existing) {
|
|
384
|
+
if (existing.textContent !== content)
|
|
385
|
+
existing.textContent = content;
|
|
386
|
+
return;
|
|
387
|
+
}
|
|
388
|
+
const style = doc.createElement("style");
|
|
389
|
+
style.setAttribute(key, value);
|
|
390
|
+
style.textContent = content;
|
|
391
|
+
doc.head.append(style);
|
|
392
|
+
}
|
|
393
|
+
function injectTheme(doc, theme) {
|
|
394
|
+
themes.set(theme.name, theme);
|
|
395
|
+
upsertStyle(doc, "data-knobs-theme-css", theme.name, theme.css({ selector: themeSelector(theme.name) }));
|
|
396
|
+
}
|
|
397
|
+
var presets = new Map;
|
|
398
|
+
function injectPreset(doc, preset) {
|
|
399
|
+
presets.set(preset.name, preset);
|
|
400
|
+
upsertStyle(doc, "data-knobs-preset", preset.name, presetCss(preset));
|
|
401
|
+
}
|
|
402
|
+
var setAttr = (el, name, value) => {
|
|
403
|
+
if (value === undefined)
|
|
404
|
+
el.removeAttribute(name);
|
|
405
|
+
else if (el.getAttribute(name) !== value)
|
|
406
|
+
el.setAttribute(name, value);
|
|
407
|
+
};
|
|
408
|
+
function applyLook(el, look) {
|
|
409
|
+
const doc = el.ownerDocument;
|
|
410
|
+
if (look.theme)
|
|
411
|
+
injectTheme(doc, look.theme);
|
|
412
|
+
if (look.preset)
|
|
413
|
+
injectPreset(doc, look.preset);
|
|
414
|
+
setAttr(el, "data-knobs-theme", look.theme?.name);
|
|
415
|
+
setAttr(el, "data-preset", look.preset?.name);
|
|
416
|
+
setAttr(el, "data-appearance", look.appearance === "inherit" ? undefined : look.appearance);
|
|
417
|
+
if (look.appearance === "inherit")
|
|
418
|
+
followPage(el);
|
|
419
|
+
else
|
|
420
|
+
clearInherited(el);
|
|
421
|
+
}
|
|
422
|
+
var clearInherited = (el) => {
|
|
423
|
+
el.style.removeProperty("color-scheme");
|
|
424
|
+
el.style.removeProperty("--_k-light");
|
|
425
|
+
};
|
|
426
|
+
function resolveInherited(el) {
|
|
427
|
+
const parent = el.parentElement;
|
|
428
|
+
const win = el.ownerDocument.defaultView;
|
|
429
|
+
if (!parent || !win || el.hasAttribute("data-appearance"))
|
|
430
|
+
return;
|
|
431
|
+
if (parent.closest(".knobs-root"))
|
|
432
|
+
return clearInherited(el);
|
|
433
|
+
const scheme = win.getComputedStyle(parent).colorScheme.trim();
|
|
434
|
+
const dark = /\bdark\b/.test(scheme);
|
|
435
|
+
const light = /\blight\b/.test(scheme);
|
|
436
|
+
if (!dark && !light)
|
|
437
|
+
return clearInherited(el);
|
|
438
|
+
const isLight = dark && light ? win.matchMedia?.("(prefers-color-scheme: light)").matches ?? false : light;
|
|
439
|
+
el.style.setProperty("color-scheme", "inherit");
|
|
440
|
+
el.style.setProperty("--_k-light", isLight ? "1" : "0");
|
|
441
|
+
}
|
|
442
|
+
var watched = new WeakSet;
|
|
443
|
+
function followPage(el) {
|
|
444
|
+
const doc = el.ownerDocument;
|
|
445
|
+
const win = doc.defaultView;
|
|
446
|
+
if (!win)
|
|
447
|
+
return;
|
|
448
|
+
const run = () => resolveInherited(el);
|
|
449
|
+
if (el.isConnected)
|
|
450
|
+
run();
|
|
451
|
+
queueMicrotask(run);
|
|
452
|
+
win.requestAnimationFrame?.(run);
|
|
453
|
+
if (watched.has(doc))
|
|
454
|
+
return;
|
|
455
|
+
watched.add(doc);
|
|
456
|
+
const all = () => {
|
|
457
|
+
for (const root of doc.querySelectorAll(".knobs-root:not([data-appearance])"))
|
|
458
|
+
resolveInherited(root);
|
|
459
|
+
};
|
|
460
|
+
const observer = new MutationObserver(all);
|
|
461
|
+
const attributeFilter = ["class", "data-theme", "data-appearance"];
|
|
462
|
+
observer.observe(doc.documentElement, { attributes: true, attributeFilter });
|
|
463
|
+
if (doc.body)
|
|
464
|
+
observer.observe(doc.body, { attributes: true, attributeFilter });
|
|
465
|
+
win.matchMedia?.("(prefers-color-scheme: light)").addEventListener?.("change", all);
|
|
466
|
+
}
|
|
467
|
+
|
|
182
468
|
// src/core/adapter.ts
|
|
183
|
-
|
|
469
|
+
var panelLook = (controls, look = {}) => resolveLook(look, resolveLook({ theme: controls.theme, appearance: controls.appearance }));
|
|
470
|
+
function syncPanelLook(host, controls, look = {}, density) {
|
|
184
471
|
const panel = host?.firstElementChild;
|
|
185
472
|
if (!panel)
|
|
186
473
|
return;
|
|
187
|
-
panel
|
|
474
|
+
applyLook(panel, panelLook(controls, look));
|
|
188
475
|
panel.dataset.density = density ?? controls.density;
|
|
189
476
|
}
|
|
190
477
|
function syncPanelValues(controls, descriptors, values, land = false) {
|
|
@@ -200,6 +487,7 @@ function mountPanelAdapter(host, controls, getProps) {
|
|
|
200
487
|
return controls.mount(host, {
|
|
201
488
|
title: p.title,
|
|
202
489
|
theme: p.theme,
|
|
490
|
+
appearance: p.appearance,
|
|
203
491
|
density: p.density,
|
|
204
492
|
renderer: p.renderer,
|
|
205
493
|
variants: p.variants,
|
|
@@ -214,7 +502,7 @@ function mountPanelAdapter(host, controls, getProps) {
|
|
|
214
502
|
onClose: p.onClose ? () => getProps().onClose?.() : undefined,
|
|
215
503
|
onReady(panel) {
|
|
216
504
|
const cur = getProps();
|
|
217
|
-
syncPanelLook(host, controls, cur
|
|
505
|
+
syncPanelLook(host, controls, cur, cur.density);
|
|
218
506
|
cur.onReady?.(panel);
|
|
219
507
|
}
|
|
220
508
|
});
|
|
@@ -285,7 +573,7 @@ function KnobsPanel(props) {
|
|
|
285
573
|
syncPanelValues(props.controls, props.descriptors, props.values, Boolean(props.land));
|
|
286
574
|
});
|
|
287
575
|
createEffect(() => {
|
|
288
|
-
syncPanelLook(host, props.controls, props.theme, props.density);
|
|
576
|
+
syncPanelLook(host, props.controls, { theme: props.theme, appearance: props.appearance, preset: props.preset }, props.density);
|
|
289
577
|
});
|
|
290
578
|
return host;
|
|
291
579
|
}
|