@fusion.dev/helix-headless 0.147.0 → 0.149.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 (296) hide show
  1. package/custom-elements.json +11222 -2332
  2. package/dist/accordion/item/accordion-item.d.ts +5 -2
  3. package/dist/accordion/item/accordion-item.js +11 -7
  4. package/dist/accordion/root/accordion-root.js +4 -6
  5. package/dist/announcement/root/announcement-root.d.ts +61 -5
  6. package/dist/announcement/root/announcement-root.js +126 -20
  7. package/dist/area-chart/root/area-chart-root.d.ts +11 -0
  8. package/dist/area-chart/root/area-chart-root.js +21 -9
  9. package/dist/avatar/group/avatar-group.d.ts +10 -2
  10. package/dist/avatar/group/avatar-group.js +10 -5
  11. package/dist/badge/count.d.ts +19 -0
  12. package/dist/badge/count.js +20 -0
  13. package/dist/badge/root/badge-root.d.ts +6 -2
  14. package/dist/badge/root/badge-root.js +8 -22
  15. package/dist/bar-chart/root/bar-chart-root.d.ts +13 -1
  16. package/dist/bar-chart/root/bar-chart-root.js +17 -4
  17. package/dist/blockquote/root/blockquote-root.d.ts +66 -8
  18. package/dist/blockquote/root/blockquote-root.js +85 -8
  19. package/dist/breadcrumbs/breadcrumb/breadcrumb.js +2 -2
  20. package/dist/breadcrumbs/root/breadcrumbs-root.d.ts +8 -1
  21. package/dist/breadcrumbs/root/breadcrumbs-root.js +5 -2
  22. package/dist/button/root/button-root.d.ts +10 -1
  23. package/dist/button/root/button-root.js +3 -2
  24. package/dist/button-group/arrows.d.ts +14 -0
  25. package/dist/button-group/arrows.js +10 -0
  26. package/dist/button-group/root/button-group-root.d.ts +144 -3
  27. package/dist/button-group/root/button-group-root.js +142 -2
  28. package/dist/callout/root/callout-root.d.ts +16 -2
  29. package/dist/callout/root/callout-root.js +16 -4
  30. package/dist/canvas/describe.d.ts +10 -0
  31. package/dist/canvas/describe.js +9 -0
  32. package/dist/canvas/edge-pan.d.ts +61 -0
  33. package/dist/canvas/edge-pan.js +63 -0
  34. package/dist/canvas/neighbor.d.ts +17 -0
  35. package/dist/canvas/neighbor.js +1 -0
  36. package/dist/canvas/node/canvas-node.d.ts +12 -2
  37. package/dist/canvas/node/canvas-node.js +8 -3
  38. package/dist/canvas/root/canvas-document.d.ts +10 -0
  39. package/dist/canvas/root/canvas-document.js +1 -0
  40. package/dist/canvas/root/canvas-root.d.ts +168 -9
  41. package/dist/canvas/root/canvas-root.js +239 -69
  42. package/dist/canvas/snap.d.ts +42 -0
  43. package/dist/canvas/snap.js +32 -0
  44. package/dist/carousel/root/carousel-root.d.ts +9 -3
  45. package/dist/carousel/root/carousel-root.js +17 -10
  46. package/dist/chat/composer/chat-composer.d.ts +5 -0
  47. package/dist/chat/composer/chat-composer.js +4 -1
  48. package/dist/chat/message/chat-message.d.ts +9 -5
  49. package/dist/chat/message/chat-message.js +8 -4
  50. package/dist/chat/naming.js +2 -2
  51. package/dist/chat/root/chat-root.d.ts +40 -4
  52. package/dist/chat/root/chat-root.js +38 -14
  53. package/dist/checkbox/root/checkbox-root.d.ts +11 -0
  54. package/dist/checkbox/root/checkbox-root.js +8 -2
  55. package/dist/checkbox-group/root/checkbox-group-root.d.ts +24 -0
  56. package/dist/checkbox-group/root/checkbox-group-root.js +28 -12
  57. package/dist/checkbox-group/select-all.d.ts +11 -0
  58. package/dist/checkbox-group/select-all.js +5 -0
  59. package/dist/code-block/root/code-block-root.d.ts +20 -8
  60. package/dist/code-block/root/code-block-root.js +16 -5
  61. package/dist/color-input/root/color-input-root.d.ts +13 -0
  62. package/dist/color-input/root/color-input-root.js +18 -5
  63. package/dist/color-picker/root/color-picker-root.d.ts +19 -3
  64. package/dist/color-picker/root/color-picker-root.js +52 -24
  65. package/dist/color-picker/wheel.d.ts +11 -0
  66. package/dist/color-picker/wheel.js +9 -0
  67. package/dist/combobox/root/combobox-root.d.ts +106 -18
  68. package/dist/combobox/root/combobox-root.js +101 -26
  69. package/dist/command/root/command-root.d.ts +19 -9
  70. package/dist/command/root/command-root.js +9 -4
  71. package/dist/copy-button/root/copy-button-root.d.ts +5 -0
  72. package/dist/copy-button/root/copy-button-root.js +7 -2
  73. package/dist/data-table/root/data-table-root.d.ts +171 -29
  74. package/dist/data-table/root/data-table-root.js +284 -161
  75. package/dist/date-input/root/date-input-root.d.ts +32 -9
  76. package/dist/date-input/root/date-input-root.js +66 -44
  77. package/dist/date-picker/root/date-picker-root.d.ts +38 -15
  78. package/dist/date-picker/root/date-picker-root.js +52 -33
  79. package/dist/description-list/item/description-list-item.d.ts +4 -0
  80. package/dist/description-list/item/description-list-item.js +7 -1
  81. package/dist/dialog/root/dialog-root.d.ts +12 -1
  82. package/dist/dialog/root/dialog-root.js +11 -4
  83. package/dist/divider/root/divider-root.d.ts +45 -16
  84. package/dist/divider/root/divider-root.js +28 -4
  85. package/dist/donut-chart/root/donut-chart-root.d.ts +5 -0
  86. package/dist/donut-chart/root/donut-chart-root.js +8 -5
  87. package/dist/drawer/root/drawer-root.d.ts +12 -1
  88. package/dist/drawer/root/drawer-root.js +9 -2
  89. package/dist/drilldown/item/drilldown-item.js +3 -4
  90. package/dist/drilldown/root/drilldown-root.d.ts +5 -0
  91. package/dist/drilldown/root/drilldown-root.js +4 -1
  92. package/dist/element-events.generated.js +26 -3
  93. package/dist/empty/root/empty-root.d.ts +17 -3
  94. package/dist/empty/root/empty-root.js +29 -5
  95. package/dist/file-input/root/file-input-root.d.ts +18 -3
  96. package/dist/file-input/root/file-input-root.js +34 -18
  97. package/dist/file-input/status.js +2 -1
  98. package/dist/filter-input/chip/filter-chip.d.ts +13 -0
  99. package/dist/filter-input/chip/filter-chip.js +7 -3
  100. package/dist/filter-input/menu/filter-menu.d.ts +5 -0
  101. package/dist/filter-input/menu/filter-menu.js +3 -1
  102. package/dist/filter-input/root/filter-input-root.d.ts +20 -3
  103. package/dist/filter-input/root/filter-input-root.js +8 -4
  104. package/dist/format-date/fields.d.ts +20 -0
  105. package/dist/format-date/fields.js +14 -0
  106. package/dist/format-date/options.d.ts +2 -1
  107. package/dist/format-date/options.js +9 -38
  108. package/dist/format-date/root/format-date-root.d.ts +55 -5
  109. package/dist/format-date/root/format-date-root.js +29 -34
  110. package/dist/graph/root/graph-model.d.ts +11 -0
  111. package/dist/graph/root/graph-model.js +4 -0
  112. package/dist/graph/root/graph-root.d.ts +101 -14
  113. package/dist/graph/root/graph-root.js +140 -46
  114. package/dist/heatmap/root/heatmap-root.d.ts +37 -4
  115. package/dist/heatmap/root/heatmap-root.js +51 -16
  116. package/dist/icon-button/root/icon-button-root.d.ts +5 -0
  117. package/dist/icon-button/root/icon-button-root.js +1 -0
  118. package/dist/image/root/image-root.d.ts +11 -0
  119. package/dist/input/root/input-root.d.ts +5 -0
  120. package/dist/input/root/input-root.js +4 -1
  121. package/dist/kbd/root/kbd-root.js +1 -2
  122. package/dist/legend/root/legend-root.js +4 -17
  123. package/dist/lightbox/root/lightbox-root.d.ts +14 -4
  124. package/dist/lightbox/root/lightbox-root.js +25 -7
  125. package/dist/line-chart/root/line-chart-root.d.ts +5 -0
  126. package/dist/line-chart/root/line-chart-root.js +4 -2
  127. package/dist/list/item/list-item.d.ts +32 -0
  128. package/dist/list/item/list-item.js +34 -7
  129. package/dist/list/root/list-root.d.ts +87 -0
  130. package/dist/list/root/list-root.js +119 -23
  131. package/dist/listbox/reorder/index.d.ts +1 -0
  132. package/dist/listbox/reorder/index.js +4 -0
  133. package/dist/listbox/reorder/listbox-reorder.d.ts +83 -0
  134. package/dist/listbox/reorder/listbox-reorder.js +151 -0
  135. package/dist/listbox/root/listbox-root.d.ts +185 -33
  136. package/dist/listbox/root/listbox-root.js +166 -136
  137. package/dist/loader/root/loader-root.d.ts +5 -0
  138. package/dist/loader/root/loader-root.js +3 -1
  139. package/dist/map/area/map-area.d.ts +5 -0
  140. package/dist/map/area/map-area.js +3 -1
  141. package/dist/map/buildings/map-buildings.d.ts +5 -0
  142. package/dist/map/buildings/map-buildings.js +3 -1
  143. package/dist/map/contours/map-contours.d.ts +5 -0
  144. package/dist/map/contours/map-contours.js +3 -1
  145. package/dist/map/landcover/map-landcover.d.ts +5 -0
  146. package/dist/map/landcover/map-landcover.js +3 -1
  147. package/dist/map/marker/map-marker.d.ts +18 -2
  148. package/dist/map/marker/map-marker.js +13 -5
  149. package/dist/map/points/map-points.d.ts +5 -0
  150. package/dist/map/points/map-points.js +6 -4
  151. package/dist/map/position/map-position.d.ts +5 -0
  152. package/dist/map/position/map-position.js +3 -1
  153. package/dist/map/raster/map-raster.d.ts +5 -0
  154. package/dist/map/raster/map-raster.js +3 -1
  155. package/dist/map/root/map-root.d.ts +73 -16
  156. package/dist/map/root/map-root.js +122 -44
  157. package/dist/map/route/map-route.d.ts +5 -0
  158. package/dist/map/route/map-route.js +3 -1
  159. package/dist/map/terrain/map-terrain.d.ts +5 -0
  160. package/dist/map/terrain/map-terrain.js +3 -1
  161. package/dist/megamenu/root/megamenu-root.js +4 -11
  162. package/dist/menu/root/menu-root.d.ts +7 -2
  163. package/dist/menu/root/menu-root.js +3 -1
  164. package/dist/meter/root/meter-root.d.ts +16 -3
  165. package/dist/meter/root/meter-root.js +12 -5
  166. package/dist/navigation/root/navigation-root.d.ts +5 -0
  167. package/dist/navigation/root/navigation-root.js +7 -8
  168. package/dist/notifications/group/notification-group.d.ts +8 -1
  169. package/dist/notifications/group/notification-group.js +12 -6
  170. package/dist/notifications/notification/notification.d.ts +17 -1
  171. package/dist/notifications/notification/notification.js +6 -2
  172. package/dist/notifications/root/notifications-root.d.ts +49 -5
  173. package/dist/notifications/root/notifications-root.js +36 -8
  174. package/dist/number-input/root/number-input-root.d.ts +21 -8
  175. package/dist/number-input/root/number-input-root.js +26 -11
  176. package/dist/object-inspector/root/object-inspector-root.d.ts +56 -13
  177. package/dist/object-inspector/root/object-inspector-root.js +41 -30
  178. package/dist/outline/root/outline-root.d.ts +5 -0
  179. package/dist/outline/root/outline-root.js +3 -1
  180. package/dist/pagination/root/pagination-root.d.ts +7 -1
  181. package/dist/pagination/root/pagination-root.js +16 -7
  182. package/dist/pagination/size/pagination-size.d.ts +8 -3
  183. package/dist/pagination/size/pagination-size.js +5 -3
  184. package/dist/pagination/summary/pagination-summary.d.ts +8 -6
  185. package/dist/pagination/summary/pagination-summary.js +4 -9
  186. package/dist/pin-input/code.d.ts +23 -0
  187. package/dist/pin-input/code.js +21 -0
  188. package/dist/pin-input/root/pin-input-root.d.ts +9 -3
  189. package/dist/pin-input/root/pin-input-root.js +13 -23
  190. package/dist/popover/root/popover-root.d.ts +12 -2
  191. package/dist/popover/root/popover-root.js +10 -4
  192. package/dist/progress/root/progress-root.d.ts +7 -2
  193. package/dist/progress/root/progress-root.js +5 -2
  194. package/dist/qr-code/name.d.ts +3 -2
  195. package/dist/qr-code/name.js +2 -2
  196. package/dist/qr-code/root/qr-code-root.d.ts +26 -5
  197. package/dist/qr-code/root/qr-code-root.js +27 -6
  198. package/dist/radio/group/radio-group.d.ts +11 -0
  199. package/dist/radio/group/radio-group.js +8 -2
  200. package/dist/rating/root/rating-root.d.ts +12 -1
  201. package/dist/rating/root/rating-root.js +10 -3
  202. package/dist/scatter-chart/measures.d.ts +22 -0
  203. package/dist/scatter-chart/measures.js +11 -0
  204. package/dist/scatter-chart/root/scatter-chart-root.d.ts +22 -8
  205. package/dist/scatter-chart/root/scatter-chart-root.js +25 -23
  206. package/dist/select/root/select-root.d.ts +67 -8
  207. package/dist/select/root/select-root.js +45 -11
  208. package/dist/skip-link/root/skip-link-root.d.ts +5 -0
  209. package/dist/skip-link/root/skip-link-root.js +3 -1
  210. package/dist/slider/root/slider-root.d.ts +7 -2
  211. package/dist/slider/root/slider-root.js +11 -5
  212. package/dist/sparkline/readings.d.ts +15 -5
  213. package/dist/sparkline/readings.js +3 -3
  214. package/dist/sparkline/root/sparkline-root.d.ts +9 -4
  215. package/dist/sparkline/root/sparkline-root.js +9 -3
  216. package/dist/speed-dial/group/speed-dial-group.d.ts +48 -0
  217. package/dist/speed-dial/group/speed-dial-group.js +43 -0
  218. package/dist/speed-dial/index.d.ts +1 -0
  219. package/dist/speed-dial/index.js +1 -0
  220. package/dist/speed-dial/item/speed-dial-item.d.ts +26 -1
  221. package/dist/speed-dial/item/speed-dial-item.js +41 -3
  222. package/dist/speed-dial/long-press.d.ts +50 -0
  223. package/dist/speed-dial/long-press.js +48 -0
  224. package/dist/speed-dial/root/speed-dial-root.d.ts +85 -1
  225. package/dist/speed-dial/root/speed-dial-root.js +117 -5
  226. package/dist/splitter/root/splitter-root.d.ts +12 -3
  227. package/dist/splitter/root/splitter-root.js +22 -4
  228. package/dist/steps/root/steps-root.d.ts +9 -2
  229. package/dist/steps/root/steps-root.js +6 -3
  230. package/dist/steps/step/step.d.ts +12 -0
  231. package/dist/steps/step/step.js +11 -2
  232. package/dist/switch/root/switch-root.d.ts +11 -0
  233. package/dist/switch/root/switch-root.js +8 -2
  234. package/dist/table/cell/table-cell.d.ts +8 -1
  235. package/dist/table/cell/table-cell.js +6 -2
  236. package/dist/table/column/table-column.d.ts +11 -4
  237. package/dist/table/column/table-column.js +15 -10
  238. package/dist/table/grid-controller.d.ts +122 -0
  239. package/dist/table/grid-controller.js +299 -0
  240. package/dist/table/root/table-root.d.ts +154 -8
  241. package/dist/table/root/table-root.js +197 -38
  242. package/dist/table/row/table-row.d.ts +55 -1
  243. package/dist/table/row/table-row.js +60 -7
  244. package/dist/tabs/root/tabs-root.d.ts +5 -0
  245. package/dist/tabs/root/tabs-root.js +3 -1
  246. package/dist/tag/group/tag-group.d.ts +5 -0
  247. package/dist/tag/group/tag-group.js +8 -15
  248. package/dist/tag/root/tag-root.d.ts +14 -1
  249. package/dist/tag/root/tag-root.js +11 -8
  250. package/dist/textarea/root/textarea-root.d.ts +5 -0
  251. package/dist/textarea/root/textarea-root.js +3 -1
  252. package/dist/time-input/root/time-input-root.d.ts +14 -7
  253. package/dist/time-input/root/time-input-root.js +43 -32
  254. package/dist/time-picker/root/time-picker-root.d.ts +16 -7
  255. package/dist/time-picker/root/time-picker-root.js +28 -12
  256. package/dist/toast/item/toast-item.d.ts +13 -3
  257. package/dist/toast/item/toast-item.js +2 -0
  258. package/dist/toast/root/toast-root.d.ts +22 -2
  259. package/dist/toast/root/toast-root.js +24 -17
  260. package/dist/toggle/group/toggle-group.js +3 -5
  261. package/dist/toolbar/root/toolbar-root.d.ts +36 -0
  262. package/dist/toolbar/root/toolbar-root.js +43 -9
  263. package/dist/tooltip/root/tooltip-root.d.ts +27 -17
  264. package/dist/tooltip/root/tooltip-root.js +1 -2
  265. package/dist/tour/root/tour-root.d.ts +8 -2
  266. package/dist/tour/root/tour-root.js +4 -2
  267. package/dist/tour/stop/tour-stop.d.ts +5 -0
  268. package/dist/tour/stop/tour-stop.js +6 -1
  269. package/dist/tree/grip.d.ts +5 -0
  270. package/dist/tree/grip.js +1 -0
  271. package/dist/tree/item/tree-item.d.ts +24 -0
  272. package/dist/tree/item/tree-item.js +27 -5
  273. package/dist/tree/root/tree-root.d.ts +66 -1
  274. package/dist/tree/root/tree-root.js +77 -5
  275. package/dist/trend/root/trend-root.d.ts +20 -4
  276. package/dist/trend/root/trend-root.js +20 -5
  277. package/dist/video/root/video-root.d.ts +23 -3
  278. package/dist/video/root/video-root.js +56 -15
  279. package/dist/video-playlist/menu/video-playlist-menu.d.ts +5 -0
  280. package/dist/video-playlist/menu/video-playlist-menu.js +3 -1
  281. package/dist/video-playlist/root/video-playlist-root.d.ts +5 -0
  282. package/dist/video-playlist/root/video-playlist-root.js +3 -1
  283. package/dist/virtual-list/root/virtual-list-root.d.ts +19 -3
  284. package/dist/virtual-list/root/virtual-list-root.js +10 -19
  285. package/lint.json +1 -1
  286. package/package.json +7 -6
  287. package/types/jsx.d.ts +6005 -2114
  288. package/types/svelte.d.ts +1 -0
  289. package/types/vue.d.ts +1594 -676
  290. package/types/words.d.ts +3280 -0
  291. package/dist/kbd/keys.d.ts +0 -29
  292. package/dist/kbd/keys.js +0 -52
  293. package/dist/toast/hotkey.d.ts +0 -22
  294. package/dist/toast/hotkey.js +0 -23
  295. package/dist/tooltip/focus-target.d.ts +0 -6
  296. package/dist/tooltip/focus-target.js +0 -9
