@fusion.dev/helix-headless 0.142.1 → 0.143.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 (217) hide show
  1. package/custom-elements.json +16710 -707
  2. package/dist/accordion/item/accordion-item.d.ts +38 -2
  3. package/dist/accordion/item/accordion-item.js +38 -6
  4. package/dist/accordion/root/accordion-root.d.ts +23 -1
  5. package/dist/accordion/root/accordion-root.js +39 -3
  6. package/dist/announcement/root/announcement-root.d.ts +11 -7
  7. package/dist/announcement/root/announcement-root.js +1 -1
  8. package/dist/app-header/root/app-header-root.d.ts +21 -0
  9. package/dist/app-header/root/app-header-root.js +31 -5
  10. package/dist/area-chart/root/area-chart-root.js +16 -5
  11. package/dist/avatar/group/avatar-group.d.ts +24 -3
  12. package/dist/avatar/group/avatar-group.js +34 -2
  13. package/dist/avatar/root/avatar-root.d.ts +3 -1
  14. package/dist/avatar/root/avatar-root.js +8 -1
  15. package/dist/badge/root/badge-root.d.ts +8 -0
  16. package/dist/bar-chart/root/bar-chart-root.d.ts +19 -3
  17. package/dist/bar-chart/root/bar-chart-root.js +43 -13
  18. package/dist/blockquote/root/blockquote-root.d.ts +12 -7
  19. package/dist/blockquote/root/blockquote-root.js +6 -4
  20. package/dist/breadcrumbs/root/breadcrumbs-root.d.ts +9 -3
  21. package/dist/breadcrumbs/root/breadcrumbs-root.js +9 -1
  22. package/dist/button/root/button-root.d.ts +37 -0
  23. package/dist/button/root/button-root.js +44 -0
  24. package/dist/callout/root/callout-root.d.ts +14 -5
  25. package/dist/callout/root/callout-root.js +11 -3
  26. package/dist/canvas/root/canvas-root.d.ts +1 -0
  27. package/dist/canvas/root/canvas-root.js +10 -1
  28. package/dist/carousel/root/carousel-root.d.ts +47 -5
  29. package/dist/carousel/root/carousel-root.js +53 -21
  30. package/dist/chat/composer/chat-composer.d.ts +13 -11
  31. package/dist/chat/composer/chat-composer.js +6 -12
  32. package/dist/chat/message/chat-message.js +8 -1
  33. package/dist/chat/root/chat-root.d.ts +1 -0
  34. package/dist/chat/root/chat-root.js +2 -1
  35. package/dist/checkbox/root/checkbox-root.d.ts +7 -0
  36. package/dist/checkbox/root/checkbox-root.js +7 -3
  37. package/dist/checkbox-group/root/checkbox-group-root.d.ts +65 -32
  38. package/dist/checkbox-group/root/checkbox-group-root.js +85 -37
  39. package/dist/code/root/code-root.d.ts +1 -1
  40. package/dist/code-block/root/code-block-root.d.ts +19 -0
  41. package/dist/code-block/root/code-block-root.js +21 -1
  42. package/dist/color-input/root/color-input-root.d.ts +26 -1
  43. package/dist/color-input/root/color-input-root.js +32 -3
  44. package/dist/color-picker/root/color-picker-root.d.ts +37 -7
  45. package/dist/color-picker/root/color-picker-root.js +83 -6
  46. package/dist/combobox/root/combobox-root.d.ts +90 -2
  47. package/dist/combobox/root/combobox-root.js +160 -19
  48. package/dist/command/root/command-root.d.ts +17 -6
  49. package/dist/command/root/command-root.js +12 -1
  50. package/dist/copy-button/root/copy-button-root.d.ts +21 -6
  51. package/dist/copy-button/root/copy-button-root.js +11 -1
  52. package/dist/data-table/root/data-table-root.d.ts +164 -10
  53. package/dist/data-table/root/data-table-root.js +488 -57
  54. package/dist/date-input/root/date-input-root.d.ts +53 -8
  55. package/dist/date-input/root/date-input-root.js +70 -18
  56. package/dist/date-picker/root/date-picker-root.d.ts +84 -17
  57. package/dist/date-picker/root/date-picker-root.js +125 -20
  58. package/dist/dialog/root/dialog-root.d.ts +38 -10
  59. package/dist/dialog/root/dialog-root.js +55 -2
  60. package/dist/donut-chart/root/donut-chart-root.d.ts +39 -15
  61. package/dist/donut-chart/root/donut-chart-root.js +30 -10
  62. package/dist/drawer/root/drawer-root.d.ts +32 -7
  63. package/dist/drawer/root/drawer-root.js +50 -5
  64. package/dist/drilldown/item/drilldown-item.d.ts +16 -13
  65. package/dist/drilldown/item/drilldown-item.js +6 -2
  66. package/dist/drilldown/root/drilldown-root.d.ts +21 -5
  67. package/dist/drilldown/root/drilldown-root.js +26 -10
  68. package/dist/element-events.generated.js +35 -9
  69. package/dist/file-input/root/file-input-root.d.ts +18 -1
  70. package/dist/file-input/root/file-input-root.js +34 -8
  71. package/dist/filter-input/menu/filter-menu.d.ts +9 -0
  72. package/dist/filter-input/menu/filter-menu.js +8 -0
  73. package/dist/filter-input/root/filter-input-root.d.ts +5 -2
  74. package/dist/filter-input/root/filter-input-root.js +22 -7
  75. package/dist/format-date/root/format-date-root.d.ts +11 -3
  76. package/dist/format-date/root/format-date-root.js +26 -5
  77. package/dist/graph/root/graph-root.d.ts +24 -3
  78. package/dist/graph/root/graph-root.js +66 -12
  79. package/dist/heatmap/root/buckets.d.ts +2 -1
  80. package/dist/heatmap/root/buckets.js +5 -1
  81. package/dist/heatmap/root/heatmap-root.d.ts +27 -6
  82. package/dist/heatmap/root/heatmap-root.js +23 -6
  83. package/dist/icon/root/icon-root.d.ts +24 -3
  84. package/dist/icon/root/icon-root.js +34 -1
  85. package/dist/icon-button/root/icon-button-root.d.ts +1 -1
  86. package/dist/image/root/image-root.d.ts +9 -2
  87. package/dist/image/root/image-root.js +8 -2
  88. package/dist/input/root/input-root.d.ts +51 -9
  89. package/dist/input/root/input-root.js +46 -5
  90. package/dist/kbd/root/kbd-root.d.ts +12 -4
  91. package/dist/kbd/root/kbd-root.js +10 -11
  92. package/dist/legend/root/legend-root.d.ts +7 -0
  93. package/dist/legend/root/legend-root.js +7 -2
  94. package/dist/lightbox/item/lightbox-item.d.ts +2 -1
  95. package/dist/lightbox/root/lightbox-root.d.ts +16 -5
  96. package/dist/lightbox/root/lightbox-root.js +24 -3
  97. package/dist/line-chart/root/line-chart-root.d.ts +19 -2
  98. package/dist/line-chart/root/line-chart-root.js +40 -13
  99. package/dist/list/item/list-item.d.ts +11 -5
  100. package/dist/list/item/list-item.js +5 -6
  101. package/dist/listbox/root/listbox-root.d.ts +111 -2
  102. package/dist/listbox/root/listbox-root.js +144 -16
  103. package/dist/map/root/map-root.d.ts +19 -4
  104. package/dist/map/root/map-root.js +36 -7
  105. package/dist/megamenu/root/megamenu-root.d.ts +10 -1
  106. package/dist/megamenu/root/megamenu-root.js +10 -1
  107. package/dist/menu/item/menu-item.d.ts +41 -12
  108. package/dist/menu/item/menu-item.js +46 -3
  109. package/dist/menu/root/menu-root.d.ts +32 -2
  110. package/dist/menu/root/menu-root.js +48 -8
  111. package/dist/meter/root/meter-root.d.ts +6 -0
  112. package/dist/meter/root/meter-root.js +18 -2
  113. package/dist/navigation/root/navigation-root.d.ts +10 -2
  114. package/dist/navigation/root/navigation-root.js +13 -2
  115. package/dist/notifications/group/notification-group.d.ts +1 -0
  116. package/dist/notifications/notification/notification.d.ts +12 -0
  117. package/dist/notifications/notification/notification.js +31 -2
  118. package/dist/notifications/root/notifications-root.d.ts +7 -0
  119. package/dist/notifications/root/notifications-root.js +17 -2
  120. package/dist/number-input/root/number-input-root.d.ts +62 -7
  121. package/dist/number-input/root/number-input-root.js +68 -16
  122. package/dist/object-inspector/root/object-inspector-root.d.ts +48 -5
  123. package/dist/object-inspector/root/object-inspector-root.js +91 -11
  124. package/dist/option/root/option-root.d.ts +4 -1
  125. package/dist/option/root/option-root.js +1 -0
  126. package/dist/outline/root/outline-root.d.ts +13 -2
  127. package/dist/outline/root/outline-root.js +4 -2
  128. package/dist/pagination/root/pagination-root.d.ts +19 -1
  129. package/dist/pagination/root/pagination-root.js +49 -9
  130. package/dist/pagination/size/pagination-size.d.ts +13 -3
  131. package/dist/pagination/size/pagination-size.js +7 -0
  132. package/dist/pin-input/root/pin-input-root.d.ts +16 -0
  133. package/dist/pin-input/root/pin-input-root.js +19 -5
  134. package/dist/popover/root/popover-root.d.ts +19 -2
  135. package/dist/popover/root/popover-root.js +22 -1
  136. package/dist/progress/root/progress-root.d.ts +16 -1
  137. package/dist/progress/root/progress-root.js +31 -7
  138. package/dist/qr-code/root/qr-code-root.d.ts +19 -0
  139. package/dist/qr-code/root/qr-code-root.js +29 -1
  140. package/dist/radio/group/radio-group.d.ts +41 -0
  141. package/dist/radio/group/radio-group.js +50 -14
  142. package/dist/radio/root/radio-root.d.ts +8 -5
  143. package/dist/radio/root/radio-root.js +1 -2
  144. package/dist/rating/root/rating-root.d.ts +24 -1
  145. package/dist/rating/root/rating-root.js +24 -7
  146. package/dist/scatter-chart/root/scatter-chart-root.js +15 -7
  147. package/dist/select/root/select-root.d.ts +69 -3
  148. package/dist/select/root/select-root.js +92 -8
  149. package/dist/skeleton/root/skeleton-root.d.ts +14 -3
  150. package/dist/skeleton/root/skeleton-root.js +17 -3
  151. package/dist/skip-link/root/skip-link-root.d.ts +10 -0
  152. package/dist/skip-link/root/skip-link-root.js +15 -1
  153. package/dist/slider/root/slider-root.d.ts +20 -2
  154. package/dist/slider/root/slider-root.js +41 -3
  155. package/dist/sparkline/root/sparkline-root.d.ts +9 -10
  156. package/dist/speed-dial/item/speed-dial-item.d.ts +11 -5
  157. package/dist/speed-dial/item/speed-dial-item.js +7 -2
  158. package/dist/speed-dial/root/speed-dial-root.d.ts +15 -4
  159. package/dist/speed-dial/root/speed-dial-root.js +19 -5
  160. package/dist/splitter/root/splitter-root.d.ts +28 -6
  161. package/dist/splitter/root/splitter-root.js +35 -1
  162. package/dist/stat/root/stat-root.d.ts +7 -1
  163. package/dist/stat/root/stat-root.js +14 -1
  164. package/dist/steps/root/steps-root.js +1 -1
  165. package/dist/switch/root/switch-root.d.ts +2 -0
  166. package/dist/switch/root/switch-root.js +1 -0
  167. package/dist/table/cell/table-cell.d.ts +24 -4
  168. package/dist/table/cell/table-cell.js +21 -1
  169. package/dist/table/column/table-column.d.ts +32 -6
  170. package/dist/table/column/table-column.js +36 -6
  171. package/dist/table/root/table-root.d.ts +94 -3
  172. package/dist/table/root/table-root.js +128 -5
  173. package/dist/table/row/table-row.d.ts +7 -0
  174. package/dist/table/row/table-row.js +9 -1
  175. package/dist/tabs/root/tabs-root.d.ts +6 -1
  176. package/dist/tabs/root/tabs-root.js +6 -2
  177. package/dist/tag/root/tag-root.d.ts +23 -1
  178. package/dist/tag/root/tag-root.js +16 -2
  179. package/dist/textarea/root/textarea-root.d.ts +4 -0
  180. package/dist/textarea/root/textarea-root.js +1 -1
  181. package/dist/time-input/root/time-input-root.d.ts +28 -2
  182. package/dist/time-input/root/time-input-root.js +46 -10
  183. package/dist/time-picker/root/time-picker-root.d.ts +101 -18
  184. package/dist/time-picker/root/time-picker-root.js +115 -16
  185. package/dist/toast/root/toast-root.d.ts +64 -1
  186. package/dist/toast/root/toast-root.js +147 -2
  187. package/dist/toggle/group/toggle-group.d.ts +38 -1
  188. package/dist/toggle/group/toggle-group.js +34 -8
  189. package/dist/toggle/root/toggle-root.d.ts +14 -10
  190. package/dist/toggle/root/toggle-root.js +3 -3
  191. package/dist/toolbar/root/toolbar-root.d.ts +55 -15
  192. package/dist/toolbar/root/toolbar-root.js +99 -16
  193. package/dist/tooltip/root/tooltip-root.d.ts +37 -4
  194. package/dist/tooltip/root/tooltip-root.js +48 -0
  195. package/dist/tour/root/tour-root.d.ts +34 -5
  196. package/dist/tour/root/tour-root.js +51 -14
  197. package/dist/tour/stop/tour-stop.d.ts +18 -1
  198. package/dist/tour/stop/tour-stop.js +25 -5
  199. package/dist/tree/item/tree-item.d.ts +21 -5
  200. package/dist/tree/item/tree-item.js +14 -4
  201. package/dist/tree/root/tree-root.d.ts +29 -5
  202. package/dist/tree/root/tree-root.js +64 -8
  203. package/dist/trend/root/trend-root.d.ts +23 -1
  204. package/dist/trend/root/trend-root.js +28 -7
  205. package/dist/video/root/keys.d.ts +5 -0
  206. package/dist/video/root/keys.js +13 -1
  207. package/dist/video/root/video-root.d.ts +19 -0
  208. package/dist/video/root/video-root.js +48 -4
  209. package/dist/video-playlist/menu/video-playlist-menu.d.ts +20 -2
  210. package/dist/video-playlist/menu/video-playlist-menu.js +27 -5
  211. package/dist/video-playlist/root/video-playlist-root.js +6 -3
  212. package/dist/virtual-list/root/virtual-list-root.d.ts +52 -4
  213. package/dist/virtual-list/root/virtual-list-root.js +103 -21
  214. package/lint.json +1 -1
  215. package/package.json +5 -5
  216. package/types/jsx.d.ts +4348 -965
  217. package/types/vue.d.ts +972 -232
