@ixfx/components 0.2.6 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (140) hide show
  1. package/bundle/index.d.ts +213 -117
  2. package/bundle/index.d.ts.map +1 -1
  3. package/bundle/index.js +1356 -658
  4. package/bundle/index.js.map +1 -1
  5. package/dist/ac-text.js +3 -3
  6. package/dist/ac-text.js.map +1 -1
  7. package/dist/{button-B9ztaKyl.js → button-DMt5XWUK.js} +4 -4
  8. package/dist/{button-B9ztaKyl.js.map → button-DMt5XWUK.js.map} +1 -1
  9. package/dist/button.js +1 -1
  10. package/dist/checkbox.d.ts +2 -3
  11. package/dist/checkbox.d.ts.map +1 -1
  12. package/dist/checkbox.js +1 -1
  13. package/dist/checkbox.js.map +1 -1
  14. package/dist/{colour-C3MQIjFJ-BJV-QC-3.js → colour-C3MQIjFJ-BLXg8W3U.js} +2 -2
  15. package/dist/{colour-C3MQIjFJ-BJV-QC-3.js.map → colour-C3MQIjFJ-BLXg8W3U.js.map} +1 -1
  16. package/dist/{colour-picker-BNqDz4wK.js → colour-picker-K6zu82lm.js} +5 -5
  17. package/dist/{colour-picker-BNqDz4wK.js.map → colour-picker-K6zu82lm.js.map} +1 -1
  18. package/dist/colour-picker.js +1 -1
  19. package/dist/crumbs.d.ts +2 -3
  20. package/dist/crumbs.d.ts.map +1 -1
  21. package/dist/crumbs.js +10 -10
  22. package/dist/crumbs.js.map +1 -1
  23. package/dist/data-display.js +3 -3
  24. package/dist/{decorate-O4m1U4l3.js → decorate-D7rC1gLP.js} +10 -8
  25. package/dist/decorate-D7rC1gLP.js.map +1 -0
  26. package/dist/{defaults-FEZaGiYZ.js → defaults-C7elhuyJ.js} +2 -2
  27. package/dist/{defaults-FEZaGiYZ.js.map → defaults-C7elhuyJ.js.map} +1 -1
  28. package/dist/{dist-By5URG0Y.js → dist-BX0OVIm7.js} +2 -2
  29. package/dist/{dist-By5URG0Y.js.map → dist-BX0OVIm7.js.map} +1 -1
  30. package/dist/{dist-D7kJgnSE.js → dist-TAGYwaju.js} +1 -1
  31. package/dist/{dist-D7kJgnSE.js.map → dist-TAGYwaju.js.map} +1 -1
  32. package/dist/editable-label.d.ts +6 -1
  33. package/dist/editable-label.d.ts.map +1 -1
  34. package/dist/editable-label.js +49 -2
  35. package/dist/editable-label.js.map +1 -1
  36. package/dist/{hex-editor-gH3mteMr.js → hex-editor-CsN_ySkH.js} +85 -85
  37. package/dist/hex-editor-CsN_ySkH.js.map +1 -0
  38. package/dist/{hex-editor-2_s0Ua5t.d.ts → hex-editor-DlfoA65y.d.ts} +5 -5
  39. package/dist/{hex-editor-2_s0Ua5t.d.ts.map → hex-editor-DlfoA65y.d.ts.map} +1 -1
  40. package/dist/hex.d.ts +1 -1
  41. package/dist/hex.js +1 -1
  42. package/dist/{highlight-CAjwQ4GE.js → highlight-TPbSHruI.js} +3 -3
  43. package/dist/highlight-TPbSHruI.js.map +1 -0
  44. package/dist/{icon-CYACf6o8.js → icon-9NWTXtE1.js} +4 -5
  45. package/dist/icon-9NWTXtE1.js.map +1 -0
  46. package/dist/icon-CeTDJhC7.d.ts.map +1 -1
  47. package/dist/icons.js +3 -3
  48. package/dist/{incr-search-BZawvrfl.js → incr-search-DSKKsk6w.js} +12 -10
  49. package/dist/incr-search-DSKKsk6w.js.map +1 -0
  50. package/dist/incr-search.d.ts +1 -1
  51. package/dist/incr-search.js +2 -2
  52. package/dist/{index-CwGkb9s1.d.ts → index--hrxPBkQ.d.ts} +69 -69
  53. package/dist/index--hrxPBkQ.d.ts.map +1 -0
  54. package/dist/{index-kY5gxbkI.d.ts → index-DSlPeWLK.d.ts} +15 -15
  55. package/dist/{index-kY5gxbkI.d.ts.map → index-DSlPeWLK.d.ts.map} +1 -1
  56. package/dist/{index-V2cJorlA.d.ts → index-hXFn14tM.d.ts} +4 -4
  57. package/dist/index-hXFn14tM.d.ts.map +1 -0
  58. package/dist/index.d.ts +109 -13
  59. package/dist/index.d.ts.map +1 -1
  60. package/dist/index.js +666 -24
  61. package/dist/index.js.map +1 -1
  62. package/dist/keyboard-De_vOHLg.js.map +1 -1
  63. package/dist/{labelled-input-base-BvgH7ldm.js → labelled-input-base-CqPL5rKm.js} +2 -2
  64. package/dist/labelled-input-base-CqPL5rKm.js.map +1 -0
  65. package/dist/labelled-radial-input.js +3 -3
  66. package/dist/labelled-radial-input.js.map +1 -1
  67. package/dist/labelled-range-input.js +2 -2
  68. package/dist/led.js +1 -1
  69. package/dist/{menu-C3eANB5M.js → menu-DJJuCm-5.js} +48 -48
  70. package/dist/menu-DJJuCm-5.js.map +1 -0
  71. package/dist/{menu-item-6IU5weHi.js → menu-item-CKRfP0pN.js} +10 -10
  72. package/dist/menu-item-CKRfP0pN.js.map +1 -0
  73. package/dist/menu.d.ts +1 -1
  74. package/dist/menu.js +2 -2
  75. package/dist/miller.d.ts +5 -7
  76. package/dist/miller.d.ts.map +1 -1
  77. package/dist/miller.js +14 -14
  78. package/dist/miller.js.map +1 -1
  79. package/dist/narrowed-text.d.ts.map +1 -1
  80. package/dist/narrowed-text.js +4 -4
  81. package/dist/narrowed-text.js.map +1 -1
  82. package/dist/panel.js +2 -2
  83. package/dist/panel.js.map +1 -1
  84. package/dist/plots.js +1 -1
  85. package/dist/polar-pad.d.ts.map +1 -1
  86. package/dist/polar-pad.js +1 -1
  87. package/dist/polar-pad.js.map +1 -1
  88. package/dist/{popup-Ddx9LCzY.js → popup-ImtS9KnS.js} +1 -1
  89. package/dist/{popup-Ddx9LCzY.js.map → popup-ImtS9KnS.js.map} +1 -1
  90. package/dist/{prominence-CreDBdCs.js → prominence--ic9uWBl.js} +1 -1
  91. package/dist/{prominence-CreDBdCs.js.map → prominence--ic9uWBl.js.map} +1 -1
  92. package/dist/{radial-input-Dbc6fgCK.js → radial-input-DZA6WaFu.js} +14 -14
  93. package/dist/radial-input-DZA6WaFu.js.map +1 -0
  94. package/dist/radial-input.js +1 -1
  95. package/dist/range-input.js +1 -1
  96. package/dist/range.js +2 -2
  97. package/dist/{registry-CZEB1YI9.js → registry-Q2gYQCHM.js} +1 -1
  98. package/dist/{registry-CZEB1YI9.js.map → registry-Q2gYQCHM.js.map} +1 -1
  99. package/dist/selecthorizontal.js +1 -1
  100. package/dist/snap-container.js +1 -1
  101. package/dist/split-layout.js +4 -4
  102. package/dist/split-layout.js.map +1 -1
  103. package/dist/swipe.d.ts +1 -2
  104. package/dist/swipe.d.ts.map +1 -1
  105. package/dist/swipe.js +2 -2
  106. package/dist/swipe.js.map +1 -1
  107. package/dist/tabs.js +2 -2
  108. package/dist/tabs.js.map +1 -1
  109. package/dist/{timeline-B62Sz6J_.js → timeline-Cv75Th2U.js} +120 -116
  110. package/dist/timeline-Cv75Th2U.js.map +1 -0
  111. package/dist/timeline.d.ts +1 -1
  112. package/dist/timeline.js +1 -1
  113. package/dist/tooltip-CwGfb4lp.d.ts.map +1 -1
  114. package/dist/tree-CvvKbO-f.js +1330 -0
  115. package/dist/tree-CvvKbO-f.js.map +1 -0
  116. package/dist/{tree-component-CQpoPo4s.d.ts → tree-component-D8Bg48tt.d.ts} +12 -12
  117. package/dist/{tree-component-CQpoPo4s.d.ts.map → tree-component-D8Bg48tt.d.ts.map} +1 -1
  118. package/dist/tree.d.ts +1 -1
  119. package/dist/tree.js +1 -1143
  120. package/dist/xy-axis-D9uwpGTT.d.ts.map +1 -1
  121. package/dist/{xy-axis-C7fNxDwY.js → xy-axis-DL0tfJDr.js} +10 -10
  122. package/dist/{xy-axis-C7fNxDwY.js.map → xy-axis-DL0tfJDr.js.map} +1 -1
  123. package/dist/xy-pad.js +2 -2
  124. package/package.json +3 -3
  125. package/dist/decorate-O4m1U4l3.js.map +0 -1
  126. package/dist/hex-editor-gH3mteMr.js.map +0 -1
  127. package/dist/highlight-CAjwQ4GE.js.map +0 -1
  128. package/dist/icon-CYACf6o8.js.map +0 -1
  129. package/dist/incr-search-BZawvrfl.js.map +0 -1
  130. package/dist/index-CwGkb9s1.d.ts.map +0 -1
  131. package/dist/index-V2cJorlA.d.ts.map +0 -1
  132. package/dist/labelled-input-base-BvgH7ldm.js.map +0 -1
  133. package/dist/menu-C3eANB5M.js.map +0 -1
  134. package/dist/menu-item-6IU5weHi.js.map +0 -1
  135. package/dist/radial-input-Dbc6fgCK.js.map +0 -1
  136. package/dist/timeline-B62Sz6J_.js.map +0 -1
  137. package/dist/tree-data-model-DGvRVOFY.js +0 -190
  138. package/dist/tree-data-model-DGvRVOFY.js.map +0 -1
  139. package/dist/tree.js.map +0 -1
  140. /package/dist/{interaction-CQDQJf2Q.js → interaction-DG7X1rhI.js} +0 -0
