@fusion.dev/helix-headless 0.145.0 → 0.146.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 (278) hide show
  1. package/custom-elements.json +7373 -3849
  2. package/dist/accordion/item/accordion-item.d.ts +14 -0
  3. package/dist/accordion/item/accordion-item.js +16 -6
  4. package/dist/accordion/root/accordion-root.d.ts +8 -5
  5. package/dist/announcement/root/announcement-root.d.ts +3 -2
  6. package/dist/announcement/root/announcement-root.js +3 -1
  7. package/dist/app-header/root/app-header-root.d.ts +7 -2
  8. package/dist/app-header/root/app-header-root.js +9 -1
  9. package/dist/app-header/sectioning.d.ts +3 -1
  10. package/dist/app-header/sectioning.js +3 -2
  11. package/dist/avatar/group/avatar-group.d.ts +20 -14
  12. package/dist/avatar/group/avatar-group.js +17 -19
  13. package/dist/badge/root/badge-root.d.ts +3 -1
  14. package/dist/badge/root/badge-root.js +2 -2
  15. package/dist/bar-chart/root/bar-chart-root.d.ts +18 -1
  16. package/dist/bar-chart/root/bar-chart-root.js +52 -15
  17. package/dist/bar-chart/stack.d.ts +15 -0
  18. package/dist/bar-chart/stack.js +19 -0
  19. package/dist/breadcrumbs/root/breadcrumbs-root.d.ts +25 -0
  20. package/dist/breadcrumbs/root/breadcrumbs-root.js +50 -3
  21. package/dist/button/root/button-root.d.ts +26 -0
  22. package/dist/button/root/button-root.js +38 -18
  23. package/dist/button-group/root/button-group-root.d.ts +2 -1
  24. package/dist/button-group/root/button-group-root.js +5 -1
  25. package/dist/canvas/node/canvas-node.d.ts +4 -3
  26. package/dist/canvas/node/canvas-node.js +3 -2
  27. package/dist/canvas/root/canvas-root.js +2 -2
  28. package/dist/card/root/card-root.d.ts +24 -3
  29. package/dist/card/root/card-root.js +20 -8
  30. package/dist/carousel/root/carousel-root.d.ts +43 -4
  31. package/dist/carousel/root/carousel-root.js +40 -12
  32. package/dist/carousel/stops.d.ts +20 -0
  33. package/dist/carousel/stops.js +30 -0
  34. package/dist/chat/message/chat-message.js +5 -4
  35. package/dist/chat/naming.d.ts +5 -1
  36. package/dist/chat/naming.js +4 -2
  37. package/dist/chat/root/chat-root.d.ts +25 -3
  38. package/dist/chat/root/chat-root.js +22 -5
  39. package/dist/checkbox/root/checkbox-root.d.ts +20 -0
  40. package/dist/checkbox/root/checkbox-root.js +14 -1
  41. package/dist/checkbox-group/root/checkbox-group-root.d.ts +8 -2
  42. package/dist/checkbox-group/root/checkbox-group-root.js +12 -10
  43. package/dist/checkbox-group/select-all.d.ts +27 -0
  44. package/dist/checkbox-group/select-all.js +12 -0
  45. package/dist/code-block/highlight.d.ts +15 -0
  46. package/dist/code-block/highlight.js +4 -0
  47. package/dist/code-block/root/code-block-root.d.ts +49 -1
  48. package/dist/code-block/root/code-block-root.js +58 -3
  49. package/dist/color-input/root/color-input-root.d.ts +3 -0
  50. package/dist/color-input/root/color-input-root.js +6 -3
  51. package/dist/color-picker/root/color-picker-root.d.ts +33 -4
  52. package/dist/color-picker/root/color-picker-root.js +80 -21
  53. package/dist/color-picker/swatches.d.ts +12 -0
  54. package/dist/color-picker/swatches.js +26 -0
  55. package/dist/combobox/root/combobox-root.d.ts +43 -0
  56. package/dist/combobox/root/combobox-root.js +79 -15
  57. package/dist/command/root/command-root.d.ts +16 -1
  58. package/dist/command/root/command-root.js +22 -4
  59. package/dist/copy-button/root/copy-button-root.d.ts +5 -0
  60. package/dist/copy-button/root/copy-button-root.js +10 -3
  61. package/dist/data-table/index.d.ts +1 -1
  62. package/dist/data-table/index.js +1 -1
  63. package/dist/data-table/keys.d.ts +24 -0
  64. package/dist/data-table/keys.js +24 -0
  65. package/dist/data-table/root/data-table-root.d.ts +27 -18
  66. package/dist/data-table/root/data-table-root.js +20 -52
  67. package/dist/data-table/tree.d.ts +16 -1
  68. package/dist/data-table/tree.js +2 -3
  69. package/dist/date-input/root/date-input-root.d.ts +3 -1
  70. package/dist/date-input/root/date-input-root.js +18 -7
  71. package/dist/date-picker/root/date-picker-root.js +12 -6
  72. package/dist/dialog/description.js +15 -1
  73. package/dist/dialog/root/dialog-root.d.ts +8 -2
  74. package/dist/dialog/root/dialog-root.js +16 -1
  75. package/dist/divider/root/divider-root.d.ts +3 -0
  76. package/dist/divider/root/divider-root.js +2 -1
  77. package/dist/donut-chart/root/donut-chart-root.d.ts +31 -0
  78. package/dist/donut-chart/root/donut-chart-root.js +48 -1
  79. package/dist/drawer/reveal.d.ts +8 -0
  80. package/dist/drawer/reveal.js +1 -0
  81. package/dist/drawer/root/drawer-root.d.ts +59 -0
  82. package/dist/drawer/root/drawer-root.js +63 -4
  83. package/dist/drilldown/item/drilldown-item.js +1 -1
  84. package/dist/drilldown/root/drilldown-root.d.ts +21 -3
  85. package/dist/drilldown/root/drilldown-root.js +21 -3
  86. package/dist/element-events.generated.js +31 -5
  87. package/dist/empty/root/empty-root.d.ts +3 -1
  88. package/dist/empty/root/empty-root.js +3 -2
  89. package/dist/file-input/root/file-input-root.d.ts +69 -6
  90. package/dist/file-input/root/file-input-root.js +82 -19
  91. package/dist/file-input/screen.d.ts +2 -1
  92. package/dist/filter-input/menu/filter-menu.d.ts +2 -0
  93. package/dist/filter-input/menu/filter-menu.js +12 -4
  94. package/dist/filter-input/root/filter-input-root.d.ts +30 -6
  95. package/dist/filter-input/root/filter-input-root.js +1 -1
  96. package/dist/filter-input/suggest.d.ts +28 -3
  97. package/dist/filter-input/suggest.js +18 -8
  98. package/dist/format-date/root/format-date-root.d.ts +9 -16
  99. package/dist/format-date/root/format-date-root.js +10 -27
  100. package/dist/heatmap/root/heatmap-root.d.ts +24 -13
  101. package/dist/heatmap/root/heatmap-root.js +34 -12
  102. package/dist/icon/root/icon-root.d.ts +12 -1
  103. package/dist/icon/root/icon-root.js +21 -10
  104. package/dist/icon/settle.d.ts +7 -0
  105. package/dist/icon/settle.js +10 -0
  106. package/dist/icon-button/root/icon-button-root.d.ts +2 -0
  107. package/dist/image/root/image-root.d.ts +5 -1
  108. package/dist/image/root/image-root.js +1 -1
  109. package/dist/input/root/input-root.d.ts +12 -2
  110. package/dist/input/root/input-root.js +11 -2
  111. package/dist/kbd/root/kbd-root.d.ts +35 -1
  112. package/dist/kbd/root/kbd-root.js +23 -4
  113. package/dist/legend/root/legend-root.d.ts +55 -8
  114. package/dist/legend/root/legend-root.js +55 -13
  115. package/dist/lightbox/root/lightbox-root.d.ts +49 -6
  116. package/dist/lightbox/root/lightbox-root.js +86 -19
  117. package/dist/lightbox/zoom-controller.d.ts +59 -0
  118. package/dist/lightbox/zoom-controller.js +128 -0
  119. package/dist/lightbox/zoom.d.ts +22 -0
  120. package/dist/lightbox/zoom.js +16 -0
  121. package/dist/line-chart/root/line-chart-root.d.ts +22 -1
  122. package/dist/line-chart/root/line-chart-root.js +21 -1
  123. package/dist/list/item/list-item.d.ts +2 -0
  124. package/dist/list/item/list-item.js +11 -2
  125. package/dist/list/root/list-root.d.ts +62 -13
  126. package/dist/list/root/list-root.js +70 -13
  127. package/dist/list/selection.d.ts +37 -7
  128. package/dist/list/selection.js +16 -7
  129. package/dist/listbox/root/listbox-root.d.ts +37 -1
  130. package/dist/listbox/root/listbox-root.js +49 -3
  131. package/dist/loader/busy.d.ts +10 -0
  132. package/dist/loader/busy.js +11 -0
  133. package/dist/loader/root/loader-root.d.ts +9 -2
  134. package/dist/loader/root/loader-root.js +23 -3
  135. package/dist/megamenu/root/megamenu-root.d.ts +51 -10
  136. package/dist/megamenu/root/megamenu-root.js +76 -5
  137. package/dist/menu/item/menu-item.d.ts +51 -2
  138. package/dist/menu/item/menu-item.js +47 -23
  139. package/dist/menu/root/menu-root.d.ts +14 -0
  140. package/dist/menu/root/menu-root.js +2 -2
  141. package/dist/meter/root/meter-root.d.ts +20 -1
  142. package/dist/meter/root/meter-root.js +11 -15
  143. package/dist/navigation/root/navigation-root.d.ts +2 -1
  144. package/dist/navigation/root/navigation-root.js +2 -2
  145. package/dist/notifications/root/notifications-root.d.ts +10 -3
  146. package/dist/notifications/root/notifications-root.js +19 -7
  147. package/dist/number-input/root/number-input-root.d.ts +17 -8
  148. package/dist/number-input/root/number-input-root.js +2 -7
  149. package/dist/object-inspector/root/object-inspector-root.d.ts +75 -27
  150. package/dist/object-inspector/root/object-inspector-root.js +117 -76
  151. package/dist/object-inspector/rows.d.ts +18 -0
  152. package/dist/object-inspector/rows.js +33 -0
  153. package/dist/option/root/option-root.d.ts +5 -3
  154. package/dist/outline/root/outline-root.d.ts +18 -0
  155. package/dist/outline/root/outline-root.js +23 -5
  156. package/dist/pagination/size/pagination-size.d.ts +1 -0
  157. package/dist/pagination/size/pagination-size.js +1 -1
  158. package/dist/pin-input/code.d.ts +10 -0
  159. package/dist/pin-input/code.js +13 -0
  160. package/dist/pin-input/root/pin-input-root.d.ts +25 -1
  161. package/dist/pin-input/root/pin-input-root.js +10 -11
  162. package/dist/popover/hide-outside.d.ts +14 -0
  163. package/dist/popover/hide-outside.js +41 -0
  164. package/dist/popover/root/popover-root.d.ts +57 -7
  165. package/dist/popover/root/popover-root.js +58 -3
  166. package/dist/progress/root/progress-root.d.ts +20 -0
  167. package/dist/progress/root/progress-root.js +15 -15
  168. package/dist/qr-code/export.d.ts +26 -1
  169. package/dist/qr-code/export.js +14 -0
  170. package/dist/qr-code/root/qr-code-root.d.ts +19 -5
  171. package/dist/qr-code/root/qr-code-root.js +58 -9
  172. package/dist/quote/marks.d.ts +8 -0
  173. package/dist/quote/marks.js +5 -0
  174. package/dist/quote/root/quote-root.d.ts +14 -2
  175. package/dist/quote/root/quote-root.js +23 -1
  176. package/dist/radio/root/radio-root.d.ts +6 -2
  177. package/dist/radio/root/radio-root.js +6 -1
  178. package/dist/rating/root/rating-root.d.ts +9 -4
  179. package/dist/rating/root/rating-root.js +31 -7
  180. package/dist/rating/steps.d.ts +7 -0
  181. package/dist/rating/steps.js +9 -0
  182. package/dist/scatter-chart/fit.d.ts +15 -0
  183. package/dist/scatter-chart/fit.js +35 -0
  184. package/dist/scatter-chart/root/scatter-chart-root.d.ts +21 -1
  185. package/dist/scatter-chart/root/scatter-chart-root.js +30 -17
  186. package/dist/scroll-area/root/scroll-area-root.d.ts +22 -51
  187. package/dist/scroll-area/root/scroll-area-root.js +57 -173
  188. package/dist/scroll-area/scrollbar-controller.d.ts +111 -0
  189. package/dist/scroll-area/scrollbar-controller.js +172 -0
  190. package/dist/scroll-area/scrollbar.d.ts +27 -0
  191. package/dist/scroll-area/scrollbar.js +9 -0
  192. package/dist/select/root/select-root.d.ts +15 -0
  193. package/dist/select/root/select-root.js +18 -6
  194. package/dist/skeleton/root/skeleton-root.d.ts +3 -0
  195. package/dist/skeleton/root/skeleton-root.js +4 -2
  196. package/dist/skip-link/root/skip-link-root.js +2 -2
  197. package/dist/slider/root/slider-root.d.ts +41 -4
  198. package/dist/slider/root/slider-root.js +23 -3
  199. package/dist/sparkline/readings.d.ts +18 -0
  200. package/dist/sparkline/readings.js +19 -0
  201. package/dist/sparkline/root/sparkline-root.d.ts +78 -7
  202. package/dist/sparkline/root/sparkline-root.js +118 -23
  203. package/dist/speed-dial/root/speed-dial-root.js +2 -2
  204. package/dist/splitter/root/splitter-root.d.ts +7 -12
  205. package/dist/splitter/root/splitter-root.js +209 -204
  206. package/dist/stat/root/stat-root.d.ts +14 -5
  207. package/dist/stat/root/stat-root.js +21 -5
  208. package/dist/steps/reach.d.ts +5 -0
  209. package/dist/steps/reach.js +3 -0
  210. package/dist/steps/root/steps-root.d.ts +49 -3
  211. package/dist/steps/root/steps-root.js +44 -5
  212. package/dist/steps/step/step.d.ts +7 -0
  213. package/dist/steps/step/step.js +7 -2
  214. package/dist/switch/root/switch-root.d.ts +10 -0
  215. package/dist/table/column/table-column.d.ts +0 -10
  216. package/dist/table/column/table-column.js +3 -19
  217. package/dist/table/root/table-root.d.ts +31 -10
  218. package/dist/table/root/table-root.js +2 -13
  219. package/dist/tabs/panel/tab-panel.d.ts +16 -3
  220. package/dist/tabs/panel/tab-panel.js +34 -5
  221. package/dist/tabs/root/tabs-root.d.ts +12 -0
  222. package/dist/tabs/root/tabs-root.js +1 -1
  223. package/dist/tabs/tab/tab.d.ts +5 -0
  224. package/dist/tabs/tab/tab.js +5 -2
  225. package/dist/tag/group/tag-group.d.ts +31 -4
  226. package/dist/tag/group/tag-group.js +46 -7
  227. package/dist/tag/root/tag-root.js +9 -2
  228. package/dist/textarea/root/textarea-root.d.ts +28 -1
  229. package/dist/textarea/root/textarea-root.js +40 -1
  230. package/dist/time-input/root/time-input-root.d.ts +5 -1
  231. package/dist/time-input/root/time-input-root.js +16 -8
  232. package/dist/time-picker/root/time-picker-root.d.ts +18 -4
  233. package/dist/time-picker/root/time-picker-root.js +7 -10
  234. package/dist/time-picker/wheel-name.d.ts +9 -0
  235. package/dist/time-picker/wheel-name.js +15 -0
  236. package/dist/timeline/group/timeline-group.js +2 -2
  237. package/dist/toast/item/toast-item.d.ts +14 -1
  238. package/dist/toast/item/toast-item.js +22 -5
  239. package/dist/toast/root/toast-root.d.ts +6 -0
  240. package/dist/toast/root/toast-root.js +16 -1
  241. package/dist/toggle/group/toggle-group.d.ts +24 -3
  242. package/dist/toggle/group/toggle-group.js +34 -5
  243. package/dist/tooltip/root/tooltip-root.d.ts +13 -2
  244. package/dist/tooltip/root/tooltip-root.js +9 -1
  245. package/dist/tour/back.d.ts +10 -0
  246. package/dist/tour/back.js +8 -0
  247. package/dist/tour/root/tour-root.d.ts +30 -2
  248. package/dist/tour/root/tour-root.js +34 -8
  249. package/dist/tree/item/tree-item.d.ts +7 -3
  250. package/dist/tree/item/tree-item.js +3 -0
  251. package/dist/tree/root/tree-root.d.ts +24 -3
  252. package/dist/tree/root/tree-root.js +32 -13
  253. package/dist/tree/selection.js +2 -15
  254. package/dist/trend/root/trend-root.d.ts +43 -18
  255. package/dist/trend/root/trend-root.js +31 -6
  256. package/dist/video/media-events.d.ts +13 -18
  257. package/dist/video/media-events.js +1 -5
  258. package/dist/video/root/video-root.d.ts +18 -5
  259. package/dist/video/root/video-root.js +19 -10
  260. package/dist/video-playlist/menu/video-playlist-menu.d.ts +2 -0
  261. package/dist/video-playlist/menu/video-playlist-menu.js +2 -1
  262. package/dist/video-playlist/root/video-playlist-root.d.ts +7 -1
  263. package/dist/virtual-list/fill.d.ts +0 -8
  264. package/dist/virtual-list/fill.js +1 -17
  265. package/dist/virtual-list/plan.d.ts +49 -0
  266. package/dist/virtual-list/plan.js +16 -0
  267. package/dist/virtual-list/root/virtual-list-root.d.ts +114 -13
  268. package/dist/virtual-list/root/virtual-list-root.js +183 -40
  269. package/lint.json +1 -1
  270. package/package.json +8 -8
  271. package/types/jsx.d.ts +4577 -835
  272. package/types/vue.d.ts +926 -168
  273. package/dist/chat/relative-clock.d.ts +0 -39
  274. package/dist/chat/relative-clock.js +0 -31
  275. package/dist/data-table/root/order.d.ts +0 -141
  276. package/dist/data-table/root/order.js +0 -76
  277. package/dist/tag/selection.d.ts +0 -10
  278. package/dist/tag/selection.js +0 -12
