@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.
Files changed (65) hide show
  1. package/README.md +303 -41
  2. package/dist/dev/{chunk-qtt698hp.js → chunk-7xgkerd2.js} +34 -11
  3. package/dist/dev/{chunk-ktsn42p7.js → chunk-jx1ktap3.js} +13762 -11794
  4. package/dist/dev/{chunk-kdewv0mt.js → chunk-pmkvb9ep.js} +1692 -207
  5. package/dist/dev/{chunk-e13znr7c.js → chunk-v8ssbcbk.js} +18 -7
  6. package/dist/dev/index.js +557 -130
  7. package/dist/index.js +589 -141
  8. package/dist/panel.js +21615 -17048
  9. package/dist/types/core/keys.d.ts +2 -0
  10. package/dist/types/core/random.d.ts +61 -1
  11. package/dist/types/core/remote.d.ts +5 -1
  12. package/dist/types/core/schema.d.ts +35 -6
  13. package/dist/types/core/store.d.ts +97 -8
  14. package/dist/types/core/unlock.d.ts +77 -0
  15. package/dist/types/core/variants.d.ts +10 -2
  16. package/dist/types/index.d.ts +4 -2
  17. package/dist/types/panel/attach.d.ts +2 -0
  18. package/dist/types/panel/crumbs.d.ts +19 -0
  19. package/dist/types/panel/editors.d.ts +20 -0
  20. package/dist/types/panel/feel.d.ts +103 -0
  21. package/dist/types/panel/flash.d.ts +13 -0
  22. package/dist/types/panel/give.d.ts +34 -1
  23. package/dist/types/panel/gpu/color.d.ts +4 -4
  24. package/dist/types/panel/gpu/renderer.d.ts +110 -6
  25. package/dist/types/panel/gpu/shader.wgsl.d.ts +1 -1
  26. package/dist/types/panel/haptics.d.ts +6 -2
  27. package/dist/types/panel/has.d.ts +0 -1
  28. package/dist/types/panel/index.d.ts +3 -1
  29. package/dist/types/panel/inspector.d.ts +33 -3
  30. package/dist/types/panel/lens.d.ts +113 -0
  31. package/dist/types/panel/motion.d.ts +2 -0
  32. package/dist/types/panel/optkeys.d.ts +7 -0
  33. package/dist/types/panel/page-hints.d.ts +2 -1
  34. package/dist/types/panel/prefs.d.ts +2 -2
  35. package/dist/types/panel/presence.d.ts +20 -0
  36. package/dist/types/panel/presets.d.ts +17 -5
  37. package/dist/types/panel/ramp-morph.d.ts +117 -0
  38. package/dist/types/panel/ramps.d.ts +1 -1
  39. package/dist/types/panel/reel.d.ts +43 -0
  40. package/dist/types/panel/scope.d.ts +48 -0
  41. package/dist/types/panel/slider.d.ts +22 -5
  42. package/dist/types/panel/sound.d.ts +137 -0
  43. package/dist/types/panel/styles.d.ts +1 -1
  44. package/dist/types/panel/tab-transition.d.ts +15 -0
  45. package/dist/types/panel/tabs.d.ts +1 -1
  46. package/dist/types/panel/toggle.d.ts +27 -0
  47. package/dist/types/panel/toolbar-grid.d.ts +6 -0
  48. package/dist/types/ui/activity-css.d.ts +1 -0
  49. package/dist/types/ui/activity-model.d.ts +122 -0
  50. package/dist/types/ui/activity.d.ts +67 -0
  51. package/dist/types/ui/follow.d.ts +17 -0
  52. package/dist/types/ui/index.d.ts +5 -1
  53. package/dist/types/ui/look.d.ts +9 -0
  54. package/dist/types/ui/picker-css.d.ts +1 -0
  55. package/dist/types/ui/picker-model.d.ts +53 -0
  56. package/dist/types/ui/picker.d.ts +67 -0
  57. package/dist/types/ui/react.d.ts +27 -0
  58. package/dist/types/ui/scrollbar.d.ts +12 -0
  59. package/dist/types/ui/solid.d.ts +23 -0
  60. package/dist/types/ui/split-model.d.ts +55 -0
  61. package/dist/types/ui/split.d.ts +22 -3
  62. package/dist/ui-react.js +3462 -690
  63. package/dist/ui-solid.js +3440 -689
  64. package/dist/ui.js +2963 -264
  65. package/package.json +1 -1
