@kitlangton/knobs 0.2.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 +135 -17
- package/dist/dev/{chunk-gezhc24g.js → chunk-7xgkerd2.js} +14 -5
- package/dist/dev/{chunk-5cr85vv6.js → chunk-jx1ktap3.js} +7843 -7933
- package/dist/dev/{chunk-693jd1gj.js → chunk-pmkvb9ep.js} +1544 -160
- package/dist/dev/{chunk-4km87zfx.js → chunk-v8ssbcbk.js} +18 -7
- package/dist/dev/index.js +187 -31
- package/dist/index.js +197 -33
- package/dist/panel.js +20260 -18462
- package/dist/types/core/keys.d.ts +2 -0
- package/dist/types/core/remote.d.ts +2 -0
- package/dist/types/core/schema.d.ts +5 -0
- package/dist/types/core/store.d.ts +29 -2
- package/dist/types/core/unlock.d.ts +77 -0
- package/dist/types/index.d.ts +1 -0
- 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 +9 -0
- package/dist/types/panel/feel.d.ts +103 -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 +32 -0
- package/dist/types/panel/gpu/shader.wgsl.d.ts +1 -1
- package/dist/types/panel/index.d.ts +2 -1
- package/dist/types/panel/inspector.d.ts +1 -1
- package/dist/types/panel/lens.d.ts +113 -0
- package/dist/types/panel/motion.d.ts +2 -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/scope.d.ts +29 -0
- package/dist/types/panel/slider.d.ts +21 -4
- 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/ui/look.d.ts +1 -1
- package/dist/types/ui/scrollbar.d.ts +12 -0
- package/dist/types/ui/split-model.d.ts +4 -3
- package/dist/types/ui/split.d.ts +8 -6
- package/dist/ui-react.js +232 -132
- package/dist/ui-solid.js +232 -132
- package/dist/ui.js +285 -174
- package/package.json +1 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { PanelCommand, PanelKeys } from "../core/store.js";
|
|
2
2
|
/** How a panel reads keys that aren't commands (see `PanelKeys`): resolved once per panel. */
|
|
3
3
|
export interface KeyPrefs {
|
|
4
|
-
/** j/k
|
|
4
|
+
/** j/k as aliases for ↑/↓ (l is Lock, so ←/→ have no letters). */
|
|
5
5
|
readonly vim: boolean;
|
|
6
6
|
/** Digits, `.`, `-` and Enter on a slider open its inline number editor. */
|
|
7
7
|
readonly edit: boolean;
|
|
@@ -14,7 +14,7 @@ export declare const DEFAULT_PREFS: KeyPrefs;
|
|
|
14
14
|
export declare const setKeyPrefs: (root: Element, prefs: KeyPrefs) => WeakMap<Element, KeyPrefs>;
|
|
15
15
|
/** The preferences of the panel `node` sits in. */
|
|
16
16
|
export declare function keyPrefs(node: EventTarget | null): KeyPrefs;
|
|
17
|
-
/** -1, 1 or 0 for
|
|
17
|
+
/** -1, 1 or 0 for ←/→. */
|
|
18
18
|
export declare function arrowOf(event: KeyboardEvent): -1 | 0 | 1;
|
|
19
19
|
/** ⇧'s multiplier for this event (1 without ⇧). */
|
|
20
20
|
export declare const bigOf: (event: KeyboardEvent) => number;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { MorphFrame } from "./morph.js";
|
|
2
|
+
export interface Presence {
|
|
3
|
+
readonly shown: boolean;
|
|
4
|
+
/** Shows or hides the panel; `animate: false` puts it there at once (a reload, a first paint). */
|
|
5
|
+
set(shown: boolean, animate: boolean): void;
|
|
6
|
+
/** The shape the GPU overlay draws while it shows or hides (see `MorphFrame`), else undefined. */
|
|
7
|
+
frame(now: number): MorphFrame | undefined;
|
|
8
|
+
dispose(): void;
|
|
9
|
+
}
|
|
10
|
+
/** What the panel looks like at `x` (0 hidden, 1 shown) on the way in or out. */
|
|
11
|
+
export declare function presenceLook(x: number, inline: boolean, reduced: boolean): {
|
|
12
|
+
opacity: number;
|
|
13
|
+
blur: number;
|
|
14
|
+
scale: number;
|
|
15
|
+
fold: number;
|
|
16
|
+
};
|
|
17
|
+
export declare function createPresence(root: HTMLElement, options: {
|
|
18
|
+
readonly inline: boolean;
|
|
19
|
+
readonly wake: () => void;
|
|
20
|
+
}): Presence;
|
|
@@ -7,6 +7,35 @@ export type CommandScope = "selection" | "row" | "group" | "all";
|
|
|
7
7
|
export declare function commandScope(level: FocusLevel, selection?: boolean): CommandScope;
|
|
8
8
|
/** How a command reads from where it would land: "Random this", "Reset group", "Random all". */
|
|
9
9
|
export declare function scopeLabel(verb: string, scope: CommandScope): string;
|
|
10
|
+
/** A level below the panel that the header's crumbs name: a card, a row, an open editor's part. */
|
|
11
|
+
export type CrumbLevel = "card" | "row" | "editor";
|
|
12
|
+
export interface Crumb {
|
|
13
|
+
readonly level: CrumbLevel;
|
|
14
|
+
readonly label: string;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Where keys go, as the header reads after the panel's title: `Shape › Cohesion`. A level that
|
|
18
|
+
* isn't focused (or has no name) is left out; the last crumb is the deepest, the one focused.
|
|
19
|
+
*/
|
|
20
|
+
export declare function crumbTrail(path: {
|
|
21
|
+
readonly card?: string;
|
|
22
|
+
readonly row?: string;
|
|
23
|
+
readonly editor?: string;
|
|
24
|
+
}): Crumb[];
|
|
25
|
+
/**
|
|
26
|
+
* Where Esc goes from the deepest crumb: the crumb before it, else the panel (`title`). Nothing
|
|
27
|
+
* at the panel itself (no crumbs), where Esc leaves.
|
|
28
|
+
*/
|
|
29
|
+
export declare function escTarget(trail: readonly Crumb[], title: string): string | undefined;
|
|
30
|
+
/**
|
|
31
|
+
* How much of a trail fits `room` px: crumbs from `from` on show (the ones before it fold into
|
|
32
|
+
* one "…"), and the Esc hint shows only when it fits too. The deepest crumb always shows.
|
|
33
|
+
* `widths` are the crumbs' own; `sep` a separator's (with its gaps), `more` the "…"'s.
|
|
34
|
+
*/
|
|
35
|
+
export declare function fitCrumbs(widths: readonly number[], room: number, sep: number, more: number, hint?: number): {
|
|
36
|
+
from: number;
|
|
37
|
+
hint: boolean;
|
|
38
|
+
};
|
|
10
39
|
/**
|
|
11
40
|
* The option a digit picks among `count` (0-based), or undefined when it names none: 1–9 pick
|
|
12
41
|
* the first nine, as they read.
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Knob as KnobField } from "../core/schema.js";
|
|
2
|
+
import { type DetentKind } from "./feel.js";
|
|
2
3
|
import { type Roll, Spring, VelocityTracker } from "./motion.js";
|
|
3
4
|
export interface DigitPlace {
|
|
4
5
|
ch: string;
|
|
@@ -39,6 +40,17 @@ export interface Slider {
|
|
|
39
40
|
readonly notchRatio: number;
|
|
40
41
|
/** Whether a drag is currently held on the default by the notch's magnet. */
|
|
41
42
|
isMagnetized(): boolean;
|
|
43
|
+
/** The detent holding a drag right now, if any. */
|
|
44
|
+
heldDetent(): DetentKind | undefined;
|
|
45
|
+
/** Where the active preset's value sits [0..1], when it differs from the default. */
|
|
46
|
+
readonly baseRatio: number | undefined;
|
|
47
|
+
/** When the handle last caught a detent (see `settleScale`). */
|
|
48
|
+
readonly settledAt: number;
|
|
49
|
+
/**
|
|
50
|
+
* How many halvings the drag in hand moves at, for its ruler (0 at 1:1 or at rest, up to 3; each
|
|
51
|
+
* level halves the tenths again). Each level shows `rulerAlpha(depth, level)` of the way.
|
|
52
|
+
*/
|
|
53
|
+
rulerDepth(): number;
|
|
42
54
|
/** When the readout last popped (a click landing on a decile, or the default's magnet). */
|
|
43
55
|
poppedAt: number;
|
|
44
56
|
/** Formatted numeric string without unit (e.g. "0.45" or "98"). */
|
|
@@ -83,10 +95,15 @@ export declare function stepValue(field: {
|
|
|
83
95
|
/**
|
|
84
96
|
* A DialKit-style slider: the whole row is the track, the fill is a full-height block,
|
|
85
97
|
* the handle is a hairline that only shows on hover, and the label + value sit on the
|
|
86
|
-
* track itself. Dragging follows the pointer exactly
|
|
87
|
-
*
|
|
88
|
-
*
|
|
98
|
+
* track itself. Dragging follows the pointer exactly, slower the further the pointer strays off
|
|
99
|
+
* the row (and ⌥ for 1/10 speed); detents at the default, the active preset's value and round
|
|
100
|
+
* values hold it for a few px, and past an end the row stretches like rubber. A click snaps
|
|
101
|
+
* to the nearest step (or nearest 10% when there are many steps) with a short spring-like ease.
|
|
102
|
+
* A sideways trackpad pan moves it like a drag.
|
|
89
103
|
*/
|
|
90
104
|
export declare function createSlider(doc: Document, key: string, initialField: KnobField, set: (value: number, options?: {
|
|
91
105
|
coalesce?: boolean;
|
|
92
|
-
}) => void, onMotionWake?: () => void
|
|
106
|
+
}) => void, onMotionWake?: () => void, options?: {
|
|
107
|
+
/** The active preset's value for this key (what Reset goes back to first). */
|
|
108
|
+
readonly base?: () => number | undefined;
|
|
109
|
+
}): Slider;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A tab change, as one layout animation: what leaves fades out where it stood (lifted out of the
|
|
3
|
+
* flow, so it takes no room), what arrives fades in block by block with a small rise, what stays
|
|
4
|
+
* glides to its new place, and the surface (and any card whose rows change) springs to its new
|
|
5
|
+
* height. Every spring keeps its position and velocity when another tab is picked mid-flight.
|
|
6
|
+
*
|
|
7
|
+
* While the pointer stays on the panel the surface never shrinks: a panel anchored at its foot
|
|
8
|
+
* (or centred) would otherwise move its tabs out from under the pointer between two clicks. It
|
|
9
|
+
* settles to its size once the pointer leaves.
|
|
10
|
+
*/
|
|
11
|
+
export declare function tabTransition(body: HTMLElement, root: HTMLElement, wake: () => void): {
|
|
12
|
+
readonly running: boolean;
|
|
13
|
+
finish: () => void;
|
|
14
|
+
to(want: Map<HTMLElement, boolean>): void;
|
|
15
|
+
};
|
|
@@ -28,4 +28,4 @@ export interface TabStrip {
|
|
|
28
28
|
focus(options?: FocusOptions): void;
|
|
29
29
|
dispose(): void;
|
|
30
30
|
}
|
|
31
|
-
export declare function createTabStrip(doc: Document, choose: (id: string) => void): TabStrip;
|
|
31
|
+
export declare function createTabStrip(doc: Document, choose: (id: string, animate?: boolean) => void): TabStrip;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { type StoragePort } from "../core/storage.js";
|
|
2
|
+
type KeyEventLike = Pick<KeyboardEvent, "key" | "code" | "ctrlKey" | "metaKey" | "altKey" | "shiftKey" | "repeat" | "isComposing" | "defaultPrevented" | "target">;
|
|
3
|
+
/** Whether a keydown is `key` for the toggle: outside a text field, with no modifier held. */
|
|
4
|
+
export declare function isToggleKey(event: KeyEventLike, key: string): boolean;
|
|
5
|
+
/** A panel or chip that comes and goes with the toggle key. */
|
|
6
|
+
export interface ToggleSurface {
|
|
7
|
+
/** Its store's id: what's remembered. */
|
|
8
|
+
readonly id: string;
|
|
9
|
+
readonly key: string;
|
|
10
|
+
readonly storage: () => StoragePort | null;
|
|
11
|
+
/** Where focus may be when it hides, to give back when it shows. */
|
|
12
|
+
readonly root: HTMLElement;
|
|
13
|
+
/** Shows or hides it; `animate: false` puts it there at once. */
|
|
14
|
+
show(shown: boolean, animate: boolean): void;
|
|
15
|
+
}
|
|
16
|
+
export interface ToggleLayer {
|
|
17
|
+
/** Joins the layer; `shown` is how it should start (what its store remembers). */
|
|
18
|
+
register(surface: ToggleSurface): {
|
|
19
|
+
readonly shown: boolean;
|
|
20
|
+
dispose(): void;
|
|
21
|
+
};
|
|
22
|
+
/** Shows or hides everything listening for `key`; false when nothing does. */
|
|
23
|
+
toggle(key: string): boolean;
|
|
24
|
+
}
|
|
25
|
+
/** The page's toggle layer, for `doc`. */
|
|
26
|
+
export declare function toggleLayer(doc: Document): ToggleLayer;
|
|
27
|
+
export {};
|
package/dist/types/ui/look.d.ts
CHANGED
|
@@ -39,7 +39,7 @@ export declare const tune: <T extends {
|
|
|
39
39
|
readonly zeta: number;
|
|
40
40
|
}) => T;
|
|
41
41
|
/** Whether `target` is an editable field or select that takes typed keys. */
|
|
42
|
-
export
|
|
42
|
+
export { isTypingTarget } from "../core/keys.js";
|
|
43
43
|
/**
|
|
44
44
|
* Tells the page's GPU overlay that layout moved (a pane resizing, collapsing or sliding): it
|
|
45
45
|
* reads rects afresh on its next frame, so a panel inside a pane keeps up.
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A thin scrollbar drawn over a scroller's content, in place of the native one beside it. A native
|
|
3
|
+
* scrollbar that's always shown (as a system may be set) takes its width from the rows the moment
|
|
4
|
+
* the content overflows, so every row jumps sideways, and gives it back when it stops; this one
|
|
5
|
+
* takes no room. It shows while the content scrolls and while the pointer is over the scroller,
|
|
6
|
+
* and drags. `content` is the element whose height makes the scroll: it's watched for changes.
|
|
7
|
+
* The scroller hides its own (`scrollbar-width: none`) and is positioned.
|
|
8
|
+
*/
|
|
9
|
+
export declare function overlayScrollbar(scroller: HTMLElement, content: Element): {
|
|
10
|
+
update: () => void;
|
|
11
|
+
dispose(): void;
|
|
12
|
+
};
|
|
@@ -97,10 +97,11 @@ export declare function foldFaces(prev: FoldFaces, p: number): FoldFaces;
|
|
|
97
97
|
*/
|
|
98
98
|
export declare function chevronTurn(p: number, edge: "start" | "end"): number;
|
|
99
99
|
/**
|
|
100
|
-
* The fold's chevron, flipping: its
|
|
101
|
-
* `f` (0 open, 1 folded).
|
|
100
|
+
* The fold's chevron, flipping over: its turn about its vertical axis (degrees, drawn with depth)
|
|
101
|
+
* against the rail's chevron at flip progress `f` (0 open, 1 folded). Edge-on halfway, it comes
|
|
102
|
+
* round mirrored, rolling the way the pane's edge travels.
|
|
102
103
|
*/
|
|
103
|
-
export declare function chevronFlip(f: number): number;
|
|
104
|
+
export declare function chevronFlip(f: number, edge: "start" | "end"): number;
|
|
104
105
|
/** How a pane folds: see `SplitOptions.fold`. */
|
|
105
106
|
export interface FoldStyle {
|
|
106
107
|
readonly chevron: "flip" | "turn";
|
package/dist/types/ui/split.d.ts
CHANGED
|
@@ -45,8 +45,9 @@ export interface SplitOptions extends UiLook {
|
|
|
45
45
|
/** How a pane folds (each part has a default). */
|
|
46
46
|
export interface SplitFold {
|
|
47
47
|
/**
|
|
48
|
-
* The collapse chevron: `"flip"` (default)
|
|
49
|
-
*
|
|
48
|
+
* The collapse chevron: `"flip"` (default) turns it over about its vertical axis, with depth,
|
|
49
|
+
* mirrored as it travels, on its own snappy spring; `"turn"` spins it half a turn flat, with
|
|
50
|
+
* the fold.
|
|
50
51
|
*/
|
|
51
52
|
readonly chevron?: "flip" | "turn";
|
|
52
53
|
/**
|
|
@@ -54,7 +55,7 @@ export interface SplitFold {
|
|
|
54
55
|
* element all the way; `"fade"` fades it out with the header as the rail's label fades in.
|
|
55
56
|
*/
|
|
56
57
|
readonly title?: "travel" | "fade";
|
|
57
|
-
/** The fold's spring, in seconds (no bounce): 0.
|
|
58
|
+
/** The fold's spring, in seconds (no bounce): 0.25 unless set. */
|
|
58
59
|
readonly duration?: number;
|
|
59
60
|
}
|
|
60
61
|
export interface SplitPane {
|
|
@@ -85,8 +86,9 @@ export interface Split {
|
|
|
85
86
|
/**
|
|
86
87
|
* Resizable panes along a row or a column, divided by hairlines with a wider grip. Drag a divider
|
|
87
88
|
* to resize (each pane slows into its min and max), double-click it to reset, or focus it and use
|
|
88
|
-
* the arrow keys (⇧ for bigger steps) and Enter to collapse
|
|
89
|
-
*
|
|
90
|
-
*
|
|
89
|
+
* the arrow keys (⇧ for bigger steps) and Enter to collapse; in a row, double-click a pane's header
|
|
90
|
+
* to collapse it too. Collapsing springs the pane down to a slim rail, or to its header in a
|
|
91
|
+
* column, which opens it again. Sizes persist and restore before the first paint. Splits nest:
|
|
92
|
+
* call `split` on another split's pane body.
|
|
91
93
|
*/
|
|
92
94
|
export declare function split(container: HTMLElement, options: SplitOptions): Split;
|