@@ -5,7 +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
  var HelixHeadlessDataTable_1;
8
- import { customElement, fillTemplate, formatNumbers, HelixElement, HelixFilterEvent, HelixNavigateEvent, HelixReorderEvent, HelixSelectEvent, HelixSortEvent, hostAria, inlineStep, isRtl, MixinCollection, markRegion, reportRuntime, requestChange, VirtualizeController, writtenList, } from '@fusion.dev/helix-core';
8
+ import { customElement, deepActiveElement, deepContains, fillTemplate, formatNumbers, HelixActivateEvent, HelixElement, HelixFilterEvent, HelixFilteredEvent, HelixNavigateEvent, HelixReorderEvent, HelixReorderedEvent, HelixSelectEvent, HelixSelectedEvent, HelixSortEvent, HelixSortedEvent, hostAria, inlineStep, isRtl, MixinCollection, markRegion, reportRuntime, requestChange, VirtualizeController, writtenList, } from '@fusion.dev/helix-core';
9
9
  import { nothing } from 'lit';
10
10
  import { property, state } from 'lit/decorators.js';
11
11
  import { repeat } from 'lit/directives/repeat.js';
@@ -14,6 +14,16 @@ import { at, edgeOf } from '../../table/column/table-column.js';
14
14
  import '../../checkbox/index.js';
