@kitlangton/knobs 0.0.0-stage → 0.2.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 (123) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +1414 -2
  3. package/dist/dev/chunk-4km87zfx.js +155 -0
  4. package/dist/dev/chunk-5cr85vv6.js +17726 -0
  5. package/dist/dev/chunk-693jd1gj.js +1435 -0
  6. package/dist/dev/chunk-gezhc24g.js +1132 -0
  7. package/dist/dev/index.js +1660 -0
  8. package/dist/index.js +2651 -0
  9. package/dist/panel.js +26404 -0
  10. package/dist/react.js +326 -0
  11. package/dist/solid.js +336 -0
  12. package/dist/themes.js +235 -0
  13. package/dist/types/core/adapter.d.ts +21 -0
  14. package/dist/types/core/code.d.ts +3 -0
  15. package/dist/types/core/color.d.ts +27 -0
  16. package/dist/types/core/easing.d.ts +21 -0
  17. package/dist/types/core/internal.d.ts +18 -0
  18. package/dist/types/core/keys.d.ts +21 -0
  19. package/dist/types/core/mutate.d.ts +21 -0
  20. package/dist/types/core/ramp.d.ts +150 -0
  21. package/dist/types/core/random.d.ts +62 -0
  22. package/dist/types/core/readout.d.ts +73 -0
  23. package/dist/types/core/remote.d.ts +260 -0
  24. package/dist/types/core/schema.d.ts +550 -0
  25. package/dist/types/core/spring.d.ts +38 -0
  26. package/dist/types/core/storage.d.ts +8 -0
  27. package/dist/types/core/store.d.ts +536 -0
  28. package/dist/types/core/theme.d.ts +27 -0
  29. package/dist/types/core/variants.d.ts +25 -0
  30. package/dist/types/index.d.ts +14 -0
  31. package/dist/types/panel/attach.d.ts +5 -0
  32. package/dist/types/panel/choice.d.ts +56 -0
  33. package/dist/types/panel/die.d.ts +121 -0
  34. package/dist/types/panel/editors.d.ts +170 -0
  35. package/dist/types/panel/flash.d.ts +13 -0
  36. package/dist/types/panel/folds.d.ts +14 -0
  37. package/dist/types/panel/give.d.ts +73 -0
  38. package/dist/types/panel/gpu/atlas.d.ts +40 -0
  39. package/dist/types/panel/gpu/color.d.ts +128 -0
  40. package/dist/types/panel/gpu/die.wgsl.d.ts +1 -0
  41. package/dist/types/panel/gpu/renderer.d.ts +784 -0
  42. package/dist/types/panel/gpu/shader.wgsl.d.ts +2 -0
  43. package/dist/types/panel/haptics.d.ts +12 -0
  44. package/dist/types/panel/has.d.ts +13 -0
  45. package/dist/types/panel/hints.d.ts +45 -0
  46. package/dist/types/panel/icons.d.ts +30 -0
  47. package/dist/types/panel/index.d.ts +11 -0
  48. package/dist/types/panel/inspector.d.ts +50 -0
  49. package/dist/types/panel/measure.d.ts +6 -0
  50. package/dist/types/panel/menu.d.ts +38 -0
  51. package/dist/types/panel/morph.d.ts +38 -0
  52. package/dist/types/panel/motion.d.ts +77 -0
  53. package/dist/types/panel/optkeys.d.ts +7 -0
  54. package/dist/types/panel/page-hints.d.ts +82 -0
  55. package/dist/types/panel/page.d.ts +423 -0
  56. package/dist/types/panel/panel.d.ts +43 -0
  57. package/dist/types/panel/position.d.ts +5 -0
  58. package/dist/types/panel/prefs.d.ts +28 -0
  59. package/dist/types/panel/presets.d.ts +60 -0
  60. package/dist/types/panel/ramp-morph.d.ts +117 -0
  61. package/dist/types/panel/ramps.d.ts +14 -0
  62. package/dist/types/panel/readout-row.d.ts +21 -0
  63. package/dist/types/panel/reel.d.ts +43 -0
  64. package/dist/types/panel/reveal.d.ts +15 -0
  65. package/dist/types/panel/rolling-css.d.ts +2 -0
  66. package/dist/types/panel/scope.d.ts +19 -0
  67. package/dist/types/panel/search.d.ts +36 -0
  68. package/dist/types/panel/seg.d.ts +15 -0
  69. package/dist/types/panel/session.d.ts +21 -0
  70. package/dist/types/panel/slider.d.ts +92 -0
  71. package/dist/types/panel/smear.d.ts +7 -0
  72. package/dist/types/panel/sound.d.ts +137 -0
  73. package/dist/types/panel/spin.d.ts +13 -0
  74. package/dist/types/panel/styles.d.ts +11 -0
  75. package/dist/types/panel/swipe.d.ts +114 -0
  76. package/dist/types/panel/switcher.d.ts +20 -0
  77. package/dist/types/panel/tabs.d.ts +31 -0
  78. package/dist/types/panel/thumb.d.ts +36 -0
  79. package/dist/types/panel/toolbar-grid.d.ts +6 -0
  80. package/dist/types/react/Knobs.d.ts +15 -0
  81. package/dist/types/react/VariantSwitcher.d.ts +10 -0
  82. package/dist/types/react/index.d.ts +3 -0
  83. package/dist/types/react/useControls.d.ts +11 -0
  84. package/dist/types/solid/index.d.ts +50 -0
  85. package/dist/types/themes/index.d.ts +1 -0
  86. package/dist/types/ui/activity-css.d.ts +1 -0
  87. package/dist/types/ui/activity-model.d.ts +122 -0
  88. package/dist/types/ui/activity.d.ts +67 -0
  89. package/dist/types/ui/bento-css.d.ts +1 -0
  90. package/dist/types/ui/bento-model.d.ts +96 -0
  91. package/dist/types/ui/bento.d.ts +77 -0
  92. package/dist/types/ui/commands.d.ts +11 -0
  93. package/dist/types/ui/confirm.d.ts +13 -0
  94. package/dist/types/ui/follow.d.ts +17 -0
  95. package/dist/types/ui/index.d.ts +24 -0
  96. package/dist/types/ui/layer.d.ts +70 -0
  97. package/dist/types/ui/look.d.ts +62 -0
  98. package/dist/types/ui/menu.d.ts +63 -0
  99. package/dist/types/ui/overlay-css.d.ts +1 -0
  100. package/dist/types/ui/overlay-model.d.ts +87 -0
  101. package/dist/types/ui/palette.d.ts +38 -0
  102. package/dist/types/ui/picker-css.d.ts +1 -0
  103. package/dist/types/ui/picker-model.d.ts +53 -0
  104. package/dist/types/ui/picker.d.ts +67 -0
  105. package/dist/types/ui/popover.d.ts +35 -0
  106. package/dist/types/ui/react.d.ts +72 -0
  107. package/dist/types/ui/readout-css.d.ts +1 -0
  108. package/dist/types/ui/readout-model.d.ts +137 -0
  109. package/dist/types/ui/readouts.d.ts +85 -0
  110. package/dist/types/ui/rgba.d.ts +6 -0
  111. package/dist/types/ui/solid.d.ts +63 -0
  112. package/dist/types/ui/split-model.d.ts +135 -0
  113. package/dist/types/ui/split.d.ts +92 -0
  114. package/dist/types/ui/timeline-model.d.ts +83 -0
  115. package/dist/types/ui/timeline.d.ts +76 -0
  116. package/dist/types/ui/toast.d.ts +19 -0
  117. package/dist/types/ui/tooltip.d.ts +19 -0
  118. package/dist/types/ui/tree-model.d.ts +125 -0
  119. package/dist/types/ui/tree.d.ts +95 -0
  120. package/dist/ui-react.js +9230 -0
  121. package/dist/ui-solid.js +9162 -0
  122. package/dist/ui.js +11826 -0
  123. package/package.json +99 -4