@@ -0,0 +1,122 @@
1
+ /** The built-in kinds, each with its icon and tint. */
2
+ export type ActivityKind = "you" | "agent" | "proposal" | "review" | "pr" | "build" | "blocked" | "shipped";
3
+ export interface ActivityEvent {
4
+ /** Unique, and the same across `set()`: rows keep their identity and glide. */
5
+ readonly id: string;
6
+ /** A built-in kind (its icon and tint), or a name of your own with `icon` and `tint`. */
7
+ readonly kind?: ActivityKind | (string & {});
8
+ /** Who: "You", "Agent", "Ryan". */
9
+ readonly actor?: string;
10
+ /** One line; it fades at its end when cut off. A group without one says "3 updates". */
11
+ readonly title?: string;
12
+ /** Trailing, already formatted ("2m", "9:41"); it rolls when it changes. */
13
+ readonly time?: string;
14
+ /** A duration chip, "▶ 0:32": seconds, or text as it should read. */
15
+ readonly duration?: number | string;
16
+ /** Small thumbnails before the time (image URLs; four at most show). */
17
+ readonly thumbs?: readonly string[];
18
+ /** SVG markup, a glyph or a node in place of the kind's icon. */
19
+ readonly icon?: string | Node;
20
+ /** A CSS colour in place of the kind's tint. */
21
+ readonly tint?: string;
22
+ /** Makes a group that opens in place ("Agent · 3 updates"). One level deep. */
23
+ readonly children?: readonly ActivityEvent[];
24
+ /** The live or latest step: its node takes a ring. */
25
+ readonly current?: boolean;
26
+ /** Quieter: past steps, minor updates. */
27
+ readonly dimmed?: boolean;
28
+ }
29
+ export interface ActivityRow {
30
+ readonly id: string;
31
+ readonly event: ActivityEvent;
32
+ /** 0 for an event, 1 for one inside an open group. */
33
+ readonly depth: 0 | 1;
34
+ readonly parent: string | null;
35
+ /** Has children: it opens and closes. */
36
+ readonly group: boolean;
37
+ readonly expanded: boolean;
38
+ }
39
+ /** The rows on show: every event, and the children of open groups right after their group. */
40
+ export declare function flattenActivity(events: readonly ActivityEvent[], expanded: ReadonlySet<string>): ActivityRow[];
41
+ /** Every event by id, children included, with its group. */
42
+ export declare function indexActivity(events: readonly ActivityEvent[]): Map<string, {
43
+ event: ActivityEvent;
44
+ parent: string | null;
45
+ }>;
46
+ export type ActivityKey = "ArrowUp" | "ArrowDown" | "ArrowLeft" | "ArrowRight" | "Home" | "End";
47
+ export declare const isActivityKey: (key: string) => key is ActivityKey;
48
+ /**
49
+ * What a key does from the selected row: ↑/↓ move (from nothing, to the first or the last),
50
+ * Home/End go to the ends, → opens a closed group and steps into an open one, ← closes an open
51
+ * group and steps out of a child to its group.
52
+ */
53
+ export declare function navigateActivity(rows: readonly ActivityRow[], selected: string | null, key: ActivityKey): {
54
+ select?: string;
55
+ toggle?: {
56
+ id: string;
57
+ expanded: boolean;
58
+ };
59
+ };
60
+ /**
61
+ * Whether the rail takes a key it navigated: ↑/↓ and Home/End whenever there are rows (at an end
62
+ * they hold the selection), ← and → only when they open, close or step. A ← or → that does
63
+ * nothing is left to the page (a review stage stepping frames, say).
64
+ */
65
+ export declare function takesActivityKey(key: ActivityKey, result: {
66
+ select?: string;
67
+ toggle?: unknown;
68
+ }, rows: number): boolean;
69
+ /**
70
+ * Where the selection goes when its row leaves the rows on show: to its group when that closed
71
+ * over it, else nowhere.
72
+ */
73
+ export declare function keepSelection(rows: readonly ActivityRow[], selected: string | null, parentOf: (id: string) => string | null | undefined): string | null;
74
+ /** What last moved the selection: keys show it as a tint, a pointer hides it. */
75
+ export type ActivityInput = "key" | "pointer" | "blur" | "code";
76
+ /**
77
+ * Whether the selection's tint shows: keys turn it on, a pointer turns it off (a click selects
78
+ * with no ring), losing focus turns it off unless the page's keys drive it, and a host's
79
+ * `select()` leaves it as it was.
80
+ */
81
+ export declare function showsSelection(showing: boolean, input: ActivityInput, keys?: "focus" | "page"): boolean;
82
+ /** Which ids came, went and stayed between two orders of rows. */
83
+ export declare function diffActivity(before: readonly string[], after: readonly string[]): {
84
+ entered: string[];
85
+ left: string[];
86
+ kept: string[];
87
+ };
88
+ /** Rows stacked top to bottom from `top`: each one's y, and the bottom of the last. */
89
+ export declare function stackRows(heights: readonly number[], top?: number, gap?: number): {
90
+ y: number[];
91
+ bottom: number;
92
+ };
93
+ export interface RailNode {
94
+ /** The node's centre. */
95
+ readonly y: number;
96
+ /** How far the line keeps clear of it on each side. */
97
+ readonly r: number;
98
+ }
99
+ /**
100
+ * The line through the nodes, as segments between neighbours that stop clear of each node, and
101
+ * only within `[from, to]` (the line's ends, which glide as rows come and go). One continuous
102
+ * thread at rest: nothing past the last node, nothing before the first.
103
+ */
104
+ export declare function railSegments(nodes: readonly RailNode[], from: number, to: number): [number, number][];
105
+ /**
106
+ * The scroll while a change takes the content from height `h0` to `h1` (now at `height`): it goes
107
+ * from `from` to where it has to end (no further down than the shorter content allows) in step
108
+ * with the height, and the space stays tall enough for it meanwhile. Closing a group at the
109
+ * scroll's end, the rows above glide down with the drawer instead of dropping in a frame.
110
+ */
111
+ export declare function holdScroll(hold: {
112
+ readonly from: number;
113
+ readonly h0: number;
114
+ readonly h1: number;
115
+ }, height: number, view: number): {
116
+ scroll: number;
117
+ space: number;
118
+ };
119
+ /** "0:32", "4:05", "1:02:03"; text passes through as it is. */
120
+ export declare function formatDuration(duration: number | string): string;
121
+ /** A group's title when it has none of its own: "1 update", "3 updates". */
122
+ export declare function groupTitle(count: number): string;
@@ -0,0 +1,67 @@
1
+ import { type ActivityEvent } from "./activity-model.js";
2
+ import { type UiLook } from "./look.js";
3
+ export interface ActivityOptions extends UiLook {
4
+ readonly events: readonly ActivityEvent[];
5
+ /** The selected event's id. */
6
+ readonly selected?: string | null;
7
+ /** Groups open from the start. */
8
+ readonly expanded?: Iterable<string>;
9
+ /** Keys and clicks moved the selection (a host's `select()` doesn't call it). */
10
+ readonly onSelect?: (id: string, event: ActivityEvent, source: "key" | "pointer") => void;
11
+ /** Enter on the selected row (on a group with no `onActivate`, Enter opens or closes it). */
12
+ readonly onActivate?: (id: string, event: ActivityEvent) => void;
13
+ readonly onToggle?: (id: string, expanded: boolean) => void;
14
+ /** Makes the duration chip a button. */
15
+ readonly onPlay?: (id: string, event: ActivityEvent) => void;
16
+ /**
17
+ * Where the newest events are: `"bottom"` (the default; oldest first) or `"top"`. `add()` puts
18
+ * an event there, and new events slide in from that side.
19
+ */
20
+ readonly newest?: "top" | "bottom";
21
+ /** Stay pinned to the newest end when it was in view as events arrive (default true). */
22
+ readonly follow?: boolean;
23
+ /**
24
+ * Where the keys come from: `"focus"` (the default) while the rail has focus, or `"page"` from
25
+ * anywhere a focused field or widget doesn't take them.
26
+ */
27
+ readonly keys?: "focus" | "page";
28
+ /** Icons (SVG markup or a glyph) for your own kinds, or in place of built-in ones. */
29
+ readonly icons?: Readonly<Record<string, string>>;
30
+ /** Tints (CSS colours) for your own kinds, or in place of built-in ones. */
31
+ readonly tints?: Readonly<Record<string, string>>;
32
+ /** The rail's accessible name. */
33
+ readonly label?: string;
34
+ /** Shown with no events. */
35
+ readonly empty?: string;
36
+ }
37
+ export interface Activity {
38
+ readonly element: HTMLElement;
39
+ /** New events: those that stay glide to their places, new ones bloom in, gone ones soften out. */
40
+ set(events: readonly ActivityEvent[]): void;
41
+ /** One more event at the newest end. */
42
+ add(event: ActivityEvent): void;
43
+ /**
44
+ * New events and where the newest are, in one change: rows glide to their new places, as with
45
+ * `set` (flipping `newest` with the events reversed reverses the rail in place).
46
+ */
47
+ update(next: {
48
+ events?: readonly ActivityEvent[];
49
+ newest?: "top" | "bottom";
50
+ }): void;
51
+ /** Selects (opening its group); `null` clears. Doesn't call `onSelect`. */
52
+ select(id: string | null): void;
53
+ readonly selected: string | null;
54
+ expand(id: string, expanded?: boolean): void;
55
+ isExpanded(id: string): boolean;
56
+ focus(): void;
57
+ destroy(): void;
58
+ /** The same as `destroy`, as the other pieces name it. */
59
+ dispose(): void;
60
+ }
61
+ /**
62
+ * A vertical rail of events: who did what, one line each, with a kind's icon on one continuous
63
+ * line. Groups open in place with their children on the same line. ↑/↓, Home/End move the
64
+ * selection (a tint that shows only once keys move it), ←/→ close and open groups, Enter
65
+ * activates. New events bloom in while the rest glide; every move is an interruptible spring.
66
+ */
67
+ export declare function activity(container: HTMLElement, options: ActivityOptions): Activity;
@@ -0,0 +1,17 @@
1
+ /**
2
+ * A diff for each set of prop values, given the values the piece was made with: the props that
3
+ * differ from the last values seen (at first, those at creation).
4
+ */
5
+ export declare function propChanges<P extends object>(initial: P, same?: (a: unknown, b: unknown) => boolean): (next: P) => Partial<P>;
6
+ /** Whether a diff from `propChanges` has anything in it. */
7
+ export declare const anyChanged: (changed: object) => boolean;
8
+ /**
9
+ * A timeline's changed props as one `update()`: unset ones dropped, and so are values it already
10
+ * has (a `time` or `playing` it reported itself, markers it handed out).
11
+ */
12
+ export declare function timelineChanges<C extends Record<string, unknown>>(now: {
13
+ readonly time: number;
14
+ readonly playing: boolean;
15
+ readonly markers: unknown;
16
+ readonly ranges: unknown;
17
+ }, changed: C): Partial<C>;
@@ -10,7 +10,7 @@ export { popover, type Popover, type PopoverCloseReason, type PopoverOptions } f
10
10
  export { readout, type Readout } from "./readouts.js";