package/dist/index.js CHANGED
@@ -1,33 +1,33 @@
1
- import { n as buildHighlightTargets, r as clearHighlights, t as applyHighlights } from "./highlight-CAjwQ4GE.js";
2
- import { r as TickledController } from "./tickled-styles-Bg3QbcrD.js";
3
- import { a as svgToDataUri, i as registerIcon, n as hasIcon, r as iconBus, t as getIcon } from "./registry-CZEB1YI9.js";
4
- import { n as safeCustomElement, t as __decorate } from "./decorate-O4m1U4l3.js";
5
- import { t as IxfxIconElement } from "./icon-CYACf6o8.js";
1
+ import { n as buildHighlightTargets, r as clearHighlights, t as applyHighlights } from "./highlight-TPbSHruI.js";
2
+ import { n as tickledStyles, r as TickledController } from "./tickled-styles-Bg3QbcrD.js";
3
+ import { n as safeCustomElement, t as __decorate } from "./decorate-D7rC1gLP.js";
4
+ import { a as svgToDataUri, i as registerIcon, n as hasIcon, r as iconBus, t as getIcon } from "./registry-Q2gYQCHM.js";
5
+ import { t as IxfxIconElement } from "./icon-9NWTXtE1.js";
6
6
  import { AcTextElement } from "./ac-text.js";
7
- import { i as ICON_CLOSE, n as ICON_CHECK, r as ICON_CHEVRON_DOWN, t as ICON_CARET_RIGHT } from "./defaults-FEZaGiYZ.js";
7
+ import { a as createFuzzySearch, i as createAcCompletionProvider, n as IncrSearchTreeController, r as createIncrSearch, t as createElementIncrSearch } from "./incr-search-DSKKsk6w.js";
8
+ import { i as ICON_CLOSE, n as ICON_CHECK, r as ICON_CHEVRON_DOWN, t as ICON_CARET_RIGHT } from "./defaults-C7elhuyJ.js";
8
9
  import "./icons.js";
