@densedash/core 0.0.0-stage → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/dist/bare.d.ts +14 -0
- package/dist/bare.js +11 -0
- package/dist/bare.js.map +1 -0
- package/dist/collections/flatten.d.ts +8 -0
- package/dist/collections/flatten.js +59 -0
- package/dist/collections/flatten.js.map +1 -0
- package/dist/collections/move.d.ts +7 -0
- package/dist/collections/move.js +74 -0
- package/dist/collections/move.js.map +1 -0
- package/dist/collections/reconcile.d.ts +9 -0
- package/dist/collections/reconcile.js +44 -0
- package/dist/collections/reconcile.js.map +1 -0
- package/dist/collections/selection.d.ts +12 -0
- package/dist/collections/selection.js +39 -0
- package/dist/collections/selection.js.map +1 -0
- package/dist/collections/types.d.ts +48 -0
- package/dist/commands/index.d.ts +10 -0
- package/dist/commands/index.js +255 -0
- package/dist/commands/index.js.map +1 -0
- package/dist/commands/keys.js +52 -0
- package/dist/commands/keys.js.map +1 -0
- package/dist/commands/scopes.js +46 -0
- package/dist/commands/scopes.js.map +1 -0
- package/dist/commands/trading-preset.d.ts +3 -0
- package/dist/commands/trading-preset.js +90 -0
- package/dist/commands/trading-preset.js.map +1 -0
- package/dist/commands/types.d.ts +76 -0
- package/dist/conformance/index.d.ts +17 -0
- package/dist/conformance/index.js +79 -0
- package/dist/conformance/index.js.map +1 -0
- package/dist/conformance/keyboard.d.ts +14 -0
- package/dist/conformance/keyboard.js +307 -0
- package/dist/conformance/keyboard.js.map +1 -0
- package/dist/controllable.d.ts +13 -0
- package/dist/defaults/index.js +38 -0
- package/dist/defaults/index.js.map +1 -0
- package/dist/defaults/keyboard.js +137 -0
- package/dist/defaults/keyboard.js.map +1 -0
- package/dist/index.d.ts +23 -0
- package/dist/index.js +21 -0
- package/dist/index.js.map +1 -0
- package/dist/kernel.d.ts +57 -0
- package/dist/kernel.js +92 -0
- package/dist/kernel.js.map +1 -0
- package/dist/ports/clock.d.ts +6 -0
- package/dist/ports/keyboard.d.ts +62 -0
- package/dist/ports/reporter.d.ts +9 -0
- package/dist/ports/store.d.ts +12 -0
- package/dist/task.d.ts +3 -0
- package/dist/tree/commands.js +119 -0
- package/dist/tree/commands.js.map +1 -0
- package/dist/tree/index.d.ts +6 -0
- package/dist/tree/index.js +71 -0
- package/dist/tree/index.js.map +1 -0
- package/dist/tree/props.js +198 -0
- package/dist/tree/props.js.map +1 -0
- package/dist/tree/state.js +126 -0
- package/dist/tree/state.js.map +1 -0
- package/dist/tree/types.d.ts +107 -0
- package/package.json +40 -3
- package/README.md +0 -3
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Anthony Altieri
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/dist/bare.d.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { BasePorts, CheckedKernelOptions, Kernel, KernelOptions, Plugin, PortProviders, Ports, ResolvedPorts } from "./kernel.js";
|
|
2
|
+
import { createCommands } from "./commands/index.js";
|
|
3
|
+
import { tradingPreset } from "./commands/trading-preset.js";
|
|
4
|
+
import { Command, CommandContext, CommandId, CommandScopeOptions, Commands, KeyOverrideId, KeyOverrides, KeymapEntry, KeysOptions, PendingConfirm, Preset, Register, ValidatedKeyOverrides } from "./commands/types.js";
|
|
5
|
+
import { ClockPort } from "./ports/clock.js";
|
|
6
|
+
import { KeyboardBinding, KeyboardBindingOptions, KeyboardHandler, KeyboardHotkey, KeyboardHotkeyChord, KeyboardParseResult, KeyboardPendingStore, KeyboardPlatform, KeyboardPort, KeyboardScopeOptions, KeyboardTarget, PendingKeyboardSequence } from "./ports/keyboard.js";
|
|
7
|
+
import { ReporterPort } from "./ports/reporter.js";
|
|
8
|
+
import { Store, StorePort } from "./ports/store.js";
|
|
9
|
+
import { Task } from "./task.js";
|
|
10
|
+
import { ChangeDetails, Controllable } from "./controllable.js";
|
|
11
|
+
/** No defaults: every port must be supplied by plugins or explicit ports. */
|
|
12
|
+
export declare function createKernel<const Options extends KernelOptions = KernelOptions>(options?: Options & CheckedKernelOptions<Options>): Kernel<ResolvedPorts<Options>>;
|
|
13
|
+
export { type BasePorts, type ChangeDetails, type ClockPort, type Command, type CommandContext, type CommandId, type CommandScopeOptions, type Commands, type Controllable, type Kernel, type KernelOptions, type KeyOverrideId, type KeyOverrides, type KeyboardBinding, type KeyboardBindingOptions, type KeyboardHandler, type KeyboardHotkey, type KeyboardHotkeyChord, type KeyboardParseResult, type KeyboardPendingStore, type KeyboardPlatform, type KeyboardPort, type KeyboardScopeOptions, type KeyboardTarget, type KeymapEntry, type KeysOptions, type PendingConfirm, type PendingKeyboardSequence, type Plugin, type PortProviders, type Ports, type Preset, type Register, type ReporterPort, type ResolvedPorts, type Store, type StorePort, type Task, type ValidatedKeyOverrides, createCommands, tradingPreset };
|
|
14
|
+
//# sourceMappingURL=bare.d.ts.map
|
package/dist/bare.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { tradingPreset } from "./commands/trading-preset.js";
|
|
2
|
+
import { resolveKernel } from "./kernel.js";
|
|
3
|
+
import { createCommands } from "./commands/index.js";
|
|
4
|
+
// src/bare.ts
|
|
5
|
+
/** No defaults: every port must be supplied by plugins or explicit ports. */
|
|
6
|
+
function createKernel(options) {
|
|
7
|
+
return resolveKernel({ options: options ?? {} });
|
|
8
|
+
}
|
|
9
|
+
export { createCommands, createKernel, tradingPreset };
|
|
10
|
+
|
|
11
|
+
//# sourceMappingURL=bare.js.map
|
package/dist/bare.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bare.js","names":[],"sources":["../src/bare.ts"],"sourcesContent":["import { resolveKernel } from \"./kernel.js\";\nimport type { CheckedKernelOptions, Kernel, KernelOptions, ResolvedPorts } from \"./kernel.js\";\n\nexport type {\n BasePorts,\n Kernel,\n KernelOptions,\n Plugin,\n PortProviders,\n Ports,\n ResolvedPorts,\n} from \"./kernel.js\";\nexport * from \"./commands/index.js\";\nexport type { ClockPort } from \"./ports/clock.js\";\nexport type {\n KeyboardPort,\n KeyboardHotkey,\n KeyboardHotkeyChord,\n KeyboardPlatform,\n KeyboardTarget,\n KeyboardHandler,\n KeyboardParseResult,\n KeyboardScopeOptions,\n KeyboardBindingOptions,\n KeyboardBinding,\n PendingKeyboardSequence,\n KeyboardPendingStore,\n} from \"./ports/keyboard.js\";\nexport type { ReporterPort } from \"./ports/reporter.js\";\nexport type { Store, StorePort } from \"./ports/store.js\";\nexport type { Task } from \"./task.js\";\nexport type { ChangeDetails, Controllable } from \"./controllable.js\";\n\n/** No defaults: every port must be supplied by plugins or explicit ports. */\nexport function createKernel<const Options extends KernelOptions = KernelOptions>(\n options?: Options & CheckedKernelOptions<Options>,\n): Kernel<ResolvedPorts<Options>> {\n // The resolver applies the same precedence encoded by ResolvedPorts.\n return resolveKernel({ options: options ?? {} }) as Kernel<ResolvedPorts<Options>>;\n}\n"],"mappings":";;;;;AAkCA,SAAgB,aACd,SACgC;CAEhC,OAAO,cAAc,EAAE,SAAS,WAAW,CAAC,EAAE,CAAC;AACjD"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { Key, TreeRow, TreeSource } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Visible preorder rows. Index/depth are zero-based; sibling positions are one-based.
|
|
4
|
+
* Validate the entire source, including collapsed branches, in O(total items).
|
|
5
|
+
* Duplicate keys and ancestor cycles throw in every environment, naming the key.
|
|
6
|
+
*/
|
|
7
|
+
export declare function flatten<T>(source: TreeSource<T>, expanded: ReadonlySet<Key>): TreeRow<T>[];
|
|
8
|
+
//# sourceMappingURL=flatten.d.ts.map
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
// src/collections/flatten.ts
|
|
2
|
+
/**
|
|
3
|
+
* Visible preorder rows. Index/depth are zero-based; sibling positions are one-based.
|
|
4
|
+
* Validate the entire source, including collapsed branches, in O(total items).
|
|
5
|
+
* Duplicate keys and ancestor cycles throw in every environment, naming the key.
|
|
6
|
+
*/
|
|
7
|
+
function flatten(source, expanded) {
|
|
8
|
+
const rows = [];
|
|
9
|
+
const seen = /* @__PURE__ */ new Set();
|
|
10
|
+
const ancestors = /* @__PURE__ */ new Set();
|
|
11
|
+
const stack = [{
|
|
12
|
+
items: source.roots,
|
|
13
|
+
offset: 0,
|
|
14
|
+
parentKey: null,
|
|
15
|
+
visible: true
|
|
16
|
+
}];
|
|
17
|
+
while (stack.length > 0) {
|
|
18
|
+
const frame = stack[stack.length - 1];
|
|
19
|
+
if (frame.offset === frame.items.length) {
|
|
20
|
+
if (frame.parentKey !== null) ancestors.delete(frame.parentKey);
|
|
21
|
+
stack.pop();
|
|
22
|
+
continue;
|
|
23
|
+
}
|
|
24
|
+
const item = frame.items[frame.offset++];
|
|
25
|
+
const key = source.getKey(item);
|
|
26
|
+
if (ancestors.has(key)) throw new Error(`Collection cycle at key "${key}".`);
|
|
27
|
+
if (seen.has(key)) throw new Error(`Duplicate collection key "${key}".`);
|
|
28
|
+
seen.add(key);
|
|
29
|
+
const children = source.getChildren?.(item);
|
|
30
|
+
const hasChildren = children !== void 0 && children.length > 0;
|
|
31
|
+
const isExpanded = hasChildren && expanded.has(key);
|
|
32
|
+
if (frame.visible) rows.push({
|
|
33
|
+
key,
|
|
34
|
+
item,
|
|
35
|
+
index: rows.length,
|
|
36
|
+
depth: stack.length - 1,
|
|
37
|
+
parentKey: frame.parentKey,
|
|
38
|
+
hasChildren,
|
|
39
|
+
expanded: isExpanded,
|
|
40
|
+
posInSet: frame.offset,
|
|
41
|
+
setSize: frame.items.length,
|
|
42
|
+
disabled: source.isDisabled?.(item) ?? false,
|
|
43
|
+
textValue: source.getTextValue?.(item) ?? key
|
|
44
|
+
});
|
|
45
|
+
if (children !== void 0 && hasChildren) {
|
|
46
|
+
ancestors.add(key);
|
|
47
|
+
stack.push({
|
|
48
|
+
items: children,
|
|
49
|
+
offset: 0,
|
|
50
|
+
parentKey: key,
|
|
51
|
+
visible: frame.visible && isExpanded
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return rows;
|
|
56
|
+
}
|
|
57
|
+
export { flatten };
|
|
58
|
+
|
|
59
|
+
//# sourceMappingURL=flatten.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"flatten.js","names":[],"sources":["../../src/collections/flatten.ts"],"sourcesContent":["import type { Key, TreeRow, TreeSource } from \"./types.js\";\n\ninterface Frame<T> {\n items: readonly T[];\n offset: number;\n parentKey: Key | null;\n visible: boolean;\n}\n\n/**\n * Visible preorder rows. Index/depth are zero-based; sibling positions are one-based.\n * Validate the entire source, including collapsed branches, in O(total items).\n * Duplicate keys and ancestor cycles throw in every environment, naming the key.\n */\nexport function flatten<T>(source: TreeSource<T>, expanded: ReadonlySet<Key>): TreeRow<T>[] {\n const rows: TreeRow<T>[] = [];\n const seen = new Set<Key>();\n const ancestors = new Set<Key>();\n const stack: Frame<T>[] = [{ items: source.roots, offset: 0, parentKey: null, visible: true }];\n\n while (stack.length > 0) {\n const frame = stack[stack.length - 1]!;\n if (frame.offset === frame.items.length) {\n if (frame.parentKey !== null) ancestors.delete(frame.parentKey);\n stack.pop();\n continue;\n }\n\n const item = frame.items[frame.offset++]!;\n const key = source.getKey(item);\n if (ancestors.has(key)) throw new Error(`Collection cycle at key \"${key}\".`);\n if (seen.has(key)) throw new Error(`Duplicate collection key \"${key}\".`);\n seen.add(key);\n\n const children = source.getChildren?.(item);\n const hasChildren = children !== undefined && children.length > 0;\n const isExpanded = hasChildren && expanded.has(key);\n if (frame.visible) {\n rows.push({\n key,\n item,\n index: rows.length,\n depth: stack.length - 1,\n parentKey: frame.parentKey,\n hasChildren,\n expanded: isExpanded,\n posInSet: frame.offset,\n setSize: frame.items.length,\n disabled: source.isDisabled?.(item) ?? false,\n textValue: source.getTextValue?.(item) ?? key,\n });\n }\n\n if (children !== undefined && hasChildren) {\n ancestors.add(key);\n stack.push({\n items: children,\n offset: 0,\n parentKey: key,\n visible: frame.visible && isExpanded,\n });\n }\n }\n\n return rows;\n}\n"],"mappings":";;;;;;AAcA,SAAgB,QAAW,QAAuB,UAA0C;CAC1F,MAAM,OAAqB,CAAC;CAC5B,MAAM,uBAAO,IAAI,IAAS;CAC1B,MAAM,4BAAY,IAAI,IAAS;CAC/B,MAAM,QAAoB,CAAC;EAAE,OAAO,OAAO;EAAO,QAAQ;EAAG,WAAW;EAAM,SAAS;CAAK,CAAC;CAE7F,OAAO,MAAM,SAAS,GAAG;EACvB,MAAM,QAAQ,MAAM,MAAM,SAAS;EACnC,IAAI,MAAM,WAAW,MAAM,MAAM,QAAQ;GACvC,IAAI,MAAM,cAAc,MAAM,UAAU,OAAO,MAAM,SAAS;GAC9D,MAAM,IAAI;GACV;EACF;EAEA,MAAM,OAAO,MAAM,MAAM,MAAM;EAC/B,MAAM,MAAM,OAAO,OAAO,IAAI;EAC9B,IAAI,UAAU,IAAI,GAAG,GAAG,MAAM,IAAI,MAAM,4BAA4B,IAAI,GAAG;EAC3E,IAAI,KAAK,IAAI,GAAG,GAAG,MAAM,IAAI,MAAM,6BAA6B,IAAI,GAAG;EACvE,KAAK,IAAI,GAAG;EAEZ,MAAM,WAAW,OAAO,cAAc,IAAI;EAC1C,MAAM,cAAc,aAAa,KAAA,KAAa,SAAS,SAAS;EAChE,MAAM,aAAa,eAAe,SAAS,IAAI,GAAG;EAClD,IAAI,MAAM,SACR,KAAK,KAAK;GACR;GACA;GACA,OAAO,KAAK;GACZ,OAAO,MAAM,SAAS;GACtB,WAAW,MAAM;GACjB;GACA,UAAU;GACV,UAAU,MAAM;GAChB,SAAS,MAAM,MAAM;GACrB,UAAU,OAAO,aAAa,IAAI,KAAK;GACvC,WAAW,OAAO,eAAe,IAAI,KAAK;EAC5C,CAAC;EAGH,IAAI,aAAa,KAAA,KAAa,aAAa;GACzC,UAAU,IAAI,GAAG;GACjB,MAAM,KAAK;IACT,OAAO;IACP,QAAQ;IACR,WAAW;IACX,SAAS,MAAM,WAAW;GAC5B,CAAC;EACH;CACF;CAEA,OAAO;AACT"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { Key, Move, MoveOptions, TreeRow } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Return a key; never mutate rows or state. No target leaves the current enabled
|
|
4
|
+
* key in place (or null). Counts and pages count enabled rows. Empty rows return null.
|
|
5
|
+
*/
|
|
6
|
+
export declare function move<T>(rows: readonly TreeRow<T>[], from: Key | null, movement: Move, { loop }?: MoveOptions): Key | null;
|
|
7
|
+
//# sourceMappingURL=move.d.ts.map
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
// src/collections/move.ts
|
|
2
|
+
/** Move by enabled rows without iterating count times, even for huge counts. */
|
|
3
|
+
function step(rows, fromIndex, count, direction, loop) {
|
|
4
|
+
if (!Number.isSafeInteger(count) || count < 0) throw new RangeError("Collection move count/size must be a non-negative safe integer.");
|
|
5
|
+
const keys = [];
|
|
6
|
+
let before = 0;
|
|
7
|
+
let current = -1;
|
|
8
|
+
for (let index = 0; index < rows.length; index++) {
|
|
9
|
+
const row = rows[index];
|
|
10
|
+
if (row.disabled) continue;
|
|
11
|
+
if (index < fromIndex) before++;
|
|
12
|
+
if (index === fromIndex) current = keys.length;
|
|
13
|
+
keys.push(row.key);
|
|
14
|
+
}
|
|
15
|
+
if (keys.length === 0) return null;
|
|
16
|
+
if (count === 0) return current < 0 ? null : keys[current];
|
|
17
|
+
let start = current;
|
|
18
|
+
if (current < 0) start = fromIndex < 0 ? direction === 1 ? -1 : keys.length : direction === 1 ? before - 1 : before;
|
|
19
|
+
const distance = loop ? count % keys.length : Math.min(count, keys.length);
|
|
20
|
+
const target = start + direction * distance;
|
|
21
|
+
return keys[loop ? (target % keys.length + keys.length) % keys.length : Math.max(0, Math.min(keys.length - 1, target))];
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Return a key; never mutate rows or state. No target leaves the current enabled
|
|
25
|
+
* key in place (or null). Counts and pages count enabled rows. Empty rows return null.
|
|
26
|
+
*/
|
|
27
|
+
function move(rows, from, movement, { loop = false } = {}) {
|
|
28
|
+
const fromIndex = from === null ? -1 : rows.findIndex((row) => row.key === from);
|
|
29
|
+
const current = rows[fromIndex];
|
|
30
|
+
const unchanged = current && !current.disabled ? current.key : null;
|
|
31
|
+
switch (movement.type) {
|
|
32
|
+
case "next":
|
|
33
|
+
case "prev": return step(rows, fromIndex, movement.count ?? 1, movement.type === "next" ? 1 : -1, loop);
|
|
34
|
+
case "page": return step(rows, fromIndex, movement.size, movement.direction, loop);
|
|
35
|
+
case "first": return rows.find((row) => !row.disabled)?.key ?? null;
|
|
36
|
+
case "last":
|
|
37
|
+
for (let index = rows.length - 1; index >= 0; index--) {
|
|
38
|
+
const row = rows[index];
|
|
39
|
+
if (!row.disabled) return row.key;
|
|
40
|
+
}
|
|
41
|
+
return null;
|
|
42
|
+
case "parent": {
|
|
43
|
+
let parentKey = current?.parentKey;
|
|
44
|
+
for (let index = fromIndex - 1; index >= 0 && parentKey != null; index--) {
|
|
45
|
+
const row = rows[index];
|
|
46
|
+
if (row.key !== parentKey) continue;
|
|
47
|
+
if (!row.disabled) return row.key;
|
|
48
|
+
parentKey = row.parentKey;
|
|
49
|
+
}
|
|
50
|
+
return unchanged;
|
|
51
|
+
}
|
|
52
|
+
case "firstChild":
|
|
53
|
+
if (!current) return null;
|
|
54
|
+
for (let index = fromIndex + 1; index < rows.length; index++) {
|
|
55
|
+
const row = rows[index];
|
|
56
|
+
if (row.depth <= current.depth) break;
|
|
57
|
+
if (row.parentKey === current.key && !row.disabled) return row.key;
|
|
58
|
+
}
|
|
59
|
+
return unchanged;
|
|
60
|
+
case "typeahead": {
|
|
61
|
+
const text = movement.text.toLowerCase();
|
|
62
|
+
if (text.length === 0) return unchanged;
|
|
63
|
+
const end = loop ? rows.length + fromIndex + 1 : rows.length;
|
|
64
|
+
for (let index = fromIndex + 1; index < end; index++) {
|
|
65
|
+
const row = rows[index % rows.length];
|
|
66
|
+
if (!row.disabled && row.textValue.toLowerCase().startsWith(text)) return row.key;
|
|
67
|
+
}
|
|
68
|
+
return unchanged;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
export { move };
|
|
73
|
+
|
|
74
|
+
//# sourceMappingURL=move.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"move.js","names":[],"sources":["../../src/collections/move.ts"],"sourcesContent":["import type { Key, Move, MoveOptions, TreeRow } from \"./types.js\";\n\n/** Move by enabled rows without iterating count times, even for huge counts. */\nfunction step<T>(\n rows: readonly TreeRow<T>[],\n fromIndex: number,\n count: number,\n direction: 1 | -1,\n loop: boolean,\n): Key | null {\n if (!Number.isSafeInteger(count) || count < 0) {\n throw new RangeError(\"Collection move count/size must be a non-negative safe integer.\");\n }\n\n const keys: Key[] = [];\n let before = 0;\n let current = -1;\n for (let index = 0; index < rows.length; index++) {\n const row = rows[index]!;\n if (row.disabled) continue;\n if (index < fromIndex) before++;\n if (index === fromIndex) current = keys.length;\n keys.push(row.key);\n }\n if (keys.length === 0) return null;\n if (count === 0) return current < 0 ? null : keys[current]!;\n\n let start = current;\n if (current < 0) {\n start =\n fromIndex < 0 ? (direction === 1 ? -1 : keys.length) : direction === 1 ? before - 1 : before;\n }\n // Reduce before addition so even MAX_SAFE_INTEGER stays arithmetically exact.\n const distance = loop ? count % keys.length : Math.min(count, keys.length);\n const target = start + direction * distance;\n const bounded = loop\n ? ((target % keys.length) + keys.length) % keys.length\n : Math.max(0, Math.min(keys.length - 1, target));\n return keys[bounded]!;\n}\n\n/**\n * Return a key; never mutate rows or state. No target leaves the current enabled\n * key in place (or null). Counts and pages count enabled rows. Empty rows return null.\n */\nexport function move<T>(\n rows: readonly TreeRow<T>[],\n from: Key | null,\n movement: Move,\n { loop = false }: MoveOptions = {},\n): Key | null {\n const fromIndex = from === null ? -1 : rows.findIndex((row) => row.key === from);\n const current = rows[fromIndex];\n const unchanged = current && !current.disabled ? current.key : null;\n\n switch (movement.type) {\n case \"next\":\n case \"prev\":\n return step(rows, fromIndex, movement.count ?? 1, movement.type === \"next\" ? 1 : -1, loop);\n case \"page\":\n return step(rows, fromIndex, movement.size, movement.direction, loop);\n case \"first\":\n return rows.find((row) => !row.disabled)?.key ?? null;\n case \"last\":\n for (let index = rows.length - 1; index >= 0; index--) {\n const row = rows[index]!;\n if (!row.disabled) return row.key;\n }\n return null;\n case \"parent\": {\n let parentKey = current?.parentKey;\n for (let index = fromIndex - 1; index >= 0 && parentKey != null; index--) {\n const row = rows[index]!;\n if (row.key !== parentKey) continue;\n if (!row.disabled) return row.key;\n parentKey = row.parentKey;\n }\n return unchanged;\n }\n case \"firstChild\":\n if (!current) return null;\n for (let index = fromIndex + 1; index < rows.length; index++) {\n const row = rows[index]!;\n if (row.depth <= current.depth) break;\n if (row.parentKey === current.key && !row.disabled) return row.key;\n }\n return unchanged;\n case \"typeahead\": {\n const text = movement.text.toLowerCase();\n if (text.length === 0) return unchanged;\n const end = loop ? rows.length + fromIndex + 1 : rows.length;\n for (let index = fromIndex + 1; index < end; index++) {\n const row = rows[index % rows.length]!;\n if (!row.disabled && row.textValue.toLowerCase().startsWith(text)) return row.key;\n }\n return unchanged;\n }\n }\n}\n"],"mappings":";;AAGA,SAAS,KACP,MACA,WACA,OACA,WACA,MACY;CACZ,IAAI,CAAC,OAAO,cAAc,KAAK,KAAK,QAAQ,GAC1C,MAAM,IAAI,WAAW,iEAAiE;CAGxF,MAAM,OAAc,CAAC;CACrB,IAAI,SAAS;CACb,IAAI,UAAU;CACd,KAAK,IAAI,QAAQ,GAAG,QAAQ,KAAK,QAAQ,SAAS;EAChD,MAAM,MAAM,KAAK;EACjB,IAAI,IAAI,UAAU;EAClB,IAAI,QAAQ,WAAW;EACvB,IAAI,UAAU,WAAW,UAAU,KAAK;EACxC,KAAK,KAAK,IAAI,GAAG;CACnB;CACA,IAAI,KAAK,WAAW,GAAG,OAAO;CAC9B,IAAI,UAAU,GAAG,OAAO,UAAU,IAAI,OAAO,KAAK;CAElD,IAAI,QAAQ;CACZ,IAAI,UAAU,GACZ,QACE,YAAY,IAAK,cAAc,IAAI,KAAK,KAAK,SAAU,cAAc,IAAI,SAAS,IAAI;CAG1F,MAAM,WAAW,OAAO,QAAQ,KAAK,SAAS,KAAK,IAAI,OAAO,KAAK,MAAM;CACzE,MAAM,SAAS,QAAQ,YAAY;CAInC,OAAO,KAHS,QACV,SAAS,KAAK,SAAU,KAAK,UAAU,KAAK,SAC9C,KAAK,IAAI,GAAG,KAAK,IAAI,KAAK,SAAS,GAAG,MAAM,CAAC;AAEnD;;;;;AAMA,SAAgB,KACd,MACA,MACA,UACA,EAAE,OAAO,UAAuB,CAAC,GACrB;CACZ,MAAM,YAAY,SAAS,OAAO,KAAK,KAAK,WAAW,QAAQ,IAAI,QAAQ,IAAI;CAC/E,MAAM,UAAU,KAAK;CACrB,MAAM,YAAY,WAAW,CAAC,QAAQ,WAAW,QAAQ,MAAM;CAE/D,QAAQ,SAAS,MAAjB;EACE,KAAK;EACL,KAAK,QACH,OAAO,KAAK,MAAM,WAAW,SAAS,SAAS,GAAG,SAAS,SAAS,SAAS,IAAI,IAAI,IAAI;EAC3F,KAAK,QACH,OAAO,KAAK,MAAM,WAAW,SAAS,MAAM,SAAS,WAAW,IAAI;EACtE,KAAK,SACH,OAAO,KAAK,MAAM,QAAQ,CAAC,IAAI,QAAQ,CAAC,EAAE,OAAO;EACnD,KAAK;GACH,KAAK,IAAI,QAAQ,KAAK,SAAS,GAAG,SAAS,GAAG,SAAS;IACrD,MAAM,MAAM,KAAK;IACjB,IAAI,CAAC,IAAI,UAAU,OAAO,IAAI;GAChC;GACA,OAAO;EACT,KAAK,UAAU;GACb,IAAI,YAAY,SAAS;GACzB,KAAK,IAAI,QAAQ,YAAY,GAAG,SAAS,KAAK,aAAa,MAAM,SAAS;IACxE,MAAM,MAAM,KAAK;IACjB,IAAI,IAAI,QAAQ,WAAW;IAC3B,IAAI,CAAC,IAAI,UAAU,OAAO,IAAI;IAC9B,YAAY,IAAI;GAClB;GACA,OAAO;EACT;EACA,KAAK;GACH,IAAI,CAAC,SAAS,OAAO;GACrB,KAAK,IAAI,QAAQ,YAAY,GAAG,QAAQ,KAAK,QAAQ,SAAS;IAC5D,MAAM,MAAM,KAAK;IACjB,IAAI,IAAI,SAAS,QAAQ,OAAO;IAChC,IAAI,IAAI,cAAc,QAAQ,OAAO,CAAC,IAAI,UAAU,OAAO,IAAI;GACjE;GACA,OAAO;EACT,KAAK,aAAa;GAChB,MAAM,OAAO,SAAS,KAAK,YAAY;GACvC,IAAI,KAAK,WAAW,GAAG,OAAO;GAC9B,MAAM,MAAM,OAAO,KAAK,SAAS,YAAY,IAAI,KAAK;GACtD,KAAK,IAAI,QAAQ,YAAY,GAAG,QAAQ,KAAK,SAAS;IACpD,MAAM,MAAM,KAAK,QAAQ,KAAK;IAC9B,IAAI,CAAC,IAAI,YAAY,IAAI,UAAU,YAAY,CAAC,CAAC,WAAW,IAAI,GAAG,OAAO,IAAI;GAChF;GACA,OAAO;EACT;CACF;AACF"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { TreeRow, TreeState } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Reconcile against supplied visible rows in O(prev + next + selected).
|
|
4
|
+
* Keep a live enabled cursor by key. Otherwise prefer the nearest enabled survivor
|
|
5
|
+
* in the old order (following wins ties), then the first enabled new row.
|
|
6
|
+
* Prune invisible selection/anchor; retain expansion for hidden descendants.
|
|
7
|
+
*/
|
|
8
|
+
export declare function reconcile<T>(prev: readonly TreeRow<T>[], next: readonly TreeRow<T>[], state: TreeState): TreeState;
|
|
9
|
+
//# sourceMappingURL=reconcile.d.ts.map
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
// src/collections/reconcile.ts
|
|
2
|
+
/**
|
|
3
|
+
* Reconcile against supplied visible rows in O(prev + next + selected).
|
|
4
|
+
* Keep a live enabled cursor by key. Otherwise prefer the nearest enabled survivor
|
|
5
|
+
* in the old order (following wins ties), then the first enabled new row.
|
|
6
|
+
* Prune invisible selection/anchor; retain expansion for hidden descendants.
|
|
7
|
+
*/
|
|
8
|
+
function reconcile(prev, next, state) {
|
|
9
|
+
const existing = /* @__PURE__ */ new Set();
|
|
10
|
+
const enabled = /* @__PURE__ */ new Set();
|
|
11
|
+
for (const row of next) {
|
|
12
|
+
existing.add(row.key);
|
|
13
|
+
if (!row.disabled) enabled.add(row.key);
|
|
14
|
+
}
|
|
15
|
+
let highlighted = state.highlighted;
|
|
16
|
+
if (highlighted !== null && !enabled.has(highlighted)) {
|
|
17
|
+
const previousIndex = prev.findIndex((row) => row.key === highlighted);
|
|
18
|
+
highlighted = null;
|
|
19
|
+
if (previousIndex >= 0) for (let distance = 1; distance < prev.length; distance++) {
|
|
20
|
+
const following = prev[previousIndex + distance];
|
|
21
|
+
const preceding = prev[previousIndex - distance];
|
|
22
|
+
if (following && enabled.has(following.key)) {
|
|
23
|
+
highlighted = following.key;
|
|
24
|
+
break;
|
|
25
|
+
}
|
|
26
|
+
if (preceding && enabled.has(preceding.key)) {
|
|
27
|
+
highlighted = preceding.key;
|
|
28
|
+
break;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
highlighted ??= next.find((row) => !row.disabled)?.key ?? null;
|
|
32
|
+
}
|
|
33
|
+
const selected = /* @__PURE__ */ new Set();
|
|
34
|
+
for (const key of state.selected) if (existing.has(key)) selected.add(key);
|
|
35
|
+
return {
|
|
36
|
+
highlighted,
|
|
37
|
+
selected,
|
|
38
|
+
anchor: state.anchor !== null && existing.has(state.anchor) ? state.anchor : null,
|
|
39
|
+
expanded: state.expanded
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
export { reconcile };
|
|
43
|
+
|
|
44
|
+
//# sourceMappingURL=reconcile.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reconcile.js","names":[],"sources":["../../src/collections/reconcile.ts"],"sourcesContent":["import type { Key, TreeRow, TreeState } from \"./types.js\";\n\n/**\n * Reconcile against supplied visible rows in O(prev + next + selected).\n * Keep a live enabled cursor by key. Otherwise prefer the nearest enabled survivor\n * in the old order (following wins ties), then the first enabled new row.\n * Prune invisible selection/anchor; retain expansion for hidden descendants.\n */\nexport function reconcile<T>(\n prev: readonly TreeRow<T>[],\n next: readonly TreeRow<T>[],\n state: TreeState,\n): TreeState {\n const existing = new Set<Key>();\n const enabled = new Set<Key>();\n for (const row of next) {\n existing.add(row.key);\n if (!row.disabled) enabled.add(row.key);\n }\n\n let highlighted = state.highlighted;\n if (highlighted !== null && !enabled.has(highlighted)) {\n const previousIndex = prev.findIndex((row) => row.key === highlighted);\n highlighted = null;\n if (previousIndex >= 0) {\n for (let distance = 1; distance < prev.length; distance++) {\n const following = prev[previousIndex + distance];\n const preceding = prev[previousIndex - distance];\n if (following && enabled.has(following.key)) {\n highlighted = following.key;\n break;\n }\n if (preceding && enabled.has(preceding.key)) {\n highlighted = preceding.key;\n break;\n }\n }\n }\n highlighted ??= next.find((row) => !row.disabled)?.key ?? null;\n }\n\n const selected = new Set<Key>();\n for (const key of state.selected) {\n if (existing.has(key)) selected.add(key);\n }\n\n return {\n highlighted,\n selected,\n anchor: state.anchor !== null && existing.has(state.anchor) ? state.anchor : null,\n expanded: state.expanded,\n };\n}\n"],"mappings":";;;;;;;AAQA,SAAgB,UACd,MACA,MACA,OACW;CACX,MAAM,2BAAW,IAAI,IAAS;CAC9B,MAAM,0BAAU,IAAI,IAAS;CAC7B,KAAK,MAAM,OAAO,MAAM;EACtB,SAAS,IAAI,IAAI,GAAG;EACpB,IAAI,CAAC,IAAI,UAAU,QAAQ,IAAI,IAAI,GAAG;CACxC;CAEA,IAAI,cAAc,MAAM;CACxB,IAAI,gBAAgB,QAAQ,CAAC,QAAQ,IAAI,WAAW,GAAG;EACrD,MAAM,gBAAgB,KAAK,WAAW,QAAQ,IAAI,QAAQ,WAAW;EACrE,cAAc;EACd,IAAI,iBAAiB,GACnB,KAAK,IAAI,WAAW,GAAG,WAAW,KAAK,QAAQ,YAAY;GACzD,MAAM,YAAY,KAAK,gBAAgB;GACvC,MAAM,YAAY,KAAK,gBAAgB;GACvC,IAAI,aAAa,QAAQ,IAAI,UAAU,GAAG,GAAG;IAC3C,cAAc,UAAU;IACxB;GACF;GACA,IAAI,aAAa,QAAQ,IAAI,UAAU,GAAG,GAAG;IAC3C,cAAc,UAAU;IACxB;GACF;EACF;EAEF,gBAAgB,KAAK,MAAM,QAAQ,CAAC,IAAI,QAAQ,CAAC,EAAE,OAAO;CAC5D;CAEA,MAAM,2BAAW,IAAI,IAAS;CAC9B,KAAK,MAAM,OAAO,MAAM,UACtB,IAAI,SAAS,IAAI,GAAG,GAAG,SAAS,IAAI,GAAG;CAGzC,OAAO;EACL;EACA;EACA,QAAQ,MAAM,WAAW,QAAQ,SAAS,IAAI,MAAM,MAAM,IAAI,MAAM,SAAS;EAC7E,UAAU,MAAM;CAClB;AACF"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Key, TreeRow } from "./types.js";
|
|
2
|
+
/** Toggle a visible enabled key, preserving the caller's selected set. */
|
|
3
|
+
export declare function toggleSelection<T>(rows: readonly TreeRow<T>[], selected: ReadonlySet<Key>, key: Key): ReadonlySet<Key>;
|
|
4
|
+
/**
|
|
5
|
+
* Replace selection with an inclusive visible range, excluding disabled rows.
|
|
6
|
+
* A missing anchor selects only the target; a missing target yields an empty set.
|
|
7
|
+
*/
|
|
8
|
+
export declare function selectRange<T>(rows: readonly TreeRow<T>[], anchor: Key | null, to: Key): ReadonlySet<Key>;
|
|
9
|
+
/** Select every visible enabled row. */
|
|
10
|
+
export declare function selectAll<T>(rows: readonly TreeRow<T>[]): ReadonlySet<Key>;
|
|
11
|
+
export declare function clearSelection(): ReadonlySet<Key>;
|
|
12
|
+
//# sourceMappingURL=selection.d.ts.map
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
// src/collections/selection.ts
|
|
2
|
+
/** Toggle a visible enabled key, preserving the caller's selected set. */
|
|
3
|
+
function toggleSelection(rows, selected, key) {
|
|
4
|
+
const row = rows.find((candidate) => candidate.key === key);
|
|
5
|
+
if (!row || row.disabled) return selected;
|
|
6
|
+
const next = new Set(selected);
|
|
7
|
+
if (next.has(key)) next.delete(key);
|
|
8
|
+
else next.add(key);
|
|
9
|
+
return next;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Replace selection with an inclusive visible range, excluding disabled rows.
|
|
13
|
+
* A missing anchor selects only the target; a missing target yields an empty set.
|
|
14
|
+
*/
|
|
15
|
+
function selectRange(rows, anchor, to) {
|
|
16
|
+
const targetIndex = rows.findIndex((row) => row.key === to);
|
|
17
|
+
const selected = /* @__PURE__ */ new Set();
|
|
18
|
+
if (targetIndex < 0) return selected;
|
|
19
|
+
const anchorIndex = anchor === null ? -1 : rows.findIndex((row) => row.key === anchor);
|
|
20
|
+
const start = anchorIndex < 0 ? targetIndex : Math.min(anchorIndex, targetIndex);
|
|
21
|
+
const end = Math.max(anchorIndex, targetIndex);
|
|
22
|
+
for (let index = start; index <= end; index++) {
|
|
23
|
+
const row = rows[index];
|
|
24
|
+
if (!row.disabled) selected.add(row.key);
|
|
25
|
+
}
|
|
26
|
+
return selected;
|
|
27
|
+
}
|
|
28
|
+
/** Select every visible enabled row. */
|
|
29
|
+
function selectAll(rows) {
|
|
30
|
+
const selected = /* @__PURE__ */ new Set();
|
|
31
|
+
for (const row of rows) if (!row.disabled) selected.add(row.key);
|
|
32
|
+
return selected;
|
|
33
|
+
}
|
|
34
|
+
function clearSelection() {
|
|
35
|
+
return /* @__PURE__ */ new Set();
|
|
36
|
+
}
|
|
37
|
+
export { clearSelection, selectAll, selectRange, toggleSelection };
|
|
38
|
+
|
|
39
|
+
//# sourceMappingURL=selection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"selection.js","names":[],"sources":["../../src/collections/selection.ts"],"sourcesContent":["import type { Key, TreeRow } from \"./types.js\";\n\n/** Toggle a visible enabled key, preserving the caller's selected set. */\nexport function toggleSelection<T>(\n rows: readonly TreeRow<T>[],\n selected: ReadonlySet<Key>,\n key: Key,\n): ReadonlySet<Key> {\n const row = rows.find((candidate) => candidate.key === key);\n if (!row || row.disabled) return selected;\n const next = new Set(selected);\n if (next.has(key)) next.delete(key);\n else next.add(key);\n return next;\n}\n\n/**\n * Replace selection with an inclusive visible range, excluding disabled rows.\n * A missing anchor selects only the target; a missing target yields an empty set.\n */\nexport function selectRange<T>(\n rows: readonly TreeRow<T>[],\n anchor: Key | null,\n to: Key,\n): ReadonlySet<Key> {\n const targetIndex = rows.findIndex((row) => row.key === to);\n const selected = new Set<Key>();\n if (targetIndex < 0) return selected;\n const anchorIndex = anchor === null ? -1 : rows.findIndex((row) => row.key === anchor);\n const start = anchorIndex < 0 ? targetIndex : Math.min(anchorIndex, targetIndex);\n const end = Math.max(anchorIndex, targetIndex);\n for (let index = start; index <= end; index++) {\n const row = rows[index]!;\n if (!row.disabled) selected.add(row.key);\n }\n return selected;\n}\n\n/** Select every visible enabled row. */\nexport function selectAll<T>(rows: readonly TreeRow<T>[]): ReadonlySet<Key> {\n const selected = new Set<Key>();\n for (const row of rows) {\n if (!row.disabled) selected.add(row.key);\n }\n return selected;\n}\n\nexport function clearSelection(): ReadonlySet<Key> {\n return new Set<Key>();\n}\n"],"mappings":";;AAGA,SAAgB,gBACd,MACA,UACA,KACkB;CAClB,MAAM,MAAM,KAAK,MAAM,cAAc,UAAU,QAAQ,GAAG;CAC1D,IAAI,CAAC,OAAO,IAAI,UAAU,OAAO;CACjC,MAAM,OAAO,IAAI,IAAI,QAAQ;CAC7B,IAAI,KAAK,IAAI,GAAG,GAAG,KAAK,OAAO,GAAG;MAC7B,KAAK,IAAI,GAAG;CACjB,OAAO;AACT;;;;;AAMA,SAAgB,YACd,MACA,QACA,IACkB;CAClB,MAAM,cAAc,KAAK,WAAW,QAAQ,IAAI,QAAQ,EAAE;CAC1D,MAAM,2BAAW,IAAI,IAAS;CAC9B,IAAI,cAAc,GAAG,OAAO;CAC5B,MAAM,cAAc,WAAW,OAAO,KAAK,KAAK,WAAW,QAAQ,IAAI,QAAQ,MAAM;CACrF,MAAM,QAAQ,cAAc,IAAI,cAAc,KAAK,IAAI,aAAa,WAAW;CAC/E,MAAM,MAAM,KAAK,IAAI,aAAa,WAAW;CAC7C,KAAK,IAAI,QAAQ,OAAO,SAAS,KAAK,SAAS;EAC7C,MAAM,MAAM,KAAK;EACjB,IAAI,CAAC,IAAI,UAAU,SAAS,IAAI,IAAI,GAAG;CACzC;CACA,OAAO;AACT;;AAGA,SAAgB,UAAa,MAA+C;CAC1E,MAAM,2BAAW,IAAI,IAAS;CAC9B,KAAK,MAAM,OAAO,MAChB,IAAI,CAAC,IAAI,UAAU,SAAS,IAAI,IAAI,GAAG;CAEzC,OAAO;AACT;AAEA,SAAgB,iBAAmC;CACjD,uBAAO,IAAI,IAAS;AACtB"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
export type Key = string;
|
|
2
|
+
/** Callbacks must be synchronous and stable for the duration of a call. */
|
|
3
|
+
export interface TreeSource<T> {
|
|
4
|
+
roots: readonly T[];
|
|
5
|
+
getKey(item: NoInfer<T>): Key;
|
|
6
|
+
getChildren?(item: NoInfer<T>): readonly NoInfer<T>[] | undefined;
|
|
7
|
+
isDisabled?(item: NoInfer<T>): boolean;
|
|
8
|
+
getTextValue?(item: NoInfer<T>): string;
|
|
9
|
+
}
|
|
10
|
+
export interface TreeRow<T> {
|
|
11
|
+
readonly key: Key;
|
|
12
|
+
readonly item: T;
|
|
13
|
+
readonly index: number;
|
|
14
|
+
readonly depth: number;
|
|
15
|
+
readonly parentKey: Key | null;
|
|
16
|
+
readonly hasChildren: boolean;
|
|
17
|
+
readonly expanded: boolean;
|
|
18
|
+
readonly posInSet: number;
|
|
19
|
+
readonly setSize: number;
|
|
20
|
+
readonly disabled: boolean;
|
|
21
|
+
readonly textValue: string;
|
|
22
|
+
}
|
|
23
|
+
export interface TreeState {
|
|
24
|
+
highlighted: Key | null;
|
|
25
|
+
selected: ReadonlySet<Key>;
|
|
26
|
+
anchor: Key | null;
|
|
27
|
+
expanded: ReadonlySet<Key>;
|
|
28
|
+
}
|
|
29
|
+
export type Move = {
|
|
30
|
+
type: "next" | "prev";
|
|
31
|
+
count?: number;
|
|
32
|
+
} | {
|
|
33
|
+
type: "first" | "last";
|
|
34
|
+
} | {
|
|
35
|
+
type: "parent" | "firstChild";
|
|
36
|
+
} | {
|
|
37
|
+
type: "page";
|
|
38
|
+
direction: 1 | -1;
|
|
39
|
+
size: number;
|
|
40
|
+
} | {
|
|
41
|
+
type: "typeahead";
|
|
42
|
+
text: string;
|
|
43
|
+
};
|
|
44
|
+
export interface MoveOptions {
|
|
45
|
+
/** Wrap next, prev, page and typeahead at the ends. Defaults to false. */
|
|
46
|
+
loop?: boolean;
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { tradingPreset } from "./trading-preset.js";
|
|
2
|
+
import { Ports } from "../kernel.js";
|
|
3
|
+
import { Command, CommandContext, CommandId, CommandScopeOptions, Commands, KeyOverrideId, KeyOverrides, KeymapEntry, KeysOptions, PendingConfirm, Preset, Register, ValidatedKeyOverrides } from "./types.js";
|
|
4
|
+
/** Only port interfaces enter this owner; bare and default kernels share the same layer. */
|
|
5
|
+
export declare function createCommands({ ports: { keyboard, store, reporter }, keys: options }: {
|
|
6
|
+
ports: Pick<Ports, "keyboard" | "store" | "reporter">;
|
|
7
|
+
keys?: KeysOptions;
|
|
8
|
+
}): Commands;
|
|
9
|
+
export { type Command, type CommandContext, type CommandId, type CommandScopeOptions, type Commands, type KeyOverrideId, type KeyOverrides, type KeymapEntry, type KeysOptions, type PendingConfirm, type Preset, type Register, type ValidatedKeyOverrides, tradingPreset };
|
|
10
|
+
//# sourceMappingURL=index.d.ts.map
|