@@ -43,11 +43,13 @@ declare const HelixHeadlessCombobox_base: (new (...args: any[]) => import("@fusi
43
43
  * @slot - The options.
44
44
  * @slot empty - What the list shows when typing hides every option, for content richer than `empty-text`.
45
45
  * @slot end - After the text, for a unit or a clear button.
46
+ * @slot error - What the list shows while `load-error` is set, for content richer than its text.
46
47
  * @slot feedback - The message that says what is wrong, for content richer than a string. It shows while there is a message.
47
48
  * @slot hint - The hint, for content richer than plain text.
48
49
  * @slot indicator - Replaces the caret that shows the field opens a list.
49
50
  * @slot label - The label, for content richer than plain text.
50
51
  * @slot loading - What the list shows while the options load, for content richer than `loading-text`.
52
+ * @slot no-results - What the list shows when typing hides every option, for content richer than `no-results-text`.
51
53
  * @slot start - Before the text, for an icon.
52
54
  *
53
55
  * @event {Event} change - Fired after the value changes.
@@ -56,6 +58,7 @@ declare const HelixHeadlessCombobox_base: (new (...args: any[]) => import("@fusi
56
58
  * @event {HelixBeforeOpenEvent} helix-before-open - Fired before the panel opens. Cancelable: cancel it to keep the panel closed.
57
59
  * @event {HelixCreateEvent} helix-create - Fired when the user adds a value that is not in the list. Cancelable.
58
60
  * @event {HelixFilterEvent} helix-filter - Fired as the user types, with the text the list is filtered by. Cancelable: cancel it to leave the list unfiltered and do the filtering yourself.
61
+ * @event {HelixLoadMoreEvent} helix-load-more - Fired once the list is scrolled within a screen of its end, once for each number of options, and not while `loading` is set. Add the next page and set `loading` while you fetch it.
59
62
  * @event {Event} input - Fired after the value changes.
60
63
  * @event {ToggleEvent} toggle - Fired when the panel opens or closes, with `newState` and `oldState`.
61
64
  *
@@ -69,6 +72,7 @@ declare const HelixHeadlessCombobox_base: (new (...args: any[]) => import("@fusi
69
72
  * @csspart label - The label above the field.
70
73
  * @csspart listbox - The list inside the panel.
71
74
  * @csspart listbox-empty - Shown when a filter has hidden everything.
75
+ * @csspart listbox-error - Shown while `load-error` is set.
72
76
  * @csspart listbox-feedback - The inner list's error message.
73
77
  * @csspart listbox-filter-icon - The icon beside the list's filter field.
74
78
  * @csspart listbox-filter-mark - The glyph beside the filter field, where none is slotted.
@@ -133,10 +137,26 @@ export declare class HelixHeadlessCombobox extends HelixHeadlessCombobox_base {
133
137
  * Text shown when the filter hides every option.
134
138
  */
135
139
  emptyText: string;
140
+ /**
141
+ * How long typing rests before the list is narrowed and `helix-filter` is
142
+ * sent, in milliseconds.
143
+ *
144
+ * For options filtered on a server, where `helix-filter` starts a request: a
145
+ * delay sends one request for a word instead of one per letter. The arrow
146
+ * keys, Enter and Escape narrow at once on what was typed. `0` narrows on
147
+ * every keystroke. See Listbox's `filter-delay`.
148
+ */
149
+ filterDelay: number;
136
150
  /**
137
151
  * The list's name, read by screen readers. The list has no visible name.
138
152
  */
139
153
  listLabel: string;
154
+ /**
155
+ * What the list says when its options could not be loaded, such as after a
156
+ * request to a server fails. Empty is no error. Passed to the list, which
157
+ * shows it under any options there are and tells screen readers.
158
+ */
159
+ loadError: string;
140
160
  /**
141
161
  * Whether the options are still loading.
142
162
  *
@@ -168,6 +188,18 @@ export declare class HelixHeadlessCombobox extends HelixHeadlessCombobox_base {
168
188
  * element is responsible for.
169
189
  */
170
190
  multiple: boolean;
191
+ /**
192
+ * The text shown when typing hides every one of the options, where there are
193
+ * some. Absent, `empty-text` shows. See Listbox's `no-results-text`.
194
+ */
195
+ noResultsText?: string;
196
+ /**
197
+ * What opens the list: `input`, typing or pressing Down; `focus`, also
198
+ * arriving in the field, by Tab or a press; or `manual`, only Down, Alt+Down
199
+ * or a press on the caret, so typing narrows a list the reader has asked
200
+ * for. React Aria's `menuTrigger`.
201
+ */
202
+ openOn: 'focus' | 'input' | 'manual';
171
203
  /**
172
204
  * Text shown while nothing has been chosen.
173
205
  */
@@ -358,6 +390,17 @@ export declare class HelixHeadlessCombobox extends HelixHeadlessCombobox_base {
358
390
  */
359
391
  private moveAroundCreate;
360
392
  private readonly handleInput;
393
+ /**
394
+ * Arriving in the field opens the list where `open-on` is `focus`, unless
395
+ * this element is handing focus back to it as the list closes.
396
+ */
397
+ private readonly handleFocus;
398
+ /** Whether `close` is putting focus back in the field, which opens nothing. */
399
+ private refocusing;
400
+ /** The narrowing waiting out `filterDelay`, if any. */
401
+ private readonly narrowing;
402
+ /** Narrows the list to what was typed, and finds the completion in what is left. */
403
+ private narrow;
361
404
  /**
362
405
  * The words of the first option the typing begins, or nothing.
363
406
  *
@@ -4,7 +4,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
4
4
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
5
  return c > 3 && r && Object.defineProperty(target, key, r), r;
6
6
  };
7
- import { AriaForwardController, afterLinkFollowed, customElement, fillTemplate, HelixCreateEvent, HelixFilterEvent, HelixFormElement, MixinControllerOpen, MixinControllerValue, MixinField, MixinTokens, PopoverController, reportValues, } from '@fusion.dev/helix-core';
7
+ import { AriaForwardController, afterLinkFollowed, customElement, DelayController, fillTemplate, HelixCreateEvent, HelixFilterEvent, HelixFormElement, MixinControllerOpen, MixinControllerValue, MixinField, MixinTokens, PopoverController, reportValues, submitImplicitly, } from '@fusion.dev/helix-core';
8
8
  import { caretDown } from '@fusion.dev/helix-icons';
9
9
  import { nothing } from 'lit';
10
10
  import { property, state } from 'lit/decorators.js';
@@ -26,10 +26,13 @@ let HelixHeadlessCombobox = class HelixHeadlessCombobox extends MixinControllerO
26
26
  this.creatable = false;
27
27
  this.createLabel = 'Add';
28
28
  this.emptyText = 'No matches';
29
+ this.filterDelay = 0;
29
30
  this.listLabel = 'Options';
31
+ this.loadError = '';
30
32
  this.loading = false;
31
33
  this.loadingText = 'Loading';
32
34
  this.multiple = false;
35
+ this.openOn = 'input';
33
36
  this.placeholder = '';
34
37
  this.readOnly = false;
35
38
  this.removeLabel = 'Remove {name}';
@@ -65,20 +68,37 @@ let HelixHeadlessCombobox = class HelixHeadlessCombobox extends MixinControllerO
65
68
  this.editing = true;
66
69
  this.onCreate = false;
67
70
  this.emptied = typed.trim() === '';
68
- const narrowing = new HelixFilterEvent({ value: typed });
69
- if (this.dispatchEvent(narrowing)) {
70
- this.listbox?.requestFilter(typed);
71
- void this.listbox?.updateComplete.then(() => this.linkActive());
71
+ const inserted = isInsertion(event);
72
+ this.narrowing.cancel();
73
+ if (this.filterDelay > 0) {
74
+ this.suggestion = '';
75
+ this.narrowing.start(this.filterDelay, () => this.narrow(typed, inserted));
72
76
  }
73
- this.suggestion = this.suggest && isInsertion(event) ? this.completionFor(typed) : '';
74
- if (!this.open) {
77
+ else {
78
+ this.narrow(typed, inserted);
79
+ }
80
+ if (!this.open && this.openOn !== 'manual') {
75
81
  this.requestOpen(true);
76
82
  }
77
83
  };
84
+ this.handleFocus = () => {
85
+ if (this.openOn !== 'focus' || this.open || this.refocusing) {
86
+ return;
87
+ }
88
+ if (this.isDisabled || this.readOnly) {
89
+ return;
90
+ }
91
+ this.requestOpen(true);
92
+ };
93
+ this.refocusing = false;
94
+ this.narrowing = new DelayController(this, { renders: false });
78
95
  this.handleKeydown = (event) => {
79
96
  if (this.isDisabled) {
80
97
  return;
81
98
  }
99
+ if (['ArrowDown', 'ArrowUp', 'Enter', 'Escape', 'PageDown', 'PageUp'].includes(event.key)) {
100
+ this.narrowing.flush();
101
+ }
82
102
  if (event.key === 'Escape') {
83
103
  this.emptied = false;
84
104
  if (this.open) {
@@ -98,6 +118,13 @@ let HelixHeadlessCombobox = class HelixHeadlessCombobox extends MixinControllerO
98
118
  if (this.open) {
99
119
  this.requestOpen(false);
100
120
  }
121
+ else if (this.openOn === 'manual' && this.editing) {
122
+ this.typed = '';
123
+ this.suggestion = '';
124
+ this.editing = false;
125
+ this.listbox?.requestFilter('');
126
+ this.requestUpdate();
127
+ }
101
128
  return;
102
129
  }
103
130
  if (this.multiple && this.tokenKeydown(event, this.typed)) {
@@ -136,7 +163,7 @@ let HelixHeadlessCombobox = class HelixHeadlessCombobox extends MixinControllerO
136
163
  };
137
164
  this.handleKeypress = (event) => {
138
165
  if (event.key === 'Enter' && !this.open && !event.defaultPrevented) {
139
- this.submitImplicitly();
166
+ submitImplicitly(this.form);
140
167
  }
141
168
  };
142
169
  this.handleChange = (event) => {
@@ -160,8 +187,11 @@ let HelixHeadlessCombobox = class HelixHeadlessCombobox extends MixinControllerO
160
187
  if (event.composedPath().some((node) => node instanceof HelixHeadlessTag)) {
161
188
  return;
162
189
  }
190
+ const onText = event.composedPath().includes(this.partNamed('control'));
191
+ this.refocusing = true;
163
192
  this.partNamed('control')?.focus();
164
- if (!this.open) {
193
+ this.refocusing = false;
194
+ if (!this.open && !(this.openOn === 'manual' && onText)) {
165
195
  this.requestOpen(true);
166
196
  }
167
197
  };
@@ -261,7 +291,9 @@ let HelixHeadlessCombobox = class HelixHeadlessCombobox extends MixinControllerO
261
291
  return;
262
292
  }
263
293
  this.requestOpen(false);
294
+ this.refocusing = true;
264
295
  this.partNamed('control')?.focus();
296
+ this.refocusing = false;
265
297
  }
266
298
  commitEmptied() {
267
299
  if (this.emptied && !this.multiple && this.value !== '') {
@@ -316,6 +348,15 @@ let HelixHeadlessCombobox = class HelixHeadlessCombobox extends MixinControllerO
316
348
  }
317
349
  return false;
318
350
  }
351
+ narrow(typed, inserted) {
352
+ this.narrowing.cancel();
353
+ const narrowing = new HelixFilterEvent({ value: typed });
354
+ if (this.dispatchEvent(narrowing)) {
355
+ this.listbox?.requestFilter(typed);
356
+ void this.listbox?.updateComplete.then(() => this.linkActive());
357
+ }
358
+ this.suggestion = this.suggest && inserted ? this.completionFor(typed) : '';
359
+ }
319
360
  completionFor(typed) {
320
361
  if (typed === '') {
321
362
  return '';
@@ -401,7 +442,7 @@ let HelixHeadlessCombobox = class HelixHeadlessCombobox extends MixinControllerO
401
442
  if (control && this.suggestion !== '') {
402
443
  control.setSelectionRange(this.typed.length, this.suggestion.length);
403
444
  }
404
- if (!this.open) {
445
+ if (!this.open && (this.openOn !== 'manual' || changed.has('open'))) {
405
446
  this.typed = '';
406
447
  this.suggestion = '';
407
448
  this.editing = false;
@@ -420,7 +461,7 @@ let HelixHeadlessCombobox = class HelixHeadlessCombobox extends MixinControllerO
420
461
  }
421
462
  }
422
463
  get fieldText() {
423
- if (this.multiple || (this.open && this.editing)) {
464
+ if (this.multiple || ((this.open || this.openOn === 'manual') && this.editing)) {
424
465
  return this.suggestion || this.typed;
425
466
  }
426
467
  return this.word;
@@ -429,13 +470,15 @@ let HelixHeadlessCombobox = class HelixHeadlessCombobox extends MixinControllerO
429
470
  return html `<${this.tag('listbox')}
430
471
  part="listbox"
431
472
  id="listbox"
432
- exportparts="empty: listbox-empty, feedback: listbox-feedback, filter-icon: listbox-filter-icon,
433
- filter-mark: listbox-filter-mark, hint: listbox-hint, items: listbox-items,
434
- label: listbox-label, live: listbox-live, loading: listbox-loading, search: listbox-search,
435
- search-field: listbox-search-field"
473
+ exportparts="empty: listbox-empty, error: listbox-error, feedback: listbox-feedback,
474
+ filter-icon: listbox-filter-icon, filter-mark: listbox-filter-mark, hint: listbox-hint,
475
+ items: listbox-items, label: listbox-label, live: listbox-live, loading: listbox-loading,
476
+ search: listbox-search, search-field: listbox-search-field"
436
477
  aria-label=${this.listLabel}
437
478
  empty-text=${this.emptyText}
479
+ load-error=${this.loadError}
438
480
  loading-text=${this.loadingText}
481
+ no-results-text=${this.noResultsText ?? nothing}
439
482
  result-label=${this.resultLabel}
440
483
  results-label=${this.resultsLabel}
441
484
  ?loading=${this.loading}
@@ -457,6 +500,14 @@ let HelixHeadlessCombobox = class HelixHeadlessCombobox extends MixinControllerO
457
500
  fills it, so the list's fallback would never show. -->
458
501
  <slot name="empty" slot="empty">${this.emptyText}</slot>
459
502
  <slot name="loading" slot="loading">${this.loadingText}</slot>
503
+ <slot name="error" slot="error">${this.loadError}</slot>
504
+ <!-- Handed on only while something fills it: an assigned slot hides the
505
+ list's own fallback, which is no-results-text or empty-text. -->
506
+ <slot
507
+ name="no-results"
508
+ slot=${this.querySelector?.(':scope > [slot="no-results"]') ? 'no-results' : nothing}
509
+ @slotchange=${() => this.requestUpdate()}
510
+ ></slot>
460
511
  </${this.tag('listbox')}>`;
461
512
  }
462
513
  renderTag(option) {
@@ -512,6 +563,7 @@ let HelixHeadlessCombobox = class HelixHeadlessCombobox extends MixinControllerO
512
563
  ?disabled=${this.isDisabled}
513
564
  ?readonly=${this.readOnly}
514
565
  .value=${this.fieldText}
566
+ @focus=${this.handleFocus}
515
567
  @input=${this.handleInput}
516
568
  @keydown=${this.handleKeydown}
517
569
  @keypress=${this.handleKeypress}
@@ -541,9 +593,15 @@ __decorate([
541
593
  __decorate([
542
594
  property({ attribute: 'empty-text' })
543
595
  ], HelixHeadlessCombobox.prototype, "emptyText", void 0);
596
+ __decorate([
597
+ property({ attribute: 'filter-delay', type: Number })
598
+ ], HelixHeadlessCombobox.prototype, "filterDelay", void 0);
544
599
  __decorate([
545
600
  property({ attribute: 'list-label' })
546
601
  ], HelixHeadlessCombobox.prototype, "listLabel", void 0);
602
+ __decorate([
603
+ property({ attribute: 'load-error' })
604
+ ], HelixHeadlessCombobox.prototype, "loadError", void 0);
547
605
  __decorate([
548
606
  property({ reflect: true, type: Boolean })
549
607
  ], HelixHeadlessCombobox.prototype, "loading", void 0);
@@ -553,6 +611,12 @@ __decorate([
553
611
  __decorate([
554
612
  property({ type: Boolean })
555
613
  ], HelixHeadlessCombobox.prototype, "multiple", void 0);
614
+ __decorate([
615
+ property({ attribute: 'no-results-text' })
616
+ ], HelixHeadlessCombobox.prototype, "noResultsText", void 0);
617
+ __decorate([
618
+ property({ attribute: 'open-on' })
619
+ ], HelixHeadlessCombobox.prototype, "openOn", void 0);
556
620
  __decorate([
557
621
  property()
558
622
  ], HelixHeadlessCombobox.prototype, "placeholder", void 0);
@@ -1,5 +1,5 @@
1
1
  import { HelixElement } from '@fusion.dev/helix-core';
2
- import type { PropertyValues, TemplateResult } from 'lit';
2
+ import { type PropertyValues, type TemplateResult } from 'lit';
3
3
  import '../../dialog/index.js';
4
4
  import '../../listbox/index.js';
5
5
  declare const HelixHeadlessCommand_base: (new (...args: any[]) => import("@fusion.dev/helix-core").MixinControllerOpenInterface) & typeof HelixElement;
@@ -34,12 +34,15 @@ declare const HelixHeadlessCommand_base: (new (...args: any[]) => import("@fusio
34
34
  *
35
35
  * @slot - The commands, and any groups of them.
36
36
  * @slot empty - What the palette shows when typing matches no commands, for content richer than `empty-text`.
37
+ * @slot error - What the palette shows while `load-error` is set, for content richer than its text.
37
38
  * @slot footer - Content under the list, such as the keys that work in the palette.
38
39
  * @slot loading - What the palette shows while the commands load, for content richer than `loading-text`.
40
+ * @slot no-results - What the palette shows when typing matches no commands, for content richer than `no-results-text`.
39
41
  *
40
42
  * @event {HelixBeforeCloseEvent} helix-before-close - The palette is about to close. Cancelable: cancel it to keep it open.
41
43
  * @event {HelixBeforeOpenEvent} helix-before-open - The palette is about to open. Cancelable: cancel it to keep it closed.
42
44
  * @event {HelixFilterEvent} helix-filter - Fired as the user types, with the text the list is filtered by. Cancelable: cancel it to leave the list unfiltered and filter the commands yourself, for example on a server while `loading` is set.
45
+ * @event {HelixLoadMoreEvent} helix-load-more - Fired once the list is scrolled within a screen of its end, once for each number of commands, and not while `loading` is set. Add the next page and set `loading` while you fetch it.
43
46
  * @event {HelixSelectEvent} helix-select - A command was chosen, with its `href` where the option is a link. Cancelable: cancel it to keep the palette open, and to keep the browser from following the link.
44
47
  * @event {ToggleEvent} toggle - The palette opened or closed. The event carries `newState` and `oldState`.
45
48
  *
@@ -52,6 +55,7 @@ declare const HelixHeadlessCommand_base: (new (...args: any[]) => import("@fusio
52
55
  * @csspart footer - The row under the list.
53
56
  * @csspart listbox - The listbox inside the palette.
54
57
  * @csspart listbox-empty - The text shown when the filter matches no commands.
58
+ * @csspart listbox-error - The text shown while `load-error` is set.
55
59
  * @csspart listbox-feedback - The listbox's error message.
56
60
  * @csspart listbox-filter-icon - The icon beside the filter field.
57
61
  * @csspart listbox-filter-mark - The default icon beside the filter field, drawn when no icon is slotted.
@@ -88,6 +92,12 @@ export declare class HelixHeadlessCommand extends HelixHeadlessCommand_base {
88
92
  * Accessible name for the overlay, which has no visible heading.
89
93
  */
90
94
  label: string;
95
+ /**
96
+ * What the list says when its commands could not be loaded, such as after a
97
+ * request to a server fails. Empty is no error. Passed to the list, which
98
+ * shows it under any commands there are and tells screen readers.
99
+ */
100
+ loadError: string;
91
101
  /**
92
102
  * Whether the commands are still loading, for a palette that asks a server
93
103
  * for them as the user types.
@@ -99,6 +109,11 @@ export declare class HelixHeadlessCommand extends HelixHeadlessCommand_base {
99
109
  * The text shown while the commands load.
100
110
  */
101
111
  loadingText: string;
112
+ /**
113
+ * The text shown when typing hides every one of the commands, where there are
114
+ * some. Absent, `empty-text` shows. See Listbox's `no-results-text`.
115
+ */
116
+ noResultsText?: string;
102
117
  /**
103
118
  * The text shown in the filter field before anything is typed.
104
119
  */
@@ -5,6 +5,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
5
5
  return c > 3 && r && Object.defineProperty(target, key, r), r;
6
6
  };
7
7
  import { customElement, HelixElement, HelixSelectEvent, MixinControllerOpen, } from '@fusion.dev/helix-core';
8
+ import { nothing } from 'lit';
8
9
  import { property, state } from 'lit/decorators.js';
9
10
  import { html } from 'lit/static-html.js';
10
11
  import '../../dialog/index.js';
@@ -25,6 +26,7 @@ let HelixHeadlessCommand = class HelixHeadlessCommand extends MixinControllerOpe
25
26
  this.filterDelay = 0;
26
27
  this.hotkey = 'mod+k';
27
28
  this.label = 'Commands';
29
+ this.loadError = '';
28
30
  this.loading = false;
29
31
  this.loadingText = 'Loading';
30
32
  this.placeholder = 'Search commands';
@@ -150,15 +152,17 @@ let HelixHeadlessCommand = class HelixHeadlessCommand extends MixinControllerOpe
150
152
  >
151
153
  <${this.tag('listbox')}
152
154
  part="listbox"
153
- exportparts="empty: listbox-empty, feedback: listbox-feedback, filter-icon: listbox-filter-icon,
154
- filter-mark: listbox-filter-mark, hint: listbox-hint, items: listbox-items,
155
- label: listbox-label, live: listbox-live, loading: listbox-loading, search: listbox-search,
156
- search-field: listbox-search-field"
155
+ exportparts="empty: listbox-empty, error: listbox-error, feedback: listbox-feedback,
156
+ filter-icon: listbox-filter-icon, filter-mark: listbox-filter-mark, hint: listbox-hint,
157
+ items: listbox-items, label: listbox-label, live: listbox-live, loading: listbox-loading,
158
+ search: listbox-search, search-field: listbox-search-field"
157
159
  aria-label=${this.label}
158
160
  empty-text=${this.emptyText}
159
161
  filter-delay=${this.filterDelay}
160
162
  filter-label=${this.placeholder}
163
+ load-error=${this.loadError}
161
164
  loading-text=${this.loadingText}
165
+ no-results-text=${this.noResultsText ?? nothing}
162
166
  result-label=${this.resultLabel}
163
167
  results-label=${this.resultsLabel}
164
168
  ?loading=${this.loading}
@@ -172,6 +176,14 @@ let HelixHeadlessCommand = class HelixHeadlessCommand extends MixinControllerOpe
172
176
  gives: the list's own fallback never shows behind a passed slot. -->
173
177
  <slot name="empty" slot="empty">${this.emptyText}</slot>
174
178
  <slot name="loading" slot="loading">${this.loadingText}</slot>
179
+ <slot name="error" slot="error">${this.loadError}</slot>
180
+ <!-- Handed on only while something fills it: an assigned slot hides the
181
+ list's own fallback, which is no-results-text or empty-text. -->
182
+ <slot
183
+ name="no-results"
184
+ slot=${this.querySelector?.(':scope > [slot="no-results"]') ? 'no-results' : nothing}
185
+ @slotchange=${() => this.requestUpdate()}
186
+ ></slot>
175
187
  </${this.tag('listbox')}>
176
188
  <div ?hidden=${!this.footed} part="footer" slot="footer">
177
189
  <slot
@@ -199,12 +211,18 @@ __decorate([
199
211
  __decorate([
200
212
  property()
201
213
  ], HelixHeadlessCommand.prototype, "label", void 0);
214
+ __decorate([
215
+ property({ attribute: 'load-error' })
216
+ ], HelixHeadlessCommand.prototype, "loadError", void 0);
202
217
  __decorate([
203
218
  property({ reflect: true, type: Boolean })
204
219
  ], HelixHeadlessCommand.prototype, "loading", void 0);
205
220
  __decorate([
206
221
  property({ attribute: 'loading-text' })
207
222
  ], HelixHeadlessCommand.prototype, "loadingText", void 0);
223
+ __decorate([
224
+ property({ attribute: 'no-results-text' })
225
+ ], HelixHeadlessCommand.prototype, "noResultsText", void 0);
208
226
  __decorate([
209
227
  property()
210
228
  ], HelixHeadlessCommand.prototype, "placeholder", void 0);
@@ -66,6 +66,11 @@ export declare class HelixHeadlessCopyButton extends HelixHeadlessIconButton {
66
66
  * clipboard.
67
67
  */
68
68
  errorLabel: string;
69
+ /**
70
+ * How long the confirmation or the failure stands, in milliseconds, before
71
+ * the button goes back to `label`.
72
+ */
73
+ feedbackDuration: number;
69
74
  /**
70
75
  * The element to copy from, by its id: `key` for its text, `key[value]` for
71
76
  * an attribute, and `key.value` for a property. Read at the press, and used
@@ -14,17 +14,17 @@ import { html } from 'lit/static-html.js';
14
14
  import { HelixHeadlessIconButton } from '../../icon-button/root/icon-button-root.js';
15
15
  import { readFrom } from '../from.js';
16
16
  import '../../tooltip/index.js';
17
- const CONFIRM = 1600;
18
17
  let HelixHeadlessCopyButton = HelixHeadlessCopyButton_1 = class HelixHeadlessCopyButton extends HelixHeadlessIconButton {
19
18
  constructor() {
20
19
  super(...arguments);
21
20
  this.copiedLabel = 'Copied';
22
21
  this.errorLabel = 'Could not copy';
22
+ this.feedbackDuration = 1600;
23
23
  this.from = '';
24
24
  this.label = 'Copy';
25
25
  this.value = '';
26
26
  this.namedBy = null;
27
- this.clipboard = new CopyController(this, { after: CONFIRM });
27
+ this.clipboard = new CopyController(this, Object.defineProperty({}, 'after', { get: () => this.feedbackDuration }));
28
28
  this.handleCopy = async (event) => {
29
29
  if (this.pending) {
30
30
  event.preventDefault();
@@ -34,7 +34,9 @@ let HelixHeadlessCopyButton = HelixHeadlessCopyButton_1 = class HelixHeadlessCop
34
34
  if (this.isDisabled) {
35
35
  return;
36
36
  }
37
- const wrote = await this.clipboard.copy(this.text);
37
+ const copying = this.clipboard.copy(this.text);
38
+ this.announcePress(event);
39
+ const wrote = await copying;
38
40
  if (!wrote && this.isConnected) {
39
41
  this.dispatchEvent(new HelixCopyErrorEvent());
40
42
  }
@@ -78,6 +80,8 @@ let HelixHeadlessCopyButton = HelixHeadlessCopyButton_1 = class HelixHeadlessCop
78
80
  tabindex=${this.focusable ? nothing : '-1'}
79
81
  ?disabled=${this.isDisabled}
80
82
  @click=${this.handleCopy}
83
+ @keydown=${this.notePress}
84
+ @pointerdown=${this.notePress}
81
85
  >
82
86
  ${this.renderCopiedIcon()} ${this.renderFailedIcon()} ${this.renderCopyIcon()}
83
87
  </button>`)}${this.renderLive()}`;
@@ -113,6 +117,9 @@ __decorate([
113
117
  __decorate([
114
118
  property({ attribute: 'error-label' })
115
119
  ], HelixHeadlessCopyButton.prototype, "errorLabel", void 0);
120
+ __decorate([
121
+ property({ attribute: 'feedback-duration', type: Number })
122
+ ], HelixHeadlessCopyButton.prototype, "feedbackDuration", void 0);
116
123
  __decorate([
117
124
  property()
118
125
  ], HelixHeadlessCopyButton.prototype, "from", void 0);
@@ -1,2 +1,2 @@
1
+ export { type Axis, cycle, type DataRow, filter, format, ordered, parse, type Sort, sort, window_, } from '@fusion.dev/helix-core';
1
2
  export { HelixHeadlessDataTable } from './root/data-table-root.js';
2
- export { type Axis, cycle, type DataRow, filter, format, ordered, parse, type Sort, sort, window_, } from './root/order.js';
@@ -1,2 +1,2 @@
1
+ export { cycle, filter, format, ordered, parse, sort, window_, } from '@fusion.dev/helix-core';
1
2
  export { HelixHeadlessDataTable } from './root/data-table-root.js';
2
- export { cycle, filter, format, ordered, parse, sort, window_, } from './root/order.js';
@@ -0,0 +1,24 @@
1
+ /**
2
+ * `keys` in the order the rows are, which is `order`: the keys of the whole
3
+ * result. A key the result does not hold, a selected row a search has hidden
4
+ * say, keeps its place after them in the order it was given.
5
+ *
6
+ * So `selected` and `expanded`, and the events that carry them, read in row
7
+ * order whatever order the rows were chosen in.
8
+ */
9
+ export declare const inRowOrder: (keys: Iterable<string>, order: readonly string[]) => string[];
10
+ /**
11
+ * The `expanded` a toggle of row `key` leaves, in row order, or `undefined`
12
+ * where the row is open or closed already. Keys are split on commas only, so a
13
+ * key may hold a space.
14
+ */
15
+ export declare const toggledOpen: (expanded: string, key: string, open: boolean, order: readonly string[]) => string | undefined;
16
+ /**
17
+ * Where a Shift range runs from, as an index into the page's `keys`: the row
18
+ * last chosen while it is on the page, and otherwise the row the reader is on,
19
+ * `from`, which becomes the one to run from.
20
+ */
21
+ export declare const anchorAt: (keys: readonly string[], anchorKey: string | undefined, from: number) => {
22
+ anchor: number;
23
+ anchorKey: string | undefined;
24
+ };
@@ -0,0 +1,24 @@
1
+ import { commaList } from '@fusion.dev/helix-core';
2
+ export const inRowOrder = (keys, order) => {
3
+ const wanted = new Set(keys);
4
+ const placed = order.filter((key) => wanted.has(key));
5
+ const seen = new Set(placed);
6
+ return [...placed, ...[...wanted].filter((key) => !seen.has(key))];
7
+ };
8
+ export const toggledOpen = (expanded, key, open, order) => {
9
+ const keys = new Set(commaList(expanded));
10
+ if (keys.has(key) === open) {
11
+ return undefined;
12
+ }
13
+ if (open) {
14
+ keys.add(key);
15
+ }
16
+ else {
17
+ keys.delete(key);
18
+ }
19
+ return inRowOrder(keys, order).join(',');
20
+ };
21
+ export const anchorAt = (keys, anchorKey, from) => {
22
+ const anchor = anchorKey === undefined ? -1 : keys.indexOf(anchorKey);
23
+ return anchor < 0 ? { anchor: from, anchorKey: keys[from] } : { anchor, anchorKey };
24
+ };
@@ -1,9 +1,8 @@
1
- import { HelixElement } from '@fusion.dev/helix-core';
1
+ import { type DataRow, HelixElement } from '@fusion.dev/helix-core';
2
2
  import { type PropertyValues, type TemplateResult } from 'lit';
3
3
  import { type HelixHeadlessTableColumn } from '../../table/column/table-column.js';
4
4
  import '../../checkbox/index.js';
5
5
  import '../../pagination/index.js';
6
- import { type DataRow } from './order.js';
7
6
  declare const HelixHeadlessDataTable_base: (new (...args: any[]) => import("@fusion.dev/helix-core").CollectionElement) & typeof HelixElement;
8
7
  /**
9
8
  * @summary A table drawn from an array of rows, with sorting, filtering, and paging.
@@ -44,20 +43,29 @@ declare const HelixHeadlessDataTable_base: (new (...args: any[]) => import("@fus
44
43
  *
45
44
  * To act on a single row, such as opening it, put a link or a button in a cell.
46
45
  *
47
- * The grid is one tab stop, and the arrow keys move between its cells, the
48
- * headings included:
46
+ * **Keyboard.** The grid is one tab stop, and the arrow keys move between its
47
+ * cells, the headings included.
49
48
  *
50
- * - The arrow keys move one cell, and Home and End to the ends of the row.
51
- * - Control with Home or End moves to the first or the last cell of the grid.
52
- * - Page Up and Page Down move by the rows that fit in view.
53
- * - Enter or F2 moves into the cell's controls, and Escape moves back to the
54
- * cell. Tab moves between the controls of one cell.
55
- * - Enter or Space on a sortable heading sorts by it, and Space on a row of a
56
- * `selectable` table selects it.
57
- * - In a `selectable` table, Shift with Up or Down selects the rows it moves
58
- * across, Shift with Space selects every row from the one last chosen, and
59
- * Control or Command with A selects every row.
60
- * - Typing letters moves to the next row whose row header starts with them.
49
+ * | Key | What it does |
50
+ * |---|---|
51
+ * | Right, Left | Moves one cell along the row. Left moves on, on a right-to-left page. |
52
+ * | Down, Up | Moves one row, the heading row and the `load-more` row included. |
53
+ * | Home, End | Moves to the first or the last cell of the row. |
54
+ * | Control with Home or End | Moves to the first or the last cell of the grid. |
55
+ * | Page Down, Page Up | Moves by the rows that fit in view. |
56
+ * | Enter, F2 | Moves into the cell's controls. Escape moves back to the cell, and Tab moves between the controls of one cell. |
57
+ * | Enter, Space on a sortable heading | Sorts by the column. |
58
+ * | Enter, Space on the `load-more` row | Sends `helix-load-more`. |
59
+ * | Space on a row | Selects the row, in a `selectable` table. |
60
+ * | Shift with Down or Up | Selects the rows it moves across, in a `selectable` table. |
61
+ * | Shift with Space | Selects every row from the one last chosen, in a `selectable` table. |
62
+ * | Control or Command with A | Selects every row, in a `selectable` table. |
63
+ * | Right on a row header in a tree grid | Opens a closed row, and moves one cell along an open one. |
64
+ * | Left on a row header in a tree grid | Closes an open row, and moves to the parent of a closed one. |
65
+ * | A letter or a word | Moves to the next row whose row header starts with what you typed. |
66
+ *
67
+ * `selected` and `expanded` hold their keys in the order of the rows, as do
68
+ * `helix-select`, `helix-selected` and `helix-expand`.
61
69
  *
62
70
  * Each row is named by its row header, the column marked `row-header`, or the
63
71
  * first column with a `field` where none is. A screen reader says it as a reader
@@ -485,8 +493,6 @@ export declare class HelixHeadlessDataTable extends HelixHeadlessDataTable_base
485
493
  private anchorKey;
486
494
  /** Whether Shift was held on the last press, for a checkbox that asks to range. */
487
495
  private shiftPressed;
488
- /** The number of rows when `helix-load-more` last went out on its own. */
489
- private askedAt;
490
496
  /** The grid's size as the last render counted it, for the internals. */
491
497
  private counts;
492
498
  /** The order while a grip is being dragged, before anybody has been asked. */
@@ -540,7 +546,10 @@ export declare class HelixHeadlessDataTable extends HelixHeadlessDataTable_base
540
546
  * sorts them.
541
547
  */
542
548
  private tree;
543
- /** The keys of the open rows. */
549
+ /**
550
+ * The keys of the open rows. Split on commas only, as every other list of
551
+ * keys is, so a key may hold a space.
552
+ */
544
553
  private get opened();
545
554
  /**
546
555
  * The result in order: the tree laid out flat in a tree grid, and the