15
15
  import '../../pagination/index.js';
16
16
  import { arranged, cycle, format, ordered, parse, window_, } from './order.js';
17
+ const CONTROL = [
18
+ 'a[href]',
19
+ 'button:not([disabled])',
20
+ 'input:not([disabled])',
21
+ 'select:not([disabled])',
22
+ 'textarea:not([disabled])',
23
+ '[contenteditable]:not([contenteditable="false"])',
24
+ '[tabindex]',
25
+ ].join(',');
26
+ const isControl = (element) => element.matches(CONTROL) || element.shadowRoot?.delegatesFocus === true;
17
27
  let HelixHeadlessDataTable = class HelixHeadlessDataTable extends MixinCollection(HelixElement) {
18
28
  constructor() {
19
29
  super(...arguments);
@@ -26,13 +36,22 @@ let HelixHeadlessDataTable = class HelixHeadlessDataTable extends MixinCollectio
26
36
  this.defaultSort = '';
27
37
  this.descendingLabel = 'descending';
28
38
  this.estimate = 32;
39
+ this.gapLabel = 'Skip to page {page}';
29
40
  this.label = '';
30
41
  this.mode = 'client';
42
+ this.nextLabel = 'Next page';
43
+ this.pageLabel = 'Page {page}';
44
+ this.paginationLabel = 'Pagination';
45
+ this.previousLabel = 'Previous page';
31
46
  this.reorderable = false;
47
+ this.resultLabel = '{count} result';
48
+ this.resultsLabel = '{count} results';
32
49
  this.rowKey = '';
33
50
  this.rows = [];
34
51
  this.selectable = false;
52
+ this.selectAllLabel = 'Select every row';
35
53
  this.selectedLabel = '{count} selected';
54
+ this.selectRowLabel = 'Select {row}';
36
55
  this.sortedLabel = 'Sorted by {column}, {order}';
37
56
  this.total = 0;
38
57
  this.unsortedLabel = 'Not sorted';
@@ -44,6 +63,15 @@ let HelixHeadlessDataTable = class HelixHeadlessDataTable extends MixinCollectio
44
63
  this.paginatedState = undefined;
45
64
  this.orderState = undefined;
46
65
  this.selectedState = undefined;
66
+ this.activeRow = undefined;
67
+ this.activeColumn = 0;
68
+ this.activeKey = undefined;
69
+ this.focusWanted = false;
70
+ this.drawnPage = [];
71
+ this.counts = {
72
+ columns: undefined,
73
+ rows: undefined,
74
+ };
47
75
  this.dragOrder = undefined;
48
76
  this.warnedAboutKey = false;
49
77
  this.virtualize = new VirtualizeController(this, {
@@ -56,33 +84,15 @@ let HelixHeadlessDataTable = class HelixHeadlessDataTable extends MixinCollectio
56
84
  this.warnedAboutSize = false;
57
85
  this.toggleRow = (key, event) => {
58
86
  event.preventDefault();
59
- const keys = this.chosen;
60
- if (event.detail.checked) {
61
- keys.add(key);
62
- }
63
- else {
64
- keys.delete(key);
65
- }
66
- this.requestSelected(keys);
87
+ this.chooseRow(key, event.detail.checked);
67
88
  };
68
89
  this.toggleAll = (event) => {
69
90
  event.preventDefault();
70
- const every = this.everyKey;
71
- const keys = this.chosen;
72
- if (every.length > 0 && every.every((key) => keys.has(key))) {
73
- for (const key of every) {
74
- keys.delete(key);
75
- }
76
- }
77
- else {
78
- for (const key of every) {
79
- keys.add(key);
80
- }
81
- }
82
- this.requestSelected(keys);
91
+ this.chooseAll();
83
92
  };
84
93
  this.heardSort = undefined;
85
94
  this.heardSelected = undefined;
95
+ this.heardFilter = undefined;
86
96
  this.handleSlotChange = () => {
87
97
  this.requestUpdate();
88
98
  };
@@ -101,6 +111,81 @@ let HelixHeadlessDataTable = class HelixHeadlessDataTable extends MixinCollectio
101
111
  this.toggleSort(column.field);
102
112
  }
103
113
  };
114
+ this.hadFocus = false;
115
+ this.handleFocusIn = (event) => {
116
+ const place = this.placeOf(event);
117
+ if (!place) {
118
+ return;
119
+ }
120
+ if (place.row >= 0 && this.keptRow(this.drawnPage) === place.row) {
121
+ this.virtualize.reveal(place.row, this.headHeight());
122
+ }
123
+ if (this.activeRow === undefined ||
124
+ place.row !== this.currentRow(this.drawnPage) ||
125
+ place.column !== this.currentColumn) {
126
+ const page = this.drawnPage;
127
+ this.activeRow = place.row;
128
+ this.activeColumn = place.column;
129
+ this.activeKey =
130
+ place.row >= 0 && this.rowKey && page[place.row]
131
+ ? this.rowKeyOf(page[place.row], place.row)
132
+ : undefined;
133
+ }
134
+ };
135
+ this.handleGridKey = (event) => {
136
+ if (event.defaultPrevented || event.altKey) {
137
+ return;
138
+ }
139
+ const place = this.placeOf(event);
140
+ if (!place) {
141
+ return;
142
+ }
143
+ if (event.composedPath()[0] !== place.cell) {
144
+ this.handleControlKey(event, place);
145
+ return;
146
+ }
147
+ const last = this.drawnPage.length - 1;
148
+ const edge = this.width - 1;
149
+ const control = event.ctrlKey || event.metaKey;
150
+ let { column, row } = place;
151
+ switch (event.key) {
152
+ case 'ArrowUp':
153
+ row = Math.max(-1, row - 1);
154
+ break;
155
+ case 'ArrowDown':
156
+ row = Math.min(last, row + 1);
157
+ break;
158
+ case 'ArrowLeft':
159
+ case 'ArrowRight':
160
+ column = Math.max(0, Math.min(edge, column + inlineStep(this, event.key)));
161
+ break;
162
+ case 'Home':
163
+ row = control ? -1 : row;
164
+ column = 0;
165
+ break;
166
+ case 'End':
167
+ row = control ? Math.max(row, last) : row;
168
+ column = edge;
169
+ break;
170
+ case 'PageUp':
171
+ row = Math.max(-1, row - this.pageStep(place.cell));
172
+ break;
173
+ case 'PageDown':
174
+ row = Math.min(last, row + this.pageStep(place.cell));
175
+ break;
176
+ case 'Enter':
177
+ case ' ':
178
+ case 'F2':
179
+ this.activate(event, place);
180
+ return;
181
+ default:
182
+ return;
183
+ }
184
+ event.preventDefault();
185
+ if (row !== place.row || column !== place.column) {
186
+ this.moveTo(row, column);
187
+ }
188
+ };
104
189
  this.handleGripKey = (event) => {
105
190
  if (!this.partIn(event, 'grip')) {
106
191
  return;
@@ -163,6 +248,9 @@ let HelixHeadlessDataTable = class HelixHeadlessDataTable extends MixinCollectio
163
248
  this.handleResize = () => {
164
249
  queueMicrotask(() => this.requestUpdate());
165
250
  };
251
+ this.stopPageNotification = (event) => {
252
+ event.stopPropagation();
253
+ };
166
254
  this.handleNavigate = (event) => {
167
255
  event.stopPropagation();
168
256
  const wanted = Number(event.detail.value);
@@ -234,7 +322,12 @@ let HelixHeadlessDataTable = class HelixHeadlessDataTable extends MixinCollectio
234
322
  this.requestUpdate('sort', previous);
235
323
  }
236
324
  drawn() {
237
- return [...this.renderRoot.querySelectorAll('[part="row"][data-index]')].map((element) => ({ element, index: Number(element.dataset.index) }));
325
+ return [...this.renderRoot.querySelectorAll('[part="row"][data-index]')].flatMap((row) => {
326
+ const cell = row.firstElementChild;
327
+ return cell instanceof HTMLElement
328
+ ? [{ element: cell, index: Number(row.dataset.index) }]
329
+ : [];
330
+ });
238
331
  }
239
332
  get available() {
240
333
  if (this.mode === 'server') {
@@ -258,11 +351,53 @@ let HelixHeadlessDataTable = class HelixHeadlessDataTable extends MixinCollectio
258
351
  return value;
259
352
  }
260
353
  windowOf(rows) {
354
+ const all = rows.map((row, index) => ({ index, row }));
355
+ if (!this.windowed) {
356
+ return all;
357
+ }
358
+ const { first, last } = this.virtualize.window;
359
+ const drawn = all.slice(first, last);
360
+ const kept = this.keptRow(rows);
361
+ if (kept === undefined) {
362
+ return drawn;
363
+ }
364
+ const row = rows[kept];
365
+ return kept < first ? [{ index: kept, row }, ...drawn] : [...drawn, { index: kept, row }];
366
+ }
367
+ keptRow(rows) {
261
368
  if (!this.windowed) {
262
- return rows;
369
+ return undefined;
263
370
  }
371
+ const row = this.currentRow(rows);
264
372
  const { first, last } = this.virtualize.window;
265
- return rows.slice(first, last);
373
+ return row >= 0 && (row < first || row >= last) ? row : undefined;
374
+ }
375
+ rowKeyOf(row, index) {
376
+ if (!this.rowKey) {
377
+ return String(index);
378
+ }
379
+ const value = at(row, this.rowKey);
380
+ return value === undefined || value === null ? String(index) : String(value);
381
+ }
382
+ currentRow(rows) {
383
+ const asked = this.activeRow;
384
+ if (asked === undefined) {
385
+ const first = this.windowed ? this.virtualize.window.first : 0;
386
+ return rows.length > 0 ? Math.min(first, rows.length - 1) : -1;
387
+ }
388
+ if (asked >= 0 && this.activeKey !== undefined && this.rowKey) {
389
+ const found = rows.findIndex((row, index) => this.rowKeyOf(row, index) === this.activeKey);
390
+ if (found >= 0) {
391
+ return found;
392
+ }
393
+ }
394
+ return Math.min(asked, rows.length - 1);
395
+ }
396
+ get width() {
397
+ return this.shownColumns.length + (this.selectable ? 1 : 0);
398
+ }
399
+ get currentColumn() {
400
+ return Math.max(0, Math.min(this.activeColumn, this.width - 1));
266
401
  }
267
402
  get tableColumns() {
268
403
  return this.knownChildren.filter((child) => 'isTableColumn' in child && child.isTableColumn === true);
@@ -320,12 +455,7 @@ let HelixHeadlessDataTable = class HelixHeadlessDataTable extends MixinCollectio
320
455
  get view() {
321
456
  if (this.mode === 'server') {
322
457
  const total = Math.max(this.total, this.rows.length);
323
- return {
324
- available: this.rows.length,
325
- matched: total,
326
- rows: this.windowOf([...this.rows]),
327
- total,
328
- };
458
+ return { available: this.rows.length, matched: total, page: this.rows, total };
329
459
  }
330
460
  if (!this.windowed) {
331
461
  const view = ordered(this.rows, this.axes, {
@@ -335,11 +465,16 @@ let HelixHeadlessDataTable = class HelixHeadlessDataTable extends MixinCollectio
335
465
  spec: this.sort,
336
466
  });
337
467
  this.warnIfCrowded(view.rows.length);
338
- return { ...view, available: view.rows.length };
468
+ return {
469
+ available: view.rows.length,
470
+ matched: view.matched,
471
+ page: view.rows,
472
+ total: view.total,
473
+ };
339
474
  }
340
475
  const { rows: inOrder, total } = this.arrange();
341
476
  const page = window_(inOrder, this.page, this.pageSize);
342
- return { available: page.length, matched: inOrder.length, rows: this.windowOf(page), total };
477
+ return { available: page.length, matched: inOrder.length, page, total };
343
478
  }
344
479
  get pages() {
345
480
  const size = this.pageSize;
@@ -375,6 +510,7 @@ let HelixHeadlessDataTable = class HelixHeadlessDataTable extends MixinCollectio
375
510
  const previous = this.sort;
376
511
  this.sortState = value;
377
512
  this.requestUpdate('sort', previous);
513
+ this.dispatchEvent(new HelixSortedEvent({ value }));
378
514
  },
379
515
  event: (value) => new HelixSortEvent({ value }),
380
516
  host: this,
@@ -387,6 +523,7 @@ let HelixHeadlessDataTable = class HelixHeadlessDataTable extends MixinCollectio
387
523
  const previous = this.order;
388
524
  this.orderState = value;
389
525
  this.requestUpdate('order', previous);
526
+ this.dispatchEvent(new HelixReorderedEvent({ value }));
390
527
  },
391
528
  event: (value) => new HelixReorderEvent({ value }),
392
529
  host: this,
@@ -399,6 +536,7 @@ let HelixHeadlessDataTable = class HelixHeadlessDataTable extends MixinCollectio
399
536
  const previous = this.selected;
400
537
  this.selectedState = value;
401
538
  this.requestUpdate('selected', previous);
539
+ this.dispatchEvent(new HelixSelectedEvent({ value }));
402
540
  },
403
541
  event: (value) => new HelixSelectEvent({ value }),
404
542
  host: this,
@@ -430,6 +568,31 @@ let HelixHeadlessDataTable = class HelixHeadlessDataTable extends MixinCollectio
430
568
  const rows = this.mode === 'server' ? this.rows : this.arrange().rows;
431
569
  return rows.map((row, place) => this.keyOf(row, place));
432
570
  }
571
+ chooseRow(key, checked) {
572
+ const keys = this.chosen;
573
+ if (checked) {
574
+ keys.add(key);
575
+ }
576
+ else {
577
+ keys.delete(key);
578
+ }
579
+ this.requestSelected(keys);
580
+ }
581
+ chooseAll() {
582
+ const every = this.everyKey;
583
+ const keys = this.chosen;
584
+ if (every.length > 0 && every.every((key) => keys.has(key))) {
585
+ for (const key of every) {
586
+ keys.delete(key);
587
+ }
588
+ }
589
+ else {
590
+ for (const key of every) {
591
+ keys.add(key);
592
+ }
593
+ }
594
+ this.requestSelected(keys);
595
+ }
433
596
  moveColumn(field, by) {
434
597
  const drawn = this.shownColumns.filter((column) => column.field !== '');
435
598
  const from = drawn.findIndex((column) => column.field === field);
@@ -467,6 +630,7 @@ let HelixHeadlessDataTable = class HelixHeadlessDataTable extends MixinCollectio
467
630
  const previous = this.filter;
468
631
  this.filterState = value;
469
632
  this.requestUpdate('filter', previous);
633
+ this.dispatchEvent(new HelixFilteredEvent({ value }));
470
634
  },
471
635
  event: (value) => new HelixFilterEvent({ value }),
472
636
  host: this,
@@ -482,6 +646,7 @@ let HelixHeadlessDataTable = class HelixHeadlessDataTable extends MixinCollectio
482
646
  const previous = this.page;
483
647
  this.pageState = value;
484
648
  this.requestUpdate('page', previous);
649
+ this.dispatchEvent(new HelixActivateEvent({ value: String(value) }));
485
650
  },
486
651
  event: (value) => new HelixNavigateEvent({ value: String(value) }),
487
652
  host: this,
@@ -544,12 +709,21 @@ let HelixHeadlessDataTable = class HelixHeadlessDataTable extends MixinCollectio
544
709
  count: formatNumbers(this.lang)(this.chosen.size),
545
710
  });
