@kitlangton/knobs 0.1.0 → 0.3.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/README.md +303 -41
- package/dist/dev/{chunk-qtt698hp.js → chunk-7xgkerd2.js} +34 -11
- package/dist/dev/{chunk-ktsn42p7.js → chunk-jx1ktap3.js} +13762 -11794
- package/dist/dev/{chunk-kdewv0mt.js → chunk-pmkvb9ep.js} +1692 -207
- package/dist/dev/{chunk-e13znr7c.js → chunk-v8ssbcbk.js} +18 -7
- package/dist/dev/index.js +557 -130
- package/dist/index.js +589 -141
- package/dist/panel.js +21615 -17048
- package/dist/types/core/keys.d.ts +2 -0
- package/dist/types/core/random.d.ts +61 -1
- package/dist/types/core/remote.d.ts +5 -1
- package/dist/types/core/schema.d.ts +35 -6
- package/dist/types/core/store.d.ts +97 -8
- package/dist/types/core/unlock.d.ts +77 -0
- package/dist/types/core/variants.d.ts +10 -2
- package/dist/types/index.d.ts +4 -2
- package/dist/types/panel/attach.d.ts +2 -0
- package/dist/types/panel/crumbs.d.ts +19 -0
- package/dist/types/panel/editors.d.ts +20 -0
- package/dist/types/panel/feel.d.ts +103 -0
- package/dist/types/panel/flash.d.ts +13 -0
- package/dist/types/panel/give.d.ts +34 -1
- package/dist/types/panel/gpu/color.d.ts +4 -4
- package/dist/types/panel/gpu/renderer.d.ts +110 -6
- package/dist/types/panel/gpu/shader.wgsl.d.ts +1 -1
- package/dist/types/panel/haptics.d.ts +6 -2
- package/dist/types/panel/has.d.ts +0 -1
- package/dist/types/panel/index.d.ts +3 -1
- package/dist/types/panel/inspector.d.ts +33 -3
- package/dist/types/panel/lens.d.ts +113 -0
- package/dist/types/panel/motion.d.ts +2 -0
- package/dist/types/panel/optkeys.d.ts +7 -0
- package/dist/types/panel/page-hints.d.ts +2 -1
- package/dist/types/panel/prefs.d.ts +2 -2
- package/dist/types/panel/presence.d.ts +20 -0
- package/dist/types/panel/presets.d.ts +17 -5
- package/dist/types/panel/ramp-morph.d.ts +117 -0
- package/dist/types/panel/ramps.d.ts +1 -1
- package/dist/types/panel/reel.d.ts +43 -0
- package/dist/types/panel/scope.d.ts +48 -0
- package/dist/types/panel/slider.d.ts +22 -5
- package/dist/types/panel/sound.d.ts +137 -0
- package/dist/types/panel/styles.d.ts +1 -1
- package/dist/types/panel/tab-transition.d.ts +15 -0
- package/dist/types/panel/tabs.d.ts +1 -1
- package/dist/types/panel/toggle.d.ts +27 -0
- package/dist/types/panel/toolbar-grid.d.ts +6 -0
- package/dist/types/ui/activity-css.d.ts +1 -0
- package/dist/types/ui/activity-model.d.ts +122 -0
- package/dist/types/ui/activity.d.ts +67 -0
- package/dist/types/ui/follow.d.ts +17 -0
- package/dist/types/ui/index.d.ts +5 -1
- package/dist/types/ui/look.d.ts +9 -0
- package/dist/types/ui/picker-css.d.ts +1 -0
- package/dist/types/ui/picker-model.d.ts +53 -0
- package/dist/types/ui/picker.d.ts +67 -0
- package/dist/types/ui/react.d.ts +27 -0
- package/dist/types/ui/scrollbar.d.ts +12 -0
- package/dist/types/ui/solid.d.ts +23 -0
- package/dist/types/ui/split-model.d.ts +55 -0
- package/dist/types/ui/split.d.ts +22 -3
- package/dist/ui-react.js +3462 -690
- package/dist/ui-solid.js +3440 -689
- package/dist/ui.js +2963 -264
- package/package.json +1 -1
|
@@ -19,3 +19,5 @@ export declare function matchesCombo(combo: string, event: KeyboardEvent): boole
|
|
|
19
19
|
*/
|
|
20
20
|
export declare function comboParts(combo: string, apple?: boolean): string[];
|
|
21
21
|
export declare function comboLabel(combo: string, apple?: boolean): string;
|
|
22
|
+
/** Whether a key goes to what has focus: a text field, a select or editable text. */
|
|
23
|
+
export declare function isTypingTarget(target: EventTarget | null): boolean;
|
|
@@ -1,2 +1,62 @@
|
|
|
1
|
-
import { type
|
|
1
|
+
import { type CurvePoint, type GradientStop } from "./ramp.js";
|
|
2
|
+
import { type Schema, type ValueField, type Values } from "./schema.js";
|
|
3
|
+
/** One field's roll across its whole range (see `randomValues`). */
|
|
4
|
+
export declare function pick(field: ValueField, random: () => number): string | number | boolean | number[] | readonly [0.25, 0.1, 0.25, 1] | readonly [0.42, 0, 1, 1] | readonly [0, 0, 0.58, 1] | readonly [0.42, 0, 0.58, 1] | readonly [0, 0, 1, 1] | readonly [0.65, 0, 0.35, 1] | readonly [0.32, 0.72, 0, 1] | readonly [0.34, 1.56, 0.64, 1] | GradientStop[] | CurvePoint[] | {
|
|
5
|
+
duration: number;
|
|
6
|
+
bounce: number;
|
|
7
|
+
l?: undefined;
|
|
8
|
+
c?: undefined;
|
|
9
|
+
h?: undefined;
|
|
10
|
+
x?: undefined;
|
|
11
|
+
y?: undefined;
|
|
12
|
+
z?: undefined;
|
|
13
|
+
} | {
|
|
14
|
+
l: number;
|
|
15
|
+
c: number;
|
|
16
|
+
h: number;
|
|
17
|
+
duration?: undefined;
|
|
18
|
+
bounce?: undefined;
|
|
19
|
+
x?: undefined;
|
|
20
|
+
y?: undefined;
|
|
21
|
+
z?: undefined;
|
|
22
|
+
} | {
|
|
23
|
+
x: number;
|
|
24
|
+
y: number;
|
|
25
|
+
duration?: undefined;
|
|
26
|
+
bounce?: undefined;
|
|
27
|
+
l?: undefined;
|
|
28
|
+
c?: undefined;
|
|
29
|
+
h?: undefined;
|
|
30
|
+
z?: undefined;
|
|
31
|
+
} | {
|
|
32
|
+
x: number;
|
|
33
|
+
y: number;
|
|
34
|
+
z: number;
|
|
35
|
+
duration?: undefined;
|
|
36
|
+
bounce?: undefined;
|
|
37
|
+
l?: undefined;
|
|
38
|
+
c?: undefined;
|
|
39
|
+
h?: undefined;
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* How far Random strays from an active preset. A number lands in a window 35% of its range wide,
|
|
43
|
+
* centred on the preset's value and slid inward at an end so it keeps its width: far enough to
|
|
44
|
+
* be a new take, near enough to stay recognisably that preset (Mutate moves 8–12% from the
|
|
45
|
+
* current values; a free roll covers 100%). Choices and opted-in switches keep the preset's
|
|
46
|
+
* pick, changing `switch` of the time. Colours keep their family: hue within ±`hue`°,
|
|
47
|
+
* lightness ±`lightness`, chroma ±`chroma` of what that hue can hold. Seeds roll freely: a new
|
|
48
|
+
* pattern is what a seed is for.
|
|
49
|
+
*/
|
|
50
|
+
export declare const AROUND: {
|
|
51
|
+
readonly spread: 0.35;
|
|
52
|
+
readonly switch: 0.3;
|
|
53
|
+
readonly hue: 20;
|
|
54
|
+
readonly lightness: 0.06;
|
|
55
|
+
readonly chroma: 0.15;
|
|
56
|
+
};
|
|
57
|
+
/**
|
|
58
|
+
* One field's roll around `base` (an active preset's value): see `AROUND`. Fields with nothing
|
|
59
|
+
* to vary around (keys, seeds) roll as `pick` does.
|
|
60
|
+
*/
|
|
61
|
+
export declare function around(field: ValueField, base: unknown, random: () => number): unknown;
|
|
2
62
|
export declare function randomValues<S extends Schema>(schema: S, random?: () => number): Values<S>;
|
|
@@ -26,9 +26,11 @@ export interface SpringBindingDescriptor extends DescriptorMeta {
|
|
|
26
26
|
};
|
|
27
27
|
readonly default?: SpringValue;
|
|
28
28
|
}
|
|
29
|
-
/** A button row: pressing it calls `onAction(key)`. */
|
|
29
|
+
/** A button row: pressing it calls `onAction(key)`. `shortcut` takes a combination here. */
|
|
30
30
|
export interface ActionDescriptor extends DescriptorMeta {
|
|
31
31
|
readonly kind: "action";
|
|
32
|
+
readonly global?: boolean;
|
|
33
|
+
readonly rebind?: boolean;
|
|
32
34
|
readonly default?: undefined;
|
|
33
35
|
readonly bind?: undefined;
|
|
34
36
|
}
|
|
@@ -116,6 +118,8 @@ export interface RemoteControlsOptions {
|
|
|
116
118
|
readonly enabled?: boolean | (() => boolean);
|
|
117
119
|
/** Ships the panel as product UI, live in production: `() => import("knobs/panel")` (see `ControlsOptions.ship`). */
|
|
118
120
|
readonly ship?: () => Promise<PanelModule>;
|
|
121
|
+
/** The key that shows and hides its panels with the page's others (see `ControlsOptions.toggleKey`). */
|
|
122
|
+
readonly toggleKey?: string | false;
|
|
119
123
|
/** How long (ms) a key changed here outranks incoming values for it; 600 by default. */
|
|
120
124
|
readonly echo?: number;
|
|
121
125
|
/**
|
|
@@ -20,7 +20,10 @@ export interface FieldMeta {
|
|
|
20
20
|
/** One muted line under the section's heading on a page (the first field that gives one wins). */
|
|
21
21
|
readonly sectionDescription?: string;
|
|
22
22
|
readonly shortcut?: string;
|
|
23
|
-
/**
|
|
23
|
+
/**
|
|
24
|
+
* `false` keeps the field out of Random and Mutate, as a lock does, but by declaration. Switches,
|
|
25
|
+
* seeds and key combinations start out; `true` brings them in.
|
|
26
|
+
*/
|
|
24
27
|
readonly random?: boolean;
|
|
25
28
|
/**
|
|
26
29
|
* The row dims and takes no edits from the pointer or keys (focus can still reach it, to read
|
|
@@ -75,6 +78,11 @@ export interface Knob extends FieldMeta {
|
|
|
75
78
|
/** Digits after the point in the readout; the step's own by default. */
|
|
76
79
|
readonly decimals?: number;
|
|
77
80
|
readonly spring?: SpringPart;
|
|
81
|
+
/**
|
|
82
|
+
* Whether a drag sticks for a moment at the default, the active preset's value and the middle
|
|
83
|
+
* (and zero); `false` lets it glide straight through.
|
|
84
|
+
*/
|
|
85
|
+
readonly detents?: boolean;
|
|
78
86
|
}
|
|
79
87
|
export interface Choice<T extends string = string> extends FieldMeta {
|
|
80
88
|
readonly kind: "choice";
|
|
@@ -141,6 +149,12 @@ export interface CurveField extends FieldMeta {
|
|
|
141
149
|
export interface ActionField extends FieldMeta {
|
|
142
150
|
readonly kind: "action";
|
|
143
151
|
readonly run?: () => void;
|
|
152
|
+
/** The combination that presses it (`"Shift+K"`), shown as a key cap at the row's end. */
|
|
153
|
+
readonly shortcut?: string;
|
|
154
|
+
/** Where `shortcut` works, as a toolbar button's (see `ToolbarShortcut`); `"panel"` by default. */
|
|
155
|
+
readonly scope?: "page" | "panel" | "none";
|
|
156
|
+
/** The user can rebind it in place: a click or Enter on the key cap listens for a new one. */
|
|
157
|
+
readonly rebind?: boolean;
|
|
144
158
|
}
|
|
145
159
|
export interface Vec3 {
|
|
146
160
|
readonly x: number;
|
|
@@ -350,9 +364,17 @@ export declare function choice<const T extends readonly [string, ...string[]]>(v
|
|
|
350
364
|
readonly labels?: Readonly<Partial<Record<T[number], string>>>;
|
|
351
365
|
readonly display?: "menu" | "segmented";
|
|
352
366
|
}): Choice<T[number]>;
|
|
353
|
-
/**
|
|
354
|
-
|
|
367
|
+
/**
|
|
368
|
+
* `action("Replay", { run, shortcut: "Shift+K", global: true, rebind: true })`: a button row. Its
|
|
369
|
+
* key also reaches the store's `onAction`. `shortcut` presses it as a toolbar button's does (a
|
|
370
|
+
* combination, or `{ key, scope }`), and `rebind` lets the user change it from its key cap.
|
|
371
|
+
*/
|
|
372
|
+
export declare function action(label?: string, meta?: Omit<FieldMeta, "label" | "shortcut"> & {
|
|
355
373
|
run?: () => void;
|
|
374
|
+
shortcut?: string | ToolbarShortcut;
|
|
375
|
+
/** A plain-string shortcut works anywhere on the page (as `scope: "page"`). */
|
|
376
|
+
global?: boolean;
|
|
377
|
+
rebind?: boolean;
|
|
356
378
|
}): ActionField;
|
|
357
379
|
type SpringHalf = number | Knob;
|
|
358
380
|
/**
|
|
@@ -369,6 +391,10 @@ export declare function flatSpring(parts?: {
|
|
|
369
391
|
readonly duration: Knob;
|
|
370
392
|
readonly bounce: Knob;
|
|
371
393
|
};
|
|
394
|
+
/**
|
|
395
|
+
* A switch. Switches usually show or hide things (a view, a scene's parts), so Random and Mutate
|
|
396
|
+
* leave them alone unless `random: true`.
|
|
397
|
+
*/
|
|
372
398
|
export declare function toggle(value: boolean, meta?: FieldMeta): Toggle;
|
|
373
399
|
/** `spring({ duration: 0.4, bounce: 0.2 })`, like SwiftUI's `.spring(duration:bounce:)`. */
|
|
374
400
|
export declare function spring(value?: Partial<SpringValue>, meta?: FieldMeta): SpringField;
|
|
@@ -469,11 +495,14 @@ export declare function curve(points: readonly CurvePoint[] | keyof typeof CURVE
|
|
|
469
495
|
readonly presets?: Readonly<Record<string, readonly CurvePoint[]>>;
|
|
470
496
|
readonly shapes?: boolean;
|
|
471
497
|
}): CurveField;
|
|
472
|
-
|
|
473
|
-
export declare function toolbarShortcut(item: ToolbarItem): {
|
|
498
|
+
type ResolvedShortcut = {
|
|
474
499
|
readonly key: string;
|
|
475
500
|
readonly scope: "page" | "panel" | "none";
|
|
476
|
-
}
|
|
501
|
+
};
|
|
502
|
+
/** A toolbar item's shortcut as `{ key, scope }`, or undefined without one. */
|
|
503
|
+
export declare function toolbarShortcut(item: ToolbarItem): ResolvedShortcut | undefined;
|
|
504
|
+
/** An action row's shortcut as `{ key, scope }`, or undefined without one. */
|
|
505
|
+
export declare function actionShortcut(field: ActionField): ResolvedShortcut | undefined;
|
|
477
506
|
/** A wrapping row of buttons with icons and shortcut chips; holds no value. */
|
|
478
507
|
export declare function toolbar(items: readonly ToolbarItem[], meta?: FieldMeta): ToolbarField;
|
|
479
508
|
type ReadoutOptions = Omit<ReadoutMeta, "shortcut" | "random" | "readOnly">;
|
|
@@ -15,7 +15,8 @@ export interface ChipOptions {
|
|
|
15
15
|
/**
|
|
16
16
|
* When the chip shows. `"hover"`: while the element is hovered or focused. `"shortcut"`: hidden
|
|
17
17
|
* until `shortcut` turns on knobs mode (remembered for the tab), then on hover. `"always"`:
|
|
18
|
-
* whenever its panel is closed. `"hover"` in development
|
|
18
|
+
* whenever its panel is closed. `"hover"` in development (and on a page someone unlocked),
|
|
19
|
+
* `"shortcut"` for a shipped store in production builds.
|
|
19
20
|
*/
|
|
20
21
|
readonly reveal?: RevealMode;
|
|
21
22
|
/** The key that toggles knobs mode for `"shortcut"` chips: `"Alt+Shift+D"` (⌥⇧D) by default. */
|
|
@@ -36,6 +37,16 @@ export interface ChangeMeta {
|
|
|
36
37
|
readonly coalesce?: boolean;
|
|
37
38
|
readonly key?: string;
|
|
38
39
|
readonly group?: string;
|
|
40
|
+
/** A reset that went back to the active preset (see `Controls.activePreset`), not the defaults. */
|
|
41
|
+
readonly base?: boolean;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* The preset last applied from the strip: a schema preset (by id) or a saved variant. It's the
|
|
45
|
+
* base Reset returns to and Random explores around.
|
|
46
|
+
*/
|
|
47
|
+
export interface PresetRef {
|
|
48
|
+
readonly kind: "preset" | "variant";
|
|
49
|
+
readonly id: string;
|
|
39
50
|
}
|
|
40
51
|
export interface ControlAction<V = State> {
|
|
41
52
|
readonly id?: string;
|
|
@@ -86,7 +97,7 @@ export type PanelCommand = "random" | "mutate" | "reset" | "resetAll" | "compare
|
|
|
86
97
|
export type PanelKeys = {
|
|
87
98
|
readonly [C in PanelCommand]?: string | boolean;
|
|
88
99
|
} & {
|
|
89
|
-
/** `false` drops the j/k
|
|
100
|
+
/** `false` drops the j/k aliases: only the arrows move; the letters reach the page. */
|
|
90
101
|
readonly vim?: boolean;
|
|
91
102
|
/**
|
|
92
103
|
* `false` stops digits, `.`, `-` and Enter from opening a slider's inline number editor (they
|
|
@@ -98,6 +109,14 @@ export type PanelKeys = {
|
|
|
98
109
|
/** `false` stops ↑/↓ at the first and last rows instead of wrapping around. */
|
|
99
110
|
readonly wrap?: boolean;
|
|
100
111
|
};
|
|
112
|
+
/** `glass` (the default): ticks with a faint ring. `mech`: drier, the rings all but gone. */
|
|
113
|
+
export type SoundTheme = "glass" | "mech";
|
|
114
|
+
/** A mount's `sound`, beyond `true`. */
|
|
115
|
+
export interface SoundOptions {
|
|
116
|
+
/** This panel's level, 0–1 (times `sound.volume`). */
|
|
117
|
+
readonly volume?: number;
|
|
118
|
+
readonly theme?: SoundTheme;
|
|
119
|
+
}
|
|
101
120
|
/** A header button (see `MountPanelOptions.header`). */
|
|
102
121
|
export type HeaderButton = "random" | "reset" | "copy" | "undo" | "redo" | "help" | "close";
|
|
103
122
|
export interface HeaderOptions {
|
|
@@ -126,6 +145,12 @@ export interface MountPanelOptions extends LabelOptions {
|
|
|
126
145
|
* don't join the page's. `keys: { hint: false }` turns hint mode off here either way.
|
|
127
146
|
*/
|
|
128
147
|
readonly hints?: "page" | "panel";
|
|
148
|
+
/**
|
|
149
|
+
* The key that shows and hides every panel and chip on the page that listens for it, outside
|
|
150
|
+
* text fields and without modifiers; remembered per store. The store's `toggleKey` by default
|
|
151
|
+
* (a backtick), `false` on a full page (`mountPage`). `false`: this panel always shows.
|
|
152
|
+
*/
|
|
153
|
+
readonly toggleKey?: string | false;
|
|
129
154
|
/**
|
|
130
155
|
* `false` hides what says a value differs from its default: modified dots and readout marks,
|
|
131
156
|
* group reset icons and the header's Reset. For panels whose values belong to someone else
|
|
@@ -141,6 +166,11 @@ export interface MountPanelOptions extends LabelOptions {
|
|
|
141
166
|
* list, every button but `help` shows (see `HeaderOptions`).
|
|
142
167
|
*/
|
|
143
168
|
readonly header?: boolean | HeaderOptions;
|
|
169
|
+
/**
|
|
170
|
+
* `false` drops the scope line beside the title (`Shape › Cohesion`, where keys go, and a faint
|
|
171
|
+
* `esc ↑ Shape` for where Esc goes). The focus lens and the armed frame stay.
|
|
172
|
+
*/
|
|
173
|
+
readonly crumbs?: boolean;
|
|
144
174
|
/**
|
|
145
175
|
* `false`: no per-tab session, so a rebuilt panel doesn't take focus back to the row it last
|
|
146
176
|
* had or reopen editors and folded groups. On while the store has storage.
|
|
@@ -185,6 +215,18 @@ export interface MountPanelOptions extends LabelOptions {
|
|
|
185
215
|
* Reduced motion turns them off too.
|
|
186
216
|
*/
|
|
187
217
|
readonly haptics?: boolean;
|
|
218
|
+
/**
|
|
219
|
+
* Magnetic detents on slider drags and pans (the default, the active preset's value, the middle
|
|
220
|
+
* and zero); on by default, `false` turns them off for the whole panel.
|
|
221
|
+
*/
|
|
222
|
+
readonly detents?: boolean;
|
|
223
|
+
/**
|
|
224
|
+
* Sound effects: quiet, short ticks and clicks synthesized live for the panel's moments (a
|
|
225
|
+
* slider's detents, a switch, Random, Copy…). Off by default; `true` turns them on, or
|
|
226
|
+
* `{ volume, theme }`. The page's switch (`sound.enable(false)` from `knobs/panel`) mutes every
|
|
227
|
+
* panel, and the `?` popover offers it as Sounds, kept in the store's storage.
|
|
228
|
+
*/
|
|
229
|
+
readonly sound?: boolean | SoundOptions;
|
|
188
230
|
/** Called once the panel is mounted, with a handle to focus it (a host's "Tune" key). */
|
|
189
231
|
readonly onReady?: (panel: PanelHandle) => void;
|
|
190
232
|
/** What Copy (and ⇧C) puts on the clipboard; `controls.code()` by default. */
|
|
@@ -255,6 +297,8 @@ export interface PanelHandle {
|
|
|
255
297
|
export interface PanelModule {
|
|
256
298
|
mountPanel(controls: Controls<any>, container: HTMLElement, options?: MountPanelOptions): PanelHandle;
|
|
257
299
|
attach(controls: Controls<any>, element: HTMLElement, chip?: ChipOptions): () => void;
|
|
300
|
+
/** A brief status at the bottom of the page ("knobs unlocked"). */
|
|
301
|
+
status?(text: string): void;
|
|
258
302
|
}
|
|
259
303
|
export interface ControlsOptions<S extends Schema> extends LabelOptions {
|
|
260
304
|
enabled?: boolean | (() => boolean);
|
|
@@ -267,6 +311,12 @@ export interface ControlsOptions<S extends Schema> extends LabelOptions {
|
|
|
267
311
|
ship?: () => Promise<PanelModule>;
|
|
268
312
|
/** The chip `attach` shows: its label, when it shows and the knobs-mode key (see `ChipOptions`). */
|
|
269
313
|
chip?: ChipOptions;
|
|
314
|
+
/**
|
|
315
|
+
* The key that shows and hides this store's panels and chips, with every other panel on the
|
|
316
|
+
* page that listens for it (see `MountPanelOptions.toggleKey`). A backtick by default; `false`
|
|
317
|
+
* for a shipped store (`ship`), whose panels are product UI. `false`: always shown.
|
|
318
|
+
*/
|
|
319
|
+
toggleKey?: string | false;
|
|
270
320
|
/**
|
|
271
321
|
* The longest (ms) a key changed here outranks incoming values for it (see `sync`), so an echo
|
|
272
322
|
* of an older value still in flight can't pull it back. The hold ends early once the remote
|
|
@@ -345,6 +395,8 @@ export interface Controls<S extends Schema = Schema> {
|
|
|
345
395
|
readonly reveal: RevealMode;
|
|
346
396
|
readonly shortcut: string;
|
|
347
397
|
};
|
|
398
|
+
/** The key that shows and hides its panels and chips, or `false` (see `ControlsOptions.toggleKey`). */
|
|
399
|
+
readonly toggleKey: string | false;
|
|
348
400
|
/** How page cards show group presets (`groupPresetDisplay`, `auto` by default). */
|
|
349
401
|
readonly groupPresetDisplay: GroupPresetDisplay;
|
|
350
402
|
/** A group's display label (`groupLabels`, else its fields' `groupLabel`), if it has one. */
|
|
@@ -406,17 +458,28 @@ export interface Controls<S extends Schema = Schema> {
|
|
|
406
458
|
readonly canRedo: boolean;
|
|
407
459
|
subscribe(cb: () => void): () => void;
|
|
408
460
|
/**
|
|
409
|
-
* Back to the
|
|
410
|
-
*
|
|
461
|
+
* Back to the active preset (see `activePreset`) while anything differs from it, else to the
|
|
462
|
+
* defaults: every field, or only `keys`. Reaching the defaults with every field also forgets
|
|
463
|
+
* the active preset. Locks don't apply; disabled and read-only fields keep their values.
|
|
411
464
|
*/
|
|
412
465
|
reset(keys?: readonly (keyof S & string)[]): void;
|
|
466
|
+
/** One key, as `reset` does: to the active preset's value, else (already there) its default. */
|
|
413
467
|
resetKey(key: keyof S & string): void;
|
|
468
|
+
/**
|
|
469
|
+
* A group, as `reset` does: to its active group preset (or the panel's active preset) while it
|
|
470
|
+
* differs from it, else to its defaults, which forgets the group's preset.
|
|
471
|
+
*/
|
|
414
472
|
resetGroup(group: string): void;
|
|
473
|
+
/** Whether the key (or anything) differs from the active preset; the defaults without one. */
|
|
415
474
|
isModified(key?: keyof S & string): boolean;
|
|
475
|
+
/** Whether `reset` (of every field, or `keys`) would change anything. */
|
|
476
|
+
canReset(keys?: readonly (keyof S & string)[]): boolean;
|
|
477
|
+
/** What differs from the defaults (the values `code()` and Swift export care about). */
|
|
416
478
|
modified(): Partial<Values<S>>;
|
|
417
479
|
/**
|
|
418
480
|
* Random values for every field that can roll (see `canRoll`), or those among `keys`, drawn
|
|
419
|
-
* from `random`.
|
|
481
|
+
* from `random`. With an active preset, they land near its values (see `AROUND`) instead of
|
|
482
|
+
* anywhere in range. One undo step.
|
|
420
483
|
*/
|
|
421
484
|
randomize(keys?: readonly (keyof S & string)[]): void;
|
|
422
485
|
/** Small changes around the current values instead of a re-roll; skips what can't roll. */
|
|
@@ -424,6 +487,17 @@ export interface Controls<S extends Schema = Schema> {
|
|
|
424
487
|
/** Keeps fields out of Random and Mutate (or lets them back in). Saved with the values. */
|
|
425
488
|
lock(keys: (keyof S & string) | readonly (keyof S & string)[], locked?: boolean): void;
|
|
426
489
|
isLocked(key: keyof S & string): boolean;
|
|
490
|
+
/**
|
|
491
|
+
* The combination that presses an action row now, or a toolbar's button (`item`, its id or
|
|
492
|
+
* label): the user's rebinding, else the declared `shortcut`; `""` when cleared, undefined
|
|
493
|
+
* when there's none.
|
|
494
|
+
*/
|
|
495
|
+
shortcut(key: keyof S & string, item?: string): string | undefined;
|
|
496
|
+
/**
|
|
497
|
+
* Rebinds an action row's shortcut (or a toolbar button's): a combination, `""` for none, or
|
|
498
|
+
* undefined to restore the declared one. Not undoable; saved with the values, as locks are.
|
|
499
|
+
*/
|
|
500
|
+
rebind(key: keyof S & string, combo: string | undefined, item?: string): void;
|
|
427
501
|
/**
|
|
428
502
|
* Whether Random and Mutate may change `key`: it holds a value and isn't locked, `random:
|
|
429
503
|
* false`, refused by `tunable`, disabled or read-only.
|
|
@@ -451,13 +525,28 @@ export interface Controls<S extends Schema = Schema> {
|
|
|
451
525
|
*/
|
|
452
526
|
compare(hold: boolean): void;
|
|
453
527
|
readonly comparing: boolean;
|
|
454
|
-
|
|
528
|
+
/**
|
|
529
|
+
* Applies a preset and makes it the active one (`"default"` clears it); one undo step, or
|
|
530
|
+
* folded into the last with `coalesce` (a pan across the strip).
|
|
531
|
+
*/
|
|
532
|
+
preset(id: string, options?: {
|
|
533
|
+
coalesce?: boolean;
|
|
534
|
+
}): void;
|
|
455
535
|
matchingPreset(): string;
|
|
536
|
+
/**
|
|
537
|
+
* The preset (or saved variant) last applied, which Reset returns to and Random explores
|
|
538
|
+
* around, or null. Kept with the values; forgotten by a reset to the defaults.
|
|
539
|
+
*/
|
|
540
|
+
activePreset(): PresetRef | null;
|
|
541
|
+
/** The group preset last applied to `group` (0-based), or -1. */
|
|
542
|
+
activeGroupPreset(group: string): number;
|
|
543
|
+
/** The values Reset returns to first: the active presets over the defaults. */
|
|
544
|
+
baseValues(): Values<S>;
|
|
456
545
|
/** Each group's numbered presets, complete over the keys they cover. */
|
|
457
546
|
readonly groupPresets: Readonly<Record<string, readonly GroupPreset<Values<S>>[]>>;
|
|
458
547
|
/**
|
|
459
|
-
* Applies a group's preset (0-based)
|
|
460
|
-
* one (a pan across a card's presets).
|
|
548
|
+
* Applies a group's preset (0-based) and makes it the group's active one, one undo step;
|
|
549
|
+
* `coalesce` folds it into the previous one (a pan across a card's presets).
|
|
461
550
|
*/
|
|
462
551
|
groupPreset(group: string, index: number, options?: {
|
|
463
552
|
coalesce?: boolean;
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import type { PanelModule } from "./store.js";
|
|
2
|
+
/** The Konami code: ↑ ↑ ↓ ↓ ← → ← → B A, as key names for `unlock({ sequence })`. */
|
|
3
|
+
export declare const KONAMI: readonly string[];
|
|
4
|
+
export type Corner = "top-left" | "top-right" | "bottom-left" | "bottom-right";
|
|
5
|
+
export interface UnlockOptions {
|
|
6
|
+
/**
|
|
7
|
+
* The panel code, loaded only once someone unlocks: `() => import("knobs/panel")`. Your bundler
|
|
8
|
+
* splits it into its own chunk, so visitors who never unlock download none of it.
|
|
9
|
+
*/
|
|
10
|
+
readonly panel: () => Promise<PanelModule>;
|
|
11
|
+
/**
|
|
12
|
+
* Typed anywhere outside a text field: a word (`"knobs"` by default) or a list of key names
|
|
13
|
+
* (`KONAMI`). Typing it again locks. `false`: none.
|
|
14
|
+
*/
|
|
15
|
+
readonly sequence?: string | readonly string[] | false;
|
|
16
|
+
/** `?knobs` in the URL unlocks and `?knobs=off` locks (`"knobs"` by default). `false`: none. */
|
|
17
|
+
readonly query?: string | false;
|
|
18
|
+
/**
|
|
19
|
+
* Three quick taps or clicks in this corner of the window (`"top-right"` by default), for
|
|
20
|
+
* phones. Three more lock. `false`: none.
|
|
21
|
+
*/
|
|
22
|
+
readonly corner?: Corner | false;
|
|
23
|
+
/** Remember being unlocked in localStorage until it's locked again (default true). */
|
|
24
|
+
readonly persist?: boolean;
|
|
25
|
+
}
|
|
26
|
+
/** A page's secret unlock (see `unlock`). */
|
|
27
|
+
export interface Unlock {
|
|
28
|
+
readonly unlocked: boolean;
|
|
29
|
+
unlock(): void;
|
|
30
|
+
lock(): void;
|
|
31
|
+
/** Stops listening for the sequence and the corner; the state stays as it is. */
|
|
32
|
+
dispose(): void;
|
|
33
|
+
}
|
|
34
|
+
/** Whether this page has been unlocked (see `unlock`). */
|
|
35
|
+
export declare const isUnlocked: () => boolean;
|
|
36
|
+
/** The panel module an unlocked page mounts from, if `unlock` named one. */
|
|
37
|
+
export declare const unlockedPanel: () => (() => Promise<PanelModule>) | undefined;
|
|
38
|
+
/** Calls `listener` whenever the page locks or unlocks. */
|
|
39
|
+
export declare function onUnlock(listener: () => void): () => void;
|
|
40
|
+
export declare const UNLOCK_KEY = "knobs:unlocked";
|
|
41
|
+
/** The keys a sequence is typed with: a word's letters, or key names as given. */
|
|
42
|
+
export declare function sequenceKeys(sequence: string | readonly string[]): string[];
|
|
43
|
+
/**
|
|
44
|
+
* Watches keys go by for `sequence`: true on the key that completes it. Letters match in either
|
|
45
|
+
* case, a wrong key starts over (keeping what it could begin), and a pause longer than `gap` ms
|
|
46
|
+
* forgets what was typed.
|
|
47
|
+
*/
|
|
48
|
+
export declare function sequenceMatcher(sequence: string | readonly string[], gap?: number): (key: string, at: number) => boolean;
|
|
49
|
+
/**
|
|
50
|
+
* What the URL says: `?knobs` (or `=1`, `=on`, `=true`) unlocks, `?knobs=off` (or `=0`, `=false`,
|
|
51
|
+
* `=lock`) locks, and without it, undefined.
|
|
52
|
+
*/
|
|
53
|
+
export declare function queryUnlock(search: string, name: string): boolean | undefined;
|
|
54
|
+
/**
|
|
55
|
+
* Whether a page view starts unlocked: the URL decides when it says, else what was remembered
|
|
56
|
+
* (only when `persist`). `remember` is what to keep afterwards (undefined: leave it).
|
|
57
|
+
*/
|
|
58
|
+
export declare function resolveUnlock(input: {
|
|
59
|
+
readonly query: boolean | undefined;
|
|
60
|
+
readonly stored: boolean;
|
|
61
|
+
readonly persist: boolean;
|
|
62
|
+
}): {
|
|
63
|
+
readonly unlocked: boolean;
|
|
64
|
+
readonly remember: boolean | undefined;
|
|
65
|
+
};
|
|
66
|
+
/** Whether a point is in `corner` of a `width` × `height` window, within `size` px. */
|
|
67
|
+
export declare function inCorner(x: number, y: number, width: number, height: number, corner: Corner, size?: number): boolean;
|
|
68
|
+
/** Counts quick taps: true on the `count`th, each within `within` ms of the last. */
|
|
69
|
+
export declare function tapCounter(count?: number, within?: number): (at: number) => boolean;
|
|
70
|
+
/**
|
|
71
|
+
* Lets this deploy be unlocked: stores stay locked to their shipped values and mount nothing
|
|
72
|
+
* until someone types the sequence, opens the page with `?knobs`, or taps the corner three
|
|
73
|
+
* times. Then they come alive (values from this browser's storage) and the panel code loads.
|
|
74
|
+
* The same again locks, back to the shipped values. In development it changes nothing: stores
|
|
75
|
+
* are live there anyway.
|
|
76
|
+
*/
|
|
77
|
+
export declare function unlock(options: UnlockOptions): Unlock;
|
|
@@ -9,9 +9,17 @@ export interface Variants<V> {
|
|
|
9
9
|
readonly ready: boolean;
|
|
10
10
|
list(): readonly Variant<V>[];
|
|
11
11
|
save(name?: string): Variant<V>;
|
|
12
|
-
|
|
12
|
+
/**
|
|
13
|
+
* Applies a saved variant, making it the active preset (see `Controls.activePreset`); one undo
|
|
14
|
+
* step, or folded into the last with `coalesce` (a pan across the strip).
|
|
15
|
+
*/
|
|
16
|
+
load(id: string, options?: {
|
|
17
|
+
coalesce?: boolean;
|
|
18
|
+
}): void;
|
|
19
|
+
/** Renames a saved variant (an empty name clears it); kept in storage with the variants. */
|
|
20
|
+
rename(id: string, name: string): void;
|
|
13
21
|
remove(id: string): void;
|
|
14
22
|
export(): string;
|
|
15
23
|
import(json: string): void;
|
|
16
24
|
}
|
|
17
|
-
export declare function createVariants<S extends Schema>(schema: () => S, id: string, key: string, storage: () => StoragePort | null, get: () => Values<S>, set: (v: Values<S
|
|
25
|
+
export declare function createVariants<S extends Schema>(schema: () => S, id: string, key: string, storage: () => StoragePort | null, get: () => Values<S>, set: (v: Values<S>, id: string, coalesce: boolean) => void, notify: () => void, enabled: () => boolean): Variants<Values<S>>;
|
package/dist/types/index.d.ts
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
|
-
export { knob, choice, toggle, spring, color, point, easing, action, flatSpring, vec2, vec3, range, angle, seed, keybind, gradient, curve, toolbar, toolbarShortcut, watch, sparkline, graph, meter, table, log, hasValue, isReadout, wrapAngle, SPRING, type FieldMeta, type ActionField, type SpringPart, type ValueField, type Knob, type Choice, type Toggle, type SpringField, type ColorField, type PointField, type EasingField, type VecField, type Vec3, type RangeField, type AngleField, type SeedField, type KeybindField, type GradientField, type CurveField, type ToolbarField, type ToolbarItem, type ToolbarShortcut, type WatchField, type SparklineField, type GraphField, type GraphSeries, type GraphThreshold, type MeterField, type TableField, type LogField, type ReadoutField, type ReadoutKeys, type ReadoutInput, type Point, type Field, type Schema, type Values, type Value, type State, } from "./core/schema.js";
|
|
1
|
+
export { knob, choice, toggle, spring, color, point, easing, action, flatSpring, vec2, vec3, range, angle, seed, keybind, gradient, curve, toolbar, toolbarShortcut, actionShortcut, watch, sparkline, graph, meter, table, log, hasValue, isReadout, wrapAngle, SPRING, type FieldMeta, type ActionField, type SpringPart, type ValueField, type Knob, type Choice, type Toggle, type SpringField, type ColorField, type PointField, type EasingField, type VecField, type Vec3, type RangeField, type AngleField, type SeedField, type KeybindField, type GradientField, type CurveField, type ToolbarField, type ToolbarItem, type ToolbarShortcut, type WatchField, type SparklineField, type GraphField, type GraphSeries, type GraphThreshold, type MeterField, type TableField, type LogField, type ReadoutField, type ReadoutKeys, type ReadoutInput, type Point, type Field, type Schema, type Values, type Value, type State, } from "./core/schema.js";
|
|
2
2
|
export { springCss, springMotion, type SpringValue } from "./core/spring.js";
|
|
3
3
|
export { colorHex, parseColor, type Oklch } from "./core/color.js";
|
|
4
4
|
export { sampleGradient, sampleCurve, gradientCss, CURVE_SHAPES, type GradientStop, type GradientSpace, type CurvePoint, type CurveInterp, type SampleGradientOptions, type SampleCurveOptions, } from "./core/ramp.js";
|
|
5
5
|
export { bezierCss, bezierPoint, EASINGS, type Bezier, type EasingName } from "./core/easing.js";
|
|
6
|
-
export {
|
|
6
|
+
export { AROUND } from "./core/random.js";
|
|
7
|
+
export { defineControls, type ChangeMeta, type GestureEvent, type ChangeSource, type ChipOptions, type ControlAction, type Controls, type ControlsOptions, type DensityMode, type GroupPreset, type GroupPresetDisplay, type PresetRef, type HeaderButton, type HeaderOptions, type HostHistory, type LabelOptions, type MountPanelOptions, type PanelCommand, type PanelHandle, type PanelModule, type PanelKeys, type PersistMode, type SearchChip, type SearchOptions, type SyncOptions, type RendererMode, type RevealMode, type SectionFolded, type SoundOptions, type SoundTheme, type ThemeMode, } from "./core/store.js";
|
|
7
8
|
export { createRemoteControls, descriptorToField, formatSwift, fromDescriptors, fromSettings, type SettingsGroup, type SettingsItem, type ActionDescriptor, type ChoiceOption, type ControlDescriptor, type SpringBindingDescriptor, type ToolbarDescriptor, type ReadoutDescriptor, type ValueDescriptor, type RemoteControls, type RemoteControlsOptions, } from "./core/remote.js";
|
|
8
9
|
export type { LogEntry, LogLevel, TableRows, WatchValue } from "./core/readout.js";
|
|
9
10
|
export { memoryStorage, urlFlag, type StoragePort } from "./core/storage.js";
|
|
11
|
+
export { KONAMI, unlock, type Corner, type Unlock, type UnlockOptions } from "./core/unlock.js";
|
|
10
12
|
export type { TokenPreset } from "./core/theme.js";
|
|
11
13
|
export { formatCode, type CodeFormat } from "./core/code.js";
|
|
12
14
|
export { comboFromEvent, letterOf, comboLabel, comboParts, matchesCombo, normalizeCombo, } from "./core/keys.js";
|
|
@@ -3,3 +3,5 @@ import type { Schema } from "../core/schema.js";
|
|
|
3
3
|
export declare function attach<S extends Schema>(controls: Controls<S>, element: HTMLElement, options?: ChipOptions): () => void;
|
|
4
4
|
/** Parses `"Alt+Shift+D"` into a test for keydown events. Letters and digits match by key position. */
|
|
5
5
|
export declare function matchShortcut(shortcut: string): (event: KeyboardEvent) => boolean;
|
|
6
|
+
/** A brief status at the bottom of the page, as knobs mode's "knobs on" ("knobs unlocked"). */
|
|
7
|
+
export declare function status(text: string, doc?: Document): void;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { type Crumb, type CrumbLevel } from "./scope.js";
|
|
2
|
+
export declare const CRUMB_GLIDE: string;
|
|
3
|
+
export interface CrumbsView {
|
|
4
|
+
readonly element: HTMLElement;
|
|
5
|
+
/** The trail for where focus is, and where Esc goes from there (none at the panel). */
|
|
6
|
+
set(trail: readonly Crumb[], esc?: string): void;
|
|
7
|
+
/** Shows or quiets the Esc hint. */
|
|
8
|
+
hint(on: boolean): void;
|
|
9
|
+
/** Re-place it after the header's layout changed. */
|
|
10
|
+
layout(): void;
|
|
11
|
+
dispose(): void;
|
|
12
|
+
}
|
|
13
|
+
export declare function createCrumbs(o: {
|
|
14
|
+
header: HTMLElement;
|
|
15
|
+
title: HTMLElement;
|
|
16
|
+
jump: (level: CrumbLevel | "panel") => void;
|
|
17
|
+
reduced: () => boolean;
|
|
18
|
+
wake: () => void;
|
|
19
|
+
}): CrumbsView;
|
|
@@ -54,6 +54,17 @@ export interface EditorRow {
|
|
|
54
54
|
dispose(): void;
|
|
55
55
|
readonly tracks: readonly SubTrack[];
|
|
56
56
|
readonly gpu: readonly GpuRowBinding[];
|
|
57
|
+
/** Named options the digits pick while the row is focused (a ramp's or easing's presets). */
|
|
58
|
+
readonly options?: RowOptions;
|
|
59
|
+
}
|
|
60
|
+
/** A row's options as the digits 1–9 pick them (see scope.ts). */
|
|
61
|
+
export interface RowOptions {
|
|
62
|
+
readonly count: number;
|
|
63
|
+
choose(i: number): void;
|
|
64
|
+
/** The options while they show (segments, chips), for a digit on each; empty while hidden. */
|
|
65
|
+
shown(): readonly HTMLElement[];
|
|
66
|
+
/** What stands for them while they're hidden (a menu's button, a head's mini curve). */
|
|
67
|
+
readonly anchor: Element;
|
|
57
68
|
}
|
|
58
69
|
export declare const reducedMotion: (doc: Document) => boolean;
|
|
59
70
|
export declare const rgbCss: (rgb: readonly number[]) => string;
|
|
@@ -154,6 +165,15 @@ export declare function panPresets(c: RowContext<unknown>, head: HTMLElement, nu
|
|
|
154
165
|
at(): number;
|
|
155
166
|
choose(i: number, coalesce: boolean): void;
|
|
156
167
|
}): void;
|
|
168
|
+
/** Named presets as chips in a radiogroup (the easing editor's look); ←/→ cycle them. */
|
|
169
|
+
export declare function presetChips(c: RowContext<unknown>, names: readonly string[], choose: (i: number) => void, cls?: string): {
|
|
170
|
+
el: HTMLDivElement;
|
|
171
|
+
buttons: HTMLButtonElement[];
|
|
172
|
+
cycle: (dir: number) => void;
|
|
173
|
+
check(i: number): void;
|
|
174
|
+
};
|
|
175
|
+
/** ←/→ on `target` itself cycle the presets (a row's head, the chips). */
|
|
176
|
+
export declare function cycleKeys(targets: readonly HTMLElement[], row: HTMLElement, cycle: (dir: number) => void): void;
|
|
157
177
|
/** A mini curve in the head; an editor with two handles and named chips in the body. */
|
|
158
178
|
export declare function easingRow(c: RowContext<EasingField>): EditorRow;
|
|
159
179
|
export {};
|