9
- import { t as prominenceStyles } from "./prominence-CreDBdCs.js";
10
- import { n as buttonStyles, t as ButtonElement } from "./button-B9ztaKyl.js";
11
- import { t as popupSurfaceStyles } from "./popup-Ddx9LCzY.js";
12
- import "./menu-item-6IU5weHi.js";
10
+ import { t as prominenceStyles } from "./prominence--ic9uWBl.js";
11
+ import { n as buttonStyles, t as ButtonElement } from "./button-DMt5XWUK.js";
12
+ import { t as popupSurfaceStyles } from "./popup-ImtS9KnS.js";
13
+ import "./menu-item-CKRfP0pN.js";
13
14
  import { Checkbox } from "./checkbox.js";
14
- import { C as resultThrow, E as throwIfFailed, d as scaler, h as without, n as clamper, p as containsDuplicateInstances, y as nullUndefTest } from "./dist-D7kJgnSE.js";
15
- import { a as computeColour, c as last, i as applyAgeModification, l as QueueMutable, n as PlotSingleAxis, o as parseColourScaleAttr, r as PlotDataSeries, s as readBaseColour, t as PlotXyAxis, u as __exportAll } from "./xy-axis-C7fNxDwY.js";
16
- import { a as toStringAbbreviate, c as isEqualDefault, l as isEqualValueDefault, o as defaultComparer, r as isPrimitive, u as isEqualValueIgnoreOrder } from "./dist-By5URG0Y.js";
17
- import { n as ColourPicker, t as ColourPickerPopup } from "./colour-picker-BNqDz4wK.js";
15
+ import { C as resultThrow, E as throwIfFailed, d as scaler, h as without, n as clamper, p as containsDuplicateInstances, y as nullUndefTest } from "./dist-TAGYwaju.js";
16
+ import { a as computeColour, c as last, i as applyAgeModification, l as QueueMutable, n as PlotSingleAxis, o as parseColourScaleAttr, r as PlotDataSeries, s as readBaseColour, t as PlotXyAxis, u as __exportAll } from "./xy-axis-DL0tfJDr.js";
17
+ import { a as toStringAbbreviate, c as isEqualDefault, l as isEqualValueDefault, o as defaultComparer, r as isPrimitive, u as isEqualValueIgnoreOrder } from "./dist-BX0OVIm7.js";
18
+ import { n as ColourPicker, t as ColourPickerPopup } from "./colour-picker-K6zu82lm.js";
18
19
  import { LabelledRangeInput } from "./labelled-range-input.js";
19
- import { t as TreeDataModel } from "./tree-data-model-DGvRVOFY.js";
20
- import { a as createFuzzySearch, i as createAcCompletionProvider, n as IncrSearchTreeController, r as createIncrSearch, t as createElementIncrSearch } from "./incr-search-BZawvrfl.js";
20
+ import { i as TreeDataModel, n as TreeController, r as TreeBaseElement, t as TreeListElement } from "./tree-CvvKbO-f.js";
21
21
  import { NarrowedTextElement } from "./narrowed-text.js";
22
22
  import { CrumbNavigationElement } from "./crumbs.js";
23
23
  import { DataDisplayComponent } from "./data-display.js";
24
24
  import { EditableLabel } from "./editable-label.js";
25
25
  import { t as resolveStep } from "./keyboard-De_vOHLg.js";
26
- import { t as IxfxHexEditorElement } from "./hex-editor-gH3mteMr.js";
27
- import { t as RadialInputElement } from "./radial-input-Dbc6fgCK.js";
26
+ import { t as IxfxHexEditorElement } from "./hex-editor-CsN_ySkH.js";
27
+ import { t as RadialInputElement } from "./radial-input-DZA6WaFu.js";
28
28
  import { LabelledRadialInput } from "./labelled-radial-input.js";
29
29
  import { LedElement } from "./led.js";
30
- import { t as menu_exports } from "./menu-C3eANB5M.js";
30
+ import { t as menu_exports } from "./menu-DJJuCm-5.js";
31
31
  import { MillerBaseElement, MillerListElement, MillerTreeController } from "./miller.js";
32
32
  import { PanelElement } from "./panel.js";
33
33
  import { PolarPad } from "./polar-pad.js";
@@ -39,14 +39,633 @@ import { SnapContainer } from "./snap-container.js";
39
39
  import { SplitLayoutElement } from "./split-layout.js";
40
40
  import { SwipeElement } from "./swipe.js";
41
41
  import { TabListElement } from "./tabs.js";
42
- import { a as attachTimelineInteractions, i as timelineStyles, n as IxfxTimelineElement, o as resolveCssVars, r as TimelineTrackTabElement, s as resolveGrid, t as TimelineController } from "./timeline-B62Sz6J_.js";
43
- import { TreeBaseElement, TreeController, TreeListElement } from "./tree.js";
42
+ import { a as resolveCssVars, i as attachTimelineInteractions, n as TimelineTrackTabElement, o as resolveGrid, r as timelineStyles, s as TimelineController, t as IxfxTimelineElement } from "./timeline-Cv75Th2U.js";
44
43
  import { XyPad } from "./xy-pad.js";
45
44
  import { LitElement, css, html, nothing } from "lit";
46
45
  import { eventOptions, property, query, queryAssignedElements, state } from "lit/decorators.js";
47
46
  import { unsafeHTML } from "lit/directives/unsafe-html.js";
48
47
  import { keyed } from "lit/directives/keyed.js";
49
48
  import { classMap } from "lit/directives/class-map.js";
