@ixfx/components 0.7.3 → 0.7.5
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/bundle/index.d.ts +1355 -526
- package/bundle/index.d.ts.map +1 -1
- package/bundle/index.js +3277 -384
- package/bundle/index.js.map +1 -1
- package/dist/ac-text.d.ts +1 -1
- package/dist/ac-text.js +1 -1
- package/dist/{ac-token-TCLAZeVg.d.ts → ac-token--_vCHXWw.d.ts} +2 -2
- package/dist/{ac-token-TCLAZeVg.d.ts.map → ac-token--_vCHXWw.d.ts.map} +1 -1
- package/dist/ac-token.d.ts +1 -1
- package/dist/ac-token.js +2 -2
- package/dist/button.d.ts +1 -1
- package/dist/button.d.ts.map +1 -1
- package/dist/colour-picker.d.ts +1 -1
- package/dist/crumbs.d.ts +6 -2
- package/dist/crumbs.d.ts.map +1 -1
- package/dist/crumbs.js +13 -3
- package/dist/crumbs.js.map +1 -1
- package/dist/{data-grid-Db4QpnII.d.ts → data-grid-CtJ35v8L.d.ts} +59 -2
- package/dist/data-grid-CtJ35v8L.d.ts.map +1 -0
- package/dist/data-grid.d.ts +1 -1
- package/dist/data-grid.js +268 -14
- package/dist/data-grid.js.map +1 -1
- package/dist/detail-list-BS5dRDda.d.ts +175 -0
- package/dist/detail-list-BS5dRDda.d.ts.map +1 -0
- package/dist/detail-list.d.ts +3 -0
- package/dist/detail-list.js +1031 -0
- package/dist/detail-list.js.map +1 -0
- package/dist/grid-list-D-GbghSH.d.ts +321 -0
- package/dist/grid-list-D-GbghSH.d.ts.map +1 -0
- package/dist/grid-list.d.ts +3 -0
- package/dist/grid-list.js +994 -0
- package/dist/grid-list.js.map +1 -0
- package/dist/{grouped-item-lister-BWlC9S4e.d.ts → grouped-item-lister-fdZHVxFM.d.ts} +3 -3
- package/dist/{grouped-item-lister-BWlC9S4e.d.ts.map → grouped-item-lister-fdZHVxFM.d.ts.map} +1 -1
- package/dist/grouped-item-lister.d.ts +1 -1
- package/dist/{icon-DR_3rSyZ.d.ts → icon-CDGprSdE.d.ts} +2 -2
- package/dist/icon-CDGprSdE.d.ts.map +1 -0
- package/dist/icons.d.ts +2 -2
- package/dist/incr-search-DpbSJtgj.js +962 -0
- package/dist/incr-search-DpbSJtgj.js.map +1 -0
- package/dist/incr-search.d.ts +2 -2
- package/dist/incr-search.js +2 -3
- package/dist/{index-C59-JEPl.d.ts → index-9AhaHIT2.d.ts} +3 -3
- package/dist/{index-C59-JEPl.d.ts.map → index-9AhaHIT2.d.ts.map} +1 -1
- package/dist/index-CBS4z1v-.d.ts +365 -0
- package/dist/index-CBS4z1v-.d.ts.map +1 -0
- package/dist/{index-DsjpDksO.d.ts → index-CS9yM8L-.d.ts} +2 -2
- package/dist/{index-DsjpDksO.d.ts.map → index-CS9yM8L-.d.ts.map} +1 -1
- package/dist/{index-BUB5SICW.d.ts → index-CoqtMSd9.d.ts} +2 -2
- package/dist/{index-BUB5SICW.d.ts.map → index-CoqtMSd9.d.ts.map} +1 -1
- package/dist/{index-CJ5fshD3.d.ts → index-UvnoZUAo.d.ts} +2 -2
- package/dist/{index-CJ5fshD3.d.ts.map → index-UvnoZUAo.d.ts.map} +1 -1
- package/dist/{index-BOUaDIW-.d.ts → index-tq6f8007.d.ts} +2 -2
- package/dist/{index-BOUaDIW-.d.ts.map → index-tq6f8007.d.ts.map} +1 -1
- package/dist/index.d.ts +188 -243
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +376 -1004
- package/dist/index.js.map +1 -1
- package/dist/interaction-Cr13azbM.js +3 -0
- package/dist/{labelled-input-base-Dp_9KP0G.d.ts → labelled-input-base-DiTme1JO.d.ts} +2 -2
- package/dist/{labelled-input-base-Dp_9KP0G.d.ts.map → labelled-input-base-DiTme1JO.d.ts.map} +1 -1
- package/dist/labelled-radial-input.d.ts +2 -2
- package/dist/labelled-radial-input.d.ts.map +1 -1
- package/dist/labelled-range-input.d.ts +1 -1
- package/dist/labelled-slider-input.d.ts +1 -1
- package/dist/list-item-animation-DuiwgN3l.js +112 -0
- package/dist/list-item-animation-DuiwgN3l.js.map +1 -0
- package/dist/list-selection-controller-DTFI40li.js +264 -0
- package/dist/list-selection-controller-DTFI40li.js.map +1 -0
- package/dist/{list-selection-types-DSuRNWpx.d.ts → list-selection-types-B5ioL-dG.d.ts} +6 -1
- package/dist/list-selection-types-B5ioL-dG.d.ts.map +1 -0
- package/dist/{menu-DMzjkVnK.js → menu-Bg90Qr0B.js} +3 -3
- package/dist/{menu-DMzjkVnK.js.map → menu-Bg90Qr0B.js.map} +1 -1
- package/dist/{menu-item-D2S4i8u1.js → menu-item-Bx-Fs7jq.js} +3 -3
- package/dist/{menu-item-D2S4i8u1.js.map → menu-item-Bx-Fs7jq.js.map} +1 -1
- package/dist/{menu-item-ZmkXNjek.d.ts → menu-item-CZi9vy5O.d.ts} +2 -2
- package/dist/{menu-item-ZmkXNjek.d.ts.map → menu-item-CZi9vy5O.d.ts.map} +1 -1
- package/dist/menu.d.ts +2 -2
- package/dist/menu.js +2 -2
- package/dist/miller.d.ts +82 -4
- package/dist/miller.d.ts.map +1 -1
- package/dist/miller.js +329 -70
- package/dist/miller.js.map +1 -1
- package/dist/narrowed-text.js +3 -4
- package/dist/narrowed-text.js.map +1 -1
- package/dist/panel.d.ts +1 -1
- package/dist/plots.js +1 -1
- package/dist/select-horiz.js +2 -2
- package/dist/{split-layout-C5SYbDrq.d.ts → split-layout-JK3xWVX2.d.ts} +2 -2
- package/dist/{split-layout-C5SYbDrq.d.ts.map → split-layout-JK3xWVX2.d.ts.map} +1 -1
- package/dist/split-layout.d.ts +1 -1
- package/dist/{tab-list-DbMIL520.d.ts → tab-list-CGyPt07Z.d.ts} +2 -2
- package/dist/{tab-list-DbMIL520.d.ts.map → tab-list-CGyPt07Z.d.ts.map} +1 -1
- package/dist/tabs.d.ts +1 -1
- package/dist/{tickled-controller-Ds1DMyG7.d.ts → tickled-controller-Bn3YdQsM.d.ts} +12 -1
- package/dist/{tickled-controller-Ds1DMyG7.d.ts.map → tickled-controller-Bn3YdQsM.d.ts.map} +1 -1
- package/dist/{tickled-controller-h9GmJ_bU.js → tickled-controller-C66DgJHl.js} +16 -1
- package/dist/tickled-controller-C66DgJHl.js.map +1 -0
- package/dist/{titlebar-B23MrIbI.d.ts → titlebar-Bj5pfdw_.d.ts} +2 -2
- package/dist/{titlebar-B23MrIbI.d.ts.map → titlebar-Bj5pfdw_.d.ts.map} +1 -1
- package/dist/titlebar.d.ts +1 -1
- package/dist/{tree-Ch4W8qXQ.js → tree-DAii2A1g.js} +190 -29
- package/dist/tree-DAii2A1g.js.map +1 -0
- package/dist/{tree-component-BvV4muxx.d.ts → tree-component-F6qZ0Gdv.d.ts} +9 -1
- package/dist/{tree-component-BvV4muxx.d.ts.map → tree-component-F6qZ0Gdv.d.ts.map} +1 -1
- package/dist/tree.d.ts +28 -4
- package/dist/tree.d.ts.map +1 -1
- package/dist/tree.js +1 -1
- package/dist/vertical-list-DwtCPy1b.d.ts +143 -0
- package/dist/vertical-list-DwtCPy1b.d.ts.map +1 -0
- package/dist/vertical-list.d.ts +3 -121
- package/dist/vertical-list.js +642 -1
- package/dist/vertical-list.js.map +1 -0
- package/dist/{xy-axis-DWizs0bt.js → xy-axis-VrX8dmvS.js} +2 -2
- package/dist/{xy-axis-DWizs0bt.js.map → xy-axis-VrX8dmvS.js.map} +1 -1
- package/docs-user/README.md +1 -0
- package/docs-user/data-grid.md +70 -2
- package/docs-user/detail-list.md +39 -1
- package/docs-user/grid-list.md +298 -0
- package/docs-user/incr-search.md +12 -2
- package/docs-user/index.json +7 -2
- package/docs-user/llms.txt +1 -0
- package/docs-user/tree.md +35 -1
- package/docs-user/vertical-list.md +58 -2
- package/llms.txt +1 -0
- package/package.json +17 -2
- package/dist/data-grid-Db4QpnII.d.ts.map +0 -1
- package/dist/element-search-Y8SRfPGM.js +0 -185
- package/dist/element-search-Y8SRfPGM.js.map +0 -1
- package/dist/icon-DR_3rSyZ.d.ts.map +0 -1
- package/dist/incr-search-vCzuao-2.js +0 -137
- package/dist/incr-search-vCzuao-2.js.map +0 -1
- package/dist/index-Cu5i8zZY.d.ts +0 -160
- package/dist/index-Cu5i8zZY.d.ts.map +0 -1
- package/dist/interaction-D5XdKzbR.js +0 -2
- package/dist/list-selection-types-DSuRNWpx.d.ts.map +0 -1
- package/dist/tickled-controller-h9GmJ_bU.js.map +0 -1
- package/dist/tree-Ch4W8qXQ.js.map +0 -1
- package/dist/vertical-list-B4w_ksJk.js +0 -814
- package/dist/vertical-list-B4w_ksJk.js.map +0 -1
- package/dist/vertical-list.d.ts.map +0 -1
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ixfx/components",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.7.
|
|
4
|
+
"version": "0.7.5",
|
|
5
5
|
"packageManager": "pnpm@10.0.0",
|
|
6
6
|
"description": "Web components for ixfx — Lit-based UI toolkit",
|
|
7
7
|
"author": "Clint Heyer",
|
|
@@ -20,6 +20,18 @@
|
|
|
20
20
|
"types": "./dist/incr-search.d.ts",
|
|
21
21
|
"import": "./dist/incr-search.js"
|
|
22
22
|
},
|
|
23
|
+
"./grid-list": {
|
|
24
|
+
"types": "./dist/grid-list.d.ts",
|
|
25
|
+
"import": "./dist/grid-list.js"
|
|
26
|
+
},
|
|
27
|
+
"./detail-list": {
|
|
28
|
+
"types": "./dist/detail-list.d.ts",
|
|
29
|
+
"import": "./dist/detail-list.js"
|
|
30
|
+
},
|
|
31
|
+
"./vertical-list": {
|
|
32
|
+
"types": "./dist/vertical-list.d.ts",
|
|
33
|
+
"import": "./dist/vertical-list.js"
|
|
34
|
+
},
|
|
23
35
|
"./*.js": {
|
|
24
36
|
"types": "./dist/*.d.ts",
|
|
25
37
|
"import": "./dist/*.js"
|
|
@@ -35,6 +47,7 @@
|
|
|
35
47
|
"engines": { "node": ">=20" },
|
|
36
48
|
"scripts": {
|
|
37
49
|
"typecheck": "tsc --noEmit",
|
|
50
|
+
"test": "vitest run",
|
|
38
51
|
"start": "vite serve",
|
|
39
52
|
"dev": "vite serve",
|
|
40
53
|
"lint": "eslint",
|
|
@@ -76,11 +89,13 @@
|
|
|
76
89
|
"eslint": "10.8.1",
|
|
77
90
|
"eslint-plugin-format": "2.0.1",
|
|
78
91
|
"globals": "17.9.0",
|
|
92
|
+
"happy-dom": "^20.14.0",
|
|
79
93
|
"knip": "6.32.0",
|
|
80
94
|
"lit": "3.3.3",
|
|
81
95
|
"tsdown": "0.22.14",
|
|
82
96
|
"typescript": "npm:@typescript/typescript6@6.0.2",
|
|
83
97
|
"typescript-eslint": "8.66.0",
|
|
84
|
-
"vite": "8.2.1"
|
|
98
|
+
"vite": "8.2.1",
|
|
99
|
+
"vitest": "^5.0.0"
|
|
85
100
|
}
|
|
86
101
|
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"data-grid-Db4QpnII.d.ts","names":[],"sources":["../src/data-grid/types.ts","../src/data-grid/data-grid.ts"],"mappings":";;;KAAY;KACA;KACA;KACA;WAA+B;WAAsB,WAAW;;KAChE;KAEA,sBAAsB;WACvB,KAAK;WACL,QAAQ,eAAe;WACvB;WACA;WACA;EACT,SAAS;EACT;;KAEU,sBAAsB,gBAAgB,KAAK,sBAAsB;KAEjE,eAAe;EACzB;EACA;EACA;EACA;EACA;EACA;EACA;EACA,UAAU,GAAG,GAAG,GAAG;EACnB;EACA;EACA;EACA,YAAY,KAAK,GAAG,KAAK,eAAe,IAAI;EAC5C;EACA;EACA;EACA,SAAS,qBAAqB,sBAAsB;EACpD,gBAAgB;IAAyB;IAAe;;EACxD,aAAa,gBAAgB,KAAK,GAAG,KAAK,eAAe;;KAG/C,mBAAmB,gBAAgB,oBAAoB;KAEvD;KAEA;KACA;EAA4B;;KAE5B,kBAAkB,MAAM,KAAK,GAAG;KAChC,gBAAgB,gBAAgB,KAAK;KACrC,sBAAsB,kBAAkB;;;KClCxC;WAAgC,MAAM;WAA4B,UAAU;;KAC5E,oBAAoB,YAAY;KAChC;WAAkC,cAAc;WAA8B,UAAU;;KACxF,sBAAsB,YAAY;KAClC;WAAyC;WAAuB;WAAqB,kBAAkB;;KACvG,6BAA6B,YAAY;KACzC;WAAwC;WAAsB;;KAC9D,4BAA4B,YAAY;KACxC;WAA4C;WAAsB;;KAClE,gCAAgC,YAAY;KAC5C;WAAqC;WAAyB;WAAyB;WAA2B;;KAClH,yBAAyB,YAAY;KACrC;WAAoC;WAAyB;WAAyB;WAA4B;;KAClH,wBAAwB,YAAY;KAEpC;WAAuC,SAAS;;KAChD,2BAA2B,YAAY;UAClC;EACf,iBAAiB;EACjB,mBAAmB;EACnB,2BAA2B;EAC3B,0BAA0B;EAC1B,8BAA8B;EAC9B,uBAAuB;EACvB,sBAAsB;EACtB,yBAAyB;;cAId,wBAAwB;SACnB,sBAAM;EAoFK,SAAS;EACT;EAC8B,eAAe;EACb,iBAAiB;EAC5C,WAAW;EACU;EACrB,WAAW;EACX,oBAAoB;EACpB,sBAAsB,cAAc,KAAK;EAC9B,aAAa;EAExB,SAAS;EACiB;EAC1B,YAAY;;EAEZ;EACgD;EAChD,kBAAkB;UAC1C;UAES;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UAEW;UACK;UAEzB;UAKA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;EAEC;EAQA;UAOD;YAgBW;YAaA,QAAQ,SAAS;YAmBjB,WAAW,SAAS;UAmB/B;UAQA;UAiCA;UAOA;UAoBA;UAYA;UAcA;UA0BA;UAKA;UAMA;UAsFA;UAYA;UAEA;UAcA;UAKA;UAiBA;UAsBA;UAmCA;UAsKA;UAUA;UAKA;UAQA;;EAeR,UAAU,gBAAgB;;EAK1B,aAAa;EAWb;EAIA,mBAAmB,mBAAmB,aAAa,8BAA8B,6BAA6B,UAAU;UAkBhH;UAWA;UAYA;UAyBA;UACA;UA2BA;UAYA;UAkCA;EAoBR;IAAqB;IAAkB;IAAgB;IAAkB;;UASjE;UAaA;YAQW,wBAAM;;QAsMnB;YACI;IAAwB,kBAAkB;;;UAErC;EACf,oBAAoB,gBAAgB,yBAAyB,MAAM,GAAG,WAAW,MAAM,iBAAiB,OAAO,wBAAwB,aAAa,oBAAoB,sCAAsC,cAAc,UAAU,oCAAoC,oBAAoB;EAC9R,uBAAuB,gBAAgB,yBAAyB,MAAM,GAAG,WAAW,MAAM,iBAAiB,OAAO,wBAAwB,aAAa,oBAAoB,mCAAmC,cAAc,UAAU,oCAAoC,oBAAoB"}
|
|
@@ -1,185 +0,0 @@
|
|
|
1
|
-
import { n as buildHighlightTargets, r as clearHighlights, t as applyHighlights } from "./highlight-B-eQrhhb.js";
|
|
2
|
-
import { Fzf } from "fzf";
|
|
3
|
-
//#region src/incr-search/fuzzy.ts
|
|
4
|
-
function defaultSelector(item) {
|
|
5
|
-
if (typeof item === `string`) return item;
|
|
6
|
-
const r = item;
|
|
7
|
-
if (typeof r.label === `string`) return r.label;
|
|
8
|
-
if (typeof r.key === `string`) return r.key;
|
|
9
|
-
if (typeof r.value === `string`) return r.value;
|
|
10
|
-
return String(item);
|
|
11
|
-
}
|
|
12
|
-
function createFuzzySearch(items, options = {}) {
|
|
13
|
-
const selector = options.selector ?? defaultSelector;
|
|
14
|
-
const fzf = new Fzf(items, {
|
|
15
|
-
selector,
|
|
16
|
-
...options.fzf ?? {}
|
|
17
|
-
});
|
|
18
|
-
const find = (query) => {
|
|
19
|
-
if (!query.trim()) return items.map((item) => ({
|
|
20
|
-
item,
|
|
21
|
-
positions: /* @__PURE__ */ new Set(),
|
|
22
|
-
score: 0
|
|
23
|
-
}));
|
|
24
|
-
return fzf.find(query).map((r) => ({
|
|
25
|
-
item: r.item,
|
|
26
|
-
positions: r.positions,
|
|
27
|
-
score: r.score
|
|
28
|
-
}));
|
|
29
|
-
};
|
|
30
|
-
return {
|
|
31
|
-
find,
|
|
32
|
-
items
|
|
33
|
-
};
|
|
34
|
-
}
|
|
35
|
-
//#endregion
|
|
36
|
-
//#region src/incr-search/incr-search.ts
|
|
37
|
-
function buildState(results, query) {
|
|
38
|
-
const positionsByItem = /* @__PURE__ */ new Map();
|
|
39
|
-
for (const r of results) positionsByItem.set(r.item, r.positions);
|
|
40
|
-
return Object.freeze({
|
|
41
|
-
query,
|
|
42
|
-
results: Object.freeze([...results]),
|
|
43
|
-
positionsByItem
|
|
44
|
-
});
|
|
45
|
-
}
|
|
46
|
-
function createIncrSearch(options = {}) {
|
|
47
|
-
let items = options.items ?? [];
|
|
48
|
-
let query = ``;
|
|
49
|
-
let fuzzy = createFuzzySearch(items, {
|
|
50
|
-
selector: options.selector,
|
|
51
|
-
fzf: options.fzf
|
|
52
|
-
});
|
|
53
|
-
let state = buildState(fuzzy.find(query), query);
|
|
54
|
-
let disposed = false;
|
|
55
|
-
const observers = /* @__PURE__ */ new Set();
|
|
56
|
-
if (options.onChange) observers.add(options.onChange);
|
|
57
|
-
const notify = (s) => {
|
|
58
|
-
for (const cb of observers) cb(s);
|
|
59
|
-
};
|
|
60
|
-
const run = async (q, signal) => {
|
|
61
|
-
await Promise.resolve();
|
|
62
|
-
if (signal?.aborted || disposed) return state;
|
|
63
|
-
const results = fuzzy.find(q);
|
|
64
|
-
if (signal?.aborted || disposed) return state;
|
|
65
|
-
state = buildState(results, q);
|
|
66
|
-
notify(state);
|
|
67
|
-
return state;
|
|
68
|
-
};
|
|
69
|
-
return {
|
|
70
|
-
get state() {
|
|
71
|
-
return state;
|
|
72
|
-
},
|
|
73
|
-
async setItems(newItems, signal) {
|
|
74
|
-
items = newItems;
|
|
75
|
-
fuzzy = createFuzzySearch(items, {
|
|
76
|
-
selector: options.selector,
|
|
77
|
-
fzf: options.fzf
|
|
78
|
-
});
|
|
79
|
-
await run(query, signal);
|
|
80
|
-
},
|
|
81
|
-
async setQuery(q, signal) {
|
|
82
|
-
query = q;
|
|
83
|
-
return run(q, signal);
|
|
84
|
-
},
|
|
85
|
-
async clearQuery() {
|
|
86
|
-
query = ``;
|
|
87
|
-
await run(``, void 0);
|
|
88
|
-
},
|
|
89
|
-
onChange(cb) {
|
|
90
|
-
observers.add(cb);
|
|
91
|
-
cb(state);
|
|
92
|
-
return () => {
|
|
93
|
-
observers.delete(cb);
|
|
94
|
-
};
|
|
95
|
-
},
|
|
96
|
-
dispose() {
|
|
97
|
-
disposed = true;
|
|
98
|
-
observers.clear();
|
|
99
|
-
items = [];
|
|
100
|
-
}
|
|
101
|
-
};
|
|
102
|
-
}
|
|
103
|
-
//#endregion
|
|
104
|
-
//#region src/incr-search/element-search.ts
|
|
105
|
-
const defaultGetLabel = (el) => el.textContent?.trim() ?? ``;
|
|
106
|
-
function defaultGetKey(el) {
|
|
107
|
-
return el.getAttribute(`data-key`) ?? el.getAttribute(`data-value`) ?? el.textContent?.trim() ?? ``;
|
|
108
|
-
}
|
|
109
|
-
function createElementIncrSearch(opts) {
|
|
110
|
-
const { container, itemSelector, getLabel = defaultGetLabel, getKey = defaultGetKey, labelSelector, highlightKey } = opts;
|
|
111
|
-
let elementByKey = /* @__PURE__ */ new Map();
|
|
112
|
-
const search = createIncrSearch({
|
|
113
|
-
selector: (item) => item.label,
|
|
114
|
-
fzf: opts.fzf
|
|
115
|
-
});
|
|
116
|
-
const updateVisibility = (state) => {
|
|
117
|
-
const matchedKeys = new Set(state.results.map((r) => r.item.key));
|
|
118
|
-
const hasQuery = state.query.trim().length > 0;
|
|
119
|
-
for (const [key, el] of elementByKey) el.hidden = hasQuery ? !matchedKeys.has(key) : false;
|
|
120
|
-
};
|
|
121
|
-
const updateHighlights = (state) => {
|
|
122
|
-
if (!state.query.trim()) {
|
|
123
|
-
clearHighlights({ key: highlightKey });
|
|
124
|
-
return;
|
|
125
|
-
}
|
|
126
|
-
const targets = buildHighlightTargets(container, labelSelector ?? itemSelector, state.positionsByItem, (el) => {
|
|
127
|
-
const key = getKey(el);
|
|
128
|
-
return state.results.find((r) => r.item.key === key)?.item;
|
|
129
|
-
}, (el) => getLabel(el));
|
|
130
|
-
applyHighlights(targets, { key: highlightKey });
|
|
131
|
-
};
|
|
132
|
-
const unsubscribeState = search.onChange((state) => {
|
|
133
|
-
updateVisibility(state);
|
|
134
|
-
updateHighlights(state);
|
|
135
|
-
opts.onChange?.(state);
|
|
136
|
-
});
|
|
137
|
-
let refreshPending = false;
|
|
138
|
-
const refresh = () => {
|
|
139
|
-
if (refreshPending) return;
|
|
140
|
-
refreshPending = true;
|
|
141
|
-
Promise.resolve().then(() => {
|
|
142
|
-
refreshPending = false;
|
|
143
|
-
elementByKey = /* @__PURE__ */ new Map();
|
|
144
|
-
const els = container.querySelectorAll(itemSelector);
|
|
145
|
-
const items = [];
|
|
146
|
-
for (const el of els) {
|
|
147
|
-
const key = getKey(el);
|
|
148
|
-
elementByKey.set(key, el);
|
|
149
|
-
items.push({
|
|
150
|
-
key,
|
|
151
|
-
label: getLabel(el)
|
|
152
|
-
});
|
|
153
|
-
}
|
|
154
|
-
search.setItems(items);
|
|
155
|
-
});
|
|
156
|
-
};
|
|
157
|
-
const observer = new MutationObserver(() => refresh());
|
|
158
|
-
observer.observe(container, {
|
|
159
|
-
childList: true,
|
|
160
|
-
subtree: false
|
|
161
|
-
});
|
|
162
|
-
refresh();
|
|
163
|
-
return {
|
|
164
|
-
async setQuery(query, signal) {
|
|
165
|
-
await search.setQuery(query, signal);
|
|
166
|
-
},
|
|
167
|
-
async clearQuery() {
|
|
168
|
-
await search.clearQuery();
|
|
169
|
-
},
|
|
170
|
-
refresh,
|
|
171
|
-
onChange(cb) {
|
|
172
|
-
return search.onChange(cb);
|
|
173
|
-
},
|
|
174
|
-
dispose() {
|
|
175
|
-
observer.disconnect();
|
|
176
|
-
unsubscribeState();
|
|
177
|
-
search.dispose();
|
|
178
|
-
clearHighlights({ key: highlightKey });
|
|
179
|
-
}
|
|
180
|
-
};
|
|
181
|
-
}
|
|
182
|
-
//#endregion
|
|
183
|
-
export { createIncrSearch as n, createFuzzySearch as r, createElementIncrSearch as t };
|
|
184
|
-
|
|
185
|
-
//# sourceMappingURL=element-search-Y8SRfPGM.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"element-search-Y8SRfPGM.js","names":["FzfAny"],"sources":["../src/incr-search/fuzzy.ts","../src/incr-search/incr-search.ts","../src/incr-search/element-search.ts"],"sourcesContent":["import type { FuzzySearch, FuzzySearchOptions, IncrSearchResult } from './types.js';\nimport { Fzf } from 'fzf';\n\nfunction defaultSelector<T>(item: T): string {\n if (typeof item === `string`)\n return item;\n const r = item as Record<string, unknown>;\n if (typeof r.label === `string`)\n return r.label;\n if (typeof r.key === `string`)\n return r.key;\n if (typeof r.value === `string`)\n return r.value;\n return String(item);\n}\n\nexport function createFuzzySearch<T>(\n items: readonly T[],\n options: FuzzySearchOptions<T> = {},\n): FuzzySearch<T> {\n const selector = options.selector ?? defaultSelector<T>;\n // fzf uses a conditional SyncOptionsTuple<T> rest-parameter overload that TypeScript\n // cannot narrow through a spread when T is generic.\n const FzfAny = Fzf as new (list: readonly T[], opts: any) => { find: (q: string) => Array<{ item: T; positions: ReadonlySet<number>; score: number }> };\n const fzf = new FzfAny(items as readonly T[], { selector, ...(options.fzf ?? {}) });\n\n const find = (query: string): ReadonlyArray<IncrSearchResult<T>> => {\n if (!query.trim()) {\n return items.map(item => ({\n item,\n positions: new Set<number>(),\n score: 0,\n }));\n }\n return fzf.find(query).map(r => ({\n item: r.item,\n positions: r.positions,\n score: r.score,\n }));\n };\n\n return { find, items };\n}\n","import type {\n IncrSearch,\n IncrSearchChangeCallback,\n IncrSearchOptions,\n IncrSearchState,\n} from './types.js';\nimport { createFuzzySearch } from './fuzzy.js';\n\nfunction buildState<T>(results: ReturnType<ReturnType<typeof createFuzzySearch<T>>[`find`]>, query: string): IncrSearchState<T> {\n const positionsByItem = new Map<T, ReadonlySet<number>>();\n for (const r of results) {\n positionsByItem.set(r.item, r.positions);\n }\n return Object.freeze({\n query,\n results: Object.freeze([...results]),\n positionsByItem,\n });\n}\n\nexport function createIncrSearch<T>(options: IncrSearchOptions<T> = {}): IncrSearch<T> {\n let items: readonly T[] = options.items ?? [];\n let query = ``;\n let fuzzy = createFuzzySearch(items, { selector: options.selector, fzf: options.fzf });\n let state: IncrSearchState<T> = buildState(fuzzy.find(query), query);\n let disposed = false;\n\n const observers = new Set<IncrSearchChangeCallback<T>>();\n\n if (options.onChange) {\n observers.add(options.onChange);\n }\n\n const notify = (s: IncrSearchState<T>): void => {\n for (const cb of observers) {\n cb(s);\n }\n };\n\n const run = async (q: string, signal?: AbortSignal): Promise<IncrSearchState<T>> => {\n // Yield to the microtask queue for a consistent async interface\n await Promise.resolve();\n if (signal?.aborted || disposed) {\n return state;\n }\n const results = fuzzy.find(q);\n if (signal?.aborted || disposed) {\n return state;\n }\n state = buildState(results, q);\n notify(state);\n return state;\n };\n\n return {\n get state() {\n return state;\n },\n\n async setItems(newItems: readonly T[], signal?: AbortSignal): Promise<void> {\n items = newItems;\n fuzzy = createFuzzySearch(items, { selector: options.selector, fzf: options.fzf });\n await run(query, signal);\n },\n\n async setQuery(q: string, signal?: AbortSignal): Promise<IncrSearchState<T>> {\n query = q;\n return run(q, signal);\n },\n\n async clearQuery(): Promise<void> {\n query = ``;\n await run(``, undefined);\n },\n\n onChange(cb: IncrSearchChangeCallback<T>): () => void {\n observers.add(cb);\n cb(state);\n return () => {\n observers.delete(cb);\n };\n },\n\n dispose(): void {\n disposed = true;\n observers.clear();\n items = [];\n },\n };\n}\n","import type {\n ElementIncrSearchOptions,\n IncrSearchChangeCallback,\n IncrSearchState,\n} from './types.js';\nimport { applyHighlights, buildHighlightTargets, clearHighlights } from './highlight.js';\nimport { createIncrSearch } from './incr-search.js';\n\ntype ElementItem = { readonly key: string; readonly label: string };\n\nconst defaultGetLabel = (el: Element): string => el.textContent?.trim() ?? ``;\n\nfunction defaultGetKey(el: Element): string {\n return el.getAttribute(`data-key`)\n ?? el.getAttribute(`data-value`)\n ?? el.textContent?.trim()\n ?? ``;\n}\n\nexport type ElementIncrSearch = {\n readonly setQuery: (query: string, signal?: AbortSignal) => Promise<void>;\n readonly clearQuery: () => Promise<void>;\n readonly refresh: () => void;\n readonly onChange: (cb: IncrSearchChangeCallback<ElementItem>) => () => void;\n readonly dispose: () => void;\n};\n\nexport function createElementIncrSearch(opts: ElementIncrSearchOptions): ElementIncrSearch {\n const {\n container,\n itemSelector,\n getLabel = defaultGetLabel,\n getKey = defaultGetKey,\n labelSelector,\n highlightKey,\n } = opts;\n\n // Map from key → element reference for highlight lookup\n let elementByKey = new Map<string, Element>();\n\n const search = createIncrSearch<ElementItem>({\n selector: item => item.label,\n fzf: opts.fzf,\n });\n\n const updateVisibility = (state: IncrSearchState<ElementItem>): void => {\n const matchedKeys = new Set(state.results.map(r => r.item.key));\n const hasQuery = state.query.trim().length > 0;\n\n for (const [key, el] of elementByKey) {\n (el as HTMLElement).hidden = hasQuery ? !matchedKeys.has(key) : false;\n }\n };\n\n const updateHighlights = (state: IncrSearchState<ElementItem>): void => {\n if (!state.query.trim()) {\n clearHighlights({ key: highlightKey });\n return;\n }\n\n const sel = labelSelector ?? itemSelector;\n const targets = buildHighlightTargets(\n container,\n sel,\n state.positionsByItem,\n (el) => {\n const key = getKey(el);\n // Find the ElementItem whose key matches this element's key\n const result = state.results.find(r => r.item.key === key);\n return result?.item;\n },\n el => getLabel(el),\n );\n applyHighlights(targets, { key: highlightKey });\n };\n\n const unsubscribeState = search.onChange((state) => {\n updateVisibility(state);\n updateHighlights(state);\n opts.onChange?.(state);\n });\n\n let refreshPending = false;\n\n const refresh = (): void => {\n if (refreshPending)\n return;\n refreshPending = true;\n void Promise.resolve().then(() => {\n refreshPending = false;\n elementByKey = new Map<string, Element>();\n const els = container.querySelectorAll(itemSelector);\n const items: ElementItem[] = [];\n for (const el of els) {\n const key = getKey(el);\n elementByKey.set(key, el);\n items.push({ key, label: getLabel(el) });\n }\n void search.setItems(items);\n });\n };\n\n const observer = new MutationObserver(() => refresh());\n observer.observe(container, { childList: true, subtree: false });\n\n refresh();\n\n return {\n async setQuery(query, signal) {\n await search.setQuery(query, signal);\n },\n\n async clearQuery() {\n await search.clearQuery();\n },\n\n refresh,\n\n onChange(cb) {\n return search.onChange(cb);\n },\n\n dispose() {\n observer.disconnect();\n unsubscribeState();\n search.dispose();\n clearHighlights({ key: highlightKey });\n },\n };\n}\n"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"icon-DR_3rSyZ.d.ts","names":[],"sources":["../src/icons/icon.ts"],"mappings":";;cAUa,wBAAwB;;EACvB;EACgB;EAChB;EAC0C;EACU;EAevD;EAMA;YAMU,wBAAM,2BAAA;YA4BN,QAAQ,SAAS;SAWpB,sBAAM;;QAiDhB;YACI;IACR,aAAa"}
|
|
@@ -1,137 +0,0 @@
|
|
|
1
|
-
import { n as buildHighlightTargets, r as clearHighlights, t as applyHighlights } from "./highlight-B-eQrhhb.js";
|
|
2
|
-
import { n as createIncrSearch, r as createFuzzySearch } from "./element-search-Y8SRfPGM.js";
|
|
3
|
-
//#region src/incr-search/ac-adapter.ts
|
|
4
|
-
/**
|
|
5
|
-
* Creates an ixfx-ac-text-compatible `completionProvider` function from a
|
|
6
|
-
* static item list. Uses synchronous fuzzy search wrapped in a Promise so it
|
|
7
|
-
* fits the async provider signature.
|
|
8
|
-
*
|
|
9
|
-
* Each returned item has `positions` populated with matched character indices,
|
|
10
|
-
* which `ixfx-ac-text` uses to render CSS Custom Highlights on the label.
|
|
11
|
-
*
|
|
12
|
-
* Empty query returns all items in original order (no positions).
|
|
13
|
-
* A cancelled signal causes the returned promise to reject with an AbortError.
|
|
14
|
-
*/
|
|
15
|
-
function createAcCompletionProvider(items, options = {}) {
|
|
16
|
-
const selector = options.selector ?? ((item) => item.label);
|
|
17
|
-
const fuzzy = createFuzzySearch(items, { selector });
|
|
18
|
-
return (query, signal) => new Promise((resolve, reject) => {
|
|
19
|
-
if (signal.aborted) {
|
|
20
|
-
reject(new DOMException(`Aborted`, `AbortError`));
|
|
21
|
-
return;
|
|
22
|
-
}
|
|
23
|
-
const results = fuzzy.find(query).map((r) => ({
|
|
24
|
-
...r.item,
|
|
25
|
-
positions: r.positions
|
|
26
|
-
}));
|
|
27
|
-
if (signal.aborted) {
|
|
28
|
-
reject(new DOMException(`Aborted`, `AbortError`));
|
|
29
|
-
return;
|
|
30
|
-
}
|
|
31
|
-
resolve(results);
|
|
32
|
-
});
|
|
33
|
-
}
|
|
34
|
-
//#endregion
|
|
35
|
-
//#region src/incr-search/controller-tree.ts
|
|
36
|
-
const DEFAULT_HIGHLIGHT_KEY = `incr-search-highlight`;
|
|
37
|
-
/**
|
|
38
|
-
* Incremental-search controller for any component implementing `TreeSearchHost`
|
|
39
|
-
* (i.e. `ixfx-tree-list`, `ixfx-miller-list`, `ixfx-crumb-navigation`).
|
|
40
|
-
*
|
|
41
|
-
* Replaces the previous separate `IncrSearchTreeController` / `IncrSearchMillerController`
|
|
42
|
-
* classes — the unified `TreeFilterPredicate` (with depth) means one implementation works
|
|
43
|
-
* for all tree-like components.
|
|
44
|
-
*
|
|
45
|
-
* @example Using with ixfx-tree-list:
|
|
46
|
-
* ```typescript
|
|
47
|
-
* const ctrl = new IncrSearchTreeController(myTreeList, {
|
|
48
|
-
* selector: item => item.node.item.label,
|
|
49
|
-
* });
|
|
50
|
-
* ctrl.connect();
|
|
51
|
-
* ```
|
|
52
|
-
*
|
|
53
|
-
* @example Using with ixfx-miller-list (different label selector):
|
|
54
|
-
* ```typescript
|
|
55
|
-
* const ctrl = new IncrSearchTreeController(myMillerList, {
|
|
56
|
-
* selector: item => item.node.item.label,
|
|
57
|
-
* labelSelector: '.label',
|
|
58
|
-
* });
|
|
59
|
-
* ctrl.connect();
|
|
60
|
-
* ```
|
|
61
|
-
*/
|
|
62
|
-
var IncrSearchTreeController = class {
|
|
63
|
-
#el;
|
|
64
|
-
#opts;
|
|
65
|
-
#search;
|
|
66
|
-
#unsub;
|
|
67
|
-
#labelMap = /* @__PURE__ */ new Map();
|
|
68
|
-
constructor(el, opts) {
|
|
69
|
-
this.#el = el;
|
|
70
|
-
this.#opts = opts;
|
|
71
|
-
this.#search = createIncrSearch({
|
|
72
|
-
selector: opts.selector,
|
|
73
|
-
fzf: opts.fzf
|
|
74
|
-
});
|
|
75
|
-
}
|
|
76
|
-
connect() {
|
|
77
|
-
this.disconnect();
|
|
78
|
-
const items = this.#el.getNodes();
|
|
79
|
-
for (const item of items) this.#labelMap.set(this.#opts.selector(item), item);
|
|
80
|
-
this.#search.setItems(items);
|
|
81
|
-
if (this.#opts.input) {
|
|
82
|
-
this.#opts.input.addEventListener(`input`, this.#onInput);
|
|
83
|
-
this.#opts.input.addEventListener(`keydown`, this.#onKeydown);
|
|
84
|
-
}
|
|
85
|
-
this.#unsub = this.#search.onChange((state) => this.#onStateChange(state));
|
|
86
|
-
}
|
|
87
|
-
disconnect() {
|
|
88
|
-
if (this.#unsub) {
|
|
89
|
-
this.#unsub();
|
|
90
|
-
this.#unsub = void 0;
|
|
91
|
-
}
|
|
92
|
-
if (this.#opts.input) {
|
|
93
|
-
this.#opts.input.removeEventListener(`input`, this.#onInput);
|
|
94
|
-
this.#opts.input.removeEventListener(`keydown`, this.#onKeydown);
|
|
95
|
-
}
|
|
96
|
-
this.#el.filterPredicate = void 0;
|
|
97
|
-
clearHighlights({ key: this.#opts.highlightKey ?? DEFAULT_HIGHLIGHT_KEY });
|
|
98
|
-
this.#labelMap.clear();
|
|
99
|
-
}
|
|
100
|
-
async setQuery(query) {
|
|
101
|
-
await this.#search.setQuery(query);
|
|
102
|
-
}
|
|
103
|
-
async clearQuery() {
|
|
104
|
-
await this.#search.clearQuery();
|
|
105
|
-
}
|
|
106
|
-
#onInput = () => {
|
|
107
|
-
const value = this.#opts.input?.value ?? ``;
|
|
108
|
-
this.setQuery(value);
|
|
109
|
-
};
|
|
110
|
-
#onKeydown = (e) => {
|
|
111
|
-
if (e.key === `Escape` && this.#opts.input) {
|
|
112
|
-
this.#opts.input.value = ``;
|
|
113
|
-
this.clearQuery();
|
|
114
|
-
}
|
|
115
|
-
};
|
|
116
|
-
#onStateChange(state) {
|
|
117
|
-
const matched = new Set(state.results.map((r) => r.item.node.item.key));
|
|
118
|
-
const hasQuery = state.query.trim().length > 0;
|
|
119
|
-
this.#el.filterPredicate = hasQuery && matched.size > 0 ? (node, _depth) => matched.has(node.item.key) : void 0;
|
|
120
|
-
const key = this.#opts.highlightKey ?? DEFAULT_HIGHLIGHT_KEY;
|
|
121
|
-
if (!this.#el.shadowRoot) return;
|
|
122
|
-
if (!state.query.trim()) {
|
|
123
|
-
clearHighlights({ key });
|
|
124
|
-
return;
|
|
125
|
-
}
|
|
126
|
-
const labelSelector = this.#opts.labelSelector ?? `.tree-label`;
|
|
127
|
-
const targets = buildHighlightTargets(this.#el.shadowRoot, labelSelector, state.positionsByItem, (labelEl) => {
|
|
128
|
-
const text = labelEl.textContent ?? ``;
|
|
129
|
-
return this.#labelMap.get(text);
|
|
130
|
-
}, (labelEl) => labelEl.textContent ?? ``);
|
|
131
|
-
applyHighlights(targets, { key });
|
|
132
|
-
}
|
|
133
|
-
};
|
|
134
|
-
//#endregion
|
|
135
|
-
export { createAcCompletionProvider as n, IncrSearchTreeController as t };
|
|
136
|
-
|
|
137
|
-
//# sourceMappingURL=incr-search-vCzuao-2.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"incr-search-vCzuao-2.js","names":["#el","#opts","#search","#labelMap","#onInput","#onKeydown","#unsub","#onStateChange"],"sources":["../src/incr-search/ac-adapter.ts","../src/incr-search/controller-tree.ts"],"sourcesContent":["import type { FuzzySearchOptions } from './types.js';\nimport { createFuzzySearch } from './fuzzy.js';\n\n/**\n * Creates an ixfx-ac-text-compatible `completionProvider` function from a\n * static item list. Uses synchronous fuzzy search wrapped in a Promise so it\n * fits the async provider signature.\n *\n * Each returned item has `positions` populated with matched character indices,\n * which `ixfx-ac-text` uses to render CSS Custom Highlights on the label.\n *\n * Empty query returns all items in original order (no positions).\n * A cancelled signal causes the returned promise to reject with an AbortError.\n */\nexport function createAcCompletionProvider<T extends { label: string }>(\n items: readonly T[],\n options: Pick<FuzzySearchOptions<T>, `selector`> = {},\n): (query: string, signal: AbortSignal) => Promise<Array<T & { positions: ReadonlySet<number> }>> {\n const selector = options.selector ?? ((item: T) => item.label);\n const fuzzy = createFuzzySearch(items, { selector });\n\n return (\n query: string,\n signal: AbortSignal,\n ): Promise<Array<T & { positions: ReadonlySet<number> }>> =>\n new Promise((resolve, reject) => {\n if (signal.aborted) {\n reject(new DOMException(`Aborted`, `AbortError`));\n return;\n }\n\n const results = fuzzy.find(query).map(r => ({ ...r.item, positions: r.positions }));\n\n if (signal.aborted) {\n reject(new DOMException(`Aborted`, `AbortError`));\n return;\n }\n\n resolve(results);\n });\n}\n","import type { FzfOptions } from 'fzf';\nimport type { TreeSearchHost } from '../common/searchable.js';\nimport type { TreeNode } from '../common/types.js';\nimport type { IncrSearchState } from './types.js';\nimport { applyHighlights, buildHighlightTargets, clearHighlights } from './highlight.js';\nimport { createIncrSearch } from './incr-search.js';\n\nconst DEFAULT_HIGHLIGHT_KEY = `incr-search-highlight`;\n\nexport type IncrSearchTreeOptions = {\n selector: (item: { node: TreeNode; depth: number }) => string;\n /**\n * CSS selector for the label elements inside the shadow root.\n * Defaults to `.tree-label` (suitable for ixfx-tree-list).\n * Use `.label` for ixfx-miller-list.\n */\n labelSelector?: string;\n highlightKey?: string;\n input?: HTMLInputElement;\n fzf?: Partial<FzfOptions<{ node: TreeNode; depth: number }>>;\n};\n\ntype SearchItem = { node: TreeNode; depth: number };\n\n/**\n * Incremental-search controller for any component implementing `TreeSearchHost`\n * (i.e. `ixfx-tree-list`, `ixfx-miller-list`, `ixfx-crumb-navigation`).\n *\n * Replaces the previous separate `IncrSearchTreeController` / `IncrSearchMillerController`\n * classes — the unified `TreeFilterPredicate` (with depth) means one implementation works\n * for all tree-like components.\n *\n * @example Using with ixfx-tree-list:\n * ```typescript\n * const ctrl = new IncrSearchTreeController(myTreeList, {\n * selector: item => item.node.item.label,\n * });\n * ctrl.connect();\n * ```\n *\n * @example Using with ixfx-miller-list (different label selector):\n * ```typescript\n * const ctrl = new IncrSearchTreeController(myMillerList, {\n * selector: item => item.node.item.label,\n * labelSelector: '.label',\n * });\n * ctrl.connect();\n * ```\n */\nexport class IncrSearchTreeController {\n #el: TreeSearchHost;\n #opts: IncrSearchTreeOptions;\n #search: ReturnType<typeof createIncrSearch<SearchItem>>;\n #unsub: (() => void) | undefined;\n #labelMap = new Map<string, SearchItem>();\n\n constructor(el: TreeSearchHost, opts: IncrSearchTreeOptions) {\n this.#el = el;\n this.#opts = opts;\n this.#search = createIncrSearch<SearchItem>({\n selector: opts.selector,\n fzf: opts.fzf,\n });\n }\n\n connect(): void {\n this.disconnect();\n\n const items = this.#el.getNodes();\n for (const item of items) {\n this.#labelMap.set(this.#opts.selector(item), item);\n }\n void this.#search.setItems(items);\n\n if (this.#opts.input) {\n this.#opts.input.addEventListener(`input`, this.#onInput);\n this.#opts.input.addEventListener(`keydown`, this.#onKeydown);\n }\n\n this.#unsub = this.#search.onChange(state => this.#onStateChange(state));\n }\n\n disconnect(): void {\n if (this.#unsub) {\n this.#unsub();\n this.#unsub = undefined;\n }\n if (this.#opts.input) {\n this.#opts.input.removeEventListener(`input`, this.#onInput);\n this.#opts.input.removeEventListener(`keydown`, this.#onKeydown);\n }\n this.#el.filterPredicate = undefined;\n clearHighlights({ key: this.#opts.highlightKey ?? DEFAULT_HIGHLIGHT_KEY });\n this.#labelMap.clear();\n }\n\n async setQuery(query: string): Promise<void> {\n await this.#search.setQuery(query);\n }\n\n async clearQuery(): Promise<void> {\n await this.#search.clearQuery();\n }\n\n #onInput = () => {\n const value = this.#opts.input?.value ?? ``;\n void this.setQuery(value);\n };\n\n #onKeydown = (e: KeyboardEvent) => {\n if (e.key === `Escape` && this.#opts.input) {\n this.#opts.input.value = ``;\n void this.clearQuery();\n }\n };\n\n #onStateChange(state: IncrSearchState<SearchItem>): void {\n const matched = new Set(state.results.map(r => r.item.node.item.key));\n const hasQuery = state.query.trim().length > 0;\n this.#el.filterPredicate = hasQuery && matched.size > 0\n ? (node: TreeNode, _depth: number) => matched.has(node.item.key)\n : undefined;\n\n const key = this.#opts.highlightKey ?? DEFAULT_HIGHLIGHT_KEY;\n if (!this.#el.shadowRoot)\n return;\n\n if (!state.query.trim()) {\n clearHighlights({ key });\n return;\n }\n\n const labelSelector = this.#opts.labelSelector ?? `.tree-label`;\n const targets = buildHighlightTargets(\n this.#el.shadowRoot,\n labelSelector,\n state.positionsByItem,\n (labelEl) => {\n const text = labelEl.textContent ?? ``;\n return this.#labelMap.get(text);\n },\n labelEl => labelEl.textContent ?? ``,\n );\n applyHighlights(targets, { key });\n }\n}\n"],"mappings":"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"}
|
package/dist/index-Cu5i8zZY.d.ts
DELETED
|
@@ -1,160 +0,0 @@
|
|
|
1
|
-
import { o as TreeNode } from "./types-Bc23SI94.js";
|
|
2
|
-
import { d as TreeSearchHost } from "./tree-component-BvV4muxx.js";
|
|
3
|
-
import { FzfOptions } from "fzf";
|
|
4
|
-
//#region src/incr-search/types.d.ts
|
|
5
|
-
type IncrSearchResult<T> = {
|
|
6
|
-
readonly item: T;
|
|
7
|
-
readonly positions: ReadonlySet<number>;
|
|
8
|
-
readonly score: number;
|
|
9
|
-
};
|
|
10
|
-
type IncrSearchState<T> = {
|
|
11
|
-
readonly query: string;
|
|
12
|
-
readonly results: ReadonlyArray<IncrSearchResult<T>>;
|
|
13
|
-
readonly positionsByItem: ReadonlyMap<T, ReadonlySet<number>>;
|
|
14
|
-
};
|
|
15
|
-
type IncrSearchChangeCallback<T> = (state: IncrSearchState<T>) => void;
|
|
16
|
-
type IncrSearchOptions<T> = {
|
|
17
|
-
readonly items?: readonly T[];
|
|
18
|
-
readonly selector?: (item: T) => string;
|
|
19
|
-
readonly fzf?: Partial<FzfOptions<T>>;
|
|
20
|
-
readonly onChange?: IncrSearchChangeCallback<T>;
|
|
21
|
-
};
|
|
22
|
-
type IncrSearch<T> = {
|
|
23
|
-
readonly setItems: (items: readonly T[], signal?: AbortSignal) => Promise<void>;
|
|
24
|
-
readonly setQuery: (query: string, signal?: AbortSignal) => Promise<IncrSearchState<T>>;
|
|
25
|
-
readonly clearQuery: () => Promise<void>;
|
|
26
|
-
readonly state: IncrSearchState<T>;
|
|
27
|
-
readonly onChange: (cb: IncrSearchChangeCallback<T>) => () => void;
|
|
28
|
-
readonly dispose: () => void;
|
|
29
|
-
};
|
|
30
|
-
type FuzzySearchOptions<T> = {
|
|
31
|
-
readonly selector?: (item: T) => string;
|
|
32
|
-
readonly fzf?: Partial<FzfOptions<T>>;
|
|
33
|
-
};
|
|
34
|
-
type FuzzySearch<T> = {
|
|
35
|
-
readonly find: (query: string) => ReadonlyArray<IncrSearchResult<T>>;
|
|
36
|
-
readonly items: readonly T[];
|
|
37
|
-
};
|
|
38
|
-
type HighlightTarget = {
|
|
39
|
-
readonly element: Element;
|
|
40
|
-
readonly text?: string;
|
|
41
|
-
readonly positions: ReadonlySet<number>;
|
|
42
|
-
};
|
|
43
|
-
type HighlightOptions = {
|
|
44
|
-
readonly key?: string;
|
|
45
|
-
};
|
|
46
|
-
type ElementIncrSearchOptions = {
|
|
47
|
-
readonly container: Element;
|
|
48
|
-
readonly itemSelector: string;
|
|
49
|
-
readonly getLabel?: (el: Element) => string;
|
|
50
|
-
readonly getKey?: (el: Element) => string;
|
|
51
|
-
readonly labelSelector?: string;
|
|
52
|
-
readonly highlightKey?: string;
|
|
53
|
-
readonly fzf?: Partial<FzfOptions<{
|
|
54
|
-
key: string;
|
|
55
|
-
label: string;
|
|
56
|
-
}>>;
|
|
57
|
-
readonly onChange?: IncrSearchChangeCallback<{
|
|
58
|
-
key: string;
|
|
59
|
-
label: string;
|
|
60
|
-
}>;
|
|
61
|
-
};
|
|
62
|
-
//#endregion
|
|
63
|
-
//#region src/incr-search/ac-adapter.d.ts
|
|
64
|
-
/**
|
|
65
|
-
* Creates an ixfx-ac-text-compatible `completionProvider` function from a
|
|
66
|
-
* static item list. Uses synchronous fuzzy search wrapped in a Promise so it
|
|
67
|
-
* fits the async provider signature.
|
|
68
|
-
*
|
|
69
|
-
* Each returned item has `positions` populated with matched character indices,
|
|
70
|
-
* which `ixfx-ac-text` uses to render CSS Custom Highlights on the label.
|
|
71
|
-
*
|
|
72
|
-
* Empty query returns all items in original order (no positions).
|
|
73
|
-
* A cancelled signal causes the returned promise to reject with an AbortError.
|
|
74
|
-
*/
|
|
75
|
-
declare function createAcCompletionProvider<T extends {
|
|
76
|
-
label: string;
|
|
77
|
-
}>(items: readonly T[], options?: Pick<FuzzySearchOptions<T>, `selector`>): (query: string, signal: AbortSignal) => Promise<Array<T & {
|
|
78
|
-
positions: ReadonlySet<number>;
|
|
79
|
-
}>>;
|
|
80
|
-
//#endregion
|
|
81
|
-
//#region src/incr-search/controller-tree.d.ts
|
|
82
|
-
type IncrSearchTreeOptions = {
|
|
83
|
-
selector: (item: {
|
|
84
|
-
node: TreeNode;
|
|
85
|
-
depth: number;
|
|
86
|
-
}) => string;
|
|
87
|
-
/**
|
|
88
|
-
* CSS selector for the label elements inside the shadow root.
|
|
89
|
-
* Defaults to `.tree-label` (suitable for ixfx-tree-list).
|
|
90
|
-
* Use `.label` for ixfx-miller-list.
|
|
91
|
-
*/
|
|
92
|
-
labelSelector?: string;
|
|
93
|
-
highlightKey?: string;
|
|
94
|
-
input?: HTMLInputElement;
|
|
95
|
-
fzf?: Partial<FzfOptions<{
|
|
96
|
-
node: TreeNode;
|
|
97
|
-
depth: number;
|
|
98
|
-
}>>;
|
|
99
|
-
};
|
|
100
|
-
/**
|
|
101
|
-
* Incremental-search controller for any component implementing `TreeSearchHost`
|
|
102
|
-
* (i.e. `ixfx-tree-list`, `ixfx-miller-list`, `ixfx-crumb-navigation`).
|
|
103
|
-
*
|
|
104
|
-
* Replaces the previous separate `IncrSearchTreeController` / `IncrSearchMillerController`
|
|
105
|
-
* classes — the unified `TreeFilterPredicate` (with depth) means one implementation works
|
|
106
|
-
* for all tree-like components.
|
|
107
|
-
*
|
|
108
|
-
* @example Using with ixfx-tree-list:
|
|
109
|
-
* ```typescript
|
|
110
|
-
* const ctrl = new IncrSearchTreeController(myTreeList, {
|
|
111
|
-
* selector: item => item.node.item.label,
|
|
112
|
-
* });
|
|
113
|
-
* ctrl.connect();
|
|
114
|
-
* ```
|
|
115
|
-
*
|
|
116
|
-
* @example Using with ixfx-miller-list (different label selector):
|
|
117
|
-
* ```typescript
|
|
118
|
-
* const ctrl = new IncrSearchTreeController(myMillerList, {
|
|
119
|
-
* selector: item => item.node.item.label,
|
|
120
|
-
* labelSelector: '.label',
|
|
121
|
-
* });
|
|
122
|
-
* ctrl.connect();
|
|
123
|
-
* ```
|
|
124
|
-
*/
|
|
125
|
-
declare class IncrSearchTreeController {
|
|
126
|
-
#private;
|
|
127
|
-
constructor(el: TreeSearchHost, opts: IncrSearchTreeOptions);
|
|
128
|
-
connect(): void;
|
|
129
|
-
disconnect(): void;
|
|
130
|
-
setQuery(query: string): Promise<void>;
|
|
131
|
-
clearQuery(): Promise<void>;
|
|
132
|
-
}
|
|
133
|
-
//#endregion
|
|
134
|
-
//#region src/incr-search/element-search.d.ts
|
|
135
|
-
type ElementItem = {
|
|
136
|
-
readonly key: string;
|
|
137
|
-
readonly label: string;
|
|
138
|
-
};
|
|
139
|
-
type ElementIncrSearch = {
|
|
140
|
-
readonly setQuery: (query: string, signal?: AbortSignal) => Promise<void>;
|
|
141
|
-
readonly clearQuery: () => Promise<void>;
|
|
142
|
-
readonly refresh: () => void;
|
|
143
|
-
readonly onChange: (cb: IncrSearchChangeCallback<ElementItem>) => () => void;
|
|
144
|
-
readonly dispose: () => void;
|
|
145
|
-
};
|
|
146
|
-
declare function createElementIncrSearch(opts: ElementIncrSearchOptions): ElementIncrSearch;
|
|
147
|
-
//#endregion
|
|
148
|
-
//#region src/incr-search/fuzzy.d.ts
|
|
149
|
-
declare function createFuzzySearch<T>(items: readonly T[], options?: FuzzySearchOptions<T>): FuzzySearch<T>;
|
|
150
|
-
//#endregion
|
|
151
|
-
//#region src/incr-search/highlight.d.ts
|
|
152
|
-
declare function applyHighlights(targets: readonly HighlightTarget[], options?: HighlightOptions): void;
|
|
153
|
-
declare function clearHighlights(options?: HighlightOptions): void;
|
|
154
|
-
declare function buildHighlightTargets<T>(root: ShadowRoot | Element, itemSelector: string, positionsByItem: ReadonlyMap<T, ReadonlySet<number>>, getItem: (el: Element) => T | undefined, getText: (el: Element) => string): HighlightTarget[];
|
|
155
|
-
//#endregion
|
|
156
|
-
//#region src/incr-search/incr-search.d.ts
|
|
157
|
-
declare function createIncrSearch<T>(options?: IncrSearchOptions<T>): IncrSearch<T>;
|
|
158
|
-
//#endregion
|
|
159
|
-
export { IncrSearchChangeCallback as _, createFuzzySearch as a, IncrSearchState as b, IncrSearchTreeController as c, ElementIncrSearchOptions as d, FuzzySearch as f, IncrSearch as g, HighlightTarget as h, clearHighlights as i, IncrSearchTreeOptions as l, HighlightOptions as m, applyHighlights as n, ElementIncrSearch as o, FuzzySearchOptions as p, buildHighlightTargets as r, createElementIncrSearch as s, createIncrSearch as t, createAcCompletionProvider as u, IncrSearchOptions as v, IncrSearchResult as y };
|
|
160
|
-
//# sourceMappingURL=index-Cu5i8zZY.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index-Cu5i8zZY.d.ts","names":[],"sources":["../src/incr-search/types.ts","../src/incr-search/ac-adapter.ts","../src/incr-search/controller-tree.ts","../src/incr-search/element-search.ts","../src/incr-search/fuzzy.ts","../src/incr-search/highlight.ts","../src/incr-search/incr-search.ts"],"mappings":";;;;KAGY,iBAAiB;WAClB,MAAM;WACN,WAAW;WACX;;KAIC,gBAAgB;WACjB;WACA,SAAS,cAAc,iBAAiB;WAExC,iBAAiB,YAAY,GAAG;;KAG/B,yBAAyB,MAAM,OAAO,gBAAgB;KAEtD,kBAAkB;WACnB,iBAAiB;WACjB,YAAY,MAAM;WAClB,MAAM,QAAQ,WAAW;WACzB,WAAW,yBAAyB;;KAInC,WAAW;WACZ,WAAW,gBAAgB,KAAK,SAAS,gBAAgB;WACzD,WAAW,eAAe,SAAS,gBAAgB,QAAQ,gBAAgB;WAC3E,kBAAkB;WAClB,OAAO,gBAAgB;WACvB,WAAW,IAAI,yBAAyB;WACxC;;KAGC,mBAAmB;WACpB,YAAY,MAAM;WAClB,MAAM,QAAQ,WAAW;;KAGxB,YAAY;WACb,OAAO,kBAAkB,cAAc,iBAAiB;WACxD,gBAAgB;;KAIf;WACD,SAAS;WACT;WACA,WAAW;;KAGV;WACD;;KAGC;WACD,WAAW;WACX;WACA,YAAY,IAAI;WAChB,UAAU,IAAI;WACd;WACA;WACA,MAAM,QAAQ;IAAa;IAAa;;WACxC,WAAW;IAA2B;IAAa;;;;;;;;;;;;;;;;iBCnD9C,2BAA2B;EAAY;GACrD,gBAAgB,KAChB,UAAS,KAAK,mBAAmB,mBAC/B,eAAe,QAAQ,gBAAgB,QAAQ,MAAM;EAAM,WAAW;;;;KCR9D;EACV,WAAW;IAAQ,MAAM;IAAU;;;;;;;EAMnC;EACA;EACA,QAAQ;EACR,MAAM,QAAQ;IAAa,MAAM;IAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;cA8BhC;;EAOC,YAAA,IAAI,gBAAgB,MAAM;EAStC;EAiBA;EAcM,SAAS,gBAAgB;EAIzB,cAAc;;;;KC5FjB;WAAyB;WAAsB;;KAWxC;WACD,WAAW,eAAe,SAAS,gBAAgB;WACnD,kBAAkB;WAClB;WACA,WAAW,IAAI,yBAAyB;WACxC;;iBAGK,wBAAwB,MAAM,2BAA2B;;;iBCXzD,kBAAkB,GAChC,gBAAgB,KAChB,UAAS,mBAAmB,KAC3B,YAAY;;;iBCfC,gBACd,kBAAkB,mBAClB,UAAS;iBA+BK,gBAAgB,UAAS;iBAMzB,sBAAsB,GACpC,MAAM,aAAa,SACnB,sBACA,iBAAiB,YAAY,GAAG,sBAChC,UAAU,IAAI,YAAY,eAC1B,UAAU,IAAI,qBACb;;;iBC7Ba,iBAAiB,GAAG,UAAS,kBAAkB,KAAU,WAAW"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"list-selection-types-DSuRNWpx.d.ts","names":[],"sources":["../src/interaction/list-selection-types.ts"],"mappings":";;;;;;;;;KASY;;;;;;;;;;;;;KAcA;KAEA;WACD,UAAU,YAAY;WACtB,UAAU,YAAY;;KAGrB;WACD,MAAM;;KAGL;WACD,MAAM;;KAGL;WACD,MAAM;;KAGL,kBAAkB,YAAY;KAC9B,kBAAkB,YAAY;KAC9B,oBAAoB,YAAY;KAChC,qBAAqB,YAAY;UAE5B;EACf,eAAe;EACf,eAAe;EACf,iBAAiB;EACjB,mBAAmB"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"tickled-controller-h9GmJ_bU.js","names":[],"sources":["../src/interaction/tickled-controller.ts"],"sourcesContent":["import type { ReactiveController, ReactiveControllerHost } from 'lit';\n\n/**\n * Represents an item that can be tickled (highlighted via hover or keyboard navigation)\n */\nexport type TickledItem<T = unknown> = {\n /**\n * Unique identifier for the item (e.g., index, id, path)\n */\n readonly id: T;\n\n /**\n * Whether the item is currently enabled/interactive\n */\n readonly enabled?: boolean;\n};\n\n/**\n * Input mode determines which mechanism controls the tickled state\n */\nexport type InputMode = `keyboard` | `mouse`;\n\n/**\n * Configuration for TickledController\n */\nexport type TickledControllerConfig<T> = {\n /**\n * Function to retrieve all items that can be tickled\n */\n getItems: () => ReadonlyArray<TickledItem<T>>;\n\n /**\n * Optional callback when an item becomes tickled\n * Use this for side effects like opening submenus\n * @param id - The id of the newly tickled item, or undefined if nothing is tickled\n */\n onTickle?: (id: T | undefined) => void;\n\n /**\n * Optional callback fired after any state change (tickled id or input mode)\n * Use this to sync DOM attributes for slotted content that can't use reactive rendering\n *\n * For components that render items directly, this is usually not needed as\n * Lit's reactive rendering will handle updates automatically via requestUpdate()\n *\n * @example\n * ```ts\n * onStateChange: () => {\n * // Sync data-tickled attributes for slotted items\n * const items = this.getItems();\n * items.forEach((item, i) => {\n * if (this.tickled.isTickled(i)) {\n * item.setAttribute('data-tickled', '');\n * } else {\n * item.removeAttribute('data-tickled');\n * }\n * });\n * }\n * ```\n */\n onStateChange?: () => void;\n\n /**\n * Optional initial input mode (defaults to 'mouse')\n */\n initialInputMode?: InputMode;\n\n /**\n * Whether keyboard navigation wraps from last to first and vice versa.\n * - 'stop' (default): navigation stops at the boundary\n * - 'wrap': navigation wraps around\n */\n itemWrap?: `stop` | `wrap`;\n};\n\n/**\n * ReactiveController that manages \"tickled\" state for interactive lists.\n *\n * A \"tickled\" item is one that is under active attention via hover (mouse mode)\n * or keyboard focus (keyboard mode). Only one item can be tickled at a time.\n *\n * The input mode determines which mechanism controls tickled state:\n * - Mouse mode: hover controls tickled, keyboard navigation ignored\n * - Keyboard mode: keyboard navigation controls tickled, hover ignored\n *\n * Last interaction wins - any mouse hover switches to mouse mode, any keyboard\n * navigation switches to keyboard mode.\n *\n * ## Global Mouse Tracking\n *\n * This controller uses a single, ref-counted global `pointermove` listener (shared\n * across all instances) to track actual mouse movement. This prevents `pointerenter`\n * events caused by content scrolling from incorrectly switching to mouse mode when\n * the user is actually using keyboard navigation. The listener is attached when the\n * first host connects and removed once the last host disconnects.\n *\n * @example\n * ```ts\n * class MyList extends LitElement {\n * private tickled = new TickledController(this, {\n * getItems: () => this.items.map((item, i) => ({ id: i, enabled: !item.disabled })),\n * onTickle: (id) => {\n * // Optional: perform side effect when item is tickled\n * console.log('Tickled item:', id);\n * }\n * });\n *\n * render() {\n * return html`\n * <ul @pointerleave=${(e) => this.tickled.handlePointerLeave(e)}>\n * ${this.items.map((item, i) => html`\n * <li\n * class=\"item ${this.tickled.isTickled(i) ? 'tickled' : ''}\"\n * @pointerenter=${() => this.tickled.handlePointerEnter(i)}\n * >${item.label}</li>\n * `)}\n * </ul>\n * `;\n * }\n *\n * private handleKeyDown(e: KeyboardEvent) {\n * if (e.key === 'ArrowDown') {\n * this.tickled.handleKeyboardNavigation('next');\n * } else if (e.key === 'ArrowUp') {\n * this.tickled.handleKeyboardNavigation('previous');\n * }\n * }\n * }\n * ```\n */\nexport class TickledController<T = number> implements ReactiveController {\n private host: ReactiveControllerHost;\n private config: TickledControllerConfig<T>;\n private _tickledId: T | undefined = undefined;\n private _inputMode: InputMode;\n\n private static _lastMouseClientX: number = Number.NaN;\n private static _lastMouseClientY: number = Number.NaN;\n private static _mouseMovedSinceKeyboard: boolean = true;\n private static _listenerRefCount: number = 0;\n\n private static readonly _onGlobalPointerMove = (e: PointerEvent): void => {\n TickledController.handleGlobalPointerMove(e.clientX, e.clientY);\n };\n\n constructor(host: ReactiveControllerHost, config: TickledControllerConfig<T>) {\n this.host = host;\n this.config = config;\n this._inputMode = config.initialInputMode ?? `mouse`;\n host.addController(this);\n }\n\n hostConnected(): void {\n if (TickledController._listenerRefCount === 0) {\n document.addEventListener(`pointermove`, TickledController._onGlobalPointerMove, { passive: true });\n }\n TickledController._listenerRefCount++;\n }\n\n hostDisconnected(): void {\n TickledController._listenerRefCount--;\n if (TickledController._listenerRefCount === 0) {\n document.removeEventListener(`pointermove`, TickledController._onGlobalPointerMove);\n }\n }\n\n /**\n * Get the current input mode\n */\n get inputMode(): InputMode {\n return this._inputMode;\n }\n\n /**\n * Get the currently tickled item id\n */\n get tickledId(): T | undefined {\n return this._tickledId;\n }\n\n /**\n * Check if a specific item is tickled\n */\n isTickled(id: T): boolean {\n return this._tickledId === id;\n }\n\n /**\n * Handle global pointer move event.\n * Called automatically by the global listener.\n * Tracks mouse movement to distinguish real hover from content scrolling.\n */\n private static handleGlobalPointerMove(clientX: number, clientY: number): void {\n if (!Number.isNaN(TickledController._lastMouseClientX)) {\n if (\n clientX !== TickledController._lastMouseClientX\n || clientY !== TickledController._lastMouseClientY\n ) {\n TickledController._mouseMovedSinceKeyboard = true;\n }\n }\n TickledController._lastMouseClientX = clientX;\n TickledController._lastMouseClientY = clientY;\n }\n\n /**\n * Check if actual mouse movement has occurred since last keyboard interaction.\n * Used to distinguish real hover/leave from content-scrolling-induced events.\n */\n static get hasMouseMovedSinceKeyboard(): boolean {\n return TickledController._mouseMovedSinceKeyboard;\n }\n\n /**\n * Handle pointer enter event on an item (mouse hover).\n * Only processes if actual mouse movement is detected (not content scrolling).\n * Switches to mouse mode and tickles the item.\n */\n handlePointerEnter(id: T): void {\n if (!TickledController._mouseMovedSinceKeyboard) {\n return;\n }\n\n const items = this.config.getItems();\n const item = items.find(item => item.id === id);\n if (item && item.enabled === false) {\n return;\n }\n\n const modeChanged = this._inputMode !== `mouse`;\n this._inputMode = `mouse`;\n\n const previousId = this._tickledId;\n this._tickledId = id;\n\n this.host.requestUpdate();\n\n if (previousId !== id && this.config.onTickle) {\n this.config.onTickle(id);\n }\n\n if ((previousId !== id || modeChanged) && this.config.onStateChange) {\n this.config.onStateChange();\n }\n }\n\n /**\n * Handle pointer leave event on an item.\n * Only clears tickled state if actual mouse movement is detected.\n * @param _e The pointer event (not used, but kept for API compatibility)\n */\n handlePointerLeave(_e: PointerEvent): void {\n if (TickledController._mouseMovedSinceKeyboard) {\n this.clearTickled();\n }\n }\n\n /**\n * Handle keyboard navigation.\n * Switches to keyboard mode and moves tickled state.\n *\n * @param direction - 'next', 'previous', 'first', 'last', or specific id\n */\n handleKeyboardNavigation(direction: `next` | `previous` | `first` | `last` | T): void {\n const modeChanged = this._inputMode !== `keyboard`;\n this._inputMode = `keyboard`;\n\n const items = this.config.getItems();\n const enabledItems = items.filter(item => item.enabled !== false);\n\n if (enabledItems.length === 0) {\n return;\n }\n\n let newId: T | undefined;\n\n if (direction === `first`) {\n newId = enabledItems[0].id;\n } else if (direction === `last`) {\n newId = enabledItems.at(-1)?.id;\n } else if (direction === `next` || direction === `previous`) {\n const currentIndex = enabledItems.findIndex(item => item.id === this._tickledId);\n const wrap = this.config.itemWrap === `wrap`;\n\n if (currentIndex === -1) {\n newId = direction === `next` ? enabledItems[0].id : enabledItems.at(-1)?.id;\n } else {\n const delta = direction === `next` ? 1 : -1;\n let newIndex = currentIndex + delta;\n\n if (newIndex >= 0 && newIndex < enabledItems.length) {\n newId = enabledItems[newIndex].id;\n } else if (wrap) {\n // Wrap around\n if (newIndex < 0) {\n newIndex = enabledItems.length - 1;\n } else {\n newIndex = 0;\n }\n newId = enabledItems[newIndex].id;\n }\n // If newIndex is out of bounds and wrap is disabled, keep current tickled item\n }\n } else {\n const item = enabledItems.find(item => item.id === direction);\n if (item) {\n newId = item.id;\n }\n }\n\n if (newId !== undefined) {\n const previousId = this._tickledId;\n this._tickledId = newId;\n this.host.requestUpdate();\n\n if (previousId !== newId && this.config.onTickle) {\n this.config.onTickle(newId);\n }\n\n if ((previousId !== newId || modeChanged) && this.config.onStateChange) {\n this.config.onStateChange();\n }\n }\n }\n\n /**\n * Manually set the tickled item (useful for programmatic control).\n * Does NOT change input mode.\n */\n setTickled(id: T | undefined): void {\n const previousId = this._tickledId;\n this._tickledId = id;\n this.host.requestUpdate();\n\n if (previousId !== id && this.config.onTickle) {\n this.config.onTickle(id);\n }\n\n if (previousId !== id && this.config.onStateChange) {\n this.config.onStateChange();\n }\n }\n\n /**\n * Clear the tickled state (e.g., on pointer leave).\n * Note: For pointer leave events, prefer using handlePointerLeave() which\n * checks for actual mouse movement.\n */\n clearTickled(): void {\n if (this._tickledId !== undefined) {\n this._tickledId = undefined;\n this.host.requestUpdate();\n\n if (this.config.onTickle) {\n this.config.onTickle(undefined);\n }\n\n if (this.config.onStateChange) {\n this.config.onStateChange();\n }\n }\n }\n\n /**\n * Manually set the input mode.\n * When switching to keyboard mode, resets the mouse movement tracking.\n */\n setInputMode(mode: InputMode): void {\n if (this._inputMode !== mode) {\n this._inputMode = mode;\n this.host.requestUpdate();\n\n if (mode === `keyboard`) {\n TickledController._mouseMovedSinceKeyboard = false;\n }\n\n if (this.config.onStateChange) {\n this.config.onStateChange();\n }\n }\n }\n}\n"],"mappings":"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"}
|