@ixfx/components 0.6.2 → 0.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (181) hide show
  1. package/bundle/index.d.ts +1918 -835
  2. package/bundle/index.d.ts.map +1 -1
  3. package/bundle/index.js +22137 -16840
  4. package/bundle/index.js.map +1 -1
  5. package/bundle/style.css +1 -1
  6. package/dist/ac-text.d.ts +1 -1
  7. package/dist/ac-text.js +3 -2
  8. package/dist/ac-text.js.map +1 -1
  9. package/dist/{ac-token-BAa6ke09.d.ts → ac-token--_vCHXWw.d.ts} +2 -2
  10. package/dist/{ac-token-BAa6ke09.d.ts.map → ac-token--_vCHXWw.d.ts.map} +1 -1
  11. package/dist/ac-token.d.ts +1 -1
  12. package/dist/ac-token.js +3 -2
  13. package/dist/ac-token.js.map +1 -1
  14. package/dist/{button-Bn0BuLpO.js → button-DsFbV4XD.js} +5 -4
  15. package/dist/button-DsFbV4XD.js.map +1 -0
  16. package/dist/button.d.ts.map +1 -1
  17. package/dist/button.js +1 -1
  18. package/dist/checkbox.js +1 -1
  19. package/dist/{colour-picker-0stHB90J.js → colour-picker-Ddsk-7E_.js} +4 -3
  20. package/dist/{colour-picker-0stHB90J.js.map → colour-picker-Ddsk-7E_.js.map} +1 -1
  21. package/dist/colour-picker.js +1 -1
  22. package/dist/crumbs.d.ts +1 -1
  23. package/dist/crumbs.js +4 -2
  24. package/dist/crumbs.js.map +1 -1
  25. package/dist/data-display.js +1 -1
  26. package/dist/{data-grid-C8qIo1-u.d.ts → data-grid-Bh4YrQGK.d.ts} +2 -2
  27. package/dist/{data-grid-C8qIo1-u.d.ts.map → data-grid-Bh4YrQGK.d.ts.map} +1 -1
  28. package/dist/data-grid.d.ts +1 -1
  29. package/dist/data-grid.js +4 -2
  30. package/dist/data-grid.js.map +1 -1
  31. package/dist/{defaults-BCiDhZbF.js → defaults-BJwDsMH4.js} +27 -20
  32. package/dist/defaults-BJwDsMH4.js.map +1 -0
  33. package/dist/editable-label-rzXkjf1H.d.ts +75 -0
  34. package/dist/editable-label-rzXkjf1H.d.ts.map +1 -0
  35. package/dist/editable-label.d.ts +2 -75
  36. package/dist/editable-label.js +2 -1
  37. package/dist/editable-label.js.map +1 -1
  38. package/dist/{fallbacks-DEE1nCTt.js → fallbacks-DNI9xt0F.js} +2 -2
  39. package/dist/{fallbacks-DEE1nCTt.js.map → fallbacks-DNI9xt0F.js.map} +1 -1
  40. package/dist/{grouped-item-lister-_pMDwIo1.d.ts → grouped-item-lister-DnWB-eFT.d.ts} +2 -2
  41. package/dist/{grouped-item-lister-_pMDwIo1.d.ts.map → grouped-item-lister-DnWB-eFT.d.ts.map} +1 -1
  42. package/dist/grouped-item-lister.d.ts +1 -1
  43. package/dist/{hex-editor-Bk6rxhfg.js → hex-editor-BiRfwTz1.js} +2 -2
  44. package/dist/{hex-editor-Bk6rxhfg.js.map → hex-editor-BiRfwTz1.js.map} +1 -1
  45. package/dist/hex.js +1 -1
  46. package/dist/{icon-DpA9x2Ve.d.ts → icon-CDGprSdE.d.ts} +1 -12
  47. package/dist/icon-CDGprSdE.d.ts.map +1 -0
  48. package/dist/{icons-Bm2ByQ3s.js → icon-DcEEGQa_.js} +38 -12
  49. package/dist/icon-DcEEGQa_.js.map +1 -0
  50. package/dist/icons.d.ts +3 -3
  51. package/dist/icons.js +9 -3
  52. package/dist/icons.js.map +1 -0
  53. package/dist/{index-CKtLhgYj.d.ts → index-9AhaHIT2.d.ts} +3 -3
  54. package/dist/{index-CKtLhgYj.d.ts.map → index-9AhaHIT2.d.ts.map} +1 -1
  55. package/dist/index-CG2vIgPv.d.ts +101 -0
  56. package/dist/index-CG2vIgPv.d.ts.map +1 -0
  57. package/dist/{index-BtGFYfaK.d.ts → index-CS9yM8L-.d.ts} +14 -4
  58. package/dist/index-CS9yM8L-.d.ts.map +1 -0
  59. package/dist/index.d.ts +861 -71
  60. package/dist/index.d.ts.map +1 -1
  61. package/dist/index.js +4257 -931
  62. package/dist/index.js.map +1 -1
  63. package/dist/interaction-D5XdKzbR.js +2 -0
  64. package/dist/labelled-radial-input.js +2 -1
  65. package/dist/labelled-radial-input.js.map +1 -1
  66. package/dist/labelled-slider-input-DzigjMwP.js +808 -0
  67. package/dist/labelled-slider-input-DzigjMwP.js.map +1 -0
  68. package/dist/labelled-slider-input.d.ts +2 -0
  69. package/dist/labelled-slider-input.js +2 -0
  70. package/dist/{types-DlVNJez_.d.ts → list-selection-types-DSuRNWpx.d.ts} +10 -2
  71. package/dist/list-selection-types-DSuRNWpx.d.ts.map +1 -0
  72. package/dist/menu-CXDFJxNm.js +825 -0
  73. package/dist/menu-CXDFJxNm.js.map +1 -0
  74. package/dist/{menu-item-Bs2MYyHq.d.ts → menu-item-CZi9vy5O.d.ts} +4 -2
  75. package/dist/menu-item-CZi9vy5O.d.ts.map +1 -0
  76. package/dist/menu-item-D2S4i8u1.js +809 -0
  77. package/dist/menu-item-D2S4i8u1.js.map +1 -0
  78. package/dist/menu.d.ts +2 -2
  79. package/dist/menu.js +2 -1
  80. package/dist/miller.d.ts +1 -1
  81. package/dist/miller.js +3 -2
  82. package/dist/miller.js.map +1 -1
  83. package/dist/narrowed-text.js +4 -2
  84. package/dist/narrowed-text.js.map +1 -1
  85. package/dist/notification-pill-DyZydXoZ.d.ts.map +1 -1
  86. package/dist/notifier.js +4 -3
  87. package/dist/notifier.js.map +1 -1
  88. package/dist/panel.d.ts +13 -13
  89. package/dist/panel.d.ts.map +1 -1
  90. package/dist/panel.js +37 -253
  91. package/dist/panel.js.map +1 -1
  92. package/dist/plots.js +1 -1
  93. package/dist/polar-pad.js +1 -1
  94. package/dist/{radial-input-Dk8Wydp5.js → radial-input-Dp5qz0ly.js} +2 -2
  95. package/dist/{radial-input-Dk8Wydp5.js.map → radial-input-Dp5qz0ly.js.map} +1 -1
  96. package/dist/radial-input.js +1 -1
  97. package/dist/range-input.js +1 -1
  98. package/dist/range.js +1 -1
  99. package/dist/registry-BEtb8_wB.js +46 -0
  100. package/dist/registry-BEtb8_wB.js.map +1 -0
  101. package/dist/select-horiz.js +3 -2
  102. package/dist/select-horiz.js.map +1 -1
  103. package/dist/{slider-input-XppH3vcy.d.ts → slider-input-BfRUW2ZB.d.ts} +16 -3
  104. package/dist/slider-input-BfRUW2ZB.d.ts.map +1 -0
  105. package/dist/{slider-input-CT4gcF-o.js → slider-input-De4eoT11.js} +382 -67
  106. package/dist/slider-input-De4eoT11.js.map +1 -0
  107. package/dist/slider-input.d.ts +1 -1
  108. package/dist/slider-input.js +1 -1
  109. package/dist/snackbar.js +1 -1
  110. package/dist/split-layout-BFSbUZQv.js +969 -0
  111. package/dist/split-layout-BFSbUZQv.js.map +1 -0
  112. package/dist/split-layout-JK3xWVX2.d.ts +179 -0
  113. package/dist/split-layout-JK3xWVX2.d.ts.map +1 -0
  114. package/dist/split-layout.d.ts +2 -60
  115. package/dist/split-layout.js +1 -617
  116. package/dist/style.css +1 -1
  117. package/dist/swipe.js +1 -1
  118. package/dist/{tab-list-D_1cYhB_.d.ts → tab-list-CGyPt07Z.d.ts} +10 -2
  119. package/dist/tab-list-CGyPt07Z.d.ts.map +1 -0
  120. package/dist/tabs.d.ts +1 -1
  121. package/dist/tabs.js +128 -27
  122. package/dist/tabs.js.map +1 -1
  123. package/dist/{tickled-controller-BtevrRLV.d.ts → tickled-controller-CRzdIEjJ.d.ts} +7 -1
  124. package/dist/tickled-controller-CRzdIEjJ.d.ts.map +1 -0
  125. package/dist/{tickled-controller-DkAU-0qL.js → tickled-controller-h9GmJ_bU.js} +8 -2
  126. package/dist/tickled-controller-h9GmJ_bU.js.map +1 -0
  127. package/dist/titlebar-Bj5pfdw_.d.ts +50 -0
  128. package/dist/titlebar-Bj5pfdw_.d.ts.map +1 -0
  129. package/dist/titlebar.d.ts +2 -0
  130. package/dist/titlebar.js +324 -0
  131. package/dist/titlebar.js.map +1 -0
  132. package/dist/tooltip-BlvBUQxx.d.ts.map +1 -1
  133. package/dist/{tree-BO6BXI2b.js → tree-Ch4W8qXQ.js} +4 -3
  134. package/dist/{tree-BO6BXI2b.js.map → tree-Ch4W8qXQ.js.map} +1 -1
  135. package/dist/tree.d.ts +1 -1
  136. package/dist/tree.js +1 -1
  137. package/dist/vertical-list-ClnqTkF3.js +814 -0
  138. package/dist/vertical-list-ClnqTkF3.js.map +1 -0
  139. package/dist/vertical-list.d.ts +8 -9
  140. package/dist/vertical-list.d.ts.map +1 -1
  141. package/dist/vertical-list.js +1 -736
  142. package/dist/{xy-axis-B6yMjckW.js → xy-axis-DWizs0bt.js} +109 -3
  143. package/dist/xy-axis-DWizs0bt.js.map +1 -0
  144. package/dist/xy-pad.js +1 -1
  145. package/docs-user/README.md +5 -0
  146. package/docs-user/detail-list.md +398 -0
  147. package/docs-user/dock.md +461 -0
  148. package/docs-user/icons.md +4 -0
  149. package/docs-user/index.json +28 -3
  150. package/docs-user/labelled-slider-input.md +198 -0
  151. package/docs-user/llms.txt +6 -1
  152. package/docs-user/panel.md +20 -1
  153. package/docs-user/slider-input.md +55 -15
  154. package/docs-user/split-layout.md +136 -170
  155. package/docs-user/tabs.md +54 -0
  156. package/docs-user/titlebar.md +102 -0
  157. package/docs-user/toolbar.md +95 -22
  158. package/docs-user/twosplit-layout.md +254 -0
  159. package/docs-user/user-catalog.md +8 -1
  160. package/docs-user/user-theming.md +109 -0
  161. package/llms.txt +6 -1
  162. package/package.json +1 -2
  163. package/dist/button-Bn0BuLpO.js.map +0 -1
  164. package/dist/defaults-BCiDhZbF.js.map +0 -1
  165. package/dist/editable-label.d.ts.map +0 -1
  166. package/dist/icon-DpA9x2Ve.d.ts.map +0 -1
  167. package/dist/icons-Bm2ByQ3s.js.map +0 -1
  168. package/dist/index-BtGFYfaK.d.ts.map +0 -1
  169. package/dist/menu-DIfU70AA.js +0 -1609
  170. package/dist/menu-DIfU70AA.js.map +0 -1
  171. package/dist/menu-item-Bs2MYyHq.d.ts.map +0 -1
  172. package/dist/slider-input-CT4gcF-o.js.map +0 -1
  173. package/dist/slider-input-XppH3vcy.d.ts.map +0 -1
  174. package/dist/split-layout.d.ts.map +0 -1
  175. package/dist/split-layout.js.map +0 -1
  176. package/dist/tab-list-D_1cYhB_.d.ts.map +0 -1
  177. package/dist/tickled-controller-BtevrRLV.d.ts.map +0 -1
  178. package/dist/tickled-controller-DkAU-0qL.js.map +0 -1
  179. package/dist/types-DlVNJez_.d.ts.map +0 -1
  180. package/dist/vertical-list.js.map +0 -1
  181. package/dist/xy-axis-B6yMjckW.js.map +0 -1