49
+ //#region src/ac-token/ac-token.ts
50
+ const DEFAULT_TOKENIZER = (text) => text.split(/[\s,;]+/);
51
+ function makeLruCache(maxSize) {
52
+ const map = /* @__PURE__ */ new Map();
53
+ return {
54
+ get: (k) => map.get(k),
55
+ set: (k, v) => {
56
+ if (map.has(k)) map.delete(k);
57
+ map.set(k, v);
58
+ if (map.size > maxSize) map.delete(map.keys().next().value);
59
+ },
60
+ has: (k) => map.has(k),
61
+ clear: () => map.clear()
62
+ };
63
+ }
64
+ let AcTokenElement = class AcTokenElement extends LitElement {
65
+ #cache;
66
+ #debounceTimer;
67
+ #abortController;
68
+ #staticProvider;
69
+ constructor() {
70
+ super();
71
+ this.placeholder = ``;
72
+ this.cacheSize = 20;
73
+ this.debounceMs = 150;
74
+ this.strict = false;
75
+ this._tokens = [];
76
+ this._draft = ``;
77
+ this._suggestions = [];
78
+ this._isOpen = false;
79
+ this._isLoading = false;
80
+ this._tickled = new TickledController(this, { getItems: () => this._suggestions.map((_, i) => ({
81
+ id: i,
82
+ enabled: true
83
+ })) });
84
+ this.#cache = makeLruCache(20);
85
+ this.#onWrapperClick = (e) => {
86
+ if (!e.target.closest(`.token-chip`)) this.shadowRoot?.querySelector(`input.draft`)?.focus();
87
+ };
88
+ this.#onFocus = () => {
89
+ this._selectedTokenIndex = void 0;
90
+ this.#scheduleSuggestionFetch(this._draft);
91
+ };
92
+ this.#onBlur = () => {
93
+ setTimeout(() => {
94
+ this._isOpen = false;
95
+ this._tickled.clearTickled();
96
+ this._selectedTokenIndex = void 0;
97
+ }, 120);
98
+ };
99
+ this.#onInput = (e) => {
100
+ const value = e.target.value;
101
+ this._selectedTokenIndex = void 0;
102
+ const parts = (this.tokenizer ?? DEFAULT_TOKENIZER)(value);
103
+ if (parts.length > 1) {
104
+ for (let i = 0; i < parts.length - 1; i++) {
105
+ const label = parts[i].trim();
106
+ if (label) this.#addToken({ label });
107
+ }
108
+ this._draft = parts[parts.length - 1] ?? ``;
109
+ } else this._draft = value;
110
+ this.#scheduleSuggestionFetch(this._draft);
111
+ };
112
+ this.#onKeyDown = (e) => {
113
+ const input = e.target;
114
+ if ((e.metaKey || e.ctrlKey) && e.key === `a`) {
115
+ e.preventDefault();
116
+ const parts = [...this._tokens.map((t) => t.label), this._draft.trim()].filter(Boolean);
117
+ navigator.clipboard.writeText(parts.join(` `)).catch(() => {});
118
+ return;
119
+ }
120
+ if (this._selectedTokenIndex !== void 0 && e.key.length === 1 && !e.metaKey && !e.ctrlKey && !e.altKey) {
121
+ e.preventDefault();
122
+ this.#startEditingSelectedToken(e.key);
123
+ return;
124
+ }
125
+ this.#handleNavigationKey(e, input);
126
+ };
127
+ this.#onPaste = (e) => {
128
+ e.preventDefault();
129
+ const text = e.clipboardData?.getData(`text/plain`) ?? ``;
130
+ if (!text) return;
131
+ const parts = (this.tokenizer ?? DEFAULT_TOKENIZER)(this._draft + text).filter(Boolean);
132
+ if (parts.length === 0) return;
133
+ if (parts.length === 1) this._draft = parts[0];
134
+ else {
135
+ for (let i = 0; i < parts.length - 1; i++) {
136
+ const label = parts[i].trim();
137
+ if (label) this.#addToken({ label });
138
+ }
139
+ this._draft = parts[parts.length - 1] ?? ``;
140
+ }
141
+ this.updateComplete.then(() => {
142
+ this.shadowRoot?.querySelector(`input.draft`)?.setSelectionRange(this._draft.length, this._draft.length);
143
+ });
144
+ this.#scheduleSuggestionFetch(this._draft);
145
+ };
146
+ this.#onSuggestionPointerDown = (e, item) => {
147
+ e.preventDefault();
148
+ this.#selectSuggestion(item);
149
+ };
150
+ this.#onChipPointerDown = (e, index) => {
151
+ if (e.button !== 0) return;
152
+ e.preventDefault();
153
+ const el = e.currentTarget;
154
+ const startY = e.clientY;
155
+ let dragged = false;
156
+ el.setPointerCapture(e.pointerId);
157
+ const cleanup = () => {
158
+ el.removeEventListener(`pointermove`, onMove);
159
+ el.removeEventListener(`pointerup`, onUp);
160
+ };
161
+ const onMove = (me) => {
162
+ if (Math.abs(me.clientY - startY) > 28) {
163
+ dragged = true;
164
+ el.releasePointerCapture(me.pointerId);
165
+ cleanup();
166
+ this.#removeToken(index);
167
+ this.shadowRoot?.querySelector(`input.draft`)?.focus();
168
+ }
169
+ };
170
+ const onUp = () => {
171
+ cleanup();
172
+ if (!dragged) {
173
+ this._selectedTokenIndex = this._selectedTokenIndex === index ? void 0 : index;
174
+ this.shadowRoot?.querySelector(`input.draft`)?.focus();
175
+ }
176
+ };
177
+ el.addEventListener(`pointermove`, onMove);
178
+ el.addEventListener(`pointerup`, onUp);
179
+ };
180
+ this.#cache = makeLruCache(this.cacheSize);
181
+ }
182
+ get tokens() {
183
+ return this._tokens;
184
+ }
185
+ set tokens(value) {
186
+ this._tokens = [...value];
187
+ this.#emitChange();
188
+ }
189
+ /** All committed token labels joined with commas. */
190
+ get value() {
191
+ return this._tokens.map((t) => t.label).join(`, `);
192
+ }
193
+ connectedCallback() {
194
+ super.connectedCallback();
195
+ this.#buildStaticProvider();
196
+ }
197
+ disconnectedCallback() {
198
+ super.disconnectedCallback();
199
+ this.#cancelPending();
200
+ }
201
+ updated(changedProps) {
202
+ if (changedProps.has(`completionProvider`) || changedProps.has(`cacheSize`)) this.#cache = makeLruCache(this.cacheSize);
203
+ if (changedProps.has(`completionProvider`)) this.#buildStaticProvider();
204
+ }
205
+ #buildStaticProvider() {
206
+ const raw = this.getAttribute(`data-tokens`);
207
+ if (!raw || this.completionProvider) {
208
+ this.#staticProvider = void 0;
209
+ return;
210
+ }
211
+ const items = raw.trim().split(/[\s,;]+/).filter(Boolean).map((label) => ({ label }));
212
+ this.#staticProvider = createAcCompletionProvider(items);
213
+ }
214
+ #onWrapperClick;
215
+ #onFocus;
216
+ #onBlur;
217
+ #onInput;
218
+ #onKeyDown;
219
+ #handleNavigationKey(e, input) {
220
+ switch (e.key) {
221
+ case `ArrowLeft`:
222
+ if (input.selectionStart === 0 && input.selectionEnd === 0) {
223
+ e.preventDefault();
224
+ if (this._selectedTokenIndex === void 0) {
225
+ if (this._tokens.length > 0) this._selectedTokenIndex = this._tokens.length - 1;
226
+ } else if (this._selectedTokenIndex > 0) this._selectedTokenIndex--;
227
+ }
228
+ break;
229
+ case `ArrowRight`:
230
+ if (this._selectedTokenIndex !== void 0) {
231
+ e.preventDefault();
232
+ if (this._selectedTokenIndex < this._tokens.length - 1) this._selectedTokenIndex++;
233
+ else this._selectedTokenIndex = void 0;
234
+ }
235
+ break;
236
+ case `Backspace`:
237
+ if (input.selectionStart === 0 && input.selectionEnd === 0) {
238
+ e.preventDefault();
239
+ if (this._selectedTokenIndex !== void 0) this.#removeToken(this._selectedTokenIndex);
240
+ else if (this._tokens.length > 0) this.#removeToken(this._tokens.length - 1);
241
+ }
242
+ break;
243
+ case `Enter`: {
244
+ const tickledIdx = this._tickled.tickledId;
245
+ if (this._isOpen && tickledIdx !== void 0 && this._suggestions[tickledIdx]) {
246
+ e.preventDefault();
247
+ this.#selectSuggestion(this._suggestions[tickledIdx]);
248
+ } else if (!this.strict && this._draft.trim()) {
249
+ e.preventDefault();
250
+ this.#addToken({ label: this._draft.trim() });
251
+ this._draft = ``;
252
+ this.#closePopup();
253
+ }
254
+ break;
255
+ }
256
+ case `ArrowDown`:
257
+ if (!this._isOpen) return;
258
+ e.preventDefault();
259
+ this._tickled.handleKeyboardNavigation(`next`);
260
+ this.#scrollSuggestionIntoView();
261
+ break;
262
+ case `ArrowUp`:
263
+ if (!this._isOpen) return;
264
+ e.preventDefault();
265
+ this._tickled.handleKeyboardNavigation(`previous`);
266
+ this.#scrollSuggestionIntoView();
267
+ break;
268
+ case `Escape`:
269
+ e.preventDefault();
270
+ this.#closePopup();
271
+ this._selectedTokenIndex = void 0;
272
+ break;
273
+ }
274
+ }
275
+ #onPaste;
276
+ #onSuggestionPointerDown;
277
+ #onChipPointerDown;
278
+ #startEditingSelectedToken(key) {
279
+ const idx = this._selectedTokenIndex;
280
+ if (idx === void 0) return;
281
+ const token = this._tokens[idx];
282
+ if (!token) return;
283
+ const newDraft = token.label + key;
284
+ this.#removeToken(idx);
285
+ this._selectedTokenIndex = void 0;
286
+ this._draft = newDraft;
287
+ this.updateComplete.then(() => {
288
+ const inp = this.shadowRoot?.querySelector(`input.draft`);
289
+ if (!inp) return;
290
+ inp.setSelectionRange(inp.value.length, inp.value.length);
291
+ });
292
+ this.#scheduleSuggestionFetch(newDraft);
293
+ }
294
+ #addToken(item) {
295
+ const index = this._tokens.length;
296
+ this._tokens = [...this._tokens, item];
297
+ this.dispatchEvent(new CustomEvent(`ac-token-add`, {
298
+ detail: {
299
+ item,
300
+ index
301
+ },
302
+ bubbles: true,
303
+ composed: true
304
+ }));
305
+ this.#emitChange();
306
+ }
307
+ #removeToken(index) {
308
+ const item = this._tokens[index];
309
+ if (!item) return;
310
+ this._tokens = this._tokens.filter((_, i) => i !== index);
311
+ if (this._selectedTokenIndex !== void 0) {
312
+ if (this._selectedTokenIndex === index) this._selectedTokenIndex = void 0;
313
+ else if (this._selectedTokenIndex > index) this._selectedTokenIndex--;
314
+ }
315
+ this.dispatchEvent(new CustomEvent(`ac-token-remove`, {
316
+ detail: {
317
+ item,
318
+ index
319
+ },
320
+ bubbles: true,
321
+ composed: true
322
+ }));
323
+ this.#emitChange();
324
+ }
325
+ #selectSuggestion(item) {
326
+ this.#addToken(item);
327
+ this._draft = ``;
328
+ this.#closePopup();
329
+ }
330
+ #emitChange() {
331
+ this.dispatchEvent(new CustomEvent(`ac-token-change`, {
332
+ detail: { tokens: this._tokens },
333
+ bubbles: true,
334
+ composed: true
335
+ }));
336
+ }
337
+ #closePopup() {
338
+ this._isOpen = false;
339
+ this._tickled.clearTickled();
340
+ }
341
+ #cancelPending() {
342
+ if (this.#debounceTimer !== void 0) {
343
+ clearTimeout(this.#debounceTimer);
344
+ this.#debounceTimer = void 0;
345
+ }
346
+ this.#abortController?.abort();
347
+ this.#abortController = void 0;
348
+ this._isLoading = false;
349
+ }
350
+ #scheduleSuggestionFetch(query) {
351
+ const provider = this.completionProvider ?? this.#staticProvider;
352
+ if (!provider) {
353
+ this._isOpen = false;
354
+ return;
355
+ }
356
+ if (this.#debounceTimer !== void 0) clearTimeout(this.#debounceTimer);
357
+ this._isOpen = true;
358
+ this.#debounceTimer = setTimeout(() => {
359
+ this.#fetchSuggestions(query, provider);
360
+ }, this.debounceMs);
361
+ }
362
+ #fetchSuggestions(query, provider) {
363
+ const cached = this.#cache.get(query);
364
+ if (cached !== void 0) {
365
+ this._suggestions = cached;
366
+ this._tickled.clearTickled();
367
+ this._isLoading = false;
368
+ return;
369
+ }
370
+ this.#abortController?.abort();
371
+ this.#abortController = new AbortController();
372
+ const { signal } = this.#abortController;
373
+ this._isLoading = true;
374
+ Promise.resolve(provider(query, signal)).then((results) => {
375
+ if (signal.aborted) return;
376
+ this.#cache.set(query, results);
377
+ this._suggestions = results;
378
+ this._tickled.clearTickled();
379
+ this._isLoading = false;
380
+ }).catch((err) => {
381
+ if (signal.aborted) return;
382
+ console.error(`[ixfx-ac-token] completionProvider error:`, err);
383
+ this._suggestions = [];
384
+ this._isLoading = false;
385
+ });
386
+ }
387
+ #scrollSuggestionIntoView() {
388
+ this.updateComplete.then(() => {
389
+ this.shadowRoot?.querySelector(`.suggestion.tickled`)?.scrollIntoView({ block: `nearest` });
390
+ });
391
+ }
392
+ #renderChip(item, index) {
393
+ return html`
394
+ <span
395
+ class="token-chip ${this._selectedTokenIndex === index ? `selected` : ``}"
396
+ title=${item.subLabel ?? nothing}
397
+ @pointerdown=${(e) => this.#onChipPointerDown(e, index)}
398
+ >
399
+ ${item.icon ? html`<ixfx-icon class="chip-icon" name=${item.icon}></ixfx-icon>` : nothing}
400
+ <span class="chip-label">${item.label}</span>
401
+ </span>
402
+ `;
403
+ }
404
+ #renderSuggestion(item, index) {
405
+ const isTickled = this._tickled.isTickled(index);
406
+ return html`
407
+ <div
408
+ class="suggestion ${isTickled ? `tickled` : ``}"
409
+ role="option"
410
+ id="ac-token-sugg-${index}"
411
+ aria-selected=${isTickled}
412
+ @pointerenter=${() => this._tickled.handlePointerEnter(index)}
413
+ @pointerdown=${(e) => this.#onSuggestionPointerDown(e, item)}
414
+ >
415
+ ${item.icon ? html`<ixfx-icon class="sugg-icon" name=${item.icon}></ixfx-icon>` : nothing}
416
+ <span class="sugg-label">${item.label}</span>
417
+ ${item.subLabel ? html`<span class="sugg-sublabel">${item.subLabel}</span>` : nothing}
418
+ </div>
419
+ `;
420
+ }
421
+ #renderPopup() {
422
+ const showEmpty = !this._isLoading && this._suggestions.length === 0;
423
+ return html`
424
+ <div
425
+ class="popup"
426
+ role="listbox"
427
+ aria-label="Suggestions"
428
+ data-input-mode=${this._tickled.inputMode}
429
+ @pointerleave=${(e) => this._tickled.handlePointerLeave(e)}
430
+ >
431
+ ${showEmpty ? html`<div class="no-results">No matching results</div>` : this._suggestions.map((item, i) => this.#renderSuggestion(item, i))}
432
+ </div>
433
+ `;
434
+ }
435
+ render() {
436
+ const tickledIdx = this._tickled.tickledId ?? -1;
437
+ const activeDescendant = tickledIdx >= 0 ? `ac-token-sugg-${tickledIdx}` : void 0;
438
+ const showPlaceholder = this._tokens.length === 0 ? this.placeholder || nothing : nothing;
439
+ return html`
440
+ <div class="wrapper" @click=${this.#onWrapperClick}>
441
+ ${this._tokens.map((t, i) => this.#renderChip(t, i))}
442
+ <input
443
+ type="text"
444
+ class="draft"
445
+ .value=${this._draft}
446
+ placeholder=${showPlaceholder}
447
+ autocomplete="off"
448
+ spellcheck="false"
449
+ role="combobox"
450
+ aria-autocomplete="list"
451
+ aria-expanded=${this._isOpen}
452
+ aria-activedescendant=${activeDescendant ?? nothing}
453
+ @input=${this.#onInput}
454
+ @keydown=${this.#onKeyDown}
455
+ @focus=${this.#onFocus}
456
+ @blur=${this.#onBlur}
457
+ @paste=${this.#onPaste}
458
+ >
459
+ ${this._isLoading ? html`<span class="spinner" aria-hidden="true"></span>` : nothing}
460
+ </div>
461
+ ${this._isOpen ? this.#renderPopup() : nothing}
462
+ `;
463
+ }
464
+ static {
465
+ this.styles = [tickledStyles, css`
466
+ :host {
467
+ display: block;
468
+ position: relative;
469
+ font-family: var(--font-family, system-ui, sans-serif);
470
+ font-size: var(--text-m, 12px);
471
+ color: var(--surface-2-text);
472
+ }
473
+
474
+ /* ---- Wrapper (looks like a text input) ---- */
475
+
476
+ .wrapper {
477
+ display: flex;
478
+ flex-wrap: wrap;
479
+ align-items: center;
480
+ gap: var(--ac-token-chip-gap, var(--space-xs, 3px));
481
+ padding: var(--ac-token-input-padding, var(--space-xs, 3px) var(--space-m, 8px));
482
+ background: var(--ac-token-input-background, var(--surface-3, var(--surface-2)));
483
+ color: var(--surface-2-text);
484
+ border: var(--ac-token-input-border, var(--border));
485
+ border-radius: var(--ac-token-input-border-radius, var(--radius-m, 4px));
486
+ cursor: text;
487
+ min-height: 32px;
488
+ box-sizing: border-box;
489
+ transition: border-color var(--transition, 0.15s ease-out);
490
+ }
491
+
492
+ .wrapper:focus-within {
493
+ border-color: var(--accent);
494
+ }
495
+
496
+ /* ---- Token chips ---- */
497
+
498
+ .token-chip {
499
+ display: inline-flex;
500
+ align-items: center;
501
+ gap: var(--space-xs, 3px);
502
+ padding: 1px var(--space-m, 8px);
503
+ background: var(--ac-token-chip-background, var(--surface-4));
504
+ border: var(--ac-token-chip-border, var(--border));
505
+ border-radius: var(--ac-token-chip-border-radius, var(--radius-s, 3px));
506
+ user-select: none;
507
+ cursor: default;
508
+ font-size: var(--text-s, 11px);
509
+ white-space: nowrap;
510
+ touch-action: none;
511
+ transition:
512
+ background var(--transition, 0.1s ease-out),
513
+ border-color var(--transition, 0.1s ease-out),
514
+ color var(--transition, 0.1s ease-out);
515
+ }
516
+
517
+ .token-chip.selected {
518
+ background: var(--ac-token-chip-selected-background, var(--accent));
519
+ color: var(--ac-token-chip-selected-color, var(--accent-text, #fff));
520
+ border-color: var(--accent);
521
+ }
522
+
523
+ .chip-icon {
524
+ flex-shrink: 0;
525
+ width: 1em;
526
+ height: 1em;
527
+ }
528
+
529
+ /* ---- Draft input ---- */
530
+
531
+ input.draft {
532
+ flex: 1;
533
+ min-width: 60px;
534
+ border: none;
535
+ background: transparent;
536
+ color: inherit;
537
+ font: inherit;
538
+ outline: none;
539
+ caret-color: var(--accent);
540
+ padding: 1px 0;
541
+ anchor-name: --ac-token-draft;
542
+ }
543
+
544
+ input.draft::placeholder {
545
+ color: var(--surface-muted-text);
546
+ }
547
+
548
+ /* ---- Spinner ---- */
549
+
550
+ .spinner {
551
+ width: 12px;
552
+ height: 12px;
553
+ border: 2px solid var(--surface-5);
554
+ border-top-color: var(--accent);
555
+ border-radius: 50%;
556
+ animation: ac-token-spin 0.7s linear infinite;
557
+ flex-shrink: 0;
558
+ pointer-events: none;
559
+ margin-left: var(--space-xs, 3px);
560
+ }
561
+
562
+ @keyframes ac-token-spin {
563
+ to { transform: rotate(360deg); }
564
+ }
565
+
566
+ /* ---- Popup ---- */
567
+
568
+ .popup {
569
+ position: fixed;
570
+ position-anchor: --ac-token-draft;
571
+ top: anchor(bottom);
572
+ left: anchor(left);
573
+ margin-top: 2px;
574
+ position-try-fallbacks: --ac-token-popup-above;
575
+ z-index: 200;
576
+ background: var(--surface-3, var(--surface-2));
577
+ border: var(--border);
578
+ border-radius: var(--radius-m, 4px);
579
+ box-shadow: var(--shadow-l, 0 4px 24px rgba(0, 0, 0, 0.5));
580
+ padding: var(--space-xs, 3px) 0;
581
+ max-height: 260px;
582
+ min-width: 160px;
583
+ overflow-y: auto;
584
+ font-size: var(--ac-token-popup-font-size, var(--text-s, 11px));
585
+ }
586
+
587
+ @position-try --ac-token-popup-above {
588
+ top: auto;
589
+ bottom: anchor(top);
590
+ left: anchor(left);
591
+ margin-top: 0;
592
+ margin-bottom: 2px;
593
+ }
594
+
595
+ /* ---- Suggestion items ---- */
596
+
597
+ .suggestion {
598
+ display: flex;
599
+ align-items: center;
600
+ gap: var(--space-m, 8px);
601
+ padding: var(--space-xs, 3px) var(--space-l, 12px);
602
+ cursor: pointer;
603
+ border-radius: var(--radius-s, 3px);
604
+ margin: 0 var(--space-xs, 3px);
605
+ transition: background var(--transition, 0.1s ease-out);
606
+ user-select: none;
607
+ white-space: nowrap;
608
+ min-height: 28px;
609
+ }
610
+
611
+ .suggestion.tickled {
612
+ background: var(--_item-focused-bg, var(--accent));
613
+ color: var(--accent-text, #fff);
614
+ }
615
+
616
+ .suggestion.tickled .sugg-sublabel {
617
+ color: color-mix(in srgb, var(--accent-text, #fff) 70%, transparent);
618
+ }
619
+
620
+ .sugg-icon {
621
+ flex-shrink: 0;
622
+ width: 1em;
623
+ height: 1em;
624
+ }
625
+
626
+ .sugg-label {
627
+ flex: 1;
628
+ overflow: hidden;
629
+ text-overflow: ellipsis;
630
+ }
631
+
632
+ .sugg-sublabel {
633
+ flex-shrink: 0;
634
+ margin-left: auto;
635
+ color: var(--surface-muted-text);
636
+ font-size: var(--text-s, 11px);
637
+ }
638
+
639
+ /* ---- Empty state ---- */
640
+
641
+ .no-results {
642
+ padding: var(--space-m, 8px) var(--space-l, 12px);
643
+ color: var(--surface-muted-text);
644
+ font-style: italic;
645
+ }
646
+ `];
647
+ }
648
+ };
649
+ __decorate([property({ type: Object })], AcTokenElement.prototype, "completionProvider", void 0);
650
+ __decorate([property({ type: Object })], AcTokenElement.prototype, "tokenizer", void 0);
651
+ __decorate([property({ type: String })], AcTokenElement.prototype, "placeholder", void 0);
652
+ __decorate([property({
653
+ type: Number,
654
+ attribute: `cache-size`
655
+ })], AcTokenElement.prototype, "cacheSize", void 0);
656
+ __decorate([property({
657
+ type: Number,
658
+ attribute: `debounce-ms`
659
+ })], AcTokenElement.prototype, "debounceMs", void 0);
660
+ __decorate([property({ type: Boolean })], AcTokenElement.prototype, "strict", void 0);
661
+ __decorate([state()], AcTokenElement.prototype, "_tokens", void 0);
662
+ __decorate([state()], AcTokenElement.prototype, "_draft", void 0);
663
+ __decorate([state()], AcTokenElement.prototype, "_selectedTokenIndex", void 0);
664
+ __decorate([state()], AcTokenElement.prototype, "_suggestions", void 0);
665
+ __decorate([state()], AcTokenElement.prototype, "_isOpen", void 0);
666
+ __decorate([state()], AcTokenElement.prototype, "_isLoading", void 0);
667
+ AcTokenElement = __decorate([safeCustomElement(`ixfx-ac-token`)], AcTokenElement);
668
+ //#endregion
50
669
  //#region src/button/radio-group.ts