11
11
  export { toast, type Toast, type ToastOptions } from "./toast.js";
12
12
  export { tooltip, tooltips, type TooltipContent, type TooltipOptions } from "./tooltip.js";
13
- export { split, type PaneAction, type PaneOptions, type Split, type SplitOptions, type SplitPane, } from "./split.js";
13
+ export { split, type PaneAction, type PaneOptions, type Split, type SplitFold, type SplitOptions, type SplitPane, } from "./split.js";
14
14
  export { COLLAPSE_PAST, drag as dragDivider, parseLayout, softClamp, solve as solveSplit, type PaneSpec, type SplitDirection, type SplitLayout, } from "./split-model.js";
15
15
  export { timeline, type SeekSource, type Timeline, type TimelineMarker, type TimelineOptions, type TimelineRange, } from "./timeline.js";
16
16
  export { adjacentMarker, advance, clampView, followView, frameTime, magnet, rulerTicks, scrubTime, timeLabel, toFrame, zoomView, type Tick, type Ticks, type TimeUnits, type TimeView, } from "./timeline-model.js";
@@ -18,3 +18,7 @@ export { tree, type Tree, type TreeOptions, type TreeRowContext, type TreeToggle
18
18
  export { applyMove, plainAccess, dropTarget, flatten, indexTree, matchLabel, navigate, select, stepMove, topmost, typeahead, validMove, virtualWindow, type DropTarget, type FlatRow, type Selection, type TreeAccess, type TreeFilter, type TreeMove, } from "./tree-model.js";
19
19
  export { bento, type Bento, type BentoItem, type BentoOptions } from "./bento.js";
20
20
  export { fitRect, FIT_MAX, motionBlur, neighbour as bentoNeighbour, planBento, rowTarget, windowOf as bentoWindow, type BentoDirection, type BentoLayout, type BentoMode, type BentoPlan, type BentoRect, } from "./bento-model.js";
21
+ export { activity, type Activity, type ActivityOptions, } from "./activity.js";
22
+ export { diffActivity, flattenActivity, formatDuration, indexActivity, keepSelection as keepActivitySelection, navigateActivity, railSegments, showsSelection, stackRows, type ActivityEvent, type ActivityInput, type ActivityKey, type ActivityKind, type ActivityRow, type RailNode, } from "./activity-model.js";
23
+ export { optionPicker, type OptionPicker, type OptionPickerOptions, type PickerOption, } from "./picker.js";
24
+ export { claimsDigit, digitPick, keepPick, stepPick } from "./picker-model.js";
@@ -31,6 +31,15 @@ export declare const lookDefaults: {
31
31
  current: UiLook;
32
32
  };
33
33
  export declare const reducedMotion: (win: Window | null) => boolean;
34
+ export declare const tune: <T extends {
35
+ omega: number;
36
+ zeta: number;
37
+ }>(s: T, m: {
38
+ readonly omega: number;
39
+ readonly zeta: number;
40
+ }) => T;
41
+ /** Whether `target` is an editable field or select that takes typed keys. */
42
+ export { isTypingTarget } from "../core/keys.js";
34
43
  /**
35
44
  * Tells the page's GPU overlay that layout moved (a pane resizing, collapsing or sliding): it
36
45
  * reads rects afresh on its next frame, so a panel inside a pane keeps up.
@@ -0,0 +1 @@
1
+ export declare const pickerCss: string;
@@ -0,0 +1,53 @@
1
+ /** The option a digit names: 1–9 pick the first nine, as they read; past the last, none. */
2
+ export declare function digitPick(ids: readonly string[], key: string): string | undefined;
3
+ /** ↑/↓ (and Home/End) from `current`, stopping at the ends. */
4
+ export declare function stepPick(ids: readonly string[], current: string | null, key: "ArrowUp" | "ArrowDown" | "Home" | "End"): string | undefined;
5
+ /**
6
+ * The selection after the options change: the option a host asked for before it was there
7
+ * (`wanted`) once it comes, else the selection while its option stays, else the first.
8
+ */
9
+ export declare function keepPick(ids: readonly string[], selected: string | null, wanted?: string | null): string | null;
10
+ /**
11
+ * A host's `select(id)`: picked now if its option is there; if not, remembered (`wanted`) for
12
+ * the `set()` that brings it, so the order a host's updates land in can't lose it. A later
13
+ * select replaces what was wanted.
14
+ */
15
+ export declare function askPick(ids: readonly string[], id: string): {
16
+ pick: string | undefined;
17
+ wanted: string | null;
18
+ };
19
+ /** What's still wanted after the options change: nothing once its option has come. */
20
+ export declare const stillWanted: (ids: readonly string[], wanted: string | null) => string | null;
21
+ /** The number an option shows: its place, 1, 2, … 12 (only 1–9 are keys that pick). */
22
+ export declare const pickDigit: (index: number) => string;
23
+ /**
24
+ * Whether a key event goes to the picker's digits: a bare 1–9 that nothing focused claimed (a
25
+ * panel row picking its own options, a text field) and that isn't typed into a field.
26
+ */
27
+ export declare function claimsDigit(event: {
28
+ readonly key: string;
29
+ readonly defaultPrevented: boolean;
30
+ readonly metaKey: boolean;
31
+ readonly ctrlKey: boolean;
32
+ readonly altKey: boolean;
33
+ readonly shiftKey: boolean;
34
+ readonly repeat: boolean;
35
+ readonly typing?: boolean;
36
+ }, typing?: boolean): boolean;
37
+ /**
38
+ * Where the card comes to rest on the option at `index`: below the options before it with their
39
+ * bodies shut (once a change settles only the selected option's is open), as tall as its head
40
+ * and its body. The card aims here from the start, rather than chasing the option's top while
41
+ * the last option's body closes above it. With the body not yet measured (a panel mounting for
42
+ * the first time) there's no target yet, and the card holds where it is.
43
+ */
44
+ export declare function cardTarget(heads: readonly number[], index: number, body: number | undefined, gap?: number, top?: number): {
45
+ y: number;
46
+ h: number;
47
+ } | null;
48
+ /**
49
+ * A first-mounted body's height once it has settled: the same reading two frames running, or
50
+ * whatever it reads after `limit` frames (content that never settles doesn't hold the change
51
+ * up). Until then undefined: it's still laying out.
52
+ */
53
+ export declare function settleHeight(previous: number | undefined, now: number, frames: number, limit?: number): number | undefined;
@@ -0,0 +1,67 @@
1
+ import { type UiLook } from "./look.js";
2
+ export interface PickerOption {
3
+ readonly id: string;
4
+ readonly label: string;
5
+ /** Marked "Suggested". */
6
+ readonly suggested?: boolean;
7
+ /**
8
+ * A picture of it (an image URL), small between the number and the name. It loads lazily and
9
+ * fades in once loaded; while loading, or if it fails, nothing is drawn.
10
+ */
11
+ readonly thumb?: string;
12
+ }
13
+ export interface OptionPickerOptions extends UiLook {
14
+ readonly options: readonly PickerOption[];
15
+ /** The option on show, its parameters open under it; the first unless set. */
16
+ readonly selected?: string | null;
17
+ /** The option decided on: it takes a check. */
18
+ readonly chosen?: string | null;
19
+ /** Keys, digits and clicks moved the selection (a host's `select()` doesn't call it). */
20
+ readonly onSelect?: (id: string, source: "key" | "digit" | "pointer") => void;
21
+ /** Enter on an option. */
22
+ readonly onChoose?: (id: string) => void;
23
+ /**
24
+ * Mounts an option's parameters into `element` the first time it opens (a knobs panel, say);
25
+ * return a cleanup for when the option goes or the picker is destroyed. It stays mounted
26
+ * while closed, so a panel keeps its state.
27
+ */
28
+ readonly body?: (option: PickerOption, element: HTMLElement) => (() => void) | void;
29
+ /**
30
+ * Where 1–9 pick from: `"focus"` (the default) while focus is in the picker, its panels
31
+ * included, `"page"` from anywhere, or `false`. A focused row that picks its own options with
32
+ * digits, and text fields, keep them.
33
+ */
34
+ readonly digits?: "focus" | "page" | false;
35
+ /** The accessible name. */
36
+ readonly label?: string;
37
+ /** The suggested mark's words ("Suggested"). */
38
+ readonly suggestedLabel?: string;
39
+ }
40
+ export interface OptionPicker {
41
+ readonly element: HTMLElement;
42
+ /**
43
+ * New options: the selection stays on its option while that's still there, or goes to one
44
+ * `select()` asked for before it was there.
45
+ */
46
+ set(options: readonly PickerOption[]): void;
47
+ /**
48
+ * Opens this option's parameters (closing the last one's). Doesn't call `onSelect`. An id that
49
+ * isn't there yet is remembered, and picked when `set()` brings it.
50
+ */
51
+ select(id: string): void;
52
+ readonly selected: string | null;
53
+ /** Marks the chosen option (`null` for none). */
54
+ choose(id: string | null): void;
55
+ readonly chosen: string | null;
56
+ /** Focuses the selected option. */
57
+ focus(): void;
58
+ destroy(): void;
59
+ dispose(): void;
60
+ }
61
+ /**
62
+ * A column of options (1–n), each with a name, a "Suggested" mark and a check on the chosen one.
63
+ * The selected option sits on a card that glides between options, and its parameters (what
64
+ * `body` mounts, a knobs panel's rows) open under it in place while the last option's close.
65
+ * ↑/↓, Home/End and 1–9 pick; Enter chooses; Tab goes into the parameters.
66
+ */
67
+ export declare function optionPicker(container: HTMLElement, options: OptionPickerOptions): OptionPicker;
@@ -1,5 +1,7 @@
1
1
  import { type CSSProperties, type ReactNode } from "react";
2
+ import { type Activity as ActivityHandle, type ActivityOptions } from "./activity.js";
2
3
  import { type Bento as BentoHandle, type BentoOptions } from "./bento.js";
4
+ import { type OptionPicker as OptionPickerHandle, type OptionPickerOptions, type PickerOption } from "./picker.js";
3
5
  import { type Split as SplitHandle, type SplitOptions } from "./split.js";
4
6
  import { type Timeline as TimelineHandle, type TimelineOptions } from "./timeline.js";
5
7
  import { type Tree as TreeHandle, type TreeOptions } from "./tree.js";
@@ -43,3 +45,28 @@ export type BentoProps = BentoOptions & {
43
45
  * prop; callbacks always call the latest props.
44
46
  */
45
47
  export declare function Bento(props: BentoProps): import("react").JSX.Element;
48
+ export type ActivityProps = ActivityOptions & {
49
+ className?: string;
50
+ style?: CSSProperties;
51
+ onReady?: (activity: ActivityHandle) => void;
52
+ };
53
+ /**
54
+ * `activity()` as a component. New `events` update it in place (rows keep their identity and
55
+ * glide); `selected` follows its prop; callbacks always call the latest props.
56
+ */
57
+ export declare function Activity(props: ActivityProps): import("react").JSX.Element;
58
+ export type OptionPickerProps = Omit<OptionPickerOptions, "body"> & {
59
+ /** An option's parameters, portalled under it the first time it opens (a `<Knobs>` panel, say). */
60
+ children?: (option: PickerOption) => ReactNode;
61
+ className?: string;
62
+ style?: CSSProperties;
63
+ onReady?: (picker: OptionPickerHandle) => void;
64
+ };
65
+ /**
66
+ * `optionPicker()` as a component: `children` renders each opened option's parameters into its
67
+ * place through a portal, so context and state carry through. `options`, `selected` and
68
+ * `chosen` follow their props; callbacks always call the latest props.
69
+ */
70
+ export declare function OptionPicker(props: OptionPickerProps): import("react").JSX.Element;
71
+ export type { ActivityEvent } from "./activity-model.js";
72
+ export type { PickerOption } from "./picker.js";
@@ -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
+ };
@@ -1,5 +1,7 @@
1
1
  import { type JSX } from "solid-js";
2
+ import { type Activity as ActivityHandle, type ActivityOptions } from "./activity.js";
2
3
  import { type Bento as BentoHandle, type BentoOptions } from "./bento.js";
4
+ import { type OptionPicker as OptionPickerHandle, type OptionPickerOptions, type PickerOption } from "./picker.js";
3
5
  import { type Split as SplitHandle, type SplitOptions } from "./split.js";
4
6
  import { type Timeline as TimelineHandle, type TimelineOptions } from "./timeline.js";
5
7
  import { type Tree as TreeHandle, type TreeOptions } from "./tree.js";
@@ -38,3 +40,24 @@ export type BentoProps = BentoOptions & {
38
40
  * prop; callbacks always call the latest props.
39
41
  */
40
42
  export declare function Bento(props: BentoProps): JSX.Element;
43
+ export type ActivityProps = ActivityOptions & {
44
+ onReady?: (activity: ActivityHandle) => void;
45
+ };
46
+ /**
47
+ * `activity()` as a component. New `events` update it in place (rows keep their identity and
48
+ * glide); `selected` follows its prop; callbacks always call the latest props.
49
+ */
50
+ export declare function Activity(props: ActivityProps): JSX.Element;
51
+ export type OptionPickerProps = Omit<OptionPickerOptions, "body"> & {
52
+ /** An option's parameters, rendered once, the first time it opens (a `KnobsPanel`, say). */
53
+ children?: (option: PickerOption) => JSX.Element;
54
+ onReady?: (picker: OptionPickerHandle) => void;
55
+ };
56
+ /**
57
+ * `optionPicker()` as a component: `children` renders an option's parameters under it, in this
58
+ * component's context. `options`, `selected` and `chosen` follow their props; callbacks always
59
+ * call the latest props.
60
+ */
61
+ export declare function OptionPicker(props: OptionPickerProps): JSX.Element;
62
+ export type { ActivityEvent } from "./activity-model.js";
63
+ export type { PickerOption } from "./picker.js";
@@ -75,6 +75,61 @@ export declare function collapsibleSide(panes: readonly PaneSpec[], index: numbe
75
75
  * the rest to the end.
76
76
  */
77
77
  export declare function edgeOf(panes: readonly PaneSpec[], id: string): "start" | "end";
78
+ /** How far a folding pane is from its open size (0) to its rail (1), by the size it shows. */
79
+ export declare function foldProgress(size: number, open: number, rail: number): number;
80
+ /** How much of each face a folding pane shows (0…1): its content, open, and its rail, folded. */
81
+ export interface FoldFaces {
82
+ readonly content: number;
83
+ readonly rail: number;
84
+ }
85
+ /** A face that's leaving is gone by this far along the fold. */
86
+ export declare const FACE_OUT = 0.4;
87
+ /** A face that's arriving shows only over this last part of the fold. */
88
+ export declare const FACE_IN = 0.3;
89
+ /**
90
+ * The faces at fold progress `p`, from the last frame's. The content and the rail never show
91
+ * together: the content is gone before 40% and the rail starts past 70% (folding or opening).
92
+ */
93
+ export declare function foldFaces(prev: FoldFaces, p: number): FoldFaces;
94
+ /**
95
+ * The fold's chevron turn (degrees) at progress `p`: half a turn from the open pane's chevron to
96
+ * the rail's, rolling the way the pane's edge travels.
97
+ */
98
+ export declare function chevronTurn(p: number, edge: "start" | "end"): number;
99
+ /**
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.
103
+ */
104
+ export declare function chevronFlip(f: number, edge: "start" | "end"): number;
105
+ /** How a pane folds: see `SplitOptions.fold`. */
106
+ export interface FoldStyle {
107
+ readonly chevron: "flip" | "turn";
108
+ readonly title: "travel" | "fade";
109
+ /** Seconds, on a spring with no bounce. */
110
+ readonly duration: number;
111
+ }
112
+ export declare const FOLD_STYLE: FoldStyle;
113
+ export declare function foldStyle(options?: Partial<FoldStyle>): FoldStyle;
114
+ /**
115
+ * Where a header's title and the rail's label sit, each from its own box's start edge and the
116
+ * pane's top (`dy` is the title's height less the label's), as measured with the pane open.
117
+ */
118
+ export interface TitlePlaces {
119
+ readonly title: number;
120
+ readonly label: number;
121
+ readonly dy: number;
122
+ }
123
+ /**
124
+ * The rail's label travelling as the header's title, at fold progress `p`: the offset that puts it
125
+ * on the title (the rail holds on to the pane's moving edge, the header to the inner content that
126
+ * keeps its open size), and its turn from upright (-90°) to the rail's vertical (0°).
127
+ */
128
+ export declare function titleTravel(at: TitlePlaces, open: number, rail: number, edge: "start" | "end", p: number): {
129
+ x: number;
130
+ y: number;
131
+ turn: number;
132
+ };
78
133
  /** A saved layout, kept only where it names known panes with sane values. */
79
134
  export declare function parseLayout(raw: unknown, panes: readonly PaneSpec[]): SplitLayout | undefined;
80
135
  /** A layout as saved: sizes rounded to a tenth of a pixel. */
@@ -39,6 +39,24 @@ export interface SplitOptions extends UiLook {
39
39
  * hint mode (`s`), on by default; a code presses its button.
40
40
  */
41
41
  readonly hints?: boolean;
42
+ /** How collapsible panes fold to their rails and open again. */
43
+ readonly fold?: SplitFold;
44
+ }
45
+ /** How a pane folds (each part has a default). */
46
+ export interface SplitFold {
47
+ /**
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.
51
+ */
52
+ readonly chevron?: "flip" | "turn";
53
+ /**
54
+ * The header's title: `"travel"` (default) turns it and slides it into the rail's label, one
55
+ * element all the way; `"fade"` fades it out with the header as the rail's label fades in.
56
+ */
57
+ readonly title?: "travel" | "fade";
58
+ /** The fold's spring, in seconds (no bounce): 0.25 unless set. */
59
+ readonly duration?: number;
42
60
  }
43
61
  export interface SplitPane {
44
62
  readonly id: string;
@@ -68,8 +86,9 @@ export interface Split {
68
86
  /**
69
87
  * Resizable panes along a row or a column, divided by hairlines with a wider grip. Drag a divider
70
88
  * to resize (each pane slows into its min and max), double-click it to reset, or focus it and use
71
- * the arrow keys (⇧ for bigger steps) and Enter to collapse. Collapsing springs the pane down to a
72
- * slim rail, or to its header in a column, which opens it again. Sizes persist and restore before
73
- * the first paint. Splits nest: call `split` on another split's pane body.
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.
74
93
  */
75
94
  export declare function split(container: HTMLElement, options: SplitOptions): Split;