@@ -0,0 +1,83 @@
1
+ /** The visible window: `start` seconds at the left edge, `span` seconds across. */
2
+ export interface TimeView {
3
+ readonly start: number;
4
+ readonly span: number;
5
+ }
6
+ export type TimeUnits = "seconds" | "frames";
7
+ export interface Tick {
8
+ readonly t: number;
9
+ readonly label: string;
10
+ }
11
+ export interface Ticks {
12
+ readonly major: readonly Tick[];
13
+ readonly minor: readonly number[];
14
+ /** Seconds between major ticks. */
15
+ readonly step: number;
16
+ }
17
+ /** A frame's time, rounded to the nearest frame. */
18
+ export declare const toFrame: (t: number, fps: number) => number;
19
+ export declare const frameTime: (t: number, fps: number) => number;
20
+ /** "1.5s", "12s", "1:05", "1:02:05" for seconds; the frame number for frames. */
21
+ export declare function timeLabel(t: number, units: TimeUnits, fps: number, step?: number): string;
22
+ /**
23
+ * Ticks for a view `width` px wide: major ticks at least `minGap` px apart on a nice step (whole
24
+ * frames in frame units), labelled; minor ones between them, down to single frames once a frame
25
+ * is `frameGap` px wide.
26
+ */
27
+ export declare function rulerTicks(view: TimeView, width: number, o: {
28
+ fps: number;
29
+ units?: TimeUnits;
30
+ minGap?: number;
31
+ frameGap?: number;
32
+ }): Ticks;
33
+ /** Clamps a view to `[0, duration]` with a little room (`pad` of the span) at either end. */
34
+ export declare function clampView(view: TimeView, duration: number, o?: {
35
+ minSpan?: number;
36
+ pad?: number;
37
+ }): TimeView;
38
+ /** Zooms by `factor` (above 1 zooms in) keeping time `at` under the same point. */
39
+ export declare function zoomView(view: TimeView, factor: number, at: number): TimeView;
40
+ /** The view panned so `t` sits at least `margin` (of the span) inside it, or unchanged. */
41
+ export declare function followView(view: TimeView, t: number, margin?: number): TimeView;
42
+ /**
43
+ * The playhead's soft pull toward a marker while it's scrubbed: within `radius` px it follows the
44
+ * pointer by a curve that's flat at the marker (it sticks there) and meets the pointer at the
45
+ * edge, with no jump. Returns the time to show and the marker it rests on, if any.
46
+ */
47
+ export declare function magnet(raw: number, stops: readonly number[], pxPerSec: number, radius?: number, stick?: number): {
48
+ t: number;
49
+ stop: number | null;
50
+ };
51
+ /**
52
+ * Where a scrub lands: on a marker it's resting on, else on the nearest frame (with `frames`),
53
+ * clamped to `[0, duration]`.
54
+ */
55
+ export declare function scrubTime(raw: number, o: {
56
+ duration: number;
57
+ fps: number;
58
+ pxPerSec: number;
59
+ stops?: readonly number[];
60
+ frames?: boolean;
61
+ radius?: number;
62
+ }): {
63
+ t: number;
64
+ shown: number;
65
+ stop: number | null;
66
+ };
67
+ /** The marker before (`-1`) or after (`1`) time `t`, by a frame's margin, or null. */
68
+ export declare function adjacentMarker<M extends {
69
+ readonly time: number;
70
+ }>(markers: readonly M[], t: number, dir: 1 | -1, fps: number): M | null;
71
+ /** Advances playing time by `dt`, looping inside `loop` (or the whole) when asked. */
72
+ export declare function advance(t: number, dt: number, o: {
73
+ duration: number;
74
+ loop?: {
75
+ start: number;
76
+ end: number;
77
+ } | null;
78
+ repeat?: boolean;
79
+ }): {
80
+ t: number;
81
+ ended: boolean;
82
+ wrapped: boolean;
83
+ };
@@ -0,0 +1,76 @@
1
+ import { type UiLook } from "./look.js";
2
+ import { type TimeUnits, type TimeView } from "./timeline-model.js";
3
+ export interface TimelineMarker {
4
+ readonly id: string;
5
+ /** Seconds. */
6
+ readonly time: number;
7
+ readonly label?: string;
8
+ /** A colour of its own (CSS); the accent otherwise. */
9
+ readonly color?: string;
10
+ }
11
+ export interface TimelineRange {
12
+ readonly id: string;
13
+ readonly start: number;
14
+ readonly end: number;
15
+ readonly label?: string;
16
+ /** Playback loops inside it (`I` / `O` make the `"loop"` range, which loops). */
17
+ readonly loop?: boolean;
18
+ }
19
+ export type SeekSource = "scrub" | "key" | "marker" | "play" | "code";
20
+ export interface TimelineOptions extends UiLook {
21
+ /** Seconds. */
22
+ readonly duration: number;
23
+ readonly time?: number;
24
+ readonly playing?: boolean;
25
+ /** Frames per second (30): frame steps, frame labels, and where scrubs land. */
26
+ readonly fps?: number;
27
+ /** What the ruler counts in (`"seconds"`). */
28
+ readonly units?: TimeUnits;
29
+ readonly markers?: readonly TimelineMarker[];
30
+ readonly ranges?: readonly TimelineRange[];
31
+ /** Scrubs land on frames and stick to markers (`true`); `{ frames, markers }` picks. */
32
+ readonly snap?: boolean | {
33
+ readonly frames?: boolean;
34
+ readonly markers?: boolean;
35
+ };
36
+ /** Playback speed (1). */
37
+ readonly speed?: number;
38
+ /** Playback starts over at the end when there's no loop range (`false`: it stops). */
39
+ readonly repeat?: boolean;
40
+ readonly label?: string;
41
+ /** The time moved: scrubbed, stepped, jumped, played (every frame) or set from code. */
42
+ onSeek?(time: number, source: SeekSource): void;
43
+ onPlay?(playing: boolean): void;
44
+ /** Markers were added, moved, renamed or removed (the whole list). */
45
+ onMarkers?(markers: readonly TimelineMarker[]): void;
46
+ /** Ranges were set, moved or cleared (the whole list). */
47
+ onRanges?(ranges: readonly TimelineRange[]): void;
48
+ /** Playback passed a marker. */
49
+ onCross?(marker: TimelineMarker): void;
50
+ /**
51
+ * Play, each marker and the playhead take codes in the page's hint mode (`s`), on by default:
52
+ * a marker's code jumps to it, the playhead's focuses the timeline.
53
+ */
54
+ readonly hints?: boolean;
55
+ }
56
+ export interface Timeline {
57
+ readonly element: HTMLElement;
58
+ readonly time: number;
59
+ readonly playing: boolean;
60
+ readonly markers: readonly TimelineMarker[];
61
+ readonly ranges: readonly TimelineRange[];
62
+ readonly view: TimeView;
63
+ seek(time: number): void;
64
+ play(): void;
65
+ pause(): void;
66
+ toggle(): void;
67
+ /** New duration, markers, ranges, fps, units or speed; the time and view stay. */
68
+ update(next: Partial<Omit<TimelineOptions, "onSeek" | "onPlay" | "onMarkers" | "onRanges" | "onCross">>): void;
69
+ /** Shows the whole duration (animated). */
70
+ fit(): void;
71
+ /** Zooms by `factor` (above 1 zooms in) around a time (the playhead's by default). */
72
+ zoom(factor: number, at?: number): void;
73
+ focus(): void;
74
+ dispose(): void;
75
+ }
76
+ export declare function timeline(container: HTMLElement, options: TimelineOptions): Timeline;
@@ -0,0 +1,19 @@
1
+ import { type UiLook } from "./look.js";
2
+ export interface ToastOptions {
3
+ /** Ms it stays (3200; errors 6000). */
4
+ readonly linger?: number;
5
+ readonly tone?: "info" | "warn" | "error";
6
+ /** A button in the pill (Undo, say). */
7
+ readonly action?: {
8
+ readonly label: string;
9
+ run(): void;
10
+ };
11
+ readonly look?: UiLook;
12
+ /** Where it lives, to take that element's tokens (a page); the overlay layer by default. */
13
+ readonly within?: HTMLElement;
14
+ readonly doc?: Document;
15
+ }
16
+ export interface Toast {
17
+ dismiss(): void;
18
+ }
19
+ export declare function toast(message: string, options?: ToastOptions): Toast;
@@ -0,0 +1,19 @@
1
+ import type { UiLook } from "./look.js";
2
+ import { type Placement } from "./overlay-model.js";
3
+ export interface TooltipOptions {
4
+ /** A key or combination (`"Mod+K"`, `"Space"`): shown as chips after the text. */
5
+ readonly shortcut?: string;
6
+ /** `top` by default. */
7
+ readonly placement?: Placement;
8
+ /** Ms over the target before it shows (500); a hand-off shows at once. */
9
+ readonly delay?: number;
10
+ readonly look?: UiLook;
11
+ }
12
+ /** Text, a function read each time it shows, or text with options. */
13
+ export type TooltipContent = string | (() => string) | ({
14
+ readonly text: string | (() => string);
15
+ } & TooltipOptions);
16
+ /** Shows `content` over `el` after a pause (or on keyboard focus). Returns the remover. */
17
+ export declare function tooltip(el: HTMLElement, content: TooltipContent, options?: TooltipOptions): () => void;
18
+ /** Turns on `data-tip` (and `data-tip-shortcut`, `data-tip-placement`) tooltips in a document. */
19
+ export declare function tooltips(doc?: Document): void;
@@ -0,0 +1,125 @@
1
+ /** How a tree reads your items. */
2
+ export interface TreeAccess<T> {
3
+ id(item: T): string;
4
+ /** Children, or nothing for a leaf. An empty array is a parent with none (it takes drops). */
5
+ children(item: T): readonly T[] | null | undefined;
6
+ label(item: T): string;
7
+ }
8
+ export interface FlatRow<T> {
9
+ readonly id: string;
10
+ readonly item: T;
11
+ readonly depth: number;
12
+ readonly parent: string | null;
13
+ /** Position among its parent's children (all of them, filtered or not). */
14
+ readonly index: number;
15
+ readonly hasChildren: boolean;
16
+ /** Takes children (a drop "into" it). */
17
+ readonly container: boolean;
18
+ readonly expanded: boolean;
19
+ /** Where the filter matched its label, if it did. */
20
+ readonly match?: readonly [number, number];
21
+ /** Shown only because something under it matched. */
22
+ readonly ancestor?: boolean;
23
+ }
24
+ export type TreeFilter<T> = string | ((item: T) => boolean) | null | undefined;
25
+ /** Where the filter matches a label: a case-insensitive substring. */
26
+ export declare function matchLabel(label: string, query: string): readonly [number, number] | undefined;
27
+ /**
28
+ * The rows on show, top to bottom: expanded parents' children follow them. With a filter, rows
29
+ * that match show with every ancestor (opened while it runs, marked `ancestor` when they don't
30
+ * match themselves).
31
+ */
32
+ export declare function flatten<T>(roots: readonly T[], access: TreeAccess<T>, expanded: ReadonlySet<string>, filter?: TreeFilter<T>): FlatRow<T>[];
33
+ /** Every item by id, with its parent and position. */
34
+ export declare function indexTree<T>(roots: readonly T[], access: TreeAccess<T>): Map<string, {
35
+ item: T;
36
+ parent: string | null;
37
+ index: number;
38
+ depth: number;
39
+ }>;
40
+ /** The ids of an item's ancestors, nearest first. */
41
+ export declare function ancestors(index: ReadonlyMap<string, {
42
+ parent: string | null;
43
+ }>, id: string): string[];
44
+ export type NavKey = "ArrowUp" | "ArrowDown" | "ArrowLeft" | "ArrowRight" | "Home" | "End";
45
+ export interface NavResult {
46
+ readonly active: string | null;
47
+ /** Open or close a parent instead of moving. */
48
+ readonly toggle?: {
49
+ readonly id: string;
50
+ readonly expanded: boolean;
51
+ };
52
+ }
53
+ /** Roving focus: ↑↓ move, ← closes or goes to the parent, → opens or goes to the first child. */
54
+ export declare function navigate<T>(rows: readonly FlatRow<T>[], active: string | null, key: NavKey | "PageUp" | "PageDown", page?: number): NavResult;
55
+ /**
56
+ * Type-ahead: the next row whose label starts with what's been typed, after the active one (or
57
+ * from it, once the word is longer than a letter, so typing on refines in place).
58
+ */
59
+ export declare function typeahead<T>(rows: readonly FlatRow<T>[], active: string | null, typed: string, label: (item: T) => string): string | null;
60
+ export interface Selection {
61
+ readonly ids: readonly string[];
62
+ readonly anchor: string | null;
63
+ }
64
+ /**
65
+ * A click or keyboard selection: plain picks one, ⌘/Ctrl adds or removes, ⇧ takes the range from
66
+ * the anchor in the order shown (⇧⌘ adds it to what's there).
67
+ */
68
+ export declare function select<T>(rows: readonly FlatRow<T>[], current: Selection, id: string, mods?: {
69
+ readonly shift?: boolean;
70
+ readonly toggle?: boolean;
71
+ }): Selection;
72
+ /** The topmost of `ids`: none whose ancestor is also among them, in tree order. */
73
+ export declare function topmost<T>(roots: readonly T[], access: TreeAccess<T>, ids: Iterable<string>): string[];
74
+ /**
75
+ * A move: take `ids` out (with their subtrees), then insert them in order at `index` among
76
+ * `parent`'s remaining children (`null` is the top level).
77
+ */
78
+ export interface TreeMove {
79
+ readonly ids: readonly string[];
80
+ readonly parent: string | null;
81
+ readonly index: number;
82
+ }
83
+ /** Whether a move keeps the tree a tree: nothing goes inside itself. */
84
+ export declare function validMove<T>(roots: readonly T[], access: TreeAccess<T>, move: TreeMove): boolean;
85
+ /** The tree's defaults: `item.id`, `item.children`, and `item.label` or the id. */
86
+ export declare const plainAccess: TreeAccess<{
87
+ readonly id: string;
88
+ readonly label?: string;
89
+ readonly children?: readonly unknown[] | null;
90
+ }>;
91
+ /**
92
+ * Applies a move to plain `{ id, children }` items (or any, through `access`), returning new
93
+ * arrays along the changed paths (items themselves are copied only where their children change).
94
+ * `make(item, children)` builds a parent with new children; the default spreads the item.
95
+ */
96
+ export declare function applyMove<T extends {
97
+ readonly id: string;
98
+ }>(roots: readonly T[], move: TreeMove): T[];
99
+ export declare function applyMove<T>(roots: readonly T[], access: TreeAccess<T>, move: TreeMove, make?: (item: T, children: T[]) => T): T[];
100
+ /**
101
+ * ⌥↑/⌥↓: the selected rows step past their neighbour among their siblings. Rows under different
102
+ * parents move with the first one's parent; at an end they stay.
103
+ */
104
+ export declare function stepMove<T>(roots: readonly T[], access: TreeAccess<T>, ids: readonly string[], dir: -1 | 1): TreeMove | undefined;
105
+ export type DropZone = "before" | "after" | "into";
106
+ export interface DropTarget {
107
+ readonly move: TreeMove;
108
+ /** Draw a line after row `line` (−1: above the first row) at `depth`… */
109
+ readonly line?: {
110
+ readonly after: number;
111
+ readonly depth: number;
112
+ };
113
+ /** …or wash the row a drop goes into. */
114
+ readonly into?: string;
115
+ }
116
+ /** Which zone of a row the pointer is over (0–1 down the row): parents take a middle band. */
117
+ export declare function zoneAt(fraction: number, container: boolean): DropZone;
118
+ /**
119
+ * Where a drop lands. Over the top of a row it goes before it; over the middle of a parent, into
120
+ * it (at the end); over the bottom, after it, or first inside it when it's open. Below the last
121
+ * row of a branch, `depth` (from the pointer's x) picks how far out it goes.
122
+ */
123
+ export declare function dropTarget<T>(rows: readonly FlatRow<T>[], access: TreeAccess<T>, over: number, zone: DropZone, ids: readonly string[], depth?: number): DropTarget | undefined;
124
+ /** The rows a scroller of `height` at `scrollTop` shows, with `overscan` either side. */
125
+ export declare function virtualWindow(scrollTop: number, height: number, rowHeight: number, count: number, overscan?: number): readonly [number, number];
@@ -0,0 +1,95 @@
1
+ import { type UiLook } from "./look.js";
2
+ import { type TreeFilter, type TreeMove } from "./tree-model.js";
3
+ /** A row accessory that flips a flag: visibility, a lock, or one of your own. */
4
+ export interface TreeToggle<T> {
5
+ /** `"visible"` and `"locked"` bring their own icons. */
6
+ readonly id: string;
7
+ readonly label: string;
8
+ /** Whether the item is in its usual state (visible, unlocked): only the other one shows at rest. */
9
+ get(item: T): boolean;
10
+ /** Flip it for these ids (the selection, when the row is in it). */
11
+ set(ids: readonly string[], value: boolean): void;
12
+ /** SVG markup for each state. */
13
+ icon?(on: boolean): string;
14
+ }
15
+ export interface TreeRowContext {
16
+ readonly id: string;
17
+ readonly depth: number;
18
+ readonly expanded: boolean;
19
+ readonly selected: boolean;
20
+ readonly element: HTMLElement;
21
+ }
22
+ export interface TreeOptions<T> extends UiLook {
23
+ readonly items: readonly T[];
24
+ /** Item → id (unique); `item.id` unless set. */
25
+ readonly getId?: (item: T) => string;
26
+ /** Item → children (`item.children` unless set); an array, even empty, takes drops. */
27
+ readonly getChildren?: (item: T) => readonly T[] | null | undefined;
28
+ /** Item → label (`item.label`, else its id). */
29
+ readonly getLabel?: (item: T) => string;
30
+ /** A glyph, SVG markup or node before the label. */
31
+ readonly icon?: (item: T) => string | Node | undefined;
32
+ /** Dimmed text after the label (a count, a kind). */
33
+ readonly detail?: (item: T) => string | undefined;
34
+ /** Your own content in place of the label. */
35
+ readonly render?: (item: T, row: TreeRowContext) => Node | string | undefined | void;
36
+ readonly selection?: Iterable<string>;
37
+ readonly onSelect?: (ids: readonly string[], primary: string | null) => void;
38
+ readonly expanded?: Iterable<string>;
39
+ readonly onToggle?: (id: string, expanded: boolean) => void;
40
+ /** Drag and ⌥↑↓ report moves; apply them (`applyMove` does for plain items) and `update`. */
41
+ readonly onMove?: (move: TreeMove) => void;
42
+ readonly canDrop?: (move: TreeMove) => boolean;
43
+ /** F2 or Enter renames in place. */
44
+ readonly onRename?: (id: string, label: string) => void;
45
+ /** A double-click (and Enter, without `onRename`). */
46
+ readonly onActivate?: (id: string) => void;
47
+ readonly toggles?: readonly TreeToggle<T>[];
48
+ readonly filter?: TreeFilter<T>;
49
+ /** Pixels; `--k-row` unless set. */
50
+ readonly rowHeight?: number;
51
+ /** The tree's accessible name. */
52
+ readonly label?: string;
53
+ /** Shown with no rows. */
54
+ readonly empty?: string;
55
+ /**
56
+ * Letters jump to a matching label (on by default). `false` leaves every letter to the page (a
57
+ * host's single-key shortcuts), and a function decides by key which ones start a jump; once one
58
+ * has, the letters typed right after it carry on the run.
59
+ */
60
+ readonly typeahead?: boolean | ((key: string) => boolean);
61
+ /**
62
+ * Its rows on screen take codes in the page's hint mode (`s`), on by default; a code selects its
63
+ * row as a click does. While the page has hint mode, `s` goes to it rather than type-ahead.
64
+ */
65
+ readonly hints?: boolean;
66
+ }
67
+ export interface Tree<T> {
68
+ readonly element: HTMLElement;
69
+ /** New items: rows that stay glide to their new places, others fold in and out. */
70
+ update(items: readonly T[]): void;
71
+ select(ids: Iterable<string>, primary?: string | null): void;
72
+ readonly selection: readonly string[];
73
+ readonly active: string | null;
74
+ expand(id: string, expanded?: boolean): void;
75
+ isExpanded(id: string): boolean;
76
+ /** A query (label substring) or a test; matching rows show with their ancestors. */
77
+ filter(filter: TreeFilter<T>): void;
78
+ /** The ids on show, top to bottom. */
79
+ rows(): readonly string[];
80
+ focus(id?: string): void;
81
+ /** Opens its ancestors and scrolls it into view. */
82
+ reveal(id: string): void;
83
+ rename(id: string): void;
84
+ /** Draws rows again from their items (after you change them in place). */
85
+ refresh(): void;
86
+ dispose(): void;
87
+ }
88
+ /**
89
+ * An outliner: virtualised rows (thousands scroll at full speed), springing open and shut with
90
+ * the children cascading out from under their parent. Roving focus (↑↓, ← to close or go up, → to
91
+ * open or go down, Home/End, type-ahead, Space), ⇧/⌘ multi-selection, drag to reorder and
92
+ * reparent (⌥↑↓ by keys), inline rename, visibility and lock toggles, and a filter that keeps
93
+ * matching rows' ancestors.
94
+ */
95
+ export declare function tree<T>(container: HTMLElement, options: TreeOptions<T>): Tree<T>;