546
711
  }
712
+ else if (this.hasUpdated && this.filter !== this.heardFilter) {
713
+ const count = this.mode === 'server' ? Math.max(this.total, this.rows.length) : this.matched;
714
+ const one = new Intl.PluralRules(this.lang || undefined).select(count) === 'one';
715
+ said = fillTemplate(one ? this.resultLabel : this.resultsLabel, {
716
+ count: formatNumbers(this.lang)(count),
717
+ });
718
+ }
547
719
  this.heardSort = sort;
548
720
  this.heardSelected = selected;
721
+ this.heardFilter = this.filter;
549
722
  return said;
550
723
  }
551
724
  willUpdate(changed) {
552
725
  super.willUpdate(changed);
726
+ this.hadFocus = this.hasUpdated && this.gridHasFocus();
553
727
  this.announced = this.news();
554
728
  hostAria(this.internals, { label: this.label || 'Table', role: 'grid' });
555
729
  this.internals.ariaMultiSelectable = this.selectable ? 'true' : null;
@@ -565,17 +739,27 @@ let HelixHeadlessDataTable = class HelixHeadlessDataTable extends MixinCollectio
565
739
  }
566
740
  updated(changed) {
567
741
  super.updated(changed);
742
+ this.internals.ariaRowCount = this.counts.rows === undefined ? null : String(this.counts.rows);
743
+ this.internals.ariaColCount =
744
+ this.counts.columns === undefined ? null : String(this.counts.columns);
568
745
  this.markEmpty();
569
746
  this.assign();
570
747
  this.announceSort();
748
+ this.quietControls();
749
+ this.placeFocus();
571
750
  if (this.windowed) {
572
751
  this.virtualize.measure();
573
752
  }
574
753
  }