@@ -1,737 +1,2 @@
1
- import { t as TickledController } from "./tickled-controller-DkAU-0qL.js";
2
- import { t as themeFallbacks } from "./fallbacks-DEE1nCTt.js";
3
- import { n as safeCustomElement, t as __decorate } from "./decorate-VRK8rslU.js";
4
- import { t as createElementIncrSearch } from "./element-search-Y8SRfPGM.js";
5
- import { LitElement, css, html, render } from "lit";
6
- import { property, query, state } from "lit/decorators.js";
7
- //#region src/vertical-list/vertical-list.ts
8
- const ITEM_SELECTOR = `li, [data-list-item]`;
9
- function isMultiMode(mode) {
10
- return mode === `checked` || mode === `sticky` || mode === `vscode` || mode === `standard`;
11
- }
12
- let VerticalListElement = class VerticalListElement extends LitElement {
13
- constructor(..._args2) {
14
- super(..._args2);
15
- this.selectionMode = `single`;
16
- this.interactionMode = `standard`;
17
- this._selectedItems = /* @__PURE__ */ new Set();
18
- this._searchVisible = false;
19
- this._searchQuery = ``;
20
- this.#customWrappers = /* @__PURE__ */ new Map();
21
- this.#wrappedElements = /* @__PURE__ */ new Set();
22
- this.tickled = new TickledController(this, {
23
- getItems: () => this._getVisibleItems().map((el) => ({
24
- id: el,
25
- enabled: true
26
- })),
27
- onTickle: (id) => {
28
- if (id !== void 0) this._dispatch(`list-tickle`, { item: id });
29
- },
30
- onStateChange: () => this._syncItemStates()
31
- });
32
- this._onPointerOver = (e) => {
33
- const item = this._findListItem(e.composedPath());
34
- if (item) this.tickled.handlePointerEnter(item);
35
- };
36
- this._onPointerLeave = (e) => {
37
- this.tickled.handlePointerLeave(e);
38
- };
39
- this._onKeyDown = (e) => {
40
- if ((e.ctrlKey || e.metaKey) && e.key === `f`) {
41
- e.preventDefault();
42
- this._openSearch();
43
- return;
44
- }
45
- if ((e.ctrlKey || e.metaKey) && e.key === `a`) {
46
- if ((this.selectionMode === `multiple` || isMultiMode(this.interactionMode)) && this.selectionMode !== `none`) {
47
- e.preventDefault();
48
- this._selectAll();
49
- }
50
- return;
51
- }
52
- if (this._searchVisible) return;
53
- switch (e.key) {
54
- case `ArrowDown`:
55
- e.preventDefault();
56
- this.tickled.handleKeyboardNavigation(`next`);
57
- if (e.shiftKey && this.interactionMode === `vscode`) {
58
- const cur = this.tickled.tickledId;
59
- if (cur) this._rangeSelectTo(cur);
60
- }
61
- break;
62
- case `ArrowUp`:
63
- e.preventDefault();
64
- this.tickled.handleKeyboardNavigation(`previous`);
65
- if (e.shiftKey && this.interactionMode === `vscode`) {
66
- const cur = this.tickled.tickledId;
67
- if (cur) this._rangeSelectTo(cur);
68
- }
69
- break;
70
- case `Enter`: {
71
- const id = this.tickled.tickledId;
72
- if (id) {
73
- e.preventDefault();
74
- this._dispatch(`list-item-click`, { item: id });
75
- this._activateItem(id);
76
- }
77
- break;
78
- }
79
- case ` `: {
80
- const id = this.tickled.tickledId;
81
- if (id) {
82
- e.preventDefault();
83
- this._handleSpaceKey(id);
84
- }
85
- break;
86
- }
87
- case `Escape`: this._clearSelection();
88
- }
89
- };
90
- this._onClick = (e) => {
91
- const item = this._findListItem(e.composedPath());
92
- if (!item) return;
93
- this._dispatch(`list-item-click`, { item });
94
- this._handleClickSelection(item, e);
95
- };
96
- this._onDblClick = (e) => {
97
- const item = this._findListItem(e.composedPath());
98
- if (item) this._activateItem(item);
99
- };
100
- this._onSearchInput = (e) => {
101
- const input = e.target;
102
- this._searchQuery = input.value;
103
- this.#search?.setQuery(this._searchQuery);
104
- };
105
- this._onSearchKeydown = (e) => {
106
- if (e.key === `Escape`) {
107
- e.stopPropagation();
108
- this._closeSearch();
109
- } else if (e.key === `ArrowDown`) {
110
- e.preventDefault();
111
- this.tickled.handleKeyboardNavigation(`next`);
112
- } else if (e.key === `ArrowUp`) {
113
- e.preventDefault();
114
- this.tickled.handleKeyboardNavigation(`previous`);
115
- } else if (e.key === `Enter`) {
116
- e.preventDefault();
117
- e.stopPropagation();
118
- const id = this.tickled.tickledId ?? this._getVisibleItems()[0];
119
- if (id) {
120
- this._dispatch(`list-item-click`, { item: id });
121
- this._activateItem(id);
122
- this._closeSearch();
123
- }
124
- }
125
- };
126
- }
127
- #search;
128
- #selectionAnchor;
129
- #customWrappers;
130
- #wrappedElements;
131
- connectedCallback() {
132
- super.connectedCallback();
133
- if (!this.hasAttribute(`tabindex`)) this.tabIndex = 0;
134
- this.addEventListener(`pointerover`, this._onPointerOver);
135
- this.addEventListener(`pointerleave`, this._onPointerLeave);
136
- this.addEventListener(`keydown`, this._onKeyDown);
137
- this.addEventListener(`click`, this._onClick);
138
- this.addEventListener(`dblclick`, this._onDblClick);
139
- }
140
- disconnectedCallback() {
141
- super.disconnectedCallback();
142
- this.removeEventListener(`pointerover`, this._onPointerOver);
143
- this.removeEventListener(`pointerleave`, this._onPointerLeave);
144
- this.removeEventListener(`keydown`, this._onKeyDown);
145
- this.removeEventListener(`click`, this._onClick);
146
- this.removeEventListener(`dblclick`, this._onDblClick);
147
- this.#search?.dispose();
148
- this.#search = void 0;
149
- }
150
- firstUpdated() {
151
- this.#search = createElementIncrSearch({
152
- container: this,
153
- itemSelector: ITEM_SELECTOR,
154
- getLabel: (el) => el.getAttribute(`data-search-label`) ?? el.textContent?.trim() ?? ``,
155
- getKey: (el) => el.getAttribute(`data-key`) ?? el.getAttribute(`data-search-label`) ?? el.textContent?.trim() ?? ``,
156
- highlightKey: `vertical-list-search`
157
- });
158
- }
159
- updated(changed) {
160
- super.updated(changed);
161
- if (changed.has(`interactionMode`)) {
162
- this.#selectionAnchor = void 0;
163
- const previousSelected = this._selectedItems;
164
- const savedWrappers = changed.get(`interactionMode`) === `checked` ? new Map(this.#customWrappers) : null;
165
- this._syncCheckboxes();
166
- if (previousSelected.size > 0) {
167
- let remapped;
168
- if (savedWrappers && savedWrappers.size > 0) remapped = new Set([...previousSelected].map((el) => savedWrappers.get(el) ?? el));
169
- else if (this.#customWrappers.size > 0) {
170
- const innerToWrapper = new Map([...this.#customWrappers].map(([w, i]) => [i, w]));
171
- remapped = new Set([...previousSelected].map((el) => innerToWrapper.get(el) ?? el));
172
- } else remapped = new Set(previousSelected);
173
- this._selectedItems = remapped;
174
- }
175
- this._syncItemStates();
176
- } else if (changed.has(`checkboxRenderer`) && this.interactionMode === `checked`) this._syncCheckboxes();
177
- }
178
- /** The most recently selected item, or `undefined` if nothing is selected. */
179
- get selectedItem() {
180
- return [...this._selectedItems].at(-1);
181
- }
182
- /** The full current selection set (read-only). */
183
- get selectedItems() {
184
- return this._selectedItems;
185
- }
186
- addItem(item, options) {
187
- let el;
188
- if (typeof item === `string`) {
189
- const li = document.createElement(`li`);
190
- li.textContent = item;
191
- el = li;
192
- } else el = item;
193
- if (options?.notChecked) el.setAttribute(`not-checked`, ``);
194
- this.appendChild(el);
195
- if (this.interactionMode === `checked`) this._syncCheckboxes();
196
- }
197
- removeItem(item) {
198
- item.remove();
199
- }
200
- clearItems() {
201
- this.#customWrappers.clear();
202
- this.replaceChildren();
203
- this.#selectionAnchor = void 0;
204
- this._selectedItems = /* @__PURE__ */ new Set();
205
- this._syncItemStates();
206
- }
207
- /**
208
- * Replace the entire item list in one call.
209
- * Equivalent to `clearItems()` followed by `addItem()` for each element.
210
- * Preserves `interactionMode` checkbox wrapping.
211
- */
212
- setItems(items) {
213
- this.clearItems();
214
- for (const item of items) this.appendChild(item);
215
- if (this.interactionMode === `checked`) this._syncCheckboxes();
216
- }
217
- /**
218
- * Dispatch a command to this list. No-op by default.
219
- * Intended for use with `ixfx-grouped-item-lister`'s `dispatch()` method,
220
- * which forwards commands to all sub-components.
221
- */
222
- dispatch(_commandId, _args) {}
223
- select(item) {
224
- this._replaceSelection(item);
225
- }
226
- selectMany(items) {
227
- if (this.selectionMode !== `multiple`) throw new Error(`selectMany requires selectionMode="multiple" (current: "${this.selectionMode}")`);
228
- const previous = this._selectedItems;
229
- const next = new Set([...items].filter((el) => this._isCheckable(el)));
230
- if (next.size === 0) return;
231
- this._selectedItems = next;
232
- this.#selectionAnchor = [...next].at(-1);
233
- this._syncItemStates();
234
- this._dispatch(`list-select`, {
235
- selected: next,
236
- previous
237
- });
238
- }
239
- deselect(item) {
240
- if (!this._selectedItems.has(item)) return;
241
- const previous = this._selectedItems;
242
- const next = new Set(this._selectedItems);
243
- next.delete(item);
244
- this._selectedItems = next;
245
- this._syncItemStates();
246
- this._dispatch(`list-select`, {
247
- selected: next,
248
- previous
249
- });
250
- }
251
- clearSelection() {
252
- this._clearSelection();
253
- }
254
- selectAll() {
255
- if ((this.selectionMode === `multiple` || isMultiMode(this.interactionMode)) && this.selectionMode !== `none`) this._selectAll();
256
- }
257
- *selectedFilter(kind) {
258
- const wanted = (el) => {
259
- switch (kind) {
260
- case `selected`: return el.hasAttribute(`data-selected`);
261
- case `checked`: return el.hasAttribute(`data-checked`);
262
- case `either`: return el.hasAttribute(`data-selected`) || el.hasAttribute(`data-checked`);
263
- }
264
- };
265
- for (const el of this.querySelectorAll(ITEM_SELECTOR)) {
266
- if (this.#wrappedElements.has(el)) continue;
267
- if (el.hidden) continue;
268
- if (wanted(el)) yield el;
269
- }
270
- }
271
- _replaceSelection(item) {
272
- if (this.selectionMode === `none`) return;
273
- if (!this._isCheckable(item)) return;
274
- const previous = this._selectedItems;
275
- const next = /* @__PURE__ */ new Set([item]);
276
- this._selectedItems = next;
277
- this.#selectionAnchor = item;
278
- this._syncItemStates();
279
- this._dispatch(`list-select`, {
280
- selected: next,
281
- previous
282
- });
283
- }
284
- _toggleItem(item) {
285
- if (!this._isCheckable(item)) return;
286
- const effectiveMultiple = this.selectionMode === `multiple` || isMultiMode(this.interactionMode);
287
- if (this.selectionMode === `none` && this.interactionMode !== `checked` && this.interactionMode !== `sticky`) return;
288
- const previous = this._selectedItems;
289
- const next = new Set(this._selectedItems);
290
- if (next.has(item)) next.delete(item);
291
- else {
292
- if (!effectiveMultiple) next.clear();
293
- next.add(item);
294
- }
295
- this._selectedItems = next;
296
- this._syncItemStates();
297
- this._dispatch(`list-select`, {
298
- selected: next,
299
- previous
300
- });
301
- }
302
- _rangeSelectTo(item) {
303
- if (this.selectionMode === `none`) return;
304
- if (!this.#selectionAnchor) {
305
- this._replaceSelection(item);
306
- return;
307
- }
308
- const visible = this._getVisibleItems();
309
- const anchorIdx = visible.indexOf(this.#selectionAnchor);
310
- const targetIdx = visible.indexOf(item);
311
- if (anchorIdx === -1 || targetIdx === -1) {
312
- this._replaceSelection(item);
313
- return;
314
- }
315
- const start = Math.min(anchorIdx, targetIdx);
316
- const end = Math.max(anchorIdx, targetIdx);
317
- const previous = this._selectedItems;
318
- const next = new Set(visible.slice(start, end + 1).filter((el) => this._isCheckable(el)));
319
- this._selectedItems = next;
320
- this._syncItemStates();
321
- this._dispatch(`list-select`, {
322
- selected: next,
323
- previous
324
- });
325
- }
326
- _clearSelection() {
327
- if (this._selectedItems.size === 0) return;
328
- const previous = this._selectedItems;
329
- this._selectedItems = /* @__PURE__ */ new Set();
330
- this._syncItemStates();
331
- this._dispatch(`list-select`, {
332
- selected: /* @__PURE__ */ new Set(),
333
- previous
334
- });
335
- }
336
- _selectAll() {
337
- const visible = this._getVisibleItems();
338
- if (visible.length === 0) return;
339
- const previous = this._selectedItems;
340
- const next = new Set(visible.filter((el) => this._isCheckable(el)));
341
- if (next.size === 0) return;
342
- this._selectedItems = next;
343
- this._syncItemStates();
344
- this._dispatch(`list-select`, {
345
- selected: next,
346
- previous
347
- });
348
- }
349
- _handleClickSelection(item, e) {
350
- const mode = this.interactionMode;
351
- if (mode === `manual`) return;
352
- if (this.selectionMode === `none` && mode !== `checked` && mode !== `sticky`) return;
353
- switch (mode) {
354
- case `implicit`:
355
- this._replaceSelection(item);
356
- break;
357
- case `standard`:
358
- case `vscode`:
359
- if (e.ctrlKey || e.metaKey) {
360
- if (this.selectionMode === `multiple` || mode === `vscode`) this._toggleItem(item);
361
- } else if (e.shiftKey && (this.selectionMode === `multiple` || mode === `vscode`)) this._rangeSelectTo(item);
362
- else this._replaceSelection(item);
363
- break;
364
- case `checked`: break;
365
- case `sticky`: this._toggleItem(item);
366
- }
367
- }
368
- _handleSpaceKey(item) {
369
- const mode = this.interactionMode;
370
- if (mode === `manual`) return;
371
- if (mode === `implicit`) this._replaceSelection(item);
372
- else this._toggleItem(item);
373
- }
374
- _getVisibleItems() {
375
- return Array.from(this.querySelectorAll(ITEM_SELECTOR)).filter((el) => {
376
- if (this.#wrappedElements.has(el)) return false;
377
- if (el.hidden) return false;
378
- if (this.filterPredicate && !this.filterPredicate(el)) return false;
379
- return true;
380
- });
381
- }
382
- _isCheckable(item) {
383
- if (this.interactionMode !== `checked`) return true;
384
- return !(this.#customWrappers.get(item) ?? item).hasAttribute(`not-checked`);
385
- }
386
- _syncItemStates() {
387
- for (const el of this.querySelectorAll(ITEM_SELECTOR)) {
388
- if (this.#wrappedElements.has(el)) continue;
389
- const item = this.#customWrappers.get(el) ?? el;
390
- el.toggleAttribute(`data-tickled`, this.tickled.isTickled(el));
391
- el.toggleAttribute(`data-selected`, this._selectedItems.has(el));
392
- if (this.interactionMode === `checked`) el.toggleAttribute(`data-checked`, !item.hasAttribute(`not-checked`) && this._selectedItems.has(el));
393
- else el.removeAttribute(`data-checked`);
394
- }
395
- this.dataset.inputMode = this.tickled.inputMode;
396
- this._syncCheckboxes();
397
- }
398
- _syncCheckboxes() {
399
- const inCheckedMode = this.interactionMode === `checked`;
400
- const wantsCustom = typeof this.checkboxRenderer === `function`;
401
- if (inCheckedMode) for (const inner of Array.from(this.children)) {
402
- if (!inner.hasAttribute(`data-list-item`)) continue;
403
- if (inner.parentElement !== this) continue;
404
- const wrapper = document.createElement(`li`);
405
- wrapper.className = `ixfx-custom-row`;
406
- const key = inner.getAttribute(`data-key`);
407
- const label = inner.getAttribute(`data-search-label`);
408
- if (key !== null) wrapper.setAttribute(`data-key`, key);
409
- if (label !== null) wrapper.setAttribute(`data-search-label`, label);
410
- inner.removeAttribute(`data-list-item`);
411
- this.insertBefore(wrapper, inner);
412
- wrapper.appendChild(inner);
413
- this.#customWrappers.set(wrapper, inner);
414
- this.#wrappedElements.add(inner);
415
- }
416
- else {
417
- for (const [wrapper, inner] of this.#customWrappers) {
418
- if (wrapper.parentElement !== this) continue;
419
- inner.setAttribute(`data-list-item`, ``);
420
- this.insertBefore(inner, wrapper);
421
- wrapper.remove();
422
- }
423
- this.#customWrappers.clear();
424
- this.#wrappedElements.clear();
425
- }
426
- for (const el of this.querySelectorAll(`li`)) {
427
- const existing = el.querySelector(`.ixfx-list-checkbox`);
428
- if (!inCheckedMode) {
429
- if (existing) existing.remove();
430
- continue;
431
- }
432
- if ((this.#customWrappers.get(el) ?? el).hasAttribute(`not-checked`)) {
433
- if (existing) existing.remove();
434
- continue;
435
- }
436
- const existingIsCustom = existing?.classList.contains(`ixfx-list-checkbox-custom`) ?? false;
437
- if (existing && existingIsCustom !== wantsCustom) existing.remove();
438
- let cb = el.querySelector(`.ixfx-list-checkbox`);
439
- if (!cb) {
440
- if (wantsCustom) {
441
- const opts = this.checkboxRenderer;
442
- const margin = opts.margin ?? `0`;
443
- const width = opts.width ?? `24px`;
444
- cb = this._createCustomCheckbox(el, margin, width);
445
- } else cb = this._createNativeCheckboxCell(el);
446
- el.prepend(cb);
447
- }
448
- const checked = this._selectedItems.has(el);
449
- if (wantsCustom) {
450
- cb.setAttribute(`aria-checked`, String(checked));
451
- cb.toggleAttribute(`data-checked`, checked);
452
- if (this.checkboxRenderer) {
453
- const renderer = typeof this.checkboxRenderer === `function` ? this.checkboxRenderer : this.checkboxRenderer.renderer;
454
- render(renderer(checked), cb);
455
- }
456
- } else {
457
- const input = cb.querySelector(`input.ixfx-list-checkbox`);
458
- if (input) input.checked = checked;
459
- }
460
- }
461
- }
462
- /**
463
- * Native checkbox cell: a span that stretches to the row's full cross-axis
464
- * (so the entire column height is a click target) with a real `<input>`
465
- * centred inside. The span owns the click; the input is purely visual and
466
- * has `pointer-events:none` so a single click produces one toggle.
467
- */
468
- _createNativeCheckboxCell(el) {
469
- const cell = document.createElement(`span`);
470
- cell.className = `ixfx-list-checkbox ixfx-list-checkbox-native`;
471
- cell.style.cssText = `display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;align-self:stretch;width:18px;margin:0 6px 0 0;cursor:pointer;pointer-events:auto`;
472
- cell.tabIndex = -1;
473
- cell.setAttribute(`role`, `checkbox`);
474
- cell.setAttribute(`part`, `checkbox`);
475
- cell.addEventListener(`click`, (e) => {
476
- e.stopPropagation();
477
- this._toggleItem(el);
478
- });
479
- const input = document.createElement(`input`);
480
- input.type = `checkbox`;
481
- input.className = `ixfx-list-checkbox`;
482
- input.style.cssText = `pointer-events:none;cursor:pointer;margin:0`;
483
- cell.appendChild(input);
484
- return cell;
485
- }
486
- /**
487
- * Custom checkbox cell: same shape as the native cell (a stretching span)
488
- * so behaviour is identical. The renderer's content goes inside.
489
- */
490
- _createCustomCheckbox(el, margin, width) {
491
- const span = document.createElement(`span`);
492
- span.className = `ixfx-list-checkbox ixfx-list-checkbox-custom`;
493
- span.style.cssText = `display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;align-self:stretch;width:${width};margin:${margin};cursor:pointer;pointer-events:auto`;
494
- span.tabIndex = -1;
495
- span.setAttribute(`role`, `checkbox`);
496
- span.setAttribute(`part`, `checkbox`);
497
- span.addEventListener(`click`, (e) => {
498
- e.stopPropagation();
499
- this._toggleItem(el);
500
- });
501
- return span;
502
- }
503
- _findListItem(path) {
504
- for (const target of path) {
505
- if (!(target instanceof Element)) continue;
506
- if (target === this) break;
507
- if (target.parentElement === this && target.matches(ITEM_SELECTOR)) return target;
508
- }
509
- }
510
- _dispatch(name, detail) {
511
- this.dispatchEvent(new CustomEvent(name, {
512
- detail,
513
- bubbles: true,
514
- composed: true
515
- }));
516
- }
517
- _openSearch() {
518
- this._searchVisible = true;
519
- this.updateComplete.then(() => this._searchInputEl?.focus());
520
- }
521
- _closeSearch() {
522
- this._searchVisible = false;
523
- this._searchQuery = ``;
524
- this.#search?.clearQuery();
525
- this.focus();
526
- }
527
- _activateItem(item) {
528
- if (this.interactionMode !== `manual`) this._replaceSelection(item);
529
- this._dispatch(`list-activate`, { item });
530
- }
531
- static {
532
- this.styles = [themeFallbacks, css`
533
- :host {
534
- display: block;
535
- position: relative;
536
- background: var(--list-bg, var(--surface-3));
537
- color: var(--list-text, var(--surface-3-text));
538
- border-radius: var(--list-radius, var(--radius-s));
539
- border: 1px solid var(--list-border, var(--border));
540
- width: 100%;
541
- height: 100%;
542
- overflow: hidden;
543
- box-sizing: border-box;
544
- outline: none;
545
- --ixfx-list-item-padding: var(--ixfx-list-item-padding, var(--list-item-padding, 4px var(--space-m, 8px)));
546
- }
547
-
548
- :host(:focus-visible) {
549
- outline: 2px solid var(--accent);
550
- outline-offset: 2px;
551
- }
552
-
553
- .container {
554
- position: relative;
555
- width: 100%;
556
- height: 100%;
557
- }
558
-
559
- ul {
560
- list-style: none;
561
- margin: 0;
562
- padding: 0;
563
- width: 100%;
564
- height: 100%;
565
- overflow-x: hidden;
566
- overflow-y: auto;
567
- box-sizing: border-box;
568
- /* Scrollbar theming: end users override these CSS variables to control
569
- the native scrollbar (scrollbar-width, scrollbar-gutter, scrollbar-color). */
570
- scrollbar-width: var(--list-scrollbar-width, auto);
571
- scrollbar-gutter: var(--list-scrollbar-gutter, auto);
572
- scrollbar-color: var(--list-scrollbar-color, auto);
573
- }
574
-
575
- ::slotted([hidden]) {
576
- display: none !important;
577
- }
578
-
579
- ::slotted(li) {
580
- display: flex;
581
- align-items: center;
582
- padding: var(--ixfx-list-item-padding);
583
- min-height: var(--list-item-height, 28px);
584
- cursor: pointer;
585
- user-select: none;
586
- transition: background var(--transition, 0.1s ease-out),
587
- outline-color var(--transition, 0.1s ease-out);
588
- box-sizing: border-box;
589
- outline: 1px solid transparent;
590
- }
591
-
592
- /* Custom shadow-DOM components handle their own internal layout/padding */
593
- ::slotted([data-list-item]) {
594
- display: block;
595
- cursor: pointer;
596
- user-select: none;
597
- transition: background var(--transition, 0.1s ease-out),
598
- outline-color var(--transition, 0.1s ease-out);
599
- outline: 1px solid transparent;
600
- }
601
-
602
- /* In checked mode, only the checkbox column is clickable; the row body
603
- gets a default cursor so it doesn't suggest otherwise. */
604
- :host([interaction-mode="checked"]) ::slotted(li),
605
- :host([interaction-mode="checked"]) ::slotted([data-list-item]) {
606
- cursor: default;
607
- }
608
-
609
- /* Wrapper inserted around custom [data-list-item] elements in checked mode.
610
- Provides the flex layout so the injected checkbox can stretch to the
611
- row's full height via align-self:stretch. */
612
- .ixfx-custom-row {
613
- display: flex;
614
- align-items: center;
615
- min-height: var(--list-item-height, 28px);
616
- box-sizing: border-box;
617
- cursor: default;
618
- user-select: none;
619
- }
620
-
621
- ::slotted([data-tickled]) {
622
- background: var(--item-bg-tickled);
623
- outline: var(--item-border-tickled);
624
- }
625
-
626
- ::slotted([data-selected]) {
627
- background: var(--item-bg-selected);
628
- color: var(--item-text-selected);
629
- outline: 1px solid transparent;
630
- }
631
-
632
- ::slotted([data-selected][data-tickled]) {
633
- background: var(--item-bg-selected-tickled);
634
- outline: 2px dashed var(--surface-3);
635
- outline-offset: -2px;
636
- }
637
-
638
- /* checked mode: checkbox (injected into li) communicates selection — suppress bg highlight */
639
- :host([interaction-mode="checked"]) ::slotted([data-selected]) {
640
- background: transparent;
641
- color: inherit;
642
- outline: 1px solid transparent;
643
- }
644
-
645
- :host([interaction-mode="checked"]) ::slotted([data-selected][data-tickled]) {
646
- background: var(--item-bg-tickled);
647
- color: inherit;
648
- outline: var(--item-border-tickled);
649
- }
650
-
651
- .search-overlay {
652
- position: absolute;
653
- top: 8px;
654
- right: 8px;
655
- z-index: 10;
656
- display: flex;
657
- align-items: center;
658
- gap: 4px;
659
- background: var(--surface-4, #2a2a2a);
660
- border: 1px solid var(--border, #444);
661
- border-radius: var(--radius-m, 4px);
662
- padding: 4px 6px;
663
- box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
664
- }
665
-
666
- .search-overlay[hidden] {
667
- display: none;
668
- }
669
-
670
- .search-input {
671
- background: transparent;
672
- border: none;
673
- outline: none;
674
- color: inherit;
675
- font-size: var(--text-m, 0.875em);
676
- min-width: 140px;
677
- }
678
-
679
- .search-close {
680
- background: transparent;
681
- border: none;
682
- color: var(--surface-muted-text, #888);
683
- cursor: pointer;
684
- font-size: 1.1em;
685
- line-height: 1;
686
- padding: 0 2px;
687
- }
688
-
689
- .search-close:hover {
690
- color: inherit;
691
- }
692
- `];
693
- }
694
- render() {
695
- return html`
696
- <div class="container">
697
- <ul part="list">
698
- <slot></slot>
699
- </ul>
700
- <div
701
- class="search-overlay"
702
- part="search-overlay"
703
- ?hidden=${!this._searchVisible}
704
- >
705
- <input
706
- type="text"
707
- class="search-input"
708
- placeholder="Search…"
709
- .value=${this._searchQuery}
710
- @input=${this._onSearchInput}
711
- @keydown=${this._onSearchKeydown}
712
- />
713
- <button class="search-close" @click=${this._closeSearch} title="Close search (Esc)">×</button>
714
- </div>
715
- </div>
716
- `;
717
- }
718
- };
719
- __decorate([property({
720
- type: String,
721
- attribute: `selection-mode`
722
- })], VerticalListElement.prototype, "selectionMode", void 0);
723
- __decorate([property({
724
- type: String,
725
- attribute: `interaction-mode`
726
- })], VerticalListElement.prototype, "interactionMode", void 0);
727
- __decorate([property({ attribute: false })], VerticalListElement.prototype, "filterPredicate", void 0);
728
- __decorate([property({ attribute: false })], VerticalListElement.prototype, "checkboxRenderer", void 0);
729
- __decorate([state()], VerticalListElement.prototype, "_selectedItems", void 0);
730
- __decorate([state()], VerticalListElement.prototype, "_searchVisible", void 0);
731
- __decorate([state()], VerticalListElement.prototype, "_searchQuery", void 0);
732
- __decorate([query(`.search-input`)], VerticalListElement.prototype, "_searchInputEl", void 0);
733
- VerticalListElement = __decorate([safeCustomElement(`ixfx-vertical-list`)], VerticalListElement);
734
- //#endregion
1
+ import { t as VerticalListElement } from "./vertical-list-ClnqTkF3.js";
735
2
  export { VerticalListElement };
736
-
737
- //# sourceMappingURL=vertical-list.js.map