51
670
  let RadioGroup = class RadioGroup extends LitElement {
52
671
  constructor(..._args) {
@@ -5967,7 +6586,9 @@ TooltipElement = _TooltipElement = __decorate([safeCustomElement(`ixfx-tooltip`)
5967
6586
  //#endregion
5968
6587
  //#region src/vertical-list/vertical-list.ts
5969
6588
  const ITEM_SELECTOR = `li, [data-list-item]`;
5970
- const isMultiMode = (mode) => mode === `checked` || mode === `vscode` || mode === `standard`;
6589
+ function isMultiMode(mode) {
6590
+ return mode === `checked` || mode === `vscode` || mode === `standard`;
6591
+ }
5971
6592
  let VerticalListElement = class VerticalListElement extends LitElement {
5972
6593
  constructor(..._args) {
5973
6594
  super(..._args);
@@ -6120,6 +6741,14 @@ let VerticalListElement = class VerticalListElement extends LitElement {
6120
6741
  this._clearSelection();
6121
6742
  }
6122
6743
  }
6744
+ /** The most recently selected item, or `undefined` if nothing is selected. */
6745
+ get selectedItem() {
6746
+ return [...this._selectedItems].at(-1);
6747
+ }
6748
+ /** The full current selection set (read-only). */
6749
+ get selectedItems() {
6750
+ return this._selectedItems;
6751
+ }
6123
6752
  addItem(item) {
6124
6753
  if (typeof item === `string`) {
6125
6754
  const li = document.createElement(`li`);
@@ -6140,6 +6769,19 @@ let VerticalListElement = class VerticalListElement extends LitElement {
6140
6769
  select(item) {
6141
6770
  this._replaceSelection(item);
6142
6771
  }
6772
+ selectMany(items) {
6773
+ if (this.selectionMode !== `multiple`) throw new Error(`selectMany requires selectionMode="multiple" (current: "${this.selectionMode}")`);
6774
+ const previous = this._selectedItems;
6775
+ const next = new Set(items);
6776
+ if (next.size === 0) return;
6777
+ this._selectedItems = next;
6778
+ this.#selectionAnchor = [...next].at(-1);
6779
+ this._syncItemStates();
6780
+ this._dispatch(`list-select`, {
6781
+ selected: next,
6782
+ previous
6783
+ });
6784
+ }
6143
6785
  deselect(item) {
6144
6786
  if (!this._selectedItems.has(item)) return;
6145
6787
  const previous = this._selectedItems;
@@ -6271,7 +6913,7 @@ let VerticalListElement = class VerticalListElement extends LitElement {
6271
6913
  if (this.interactionMode === `checked`) el.toggleAttribute(`data-checked`, this._selectedItems.has(el));
6272
6914
  else el.removeAttribute(`data-checked`);
6273
6915
  }
6274
- this.dataset[`inputMode`] = this.tickled.inputMode;
6916
+ this.dataset.inputMode = this.tickled.inputMode;
6275
6917
  this._syncCheckboxes();
6276
6918
  }
6277
6919
  _syncCheckboxes() {
@@ -6516,6 +7158,6 @@ function init() {
6516
7158
  console.log(`Init`);
6517
7159
  }
6518
7160
  //#endregion
6519
- export { AcTextElement, ButtonElement, Checkbox, ColourPicker, ColourPickerPopup, CrumbNavigationElement, CrumbPathController, CrumbPathElement, DataDisplayComponent, EditableLabel, EditableNumber, ICON_CARET_RIGHT, ICON_CHECK, ICON_CHEVRON_DOWN, ICON_CLOSE, IncrSearchTreeController as IncrSearchMillerController, IncrSearchTreeController, IxfxHexEditorElement, IxfxIconElement, IxfxTimelineElement, LabelledRadialInput, LabelledRangeInput, LedElement, menu_exports as Menu, MillerBaseElement, MillerListElement, MillerTreeController, NarrowedTextElement, PanelElement, PanelGroupElement, PlotDataSeries, PlotSingleAxis, PlotXyAxis, PolarPad, RadialInputElement, RadioGroup, RangeElement, RangeInput, RangeMultiElement, SelectHorizontalElement, SnapContainer, SplitButton, SplitLayoutElement, SwipeElement, TabListElement, TabListItemElement, TabPanelElement, TabPanelsElement, TimelineController, TimelineTrackTabElement, TooltipElement, TransitoryLabelElement, TreeBaseElement, TreeController, TreeDataModel, TreeListElement, VerticalListElement, XyPad, applyAgeModification, applyHighlights, attachTimelineInteractions, buildHighlightTargets, clearHighlights, computeColour, createAcCompletionProvider, createElementIncrSearch, createFuzzySearch, createIncrSearch, getIcon, hasIcon, iconBus, init, monitorIndeterminate, parseColourScaleAttr, readBaseColour, registerIcon, resolveCssVars, resolveGrid, svgToDataUri, timelineStyles };
7161
+ export { AcTextElement, AcTokenElement, ButtonElement, Checkbox, ColourPicker, ColourPickerPopup, CrumbNavigationElement, CrumbPathController, CrumbPathElement, DataDisplayComponent, EditableLabel, EditableNumber, ICON_CARET_RIGHT, ICON_CHECK, ICON_CHEVRON_DOWN, ICON_CLOSE, IncrSearchTreeController as IncrSearchMillerController, IncrSearchTreeController, IxfxHexEditorElement, IxfxIconElement, IxfxTimelineElement, LabelledRadialInput, LabelledRangeInput, LedElement, menu_exports as Menu, MillerBaseElement, MillerListElement, MillerTreeController, NarrowedTextElement, PanelElement, PanelGroupElement, PlotDataSeries, PlotSingleAxis, PlotXyAxis, PolarPad, RadialInputElement, RadioGroup, RangeElement, RangeInput, RangeMultiElement, SelectHorizontalElement, SnapContainer, SplitButton, SplitLayoutElement, SwipeElement, TabListElement, TabListItemElement, TabPanelElement, TabPanelsElement, TimelineController, TimelineTrackTabElement, TooltipElement, TransitoryLabelElement, TreeBaseElement, TreeController, TreeDataModel, TreeListElement, VerticalListElement, XyPad, applyAgeModification, applyHighlights, attachTimelineInteractions, buildHighlightTargets, clearHighlights, computeColour, createAcCompletionProvider, createElementIncrSearch, createFuzzySearch, createIncrSearch, getIcon, hasIcon, iconBus, init, monitorIndeterminate, parseColourScaleAttr, readBaseColour, registerIcon, resolveCssVars, resolveGrid, svgToDataUri, timelineStyles };
6520
7162
 
6521
7163
  //# sourceMappingURL=index.js.map