575
754
  announceSort() {
576
755
  const current = parse(this.sort);
756
+ const stop = this.currentRow(this.drawnPage) === -1 ? this.currentColumn : -1;
757
+ const offset = this.selectable ? 1 : 0;
758
+ const shown = this.shownColumns;
577
759
  for (const column of this.tableColumns) {
578
760
  column.movable = this.reorderable && column.field !== '';
761
+ column.gridCell = true;
762
+ column.tabStop = shown.indexOf(column) + offset === stop;
579
763
  column.sorted =
580
764
  current && column.canSort && column.field === current.field
581
765
  ? current.direction === 'asc'
@@ -584,11 +768,13 @@ let HelixHeadlessDataTable = class HelixHeadlessDataTable extends MixinCollectio
584
768
  : undefined;
585
769
  }
586
770
  }
587
- renderCell(column, row, picked) {
771
+ renderCell(column, row, picked, place, stop) {
588
772
  const edge = edgeOf(column.textAlign);
589
773
  return html `<span
590
774
  part="cell${picked ? ' cell-selected' : ''}"
591
775
  role="gridcell"
776
+ tabindex=${stop ? '0' : '-1'}
777
+ data-column=${place}
592
778
  style=${edge ? `--data-table-cell-align: ${edge}` : nothing}
593
779
  >${column.read(row)}</span
594
780
  >`;
@@ -602,86 +788,107 @@ let HelixHeadlessDataTable = class HelixHeadlessDataTable extends MixinCollectio
602
788
  mark-checked: checkbox-mark-checked, mark-dash: checkbox-mark-dash,
603
789
  mark-indeterminate: checkbox-mark-indeterminate"
604
790
  aria-label=${name}
791
+ tabindex="-1"
605
792
  .checked=${checked}
606
793
  .indeterminate=${indeterminate}
607
794
  @helix-before-toggle=${toggle}
608
795
  ></${checkbox}>`;
609
796
  }
610
- renderRows(rows) {
797
+ renderRows(rows, page) {
611
798
  const columns = this.shownColumns;
612
- const field = this.rowKey;
613
- const start = this.windowStart;
614
799
  const chosen = this.selectable ? this.chosen : undefined;
615
800
  const named = columns.find((column) => column.field !== '');
616
- return html `${repeat(rows, (row, index) => (field ? String(row[field] ?? start + index) : start + index), (row, index) => {
801
+ const stopRow = this.currentRow(page);
802
+ const stopColumn = this.currentColumn;
803
+ const offset = this.selectable ? 1 : 0;
804
+ return html `${repeat(rows, ({ index, row }) => this.rowKeyOf(row, index), ({ index, row }) => {
617
805
  const key = chosen ? this.keyOf(row, this.rowIndex(index) - 2) : '';
618
806
  const picked = chosen?.has(key) ?? false;
807
+ const stop = (place) => index === stopRow && place === stopColumn;
619
808
  return html `<div
620
809
  part="row"
621
810
  role="row"
622
811
  aria-rowindex=${this.rowIndex(index)}
623
812
  aria-selected=${chosen ? String(picked) : nothing}
624
- data-index=${this.windowed ? start + index : nothing}
813
+ data-index=${this.windowed ? index : nothing}
814
+ data-row=${index}
625
815
  >
626
816
  ${chosen
627
- ? html `<span part="select${picked ? ' select-selected' : ''}" role="gridcell"
628
- >${this.renderCheckbox(`Select ${named ? String(named.order(row) ?? key) : key}`, picked, false, (event) => this.toggleRow(key, event))}</span
817
+ ? html `<span
818
+ part="select${picked ? ' select-selected' : ''}"
819
+ role="gridcell"
820
+ tabindex=${stop(0) ? '0' : '-1'}
821
+ data-column="0"
822
+ >${this.renderCheckbox(fillTemplate(this.selectRowLabel, {
823
+ row: named ? String(named.order(row) ?? key) : key,
824
+ }), picked, false, (event) => this.toggleRow(key, event))}</span
629
825
  >`
630
- : nothing}${columns.map((column) => this.renderCell(column, row, picked))}
826
+ : nothing}${columns.map((column, place) => this.renderCell(column, row, picked, place + offset, stop(place + offset)))}
631
827
  </div>`;
632
828
  })}`;
633
829
  }
634
830
  rowIndex(within) {
635
831
  const size = this.pageSize;
636
832
  const page = size > 0 ? (this.page - 1) * size : 0;
637
- return page + this.windowStart + within + 2;
833
+ return page + within + 2;
638
834
  }
639
835
  get placement() {
640
836
  return [this.mode, this.filter, this.sort, this.page, this.pageSize].join('\u0000');
641
837
  }
642
- get windowStart() {
643
- return this.windowed ? this.virtualize.window.first : 0;
644
- }
645
- renderSpacer(end) {
838
+ renderSpacer(end, kept) {
646
839
  if (!this.windowed) {
647
840
  return nothing;
648
841
  }
649
- const { after, before } = this.virtualize.window;
842
+ const window = this.virtualize.window;
843
+ const room = kept === undefined ? 0 : this.virtualize.sizeOf(kept);
844
+ const before = Math.max(0, window.before - (kept !== undefined && kept < window.first ? room : 0));
845
+ const after = Math.max(0, window.after - (kept !== undefined && kept >= window.last ? room : 0));
650
846
  return end === 'before'
651
847
  ? html `<div part="before" role="presentation" style="block-size: ${before}px"></div>`
652
848
  : html `<div part="after" role="presentation" style="block-size: ${after}px"></div>`;
653
849
  }
654
- renderSelectAll() {
850
+ renderSelectAll(stop) {
655
851
  const every = this.everyKey;
656
852
  const keys = this.chosen;
657
853
  const count = every.filter((key) => keys.has(key)).length;
658
- return html `<span part="select-all" role="columnheader">${this.renderCheckbox('Select every row', every.length > 0 && count === every.length, count > 0 && count < every.length, this.toggleAll)}</span>`;
854
+ return html `<span
855
+ part="select-all"
856
+ role="columnheader"
857
+ tabindex=${stop ? '0' : '-1'}
858
+ data-column="0"
859
+ >${this.renderCheckbox(this.selectAllLabel, every.length > 0 && count === every.length, count > 0 && count < every.length, this.toggleAll)}</span>`;
659
860
  }
660
861
  render() {
661
- const { available, matched, rows } = this.view;
862
+ const { available, matched, page } = this.view;
863
+ this.drawnPage = page;
864
+ const rows = this.windowOf(page);
865
+ const kept = this.keptRow(page);
866
+ const headStop = this.currentRow(page) === -1;
662
867
  const filled = this.hasRows;
663
868
  const template = this.template;
664
869
  const columns = this.shownColumns;
665
870
  const pagination = this.tag('pagination');
666
871
  const counted = this.mode === 'server' ? Math.max(this.total, available) : matched;
667
872
  const countKnown = counted > 0 || this.sourceKnown;
873
+ this.counts = {
874
+ columns: columns.length ? columns.length + (this.selectable ? 1 : 0) : undefined,
875
+ rows: countKnown ? counted + 1 : undefined,
876
+ };
668
877
  return html `<div part="toolbar"><slot name="toolbar"></slot></div>
669
878
  <div
670
879
  part="table"
671
880
  role="rowgroup"
672
881
  aria-busy=${this.loading ? 'true' : nothing}
673
- aria-rowcount=${countKnown ? counted + 1 : nothing}
674
- aria-colcount=${columns.length ? columns.length + (this.selectable ? 1 : 0) : nothing}
675
882
  style=${template ? `--data-table-template: ${template}` : nothing}
676
883
  @scroll=${this.handleScroll}
677
884
  >
678
- <div part="head" role="row">
679
- ${this.selectable ? this.renderSelectAll() : nothing}${this.assignsByName && !this.hydrating
885
+ <div part="head" role="row" aria-rowindex="1">
886
+ ${this.selectable ? this.renderSelectAll(headStop && this.currentColumn === 0) : nothing}${this.assignsByName && !this.hydrating
680
887
  ? this.orderedColumns.map((_, index) => html `<slot name=${`column-${index + 1}`} @slotchange=${this.handleSlotChange}></slot>`)
681
888
  : html `<slot name="columns" @slotchange=${this.handleSlotChange}></slot>`}
682
889
  </div>
683
- ${this.renderSpacer('before')}${this.renderRows(rows)}${this.renderSpacer('after')}
684
- ${this.renderStatus(filled)}
890
+ ${this.renderSpacer('before', kept)}${this.renderRows(rows, page)}${this.renderSpacer('after', kept)}
891
+ ${this.renderStatus(filled, 'gridcell')}
685
892
  </div>
686
893
  ${this.renderLive(filled)}
687
894
  <div part="footer">
@@ -697,7 +904,13 @@ let HelixHeadlessDataTable = class HelixHeadlessDataTable extends MixinCollectio
697
904
  page=${this.page}
698
905
  page-size=${this.pageSize || 1}
699
906
  total=${countKnown ? matched : nothing}
907
+ label=${this.paginationLabel}
908
+ gap-label=${this.gapLabel}
909
+ next-label=${this.nextLabel}
910
+ page-label=${this.pageLabel}
911
+ previous-label=${this.previousLabel}
700
912
  @helix-navigate=${this.handleNavigate}
913
+ @helix-activate=${this.stopPageNotification}
701
914
  ></${pagination}>`
702
915
  : nothing}
703
916
  </div>`;
@@ -705,6 +918,8 @@ let HelixHeadlessDataTable = class HelixHeadlessDataTable extends MixinCollectio
705
918
  connectedCallback() {
706
919
  super.connectedCallback();
707
920
  this.addEventListener('click', this.handleHeadClick);
921
+ this.addEventListener('focusin', this.handleFocusIn);
922
+ this.addEventListener('keydown', this.handleGridKey);
708
923
  this.addEventListener('keydown', this.handleGripKey);
709
924
  this.addEventListener('pointerdown', this.handleGripDown);
710
925
  this.addEventListener('helix-before-resize', this.handleResize);
@@ -712,11 +927,194 @@ let HelixHeadlessDataTable = class HelixHeadlessDataTable extends MixinCollectio
712
927
  disconnectedCallback() {
713
928
  super.disconnectedCallback();
714
929
  this.removeEventListener('click', this.handleHeadClick);
930
+ this.removeEventListener('focusin', this.handleFocusIn);
931
+ this.removeEventListener('keydown', this.handleGridKey);
715
932
  this.removeEventListener('keydown', this.handleGripKey);
716
933
  this.removeEventListener('pointerdown', this.handleGripDown);
717
934
  this.removeEventListener('helix-before-resize', this.handleResize);
718
935
  this.stopDrag();
719
936
  }
937
+ cellAt(row, column) {
938
+ const offset = this.selectable ? 1 : 0;
939
+ if (row === -1) {
940
+ return column < offset
941
+ ? this.partNamed('select-all')
942
+ : (this.shownColumns[column - offset]?.cellBox ?? null);
943
+ }
944
+ const line = this.renderRoot.querySelector(`[part="row"][data-row="${row}"]`);
945
+ return line?.querySelector(`:scope > [data-column="${column}"]`) ?? null;
946
+ }
947
+ placeOf(event) {
948
+ const columns = this.shownColumns;
949
+ const offset = this.selectable ? 1 : 0;
950
+ for (const node of event.composedPath()) {
951
+ if (node === this) {
952
+ break;
953
+ }
954
+ if (!(node instanceof HTMLElement)) {
955
+ continue;
956
+ }
957
+ const index = columns.indexOf(node);
958
+ if (index >= 0) {
959
+ const cell = node.cellBox;
960
+ return cell ? { cell, column: index + offset, row: -1 } : undefined;
961
+ }
962
+ const role = node.getAttribute('role');
963
+ if (node.dataset.column !== undefined &&
964
+ (role === 'gridcell' || role === 'columnheader') &&
965
+ node.getRootNode() === this.renderRoot) {
966
+ const line = node.parentElement?.dataset.row;
967
+ return {
968
+ cell: node,
969
+ column: Number(node.dataset.column),
970
+ row: line === undefined ? -1 : Number(line),
971
+ };
972
+ }
973
+ }
974
+ return undefined;
975
+ }
976
+ controlsIn(place) {
977
+ const offset = this.selectable ? 1 : 0;
978
+ if (place.row === -1 && place.column >= offset) {
979
+ return this.shownColumns[place.column - offset]?.controls ?? [];
980
+ }
981
+ return [...place.cell.querySelectorAll('*')].filter(isControl);
982
+ }
983
+ quietControls() {
984
+ const offset = this.selectable ? 1 : 0;
985
+ const drawn = this.shownColumns;
986
+ const read = new Set(drawn.flatMap((column, place) => (column.cell ? [place + offset] : [])));
987
+ if (read.size === 0) {
988
+ return;
989
+ }
990
+ for (const cell of this.renderRoot.querySelectorAll('[part~="cell"]')) {
991
+ if (!read.has(Number(cell.dataset.column))) {
992
+ continue;
993
+ }
994
+ for (const control of cell.querySelectorAll('*')) {
995
+ if (isControl(control) && control.getAttribute('tabindex') !== '-1') {
996
+ control.setAttribute('tabindex', '-1');
997
+ }
998
+ }
999
+ }
1000
+ }
1001
+ moveTo(row, column) {
1002
+ const page = this.drawnPage;
1003
+ this.activeRow = row;
1004
+ this.activeColumn = column;
1005
+ this.activeKey =
1006
+ row >= 0 && this.rowKey && page[row] ? this.rowKeyOf(page[row], row) : undefined;
1007
+ this.focusWanted = true;
1008
+ }
1009
+ pageStep(cell) {
1010
+ const box = this.partNamed('table');
1011
+ const tall = cell.getBoundingClientRect().height || this.estimate;
1012
+ const scrolls = box !== null && box.scrollHeight > box.clientHeight + 1;
1013
+ const room = scrolls ? box.clientHeight - this.headHeight() : window.innerHeight;
1014
+ return Math.max(1, Math.floor(room / tall) - 1);
1015
+ }
1016
+ headHeight() {
1017
+ return this.cellAt(-1, 0)?.getBoundingClientRect().height ?? 0;
1018
+ }
1019
+ gridHasFocus() {
1020
+ const active = deepActiveElement();
1021
+ const grid = this.partNamed('table');
1022
+ if (!active || !grid) {
1023
+ return false;
1024
+ }
1025
+ return (deepContains(grid, active) || this.shownColumns.some((column) => deepContains(column, active)));
1026
+ }
1027
+ placeFocus() {
1028
+ const lost = this.hadFocus &&
1029
+ !this.gridHasFocus() &&
1030
+ (document.activeElement === null || document.activeElement === document.body);
1031
+ if (!this.focusWanted && !lost) {
1032
+ return;
1033
+ }
1034
+ const row = this.currentRow(this.drawnPage);
1035
+ const target = this.cellAt(row, this.currentColumn);
1036
+ if (!target) {
1037
+ return;
1038
+ }
1039
+ this.focusWanted = false;
1040
+ if (!this.windowed) {
1041
+ target.focus();
1042
+ return;
1043
+ }
1044
+ target.focus({ preventScroll: true });
1045
+ const kept = this.keptRow(this.drawnPage);
1046
+ if (row >= 0 && kept === row) {
1047
+ this.virtualize.reveal(row, this.headHeight());
1048
+ return;
1049
+ }
1050
+ const box = this.partNamed('table');
1051
+ if (!box) {
1052
+ return;
1053
+ }
1054
+ const frame = box.getBoundingClientRect();
1055
+ const rect = target.getBoundingClientRect();
1056
+ const top = row === -1 ? frame.top : frame.top + this.headHeight();
1057
+ if (rect.top < top) {
1058
+ box.scrollTop -= top - rect.top;
1059
+ }
1060
+ else if (rect.bottom > frame.bottom) {
1061
+ box.scrollTop += rect.bottom - frame.bottom;
1062
+ }
1063
+ if (rect.left < frame.left) {
1064
+ box.scrollLeft -= frame.left - rect.left;
1065
+ }
1066
+ else if (rect.right > frame.right) {
1067
+ box.scrollLeft += rect.right - frame.right;
1068
+ }
1069
+ }
1070
+ activate(event, place) {
1071
+ const offset = this.selectable ? 1 : 0;
1072
+ const heading = place.row === -1 ? this.shownColumns[place.column - offset] : undefined;
1073
+ if (event.key !== 'F2') {
1074
+ if (heading?.canSort) {
1075
+ event.preventDefault();
1076
+ this.toggleSort(heading.field);
1077
+ return;
1078
+ }
1079
+ if (this.selectable && place.column === 0 && place.row === -1) {
1080
+ event.preventDefault();
1081
+ this.chooseAll();
1082
+ return;
1083
+ }
1084
+ if (event.key === ' ') {
1085
+ const row = this.drawnPage[place.row];
1086
+ if (this.selectable && row) {
1087
+ event.preventDefault();
1088
+ const key = this.keyOf(row, this.rowIndex(place.row) - 2);
1089
+ this.chooseRow(key, !this.chosen.has(key));
1090
+ }
1091
+ return;
1092
+ }
1093
+ }
1094
+ const first = this.controlsIn(place)[0];
1095
+ if (first) {
1096
+ event.preventDefault();
1097
+ first.focus();
1098
+ }
1099
+ }
1100
+ handleControlKey(event, place) {
1101
+ if (event.key === 'Escape' || event.key === 'F2') {
1102
+ event.preventDefault();
1103
+ place.cell.focus();
1104
+ return;
1105
+ }
1106
+ if (event.key !== 'Tab') {
1107
+ return;
1108
+ }
1109
+ const origin = event.composedPath()[0];
1110
+ const controls = this.controlsIn(place);
1111
+ const at = controls.findIndex((one) => deepContains(one, origin));
1112
+ const next = controls[at + (event.shiftKey ? -1 : 1)];
1113
+ if (at >= 0 && next) {
1114
+ event.preventDefault();
1115
+ next.focus();
1116
+ }
1117
+ }
720
1118
  partIn(event, name) {
721
1119
  return event
722
1120
  .composedPath()
@@ -769,27 +1167,48 @@ __decorate([
769
1167
  __decorate([
770
1168
  property()
771
1169
  ], HelixHeadlessDataTable.prototype, "filter", null);
1170
+ __decorate([
1171
+ property({ attribute: 'gap-label' })
1172
+ ], HelixHeadlessDataTable.prototype, "gapLabel", void 0);
772
1173
  __decorate([
773
1174
  property()
774
1175
  ], HelixHeadlessDataTable.prototype, "label", void 0);
775
1176
  __decorate([
776
1177
  property()
777
1178
  ], HelixHeadlessDataTable.prototype, "mode", void 0);
1179
+ __decorate([
1180
+ property({ attribute: 'next-label' })
1181
+ ], HelixHeadlessDataTable.prototype, "nextLabel", void 0);
778
1182
  __decorate([
779
1183
  property()
780
1184
  ], HelixHeadlessDataTable.prototype, "order", null);
781
1185
  __decorate([
782
1186
  property({ type: Number })
783
1187
  ], HelixHeadlessDataTable.prototype, "page", null);
1188
+ __decorate([
1189
+ property({ attribute: 'page-label' })
1190
+ ], HelixHeadlessDataTable.prototype, "pageLabel", void 0);
784
1191
  __decorate([
785
1192
  property({ attribute: 'page-size', type: Number })
786
1193
  ], HelixHeadlessDataTable.prototype, "pageSize", null);
787
1194
  __decorate([
788
1195
  property({ type: Boolean })
789
1196
  ], HelixHeadlessDataTable.prototype, "paginated", null);
1197
+ __decorate([
1198
+ property({ attribute: 'pagination-label' })
1199
+ ], HelixHeadlessDataTable.prototype, "paginationLabel", void 0);
1200
+ __decorate([
1201
+ property({ attribute: 'previous-label' })
1202
+ ], HelixHeadlessDataTable.prototype, "previousLabel", void 0);
790
1203
  __decorate([
791
1204
  property({ type: Boolean })
792
1205
  ], HelixHeadlessDataTable.prototype, "reorderable", void 0);
1206
+ __decorate([
1207
+ property({ attribute: 'result-label' })
1208
+ ], HelixHeadlessDataTable.prototype, "resultLabel", void 0);
1209
+ __decorate([
1210
+ property({ attribute: 'results-label' })
1211
+ ], HelixHeadlessDataTable.prototype, "resultsLabel", void 0);
793
1212
  __decorate([
794
1213
  property({ attribute: 'row-key' })
795
1214
  ], HelixHeadlessDataTable.prototype, "rowKey", void 0);
@@ -799,12 +1218,18 @@ __decorate([
799
1218
  __decorate([
800
1219
  property({ type: Boolean })
801
1220
  ], HelixHeadlessDataTable.prototype, "selectable", void 0);
1221
+ __decorate([
1222
+ property({ attribute: 'select-all-label' })
1223
+ ], HelixHeadlessDataTable.prototype, "selectAllLabel", void 0);
802
1224
  __decorate([
803
1225
  property()
804
1226
  ], HelixHeadlessDataTable.prototype, "selected", null);
805
1227
  __decorate([
806
1228
  property({ attribute: 'selected-label' })
807
1229
  ], HelixHeadlessDataTable.prototype, "selectedLabel", void 0);
1230
+ __decorate([
1231
+ property({ attribute: 'select-row-label' })
1232
+ ], HelixHeadlessDataTable.prototype, "selectRowLabel", void 0);
808
1233
  __decorate([
809
1234
  property()
810
1235
  ], HelixHeadlessDataTable.prototype, "sort", null);
@@ -841,6 +1266,12 @@ __decorate([
841
1266
  __decorate([
842
1267
  state()
843
1268
  ], HelixHeadlessDataTable.prototype, "selectedState", void 0);
1269
+ __decorate([
1270
+ state()
1271
+ ], HelixHeadlessDataTable.prototype, "activeRow", void 0);
1272
+ __decorate([
1273
+ state()
1274
+ ], HelixHeadlessDataTable.prototype, "activeColumn", void 0);
844
1275
  __decorate([
845
1276
  state()
846
1277
  ], HelixHeadlessDataTable.prototype, "dragOrder", void 0);