@@ -4,12 +4,13 @@ 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, commaList, customElement, cycle, everyState, fillTemplate, format, HelixElement, HelixSelectEvent, HelixSelectedEvent, HelixSortEvent, HelixSortedEvent, inRowOrder, MixinCollection, onAndroid, parse, reflectElements, requestChange, sort, splitValues, toggleEvery, whenHydrated, } from '@fusion.dev/helix-core';
7
+ import { AriaForwardController, assignSlots, commaList, customElement, cycle, everyState, followLink, format, formatWords, HelixElement, HelixSelectEvent, HelixSelectedEvent, HelixSortEvent, HelixSortedEvent, inRowOrder, MixinCollection, onAndroid, parse, ReorderController, reflectElements, requestChange, sort, splitValues, toggleEvery, whenHydrated, words, } from '@fusion.dev/helix-core';
8
8
  import { nothing } from 'lit';
9
9
  import { property, state } from 'lit/decorators.js';
10
10
  import { html } from 'lit/static-html.js';
11
11
  import '../../checkbox/index.js';
12
12
  import { edgeOf } from '../column/table-column.js';
13
+ import { TableGridController } from '../grid-controller.js';
13
14
  const tracksOf = (list, wanted) => {
14
15
  const words = splitValues(list, ' ');
15
16
  const valid = (track) => typeof CSS === 'undefined' || CSS.supports('grid-template-columns', track);
@@ -47,16 +48,25 @@ let HelixHeadlessTable = class HelixHeadlessTable extends MixinCollection(HelixE
47
48
  constructor() {
48
49
  super(...arguments);
49
50
  this.ascendingLabel = 'ascending';
51
+ this.canceledLabel = 'Canceled';
50
52
  this.columns = '';
51
53
  this.defaultSelected = '';
52
54
  this.defaultSort = '';
53
55
  this.descendingLabel = 'descending';
56
+ this.droppedLabel = 'Dropped';
57
+ this.fallbackLabel = 'Table';
58
+ this.grid = false;
54
59
  this.label = '';
60
+ this.movedLabel = '{name} moved to position {position} of {count}';
61
+ this.moveRowLabel = 'Move {row}';
62
+ this.pickedUpLabel = 'Picked up {name}';
63
+ this.reorderable = false;
64
+ this.rowGripsLabel = 'Move rows';
55
65
  this.selectable = false;
56
66
  this.selectAllLabel = 'Select every row';
57
67
  this.selectedLabel = '{count} selected';
58
68
  this.selectRowLabel = 'Select {row}';
59
- this.sortedLabel = 'Sorted by {column}, {order}';
69
+ this.sortedLabel = '{direction, select, ascending {Sorted by {column}, ascending} descending {Sorted by {column}, descending} other {Sorted by {column}}}';
60
70
  this.unsortedLabel = 'Not sorted';
61
71
  this.sortState = undefined;
62
72
  this.selectedState = undefined;
@@ -65,6 +75,35 @@ let HelixHeadlessTable = class HelixHeadlessTable extends MixinCollection(HelixE
65
75
  label: true,
66
76
  target: () => this.partNamed('table'),
67
77
  });
78
+ this.gridKeys = new TableGridController(this, {
79
+ activate: (place, event) => this.activate(place, event),
80
+ columns: () => this.tableColumns.filter((column) => column.shown),
81
+ lead: () => this.lead,
82
+ on: () => this.grid,
83
+ part: (name) => this.partNamed(name),
84
+ rows: () => (this.childrenKnown ? this.arrangedRows : []),
85
+ selectAll: () => this.selectable && this.requestSelected(new Set(this.everyKey)),
86
+ });
87
+ this.reorder = new ReorderController(this, {
88
+ axis: 'block',
89
+ box: (key) => this.gripOf(this.rowFor(key))?.getBoundingClientRect(),
90
+ enabled: () => this.reorderable && !parse(this.sort),
91
+ grip: (event) => {
92
+ const path = event.composedPath();
93
+ const found = this.keyed.find(({ row }) => path.includes(this.gripOf(row)));
94
+ const element = this.gripOf(found?.row);
95
+ return found && element ? { element, key: found.key } : undefined;
96
+ },
97
+ item: (event) => {
98
+ const path = event.composedPath();
99
+ return this.keyed.find(({ row }) => path.includes(row))?.key;
100
+ },
101
+ keys: () => this.everyKey,
102
+ kind: 'row',
103
+ name: (key) => textOf(this.rowFor(key)?.children[0]) || key,
104
+ preview: (key) => this.rowFor(key),
105
+ refocus: (key) => this.gripOf(this.rowFor(key))?.focus(),
106
+ });
68
107
  this.heardSort = undefined;
69
108
  this.heardSortBefore = undefined;
70
109
  this.heardSelected = undefined;
@@ -74,10 +113,9 @@ let HelixHeadlessTable = class HelixHeadlessTable extends MixinCollection(HelixE
74
113
  return;
75
114
  }
76
115
  const root = origin.getRootNode();
77
- const keys = this.chosen;
78
116
  if (root === this.renderRoot) {
79
117
  event.preventDefault();
80
- this.requestSelected(new Set(toggleEvery(keys, this.keyed.map(({ key }) => key))));
118
+ this.chooseAll();
81
119
  return;
82
120
  }
83
121
  const found = this.keyed.find(({ row }) => row.shadowRoot === root);
@@ -85,13 +123,7 @@ let HelixHeadlessTable = class HelixHeadlessTable extends MixinCollection(HelixE
85
123
  return;
86
124
  }
87
125
  event.preventDefault();
88
- if (event.detail.checked) {
89
- keys.add(found.key);
90
- }
91
- else {
92
- keys.delete(found.key);
93
- }
94
- this.requestSelected(keys);
126
+ this.chooseRow(found.key, event.detail.checked);
95
127
  };
96
128
  this.handleHeadClick = (event) => {
97
129
  const path = event.composedPath();
@@ -111,6 +143,7 @@ let HelixHeadlessTable = class HelixHeadlessTable extends MixinCollection(HelixE
111
143
  this.alignment = undefined;
112
144
  this.aligned = '';
113
145
  }
146
+ static { this.words = 'helix-table'; }
114
147
  get selected() {
115
148
  return this.selectedState ?? this.defaultSelected;
116
149
  }
@@ -127,6 +160,19 @@ let HelixHeadlessTable = class HelixHeadlessTable extends MixinCollection(HelixE
127
160
  this.sortState = next;
128
161
  this.requestUpdate('sort', previous);
129
162
  }
163
+ get lead() {
164
+ return [
165
+ ...(this.reorderable ? ['grip'] : []),
166
+ ...(this.selectable ? ['select'] : []),
167
+ ];
168
+ }
169
+ rowFor(key) {
170
+ return this.keyed.find((one) => one.key === key)?.row;
171
+ }
172
+ gripOf(row) {
173
+ const cell = row?.shadowRoot?.querySelector('[part~="grip"]');
174
+ return this.grid ? cell : cell?.querySelector('button');
175
+ }
130
176
  requestSort(next) {
131
177
  return requestChange({
132
178
  apply: (value) => {
@@ -170,21 +216,25 @@ let HelixHeadlessTable = class HelixHeadlessTable extends MixinCollection(HelixE
170
216
  ? this.tableColumns.find((one) => one.field === parsed.field)
171
217
  : undefined;
172
218
  said = parsed
173
- ? fillTemplate(this.sortedLabel, {
174
- column: column?.textContent?.trim() || parsed.field,
175
- order: parsed.direction === 'asc' ? this.ascendingLabel : this.descendingLabel,
176
- })
219
+ ? this.sortSaid(column?.textContent?.trim() || parsed.field, parsed.direction === 'asc' ? 'ascending' : 'descending')
177
220
  : this.unsortedLabel;
178
221
  }
179
222
  this.heardSort = current;
180
223
  const selected = this.selectable ? this.selected : '';
181
224
  if (this.hasUpdated && current === this.heardSortBefore && selected !== this.heardSelected) {
182
- said = fillTemplate(this.selectedLabel, { count: this.chosen.size });
225
+ said = formatWords(this, 'selectedLabel', { count: this.chosen.size });
183
226
  }
184
227
  this.heardSortBefore = current;
185
228
  this.heardSelected = selected;
186
229
  return said;
187
230
  }
231
+ sortSaid(column, direction) {
232
+ return formatWords(this, 'sortedLabel', {
233
+ column,
234
+ direction,
235
+ order: direction === 'ascending' ? this.ascendingLabel : this.descendingLabel,
236
+ });
237
+ }
188
238
  get keyed() {
189
239
  return this.slotted.map((row, index) => ({
190
240
  key: row.value || String(index),
@@ -207,17 +257,71 @@ let HelixHeadlessTable = class HelixHeadlessTable extends MixinCollection(HelixE
207
257
  next: inRowOrder(keys, this.keyed.map(({ key }) => key)).join(','),
208
258
  });
209
259
  }
260
+ get everyKey() {
261
+ return this.keyed.map(({ key }) => key);
262
+ }
263
+ chooseAll() {
264
+ this.requestSelected(new Set(toggleEvery(this.chosen, this.everyKey)));
265
+ }
266
+ chooseRow(key, on) {
267
+ const keys = this.chosen;
268
+ if (on) {
269
+ keys.add(key);
270
+ }
271
+ else {
272
+ keys.delete(key);
273
+ }
274
+ this.requestSelected(keys);
275
+ }
276
+ activate(place, event) {
277
+ const leads = this.lead;
278
+ const lead = leads[place.column] === 'select';
279
+ if (event.key === 'F2') {
280
+ return false;
281
+ }
282
+ if (place.row === -1) {
283
+ if (lead) {
284
+ this.chooseAll();
285
+ return true;
286
+ }
287
+ const shown = this.tableColumns.filter((one) => one.shown);
288
+ const column = shown[place.column - leads.length];
289
+ if (column?.canSort) {
290
+ this.toggleSort(column.field);
291
+ return true;
292
+ }
293
+ return false;
294
+ }
295
+ const row = this.arrangedRows[place.row];
296
+ const found = this.keyed.find((one) => one.row === row);
297
+ if (this.selectable && found && (event.key === ' ' || lead)) {
298
+ this.chooseRow(found.key, !this.chosen.has(found.key));
299
+ return true;
300
+ }
301
+ if (event.key === 'Enter' && row?.href) {
302
+ followLink(this.ownerDocument, { href: row.href, rel: row.rel, target: row.target }, event);
303
+ return true;
304
+ }
305
+ return false;
306
+ }
210
307
  markSelected() {
211
308
  const keys = this.chosen;
309
+ const still = Boolean(parse(this.sort));
212
310
  for (const { key, row } of this.keyed) {
213
311
  if (!row.isTableRow) {
214
312
  continue;
215
313
  }
216
- const label = fillTemplate(this.selectRowLabel, { row: textOf(row.children[0]) || key });
314
+ const name = textOf(row.children[0]) || key;
315
+ const label = formatWords(this, 'selectRowLabel', { row: name });
316
+ const grip = this.reorderable ? formatWords(this, 'moveRowLabel', { row: name }) : '';
317
+ const move = this.reorder.moveOf(key);
217
318
  whenHydrated(row, () => {
218
319
  row.selectable = this.selectable;
219
320
  row.selected = keys.has(key);
220
321
  row.selectLabel = label;
322
+ row.gripLabel = grip;
323
+ row.gripStill = still;
324
+ row.move = move;
221
325
  });
222
326
  }
223
327
  }
@@ -240,10 +344,7 @@ let HelixHeadlessTable = class HelixHeadlessTable extends MixinCollection(HelixE
240
344
  : undefined;
241
345
  column.sortWords =
242
346
  android && column.sorted
243
- ? fillTemplate(this.sortedLabel, {
244
- column: column.textContent?.trim() || column.field,
245
- order: column.sorted === 'ascending' ? this.ascendingLabel : this.descendingLabel,
246
- })
347
+ ? this.sortSaid(column.textContent?.trim() || column.field, column.sorted)
247
348
  : '';
248
349
  }
249
350
  }
@@ -252,7 +353,8 @@ let HelixHeadlessTable = class HelixHeadlessTable extends MixinCollection(HelixE
252
353
  }
253
354
  get template() {
254
355
  const tracks = this.tracks;
255
- return this.selectable && tracks ? `max-content ${tracks}` : tracks;
356
+ const lead = this.lead.map(() => 'max-content ').join('');
357
+ return tracks ? lead + tracks : tracks;
256
358
  }
257
359
  get tracks() {
258
360
  const declared = this.tableColumns;
@@ -325,16 +427,9 @@ let HelixHeadlessTable = class HelixHeadlessTable extends MixinCollection(HelixE
325
427
  }
326
428
  return;
327
429
  }
328
- const head = this.renderRoot?.querySelector('slot[name="columns"]');
329
- const body = this.renderRoot?.querySelector('slot:not([name])');
330
- if (!head || !body) {
331
- return;
332
- }
333
- head.assign(...this.tableColumns);
334
- body.assign(...this.arrangedRows);
335
- this.renderRoot
336
- ?.querySelector('slot[name="heading"]')
337
- ?.assign(...this.headings);
430
+ const columns = new Set(this.tableColumns);
431
+ const headings = new Set(this.headings);
432
+ assignSlots(this.renderRoot, [...columns, ...headings, ...this.arrangedRows], (child) => (columns.has(child) ? 'columns' : headings.has(child) ? 'heading' : ''));
338
433
  }
339
434
  alignCells() {
340
435
  if (typeof CSSStyleSheet === 'undefined' || !('replaceSync' in CSSStyleSheet.prototype)) {
@@ -368,6 +463,21 @@ let HelixHeadlessTable = class HelixHeadlessTable extends MixinCollection(HelixE
368
463
  this.markSorted();
369
464
  this.markSelected();
370
465
  this.nameByHeading();
466
+ if (this.childrenKnown) {
467
+ this.gridKeys.mark();
468
+ this.gridKeys.place();
469
+ }
470
+ }
471
+ renderGripHead() {
472
+ if (!this.reorderable) {
473
+ return nothing;
474
+ }
475
+ return html `<span
476
+ part="grip-head"
477
+ role="columnheader"
478
+ aria-label=${this.rowGripsLabel}
479
+ tabindex=${this.grid ? (this.gridKeys.isStop({ column: 0, row: -1 }) ? '0' : '-1') : nothing}
480
+ ></span>`;
371
481
  }
372
482
  renderSelectAll() {
373
483
  if (!this.selectable) {
@@ -376,9 +486,13 @@ let HelixHeadlessTable = class HelixHeadlessTable extends MixinCollection(HelixE
376
486
  const every = this.childrenKnown ? this.keyed.map(({ key }) => key) : [];
377
487
  const { checked, indeterminate } = everyState(this.chosen, every);
378
488
  const checkbox = this.tag('checkbox');
489
+ const grid = this.grid;
490
+ const column = this.lead.indexOf('select');
379
491
  return html `<span part="select-all" role="columnheader"
492
+ tabindex=${grid ? (this.gridKeys.isStop({ column, row: -1 }) ? '0' : '-1') : nothing}
380
493
  ><${checkbox}
381
494
  part="checkbox"
495
+ tabindex=${grid ? '-1' : nothing}
382
496
  exportparts="box: checkbox-box, control: checkbox-control, feedback: checkbox-feedback,
383
497
  field: checkbox-field, hint: checkbox-hint, label: checkbox-label, mark: checkbox-mark,
384
498
  mark-checked: checkbox-mark-checked, mark-dash: checkbox-mark-dash,
@@ -391,27 +505,36 @@ let HelixHeadlessTable = class HelixHeadlessTable extends MixinCollection(HelixE
391
505
  }
392
506
  render() {
393
507
  const template = this.template;
394
- return html `<slot name="heading"></slot><div
508
+ const grid = this.grid;
509
+ const start = grid ? html `<span part="grid-start" tabindex="-1"></span>` : nothing;
510
+ const end = grid ? html `<span part="grid-end" tabindex="-1"></span>` : nothing;
511
+ return html `<slot name="heading"></slot>${start}<div
395
512
  part="table"
396
- role="table"
513
+ role=${grid ? 'grid' : 'table'}
514
+ aria-multiselectable=${grid && this.selectable ? 'true' : nothing}
397
515
  aria-busy=${this.loading ? 'true' : nothing}
398
- aria-label=${this.label || 'Table'}
516
+ aria-label=${this.label || this.fallbackLabel}
399
517
  style=${template ? `--table-template: ${template}` : ''}
400
518
  >
401
- <div part="head" role="row">${this.renderSelectAll()}<slot name="columns"></slot></div>
519
+ <div part="head" role="row">${this.renderGripHead()}${this.renderSelectAll()}<slot name="columns"></slot></div>
402
520
  <slot
403
521
  @slotchange=${(event) => {
404
522
  this.countRows(event);
405
523
  this.handleSlotChange();
406
524
  }}
407
525
  ></slot>
408
- ${this.renderStatus(this.hasRows, 'cell')}
409
- </div>${this.renderLive(this.hasRows)}`;
526
+ ${this.renderStatus(this.hasRows, grid ? 'gridcell' : 'cell')}
527
+ </div>${end}${this.renderLive(this.hasRows)}${this.reorder.drawDragPreview()}`;
410
528
  }
411
529
  };
412
530
  __decorate([
531
+ words,
413
532
  property({ attribute: 'ascending-label' })
414
533
  ], HelixHeadlessTable.prototype, "ascendingLabel", void 0);
534
+ __decorate([
535
+ words,
536
+ property({ attribute: 'canceled-label' })
537
+ ], HelixHeadlessTable.prototype, "canceledLabel", void 0);
415
538
  __decorate([
416
539
  property()
417
540
  ], HelixHeadlessTable.prototype, "columns", void 0);
@@ -422,33 +545,69 @@ __decorate([
422
545
  property({ attribute: 'default-sort' })
423
546
  ], HelixHeadlessTable.prototype, "defaultSort", void 0);
424
547
  __decorate([
548
+ words,
425
549
  property({ attribute: 'descending-label' })
426
550
  ], HelixHeadlessTable.prototype, "descendingLabel", void 0);
551
+ __decorate([
552
+ words,
553
+ property({ attribute: 'dropped-label' })
554
+ ], HelixHeadlessTable.prototype, "droppedLabel", void 0);
555
+ __decorate([
556
+ words,
557
+ property({ attribute: 'fallback-label' })
558
+ ], HelixHeadlessTable.prototype, "fallbackLabel", void 0);
559
+ __decorate([
560
+ property({ type: Boolean })
561
+ ], HelixHeadlessTable.prototype, "grid", void 0);
427
562
  __decorate([
428
563
  property()
429
564
  ], HelixHeadlessTable.prototype, "label", void 0);
565
+ __decorate([
566
+ words,
567
+ property({ attribute: 'moved-label' })
568
+ ], HelixHeadlessTable.prototype, "movedLabel", void 0);
569
+ __decorate([
570
+ words,
571
+ property({ attribute: 'move-row-label' })
572
+ ], HelixHeadlessTable.prototype, "moveRowLabel", void 0);
573
+ __decorate([
574
+ words,
575
+ property({ attribute: 'picked-up-label' })
576
+ ], HelixHeadlessTable.prototype, "pickedUpLabel", void 0);
577
+ __decorate([
578
+ property({ type: Boolean })
579
+ ], HelixHeadlessTable.prototype, "reorderable", void 0);
580
+ __decorate([
581
+ words,
582
+ property({ attribute: 'row-grips-label' })
583
+ ], HelixHeadlessTable.prototype, "rowGripsLabel", void 0);
430
584
  __decorate([
431
585
  property({ type: Boolean })
432
586
  ], HelixHeadlessTable.prototype, "selectable", void 0);
433
587
  __decorate([
588
+ words,
434
589
  property({ attribute: 'select-all-label' })
435
590
  ], HelixHeadlessTable.prototype, "selectAllLabel", void 0);
436
591
  __decorate([
437
592
  property()
438
593
  ], HelixHeadlessTable.prototype, "selected", null);
439
594
  __decorate([
595
+ words,
440
596
  property({ attribute: 'selected-label' })
441
597
  ], HelixHeadlessTable.prototype, "selectedLabel", void 0);
442
598
  __decorate([
599
+ words,
443
600
  property({ attribute: 'select-row-label' })
444
601
  ], HelixHeadlessTable.prototype, "selectRowLabel", void 0);
445
602
  __decorate([
446
603
  property()
447
604
  ], HelixHeadlessTable.prototype, "sort", null);
448
605
  __decorate([
606
+ words,
449
607
  property({ attribute: 'sorted-label' })
450
608
  ], HelixHeadlessTable.prototype, "sortedLabel", void 0);
451
609
  __decorate([
610
+ words,
452
611
  property({ attribute: 'unsorted-label' })
453
612
  ], HelixHeadlessTable.prototype, "unsortedLabel", void 0);
454
613
  __decorate([
@@ -1,6 +1,8 @@
1
1
  import { HelixElement } from '@fusion.dev/helix-core';
2
2
  import { nothing, type PropertyValues, type TemplateResult } from 'lit';
3
3
  import '../../checkbox/index.js';
4
+ /** Where a row stands in a move: the row being moved, or the one the drop indicator is beside. */
5
+ export type TableRowMove = 'dragging' | 'drop-after' | 'drop-before';
4
6
  /**
5
7
  * @summary One row of a table.
6
8
  *
@@ -13,12 +15,19 @@ import '../../checkbox/index.js';
13
15
  * In a `selectable` table the row draws a checkbox cell before its own cells,
14
16
  * and `value` is the key the table's `selected` lists it by.
15
17
  *
18
+ * In a `reorderable` table the row draws a grip cell before those, holding a
19
+ * button named by the table's `move-row-label`, and `value` is the key
20
+ * `helix-reorder` lists it by. The table says which row is moving and where
21
+ * the drop indicator is, with the `dragging`, `drop-before`, and `drop-after`
22
+ * states.
23
+ *
16
24
  * **`href` makes the whole row a link**, as a row action does in React Aria's
17
25
  * table: a press anywhere on the row follows it, except on a link or a control
18
26
  * of the row's own, and Control, Command or Shift open it the way they open a
19
27
  * link. A drag that selects text follows nothing. A row in a table is not a
20
28
  * stop of its own, so put the same link in a cell, usually the row header,
21
- * which is what the keyboard and a screen reader reach.
29
+ * which is what the keyboard and a screen reader reach. In a `grid` table,
30
+ * Enter on any cell of the row follows it as well.
22
31
  *
23
32
  * @since 0.1.0
24
33
  * @status stable
@@ -38,9 +47,15 @@ import '../../checkbox/index.js';
38
47
  * @csspart checkbox-mark-checked - Added to `checkbox-mark` while its box is checked.
39
48
  * @csspart checkbox-mark-dash - Added to `checkbox-mark` while it draws the dash, which it keeps until its box is checked.
40
49
  * @csspart checkbox-mark-indeterminate - Added to `checkbox-mark` while only some rows are selected.
50
+ * @csspart grip - The cell that holds the row's grip, in a `reorderable` table.
51
+ * @csspart grip-button - The button that moves the row.
52
+ * @csspart grip-mark - The icon on the grip.
41
53
  * @csspart select - The cell that holds the row's checkbox, in a `selectable` table.
42
54
  * @csspart select-selected - Added to `select` while the row is selected.
43
55
  *
56
+ * @cssstate dragging - The row is being moved, in a `reorderable` table.
57
+ * @cssstate drop-after - The row being moved goes after this one when it is dropped.
58
+ * @cssstate drop-before - The row being moved goes before this one when it is dropped.
44
59
  * @cssstate link - While the row has `href`, so a press on it follows the link.
45
60
  * @cssstate selected - While the row is selected, in a `selectable` table.
46
61
  */
@@ -76,6 +91,38 @@ export declare class HelixHeadlessTableRow extends HelixElement {
76
91
  selected: boolean;
77
92
  /** @internal The name of the row's checkbox, written by the table. Not a consumer's to set. */
78
93
  selectLabel: string;
94
+ /**
95
+ * @internal The name of the row's grip, written by a `reorderable` table, and
96
+ * empty in a table that does not reorder, which draws no grip. Not a
97
+ * consumer's to set.
98
+ */
99
+ gripLabel: string;
100
+ /**
101
+ * @internal Whether the grip does nothing for now, as while the table is
102
+ * sorted, written by the table. Not a consumer's to set.
103
+ */
104
+ gripStill: boolean;
105
+ /**
106
+ * @internal Whether the grip cell holds the grid's one tab stop, written by
107
+ * the table that sets `gridCell`. Not a consumer's to set.
108
+ */
109
+ gripStop: boolean;
110
+ /**
111
+ * @internal Where the row stands in a move, written by a `reorderable` table.
112
+ * Not a consumer's to set.
113
+ */
114
+ move: TableRowMove | undefined;
115
+ /**
116
+ * @internal Whether the row is a row of a `grid` table, written by that
117
+ * table. Not a consumer's to set. The checkbox cell is then a `gridcell`
118
+ * that takes focus, and the row says whether it is selected.
119
+ */
120
+ gridCell: boolean;
121
+ /**
122
+ * @internal Whether the checkbox cell holds the grid's one tab stop, written
123
+ * by the table that sets `gridCell`. Not a consumer's to set.
124
+ */
125
+ selectStop: boolean;
79
126
  /** The table's rules this row holds, so the next ones replace them rather than pile up. */
80
127
  private columnRules;
81
128
  /**
@@ -109,6 +156,13 @@ export declare class HelixHeadlessTableRow extends HelixElement {
109
156
  * table's `selected` says.
110
157
  */
111
158
  protected renderSelect(): TemplateResult | typeof nothing;
159
+ /**
160
+ * The grip cell, in a `reorderable` table: a cell of the row's own before the
161
+ * checkbox cell, holding the button that moves the row. In a grid the cell
162
+ * takes focus and Space or Enter on it picks the row up, and the button
163
+ * leaves the tab order. `aria-disabled` while a sort decides the order.
164
+ */
165
+ protected renderGrip(): TemplateResult | typeof nothing;
112
166
  protected render(): TemplateResult;
113
167
  }
114
168
  declare global {
@@ -4,12 +4,13 @@ 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 { customElement, followLink, HelixElement, hostAria } from '@fusion.dev/helix-core';
7
+ import { customElement, followLink, HelixElement, hostAria, pressedOwnControl, } from '@fusion.dev/helix-core';
8
+ import { dotsSixVertical } from '@fusion.dev/helix-icons';
8
9
  import { nothing } from 'lit';
9
10
  import { property, state } from 'lit/decorators.js';
11
+ import { unsafeSVG } from 'lit/directives/unsafe-svg.js';
10
12
  import { html } from 'lit/static-html.js';
11
13
  import '../../checkbox/index.js';
12
- const PRESSABLE = 'a[href], button, input, label, select, summary, textarea, [tabindex]';
13
14
  let HelixHeadlessTableRow = class HelixHeadlessTableRow extends HelixElement {
14
15
  constructor() {
15
16
  super(...arguments);
@@ -21,14 +22,21 @@ let HelixHeadlessTableRow = class HelixHeadlessTableRow extends HelixElement {
21
22
  this.selectable = false;
22
23
  this.selected = false;
23
24
  this.selectLabel = '';
25
+ this.gripLabel = '';
26
+ this.gripStill = false;
27
+ this.gripStop = false;
28
+ this.move = undefined;
29
+ this.gridCell = false;
30
+ this.selectStop = false;
24
31
  this.columnRules = undefined;
25
32
  this.handleClick = (event) => {
26
33
  if (this.href === '' || event.button !== 0 || event.defaultPrevented) {
27
34
  return;
28
35
  }
29
- const path = event.composedPath();
30
- const inner = path.slice(0, Math.max(0, path.indexOf(this)));
31
- if (inner.some((node) => node instanceof Element && node.matches(PRESSABLE))) {
36
+ const cell = event
37
+ .composedPath()
38
+ .find((node) => node instanceof Element && node.parentElement === this && 'isTableCell' in node);
39
+ if (pressedOwnControl(event, cell ?? this)) {
32
40
  return;
33
41
  }
34
42
  if (globalThis.getSelection?.()?.toString()) {
@@ -59,8 +67,12 @@ let HelixHeadlessTableRow = class HelixHeadlessTableRow extends HelixElement {
59
67
  willUpdate(changed) {
60
68
  super.willUpdate(changed);
61
69
  hostAria(this.internals, { role: 'row' });
70
+ this.internals.ariaSelected = this.gridCell && this.selectable ? String(this.selected) : null;
62
71
  this.toggleState('selected', this.selectable && this.selected);
63
72
  this.toggleState('link', this.href !== '');
73
+ this.toggleState('dragging', this.move === 'dragging');
74
+ this.toggleState('drop-after', this.move === 'drop-after');
75
+ this.toggleState('drop-before', this.move === 'drop-before');
64
76
  }
65
77
  connectedCallback() {
66
78
  super.connectedCallback();
@@ -75,8 +87,13 @@ let HelixHeadlessTableRow = class HelixHeadlessTableRow extends HelixElement {
75
87
  return nothing;
76
88
  }
77
89
  const checkbox = this.tag('checkbox');
78
- return html `<span part="select${this.selected ? ' select-selected' : ''}" role="cell"
90
+ const grid = this.gridCell;
91
+ return html `<span
92
+ part="select${this.selected ? ' select-selected' : ''}"
93
+ role=${grid ? 'gridcell' : 'cell'}
94
+ tabindex=${grid ? (this.selectStop ? '0' : '-1') : nothing}
79
95
  ><${checkbox}
96
+ tabindex=${grid ? '-1' : nothing}
80
97
  part="checkbox"
81
98
  exportparts="box: checkbox-box, control: checkbox-control, feedback: checkbox-feedback,
82
99
  field: checkbox-field, hint: checkbox-hint, label: checkbox-label, mark: checkbox-mark,
@@ -87,8 +104,26 @@ let HelixHeadlessTableRow = class HelixHeadlessTableRow extends HelixElement {
87
104
  ></${checkbox}
88
105
  ></span>`;
89
106
  }
107
+ renderGrip() {
108
+ if (!this.gripLabel) {
109
+ return nothing;
110
+ }
111
+ const grid = this.gridCell;
112
+ return html `<span
113
+ part="grip"
114
+ role=${grid ? 'gridcell' : 'cell'}
115
+ tabindex=${grid ? (this.gripStop ? '0' : '-1') : nothing}
116
+ ><button
117
+ part="grip-button"
118
+ type="button"
119
+ tabindex=${grid ? '-1' : nothing}
120
+ aria-label=${this.gripLabel}
121
+ aria-disabled=${this.gripStill ? 'true' : nothing}
122
+ ><svg aria-hidden="true" fill="currentColor" part="grip-mark" viewBox=${dotsSixVertical.viewBox}>${unsafeSVG(dotsSixVertical.content)}</svg></button
123
+ ></span>`;
124
+ }
90
125
  render() {
91
- return html `${this.renderSelect()}<slot @slotchange=${this.handleSlotChange}></slot>`;
126
+ return html `${this.renderGrip()}${this.renderSelect()}<slot @slotchange=${this.handleSlotChange}></slot>`;
92
127
  }
93
128
  };
94
129
  __decorate([
@@ -112,6 +147,24 @@ __decorate([
112
147
  __decorate([
113
148
  state()
114
149
  ], HelixHeadlessTableRow.prototype, "selectLabel", void 0);
150
+ __decorate([
151
+ state()
152
+ ], HelixHeadlessTableRow.prototype, "gripLabel", void 0);
153
+ __decorate([
154
+ state()
155
+ ], HelixHeadlessTableRow.prototype, "gripStill", void 0);
156
+ __decorate([
157
+ state()
158
+ ], HelixHeadlessTableRow.prototype, "gripStop", void 0);
159
+ __decorate([
160
+ state()
161
+ ], HelixHeadlessTableRow.prototype, "move", void 0);
162
+ __decorate([
163
+ state()
164
+ ], HelixHeadlessTableRow.prototype, "gridCell", void 0);
165
+ __decorate([
166
+ state()
167
+ ], HelixHeadlessTableRow.prototype, "selectStop", void 0);
115
168
  HelixHeadlessTableRow = __decorate([
116
169
  customElement('helix-headless-table-row')
117
170
  ], HelixHeadlessTableRow);
@@ -63,6 +63,11 @@ declare const HelixHeadlessTabs_base: (new (...args: any[]) => import("@fusion.d
63
63
  * @csspart tabs - The tab list.
64
64
  */
65
65
  export declare class HelixHeadlessTabs extends HelixHeadlessTabs_base {
66
+ /**
67
+ * The key this family's words are registered under, its styled tag:
68
+ * `registerWords('de', { 'helix-tabs': { label: 'Reiter' } })`.
69
+ */
70
+ static words: string;
66
71
  protected readonly keys: KeyboardNavigationController;
67
72
  private readonly indicator;
68
73
  /** Carries a host `aria-label` and `aria-labelledby` to the tab list. */