@fusion.dev/helix-headless 0.146.0 → 0.148.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 (288) hide show
  1. package/custom-elements.json +9287 -1084
  2. package/dist/accordion/item/accordion-item.d.ts +43 -21
  3. package/dist/accordion/item/accordion-item.js +37 -11
  4. package/dist/accordion/root/accordion-root.d.ts +8 -2
  5. package/dist/accordion/root/accordion-root.js +6 -8
  6. package/dist/announcement/root/announcement-root.d.ts +66 -6
  7. package/dist/announcement/root/announcement-root.js +144 -13
  8. package/dist/area-chart/root/area-chart-root.d.ts +18 -1
  9. package/dist/area-chart/root/area-chart-root.js +14 -7
  10. package/dist/avatar/root/avatar-root.d.ts +31 -1
  11. package/dist/avatar/root/avatar-root.js +11 -1
  12. package/dist/badge/count.d.ts +14 -0
  13. package/dist/badge/count.js +20 -0
  14. package/dist/badge/root/badge-root.d.ts +57 -6
  15. package/dist/badge/root/badge-root.js +77 -8
  16. package/dist/bar-chart/root/bar-chart-root.js +11 -20
  17. package/dist/bar-chart/stack.d.ts +10 -0
  18. package/dist/bar-chart/stack.js +8 -0
  19. package/dist/blockquote/root/blockquote-root.d.ts +66 -8
  20. package/dist/blockquote/root/blockquote-root.js +85 -8
  21. package/dist/breadcrumbs/breadcrumb/breadcrumb.d.ts +14 -0
  22. package/dist/breadcrumbs/breadcrumb/breadcrumb.js +12 -2
  23. package/dist/breadcrumbs/root/breadcrumbs-root.js +2 -2
  24. package/dist/button/root/button-root.d.ts +24 -38
  25. package/dist/button/root/button-root.js +6 -37
  26. package/dist/button/submitter.d.ts +27 -0
  27. package/dist/button/submitter.js +25 -0
  28. package/dist/button-group/arrows.d.ts +14 -0
  29. package/dist/button-group/arrows.js +10 -0
  30. package/dist/button-group/root/button-group-root.d.ts +141 -3
  31. package/dist/button-group/root/button-group-root.js +142 -2
  32. package/dist/canvas/edge-pan.d.ts +61 -0
  33. package/dist/canvas/edge-pan.js +63 -0
  34. package/dist/canvas/node/canvas-node.d.ts +12 -2
  35. package/dist/canvas/node/canvas-node.js +6 -2
  36. package/dist/canvas/root/canvas-document.d.ts +10 -0
  37. package/dist/canvas/root/canvas-document.js +1 -0
  38. package/dist/canvas/root/canvas-root.d.ts +107 -5
  39. package/dist/canvas/root/canvas-root.js +140 -36
  40. package/dist/canvas/snap.d.ts +42 -0
  41. package/dist/canvas/snap.js +32 -0
  42. package/dist/card/root/card-root.d.ts +12 -1
  43. package/dist/card/root/card-root.js +11 -4
  44. package/dist/carousel/root/carousel-root.d.ts +4 -3
  45. package/dist/carousel/root/carousel-root.js +2 -6
  46. package/dist/chat/root/chat-root.d.ts +28 -4
  47. package/dist/chat/root/chat-root.js +12 -7
  48. package/dist/checkbox/root/checkbox-root.js +5 -7
  49. package/dist/checkbox-group/root/checkbox-group-root.d.ts +13 -0
  50. package/dist/checkbox-group/root/checkbox-group-root.js +16 -7
  51. package/dist/checkbox-group/select-all.d.ts +9 -4
  52. package/dist/checkbox-group/select-all.js +1 -1
  53. package/dist/code-block/root/code-block-root.d.ts +41 -18
  54. package/dist/code-block/root/code-block-root.js +21 -6
  55. package/dist/color-input/root/color-input-root.d.ts +11 -0
  56. package/dist/color-input/root/color-input-root.js +12 -5
  57. package/dist/color-picker/channels.js +1 -2
  58. package/dist/color-picker/root/color-picker-root.d.ts +32 -24
  59. package/dist/color-picker/root/color-picker-root.js +99 -55
  60. package/dist/color-picker/wheel.d.ts +28 -0
  61. package/dist/color-picker/wheel.js +15 -0
  62. package/dist/combobox/root/combobox-root.d.ts +83 -11
  63. package/dist/combobox/root/combobox-root.js +81 -18
  64. package/dist/command/root/command-root.d.ts +7 -4
  65. package/dist/command/root/command-root.js +2 -19
  66. package/dist/copy-button/root/copy-button-root.d.ts +16 -1
  67. package/dist/copy-button/root/copy-button-root.js +7 -2
  68. package/dist/data-table/keys.d.ts +0 -18
  69. package/dist/data-table/keys.js +1 -11
  70. package/dist/data-table/root/data-table-root.js +29 -50
  71. package/dist/date-input/root/date-input-root.d.ts +8 -1
  72. package/dist/date-input/root/date-input-root.js +8 -5
  73. package/dist/date-picker/root/date-picker-root.d.ts +14 -9
  74. package/dist/date-picker/root/date-picker-root.js +21 -16
  75. package/dist/description-list/item/description-list-item.d.ts +22 -4
  76. package/dist/description-list/item/description-list-item.js +14 -4
  77. package/dist/divider/root/divider-root.d.ts +45 -16
  78. package/dist/divider/root/divider-root.js +28 -4
  79. package/dist/donut-chart/root/donut-chart-root.js +13 -6
  80. package/dist/donut-chart/slice-label.d.ts +35 -0
  81. package/dist/donut-chart/slice-label.js +11 -0
  82. package/dist/drawer/root/drawer-root.d.ts +4 -2
  83. package/dist/drawer/root/drawer-root.js +15 -3
  84. package/dist/drilldown/item/drilldown-item.d.ts +21 -1
  85. package/dist/drilldown/item/drilldown-item.js +38 -4
  86. package/dist/drilldown/root/drilldown-root.js +3 -2
  87. package/dist/element-events.generated.js +5 -1
  88. package/dist/empty/root/empty-root.d.ts +46 -2
  89. package/dist/empty/root/empty-root.js +50 -5
  90. package/dist/file-input/root/file-input-root.d.ts +34 -6
  91. package/dist/file-input/root/file-input-root.js +55 -21
  92. package/dist/file-input/status.d.ts +24 -0
  93. package/dist/file-input/status.js +11 -0
  94. package/dist/filter-input/chip/filter-chip.d.ts +23 -0
  95. package/dist/filter-input/chip/filter-chip.js +10 -2
  96. package/dist/filter-input/root/filter-input-root.d.ts +8 -0
  97. package/dist/filter-input/root/filter-input-root.js +17 -27
  98. package/dist/format-date/fields.d.ts +20 -0
  99. package/dist/format-date/fields.js +14 -0
  100. package/dist/format-date/options.d.ts +5 -5
  101. package/dist/format-date/options.js +10 -39
  102. package/dist/format-date/root/format-date-root.d.ts +53 -4
  103. package/dist/format-date/root/format-date-root.js +38 -50
  104. package/dist/graph/root/graph-root.d.ts +23 -5
  105. package/dist/graph/root/graph-root.js +17 -20
  106. package/dist/heatmap/root/buckets.d.ts +21 -0
  107. package/dist/heatmap/root/buckets.js +34 -0
  108. package/dist/heatmap/root/heatmap-root.d.ts +76 -3
  109. package/dist/heatmap/root/heatmap-root.js +105 -20
  110. package/dist/icon/index.d.ts +1 -1
  111. package/dist/icon/index.js +1 -1
  112. package/dist/icon/registry.d.ts +26 -1
  113. package/dist/icon/registry.js +12 -1
  114. package/dist/icon/root/icon-root.d.ts +13 -0
  115. package/dist/icon/root/icon-root.js +23 -2
  116. package/dist/icon/root/index.d.ts +1 -1
  117. package/dist/icon/root/index.js +1 -1
  118. package/dist/image/root/image-root.d.ts +20 -0
  119. package/dist/image/root/image-root.js +6 -1
  120. package/dist/input/root/input-root.d.ts +23 -2
  121. package/dist/input/root/input-root.js +12 -8
  122. package/dist/kbd/root/kbd-root.d.ts +20 -3
  123. package/dist/kbd/root/kbd-root.js +23 -50
  124. package/dist/legend/hidden-series.d.ts +10 -2
  125. package/dist/legend/hidden-series.js +5 -2
  126. package/dist/legend/root/legend-root.d.ts +25 -7
  127. package/dist/legend/root/legend-root.js +25 -26
  128. package/dist/lightbox/root/lightbox-root.d.ts +50 -5
  129. package/dist/lightbox/root/lightbox-root.js +76 -8
  130. package/dist/lightbox/zoom.d.ts +2 -0
  131. package/dist/lightbox/zoom.js +5 -3
  132. package/dist/line-chart/root/line-chart-root.d.ts +16 -0
  133. package/dist/line-chart/root/line-chart-root.js +10 -2
  134. package/dist/list/root/list-root.d.ts +10 -2
  135. package/dist/list/root/list-root.js +31 -24
  136. package/dist/list/selection.d.ts +17 -0
  137. package/dist/list/selection.js +16 -0
  138. package/dist/listbox/root/listbox-root.d.ts +125 -26
  139. package/dist/listbox/root/listbox-root.js +156 -166
  140. package/dist/map/marker/map-marker.d.ts +2 -1
  141. package/dist/map/root/map-root.d.ts +40 -2
  142. package/dist/map/root/map-root.js +64 -23
  143. package/dist/megamenu/hand-over.d.ts +75 -0
  144. package/dist/megamenu/hand-over.js +67 -0
  145. package/dist/megamenu/root/megamenu-root.d.ts +38 -14
  146. package/dist/megamenu/root/megamenu-root.js +29 -50
  147. package/dist/menu/item/menu-item.js +4 -4
  148. package/dist/menu/root/menu-root.d.ts +5 -2
  149. package/dist/meter/root/meter-root.d.ts +42 -0
  150. package/dist/meter/root/meter-root.js +33 -7
  151. package/dist/navigation/root/navigation-root.js +5 -8
  152. package/dist/notifications/group/notification-group.d.ts +8 -1
  153. package/dist/notifications/group/notification-group.js +12 -6
  154. package/dist/notifications/notification/notification.d.ts +12 -1
  155. package/dist/notifications/notification/notification.js +3 -1
  156. package/dist/notifications/root/notifications-root.d.ts +48 -3
  157. package/dist/notifications/root/notifications-root.js +36 -6
  158. package/dist/number-input/grain.d.ts +28 -0
  159. package/dist/number-input/grain.js +14 -0
  160. package/dist/number-input/root/number-input-root.d.ts +17 -1
  161. package/dist/number-input/root/number-input-root.js +29 -18
  162. package/dist/object-inspector/root/object-inspector-root.d.ts +17 -6
  163. package/dist/object-inspector/root/object-inspector-root.js +31 -20
  164. package/dist/option/index.d.ts +1 -0
  165. package/dist/option/index.js +1 -0
  166. package/dist/option/separator/option-separator.d.ts +30 -0
  167. package/dist/option/separator/option-separator.js +21 -0
  168. package/dist/outline/root/outline-root.d.ts +12 -0
  169. package/dist/outline/root/outline-root.js +5 -19
  170. package/dist/pagination/size/pagination-size.d.ts +6 -0
  171. package/dist/pagination/size/pagination-size.js +5 -3
  172. package/dist/pin-input/code.d.ts +51 -1
  173. package/dist/pin-input/code.js +37 -0
  174. package/dist/pin-input/root/pin-input-root.d.ts +98 -121
  175. package/dist/pin-input/root/pin-input-root.js +151 -156
  176. package/dist/popover/hide-outside.js +2 -9
  177. package/dist/popover/root/popover-root.d.ts +7 -1
  178. package/dist/popover/root/popover-root.js +9 -1
  179. package/dist/progress/root/progress-root.d.ts +27 -0
  180. package/dist/progress/root/progress-root.js +25 -7
  181. package/dist/qr-code/export.d.ts +19 -0
  182. package/dist/qr-code/export.js +14 -0
  183. package/dist/qr-code/name.d.ts +11 -0
  184. package/dist/qr-code/name.js +7 -0
  185. package/dist/qr-code/root/qr-code-root.d.ts +31 -9
  186. package/dist/qr-code/root/qr-code-root.js +29 -17
  187. package/dist/radio/group/radio-group.d.ts +15 -0
  188. package/dist/radio/root/radio-root.js +2 -2
  189. package/dist/rating/root/rating-root.d.ts +22 -9
  190. package/dist/rating/root/rating-root.js +15 -39
  191. package/dist/scatter-chart/measures.d.ts +22 -0
  192. package/dist/scatter-chart/measures.js +11 -0
  193. package/dist/scatter-chart/root/scatter-chart-root.d.ts +26 -0
  194. package/dist/scatter-chart/root/scatter-chart-root.js +21 -7
  195. package/dist/scroll-area/scrollbar.d.ts +0 -8
  196. package/dist/scroll-area/scrollbar.js +1 -1
  197. package/dist/select/align.d.ts +47 -0
  198. package/dist/select/align.js +7 -0
  199. package/dist/select/root/select-root.d.ts +115 -11
  200. package/dist/select/root/select-root.js +104 -20
  201. package/dist/slider/root/slider-root.d.ts +18 -1
  202. package/dist/slider/root/slider-root.js +22 -0
  203. package/dist/sparkline/readings.d.ts +30 -12
  204. package/dist/sparkline/readings.js +32 -15
  205. package/dist/sparkline/root/sparkline-root.d.ts +46 -3
  206. package/dist/sparkline/root/sparkline-root.js +60 -21
  207. package/dist/speed-dial/group/speed-dial-group.d.ts +48 -0
  208. package/dist/speed-dial/group/speed-dial-group.js +43 -0
  209. package/dist/speed-dial/index.d.ts +1 -0
  210. package/dist/speed-dial/index.js +1 -0
  211. package/dist/speed-dial/item/speed-dial-item.d.ts +27 -2
  212. package/dist/speed-dial/item/speed-dial-item.js +43 -5
  213. package/dist/speed-dial/long-press.d.ts +50 -0
  214. package/dist/speed-dial/long-press.js +48 -0
  215. package/dist/speed-dial/root/speed-dial-root.d.ts +86 -1
  216. package/dist/speed-dial/root/speed-dial-root.js +123 -6
  217. package/dist/splitter/root/splitter-root.d.ts +9 -2
  218. package/dist/splitter/root/splitter-root.js +18 -3
  219. package/dist/steps/root/steps-root.d.ts +8 -1
  220. package/dist/steps/root/steps-root.js +6 -1
  221. package/dist/steps/step/step.d.ts +1 -0
  222. package/dist/steps/step/step.js +1 -1
  223. package/dist/table/cell/table-cell.d.ts +8 -1
  224. package/dist/table/cell/table-cell.js +6 -2
  225. package/dist/table/column/table-column.d.ts +6 -0
  226. package/dist/table/column/table-column.js +5 -1
  227. package/dist/table/grid-controller.d.ts +117 -0
  228. package/dist/table/grid-controller.js +293 -0
  229. package/dist/table/root/table-root.d.ts +47 -3
  230. package/dist/table/root/table-root.js +93 -29
  231. package/dist/table/row/table-row.d.ts +36 -0
  232. package/dist/table/row/table-row.js +52 -2
  233. package/dist/tabs/root/tabs-root.d.ts +5 -3
  234. package/dist/tag/group/tag-group.d.ts +16 -4
  235. package/dist/tag/group/tag-group.js +23 -20
  236. package/dist/textarea/root/textarea-root.d.ts +14 -2
  237. package/dist/textarea/root/textarea-root.js +6 -7
  238. package/dist/time-input/root/time-input-root.d.ts +5 -1
  239. package/dist/time-input/root/time-input-root.js +10 -7
  240. package/dist/time-picker/root/time-picker-root.d.ts +12 -14
  241. package/dist/time-picker/root/time-picker-root.js +18 -23
  242. package/dist/toast/item/toast-item.d.ts +9 -6
  243. package/dist/toast/item/toast-item.js +1 -1
  244. package/dist/toast/root/toast-root.d.ts +40 -4
  245. package/dist/toast/root/toast-root.js +68 -16
  246. package/dist/toast/words.d.ts +12 -0
  247. package/dist/toast/words.js +25 -0
  248. package/dist/toggle/group/toggle-group.d.ts +29 -5
  249. package/dist/toggle/group/toggle-group.js +26 -43
  250. package/dist/toggle/root/toggle-root.js +2 -4
  251. package/dist/toolbar/root/toolbar-root.d.ts +52 -5
  252. package/dist/toolbar/root/toolbar-root.js +88 -13
  253. package/dist/tooltip/root/tooltip-root.d.ts +7 -1
  254. package/dist/tooltip/root/tooltip-root.js +10 -2
  255. package/dist/tour/root/tour-root.d.ts +15 -0
  256. package/dist/tour/root/tour-root.js +20 -1
  257. package/dist/tour/stop/tour-stop.d.ts +3 -0
  258. package/dist/tour/stop/tour-stop.js +3 -3
  259. package/dist/tree/root/tree-root.js +2 -2
  260. package/dist/trend/figure.d.ts +16 -0
  261. package/dist/trend/figure.js +8 -0
  262. package/dist/trend/root/trend-root.d.ts +41 -2
  263. package/dist/trend/root/trend-root.js +29 -3
  264. package/dist/video/root/extra-controls.d.ts +12 -0
  265. package/dist/video/root/extra-controls.js +6 -2
  266. package/dist/video/root/video-root.d.ts +16 -1
  267. package/dist/video/root/video-root.js +15 -1
  268. package/dist/video-playlist/root/video-playlist-root.d.ts +11 -1
  269. package/dist/video-playlist/root/video-playlist-root.js +3 -0
  270. package/dist/virtual-list/fill.d.ts +11 -0
  271. package/dist/virtual-list/fill.js +9 -0
  272. package/dist/virtual-list/keys.d.ts +16 -7
  273. package/dist/virtual-list/keys.js +17 -6
  274. package/dist/virtual-list/plan.d.ts +17 -1
  275. package/dist/virtual-list/plan.js +13 -2
  276. package/dist/virtual-list/root/virtual-list-root.d.ts +25 -3
  277. package/dist/virtual-list/root/virtual-list-root.js +53 -41
  278. package/lint.json +1 -1
  279. package/package.json +5 -5
  280. package/types/jsx.d.ts +4934 -954
  281. package/types/svelte.d.ts +2 -0
  282. package/types/vue.d.ts +946 -253
  283. package/dist/color-picker/swatches.d.ts +0 -12
  284. package/dist/color-picker/swatches.js +0 -26
  285. package/dist/rating/steps.d.ts +0 -7
  286. package/dist/rating/steps.js +0 -9
  287. package/dist/tooltip/focus-target.d.ts +0 -6
  288. 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, fillTemplate, format, HelixElement, HelixSelectEvent, HelixSelectedEvent, HelixSortEvent, HelixSortedEvent, MixinCollection, parse, reflectElements, requestChange, sort, splitValues, toggleEvery, whenHydrated, } from '@fusion.dev/helix-core';
7
+ import { AriaForwardController, assignSlots, commaList, customElement, cycle, everyState, fillTemplate, followLink, format, HelixElement, HelixSelectEvent, HelixSelectedEvent, HelixSortEvent, HelixSortedEvent, inRowOrder, MixinCollection, onAndroid, parse, reflectElements, requestChange, sort, splitValues, toggleEvery, whenHydrated, } 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);
@@ -51,6 +52,7 @@ let HelixHeadlessTable = class HelixHeadlessTable extends MixinCollection(HelixE
51
52
  this.defaultSelected = '';
52
53
  this.defaultSort = '';
53
54
  this.descendingLabel = 'descending';
55
+ this.grid = false;
54
56
  this.label = '';
55
57
  this.selectable = false;
56
58
  this.selectAllLabel = 'Select every row';
@@ -65,6 +67,15 @@ let HelixHeadlessTable = class HelixHeadlessTable extends MixinCollection(HelixE
65
67
  label: true,
66
68
  target: () => this.partNamed('table'),
67
69
  });
70
+ this.gridKeys = new TableGridController(this, {
71
+ activate: (place, event) => this.activate(place, event),
72
+ columns: () => this.tableColumns.filter((column) => column.shown),
73
+ on: () => this.grid,
74
+ part: (name) => this.partNamed(name),
75
+ rows: () => (this.childrenKnown ? this.arrangedRows : []),
76
+ selectAll: () => this.selectable && this.requestSelected(new Set(this.everyKey)),
77
+ selectable: () => this.selectable,
78
+ });
68
79
  this.heardSort = undefined;
69
80
  this.heardSortBefore = undefined;
70
81
  this.heardSelected = undefined;
@@ -74,10 +85,9 @@ let HelixHeadlessTable = class HelixHeadlessTable extends MixinCollection(HelixE
74
85
  return;
75
86
  }
76
87
  const root = origin.getRootNode();
77
- const keys = this.chosen;
78
88
  if (root === this.renderRoot) {
79
89
  event.preventDefault();
80
- this.requestSelected(new Set(toggleEvery(keys, this.keyed.map(({ key }) => key))));
90
+ this.chooseAll();
81
91
  return;
82
92
  }
83
93
  const found = this.keyed.find(({ row }) => row.shadowRoot === root);
@@ -85,13 +95,7 @@ let HelixHeadlessTable = class HelixHeadlessTable extends MixinCollection(HelixE
85
95
  return;
86
96
  }
87
97
  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);
98
+ this.chooseRow(found.key, event.detail.checked);
95
99
  };
96
100
  this.handleHeadClick = (event) => {
97
101
  const path = event.composedPath();
@@ -204,9 +208,55 @@ let HelixHeadlessTable = class HelixHeadlessTable extends MixinCollection(HelixE
204
208
  },
205
209
  event: (value) => new HelixSelectEvent({ value }),
206
210
  host: this,
207
- next: [...keys].join(','),
211
+ next: inRowOrder(keys, this.keyed.map(({ key }) => key)).join(','),
208
212
  });
209
213
  }
214
+ get everyKey() {
215
+ return this.keyed.map(({ key }) => key);
216
+ }
217
+ chooseAll() {
218
+ this.requestSelected(new Set(toggleEvery(this.chosen, this.everyKey)));
219
+ }
220
+ chooseRow(key, on) {
221
+ const keys = this.chosen;
222
+ if (on) {
223
+ keys.add(key);
224
+ }
225
+ else {
226
+ keys.delete(key);
227
+ }
228
+ this.requestSelected(keys);
229
+ }
230
+ activate(place, event) {
231
+ const lead = this.selectable && place.column === 0;
232
+ if (event.key === 'F2') {
233
+ return false;
234
+ }
235
+ if (place.row === -1) {
236
+ if (lead) {
237
+ this.chooseAll();
238
+ return true;
239
+ }
240
+ const shown = this.tableColumns.filter((one) => one.shown);
241
+ const column = shown[place.column - (this.selectable ? 1 : 0)];
242
+ if (column?.canSort) {
243
+ this.toggleSort(column.field);
244
+ return true;
245
+ }
246
+ return false;
247
+ }
248
+ const row = this.arrangedRows[place.row];
249
+ const found = this.keyed.find((one) => one.row === row);
250
+ if (this.selectable && found && (event.key === ' ' || lead)) {
251
+ this.chooseRow(found.key, !this.chosen.has(found.key));
252
+ return true;
253
+ }
254
+ if (event.key === 'Enter' && row?.href) {
255
+ followLink(this.ownerDocument, { href: row.href, rel: row.rel, target: row.target }, event);
256
+ return true;
257
+ }
258
+ return false;
259
+ }
210
260
  markSelected() {
211
261
  const keys = this.chosen;
212
262
  for (const { key, row } of this.keyed) {
@@ -230,6 +280,7 @@ let HelixHeadlessTable = class HelixHeadlessTable extends MixinCollection(HelixE
230
280
  }
231
281
  markSorted() {
232
282
  const current = parse(this.sort);
283
+ const android = onAndroid();
233
284
  for (const column of this.tableColumns) {
234
285
  column.sorted =
235
286
  current && column.canSort && column.field === current.field
@@ -237,6 +288,13 @@ let HelixHeadlessTable = class HelixHeadlessTable extends MixinCollection(HelixE
237
288
  ? 'ascending'
238
289
  : 'descending'
239
290
  : undefined;
291
+ column.sortWords =
292
+ android && column.sorted
293
+ ? fillTemplate(this.sortedLabel, {
294
+ column: column.textContent?.trim() || column.field,
295
+ order: column.sorted === 'ascending' ? this.ascendingLabel : this.descendingLabel,
296
+ })
297
+ : '';
240
298
  }
241
299
  }
242
300
  get tableColumns() {
@@ -317,16 +375,9 @@ let HelixHeadlessTable = class HelixHeadlessTable extends MixinCollection(HelixE
317
375
  }
318
376
  return;
319
377
  }
320
- const head = this.renderRoot?.querySelector('slot[name="columns"]');
321
- const body = this.renderRoot?.querySelector('slot:not([name])');
322
- if (!head || !body) {
323
- return;
324
- }
325
- head.assign(...this.tableColumns);
326
- body.assign(...this.arrangedRows);
327
- this.renderRoot
328
- ?.querySelector('slot[name="heading"]')
329
- ?.assign(...this.headings);
378
+ const columns = new Set(this.tableColumns);
379
+ const headings = new Set(this.headings);
380
+ assignSlots(this.renderRoot, [...columns, ...headings, ...this.arrangedRows], (child) => (columns.has(child) ? 'columns' : headings.has(child) ? 'heading' : ''));
330
381
  }
331
382
  alignCells() {
332
383
  if (typeof CSSStyleSheet === 'undefined' || !('replaceSync' in CSSStyleSheet.prototype)) {
@@ -360,33 +411,43 @@ let HelixHeadlessTable = class HelixHeadlessTable extends MixinCollection(HelixE
360
411
  this.markSorted();
361
412
  this.markSelected();
362
413
  this.nameByHeading();
414
+ if (this.childrenKnown) {
415
+ this.gridKeys.mark();
416
+ this.gridKeys.place();
417
+ }
363
418
  }
364
419
  renderSelectAll() {
365
420
  if (!this.selectable) {
366
421
  return nothing;
367
422
  }
368
423
  const every = this.childrenKnown ? this.keyed.map(({ key }) => key) : [];
369
- const keys = this.chosen;
370
- const count = every.filter((key) => keys.has(key)).length;
424
+ const { checked, indeterminate } = everyState(this.chosen, every);
371
425
  const checkbox = this.tag('checkbox');
426
+ const grid = this.grid;
372
427
  return html `<span part="select-all" role="columnheader"
428
+ tabindex=${grid ? (this.gridKeys.isStop({ column: 0, row: -1 }) ? '0' : '-1') : nothing}
373
429
  ><${checkbox}
374
430
  part="checkbox"
431
+ tabindex=${grid ? '-1' : nothing}
375
432
  exportparts="box: checkbox-box, control: checkbox-control, feedback: checkbox-feedback,
376
433
  field: checkbox-field, hint: checkbox-hint, label: checkbox-label, mark: checkbox-mark,
377
434
  mark-checked: checkbox-mark-checked, mark-dash: checkbox-mark-dash,
378
435
  mark-indeterminate: checkbox-mark-indeterminate"
379
436
  aria-label=${this.selectAllLabel}
380
- .checked=${every.length > 0 && count === every.length}
381
- .indeterminate=${count > 0 && count < every.length}
437
+ .checked=${checked}
438
+ .indeterminate=${indeterminate}
382
439
  ></${checkbox}
383
440
  ></span>`;
384
441
  }
385
442
  render() {
386
443
  const template = this.template;
387
- return html `<slot name="heading"></slot><div
444
+ const grid = this.grid;
445
+ const start = grid ? html `<span part="grid-start" tabindex="-1"></span>` : nothing;
446
+ const end = grid ? html `<span part="grid-end" tabindex="-1"></span>` : nothing;
447
+ return html `<slot name="heading"></slot>${start}<div
388
448
  part="table"
389
- role="table"
449
+ role=${grid ? 'grid' : 'table'}
450
+ aria-multiselectable=${grid && this.selectable ? 'true' : nothing}
390
451
  aria-busy=${this.loading ? 'true' : nothing}
391
452
  aria-label=${this.label || 'Table'}
392
453
  style=${template ? `--table-template: ${template}` : ''}
@@ -398,8 +459,8 @@ let HelixHeadlessTable = class HelixHeadlessTable extends MixinCollection(HelixE
398
459
  this.handleSlotChange();
399
460
  }}
400
461
  ></slot>
401
- ${this.renderStatus(this.hasRows, 'cell')}
402
- </div>${this.renderLive(this.hasRows)}`;
462
+ ${this.renderStatus(this.hasRows, grid ? 'gridcell' : 'cell')}
463
+ </div>${end}${this.renderLive(this.hasRows)}`;
403
464
  }
404
465
  };
405
466
  __decorate([
@@ -417,6 +478,9 @@ __decorate([
417
478
  __decorate([
418
479
  property({ attribute: 'descending-label' })
419
480
  ], HelixHeadlessTable.prototype, "descendingLabel", void 0);
481
+ __decorate([
482
+ property({ type: Boolean })
483
+ ], HelixHeadlessTable.prototype, "grid", void 0);
420
484
  __decorate([
421
485
  property()
422
486
  ], HelixHeadlessTable.prototype, "label", void 0);
@@ -13,6 +13,14 @@ import '../../checkbox/index.js';
13
13
  * In a `selectable` table the row draws a checkbox cell before its own cells,
14
14
  * and `value` is the key the table's `selected` lists it by.
15
15
  *
16
+ * **`href` makes the whole row a link**, as a row action does in React Aria's
17
+ * table: a press anywhere on the row follows it, except on a link or a control
18
+ * of the row's own, and Control, Command or Shift open it the way they open a
19
+ * link. A drag that selects text follows nothing. A row in a table is not a
20
+ * 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. In a `grid` table,
22
+ * Enter on any cell of the row follows it as well.
23
+ *
16
24
  * @since 0.1.0
17
25
  * @status stable
18
26
  * @aliases Row, TableRow
@@ -34,6 +42,7 @@ import '../../checkbox/index.js';
34
42
  * @csspart select - The cell that holds the row's checkbox, in a `selectable` table.
35
43
  * @csspart select-selected - Added to `select` while the row is selected.
36
44
  *
45
+ * @cssstate link - While the row has `href`, so a press on it follows the link.
37
46
  * @cssstate selected - While the row is selected, in a `selectable` table.
38
47
  */
39
48
  export declare class HelixHeadlessTableRow extends HelixElement {
@@ -42,6 +51,15 @@ export declare class HelixHeadlessTableRow extends HelixElement {
42
51
  * finds its columns. Not a consumer's to read or set.
43
52
  */
44
53
  readonly isTableRow = true;
54
+ /**
55
+ * The URL a press on the row follows, which makes the whole row a link.
56
+ * Empty, the default, leaves presses to the row's cells.
57
+ */
58
+ href: string;
59
+ /** The `rel` of the row's link. You set it yourself, as on an anchor. */
60
+ rel: string;
61
+ /** Where the row's link opens, such as `_blank`. */
62
+ target: string;
45
63
  /**
46
64
  * The key the table's `selected` lists this row by. Left empty, the row is
47
65
  * known by its place among the rows as written.
@@ -59,6 +77,17 @@ export declare class HelixHeadlessTableRow extends HelixElement {
59
77
  selected: boolean;
60
78
  /** @internal The name of the row's checkbox, written by the table. Not a consumer's to set. */
61
79
  selectLabel: string;
80
+ /**
81
+ * @internal Whether the row is a row of a `grid` table, written by that
82
+ * table. Not a consumer's to set. The checkbox cell is then a `gridcell`
83
+ * that takes focus, and the row says whether it is selected.
84
+ */
85
+ gridCell: boolean;
86
+ /**
87
+ * @internal Whether the checkbox cell holds the grid's one tab stop, written
88
+ * by the table that sets `gridCell`. Not a consumer's to set.
89
+ */
90
+ selectStop: boolean;
62
91
  /** The table's rules this row holds, so the next ones replace them rather than pile up. */
63
92
  private columnRules;
64
93
  /**
@@ -69,6 +98,13 @@ export declare class HelixHeadlessTableRow extends HelixElement {
69
98
  */
70
99
  alignCells(rules: CSSStyleSheet): void;
71
100
  protected willUpdate(changed: PropertyValues): void;
101
+ connectedCallback(): void;
102
+ disconnectedCallback(): void;
103
+ /**
104
+ * A press on the row follows `href`, unless it landed on a link or control
105
+ * of the row's own, or ended a drag that selected text.
106
+ */
107
+ private readonly handleClick;
72
108
  /**
73
109
  * Asks each cell to read its role again once the cells change.
74
110
  *
@@ -4,7 +4,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
4
4
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
5
  return c > 3 && r && Object.defineProperty(target, key, r), r;
6
6
  };
7
- import { customElement, HelixElement, hostAria } from '@fusion.dev/helix-core';
7
+ import { customElement, followLink, HelixElement, hostAria, pressedOwnControl, } 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';
@@ -13,11 +13,31 @@ let HelixHeadlessTableRow = class HelixHeadlessTableRow extends HelixElement {
13
13
  constructor() {
14
14
  super(...arguments);
15
15
  this.isTableRow = true;
16
+ this.href = '';
17
+ this.rel = '';
18
+ this.target = '';
16
19
  this.value = '';
17
20
  this.selectable = false;
18
21
  this.selected = false;
19
22
  this.selectLabel = '';
23
+ this.gridCell = false;
24
+ this.selectStop = false;
20
25
  this.columnRules = undefined;
26
+ this.handleClick = (event) => {
27
+ if (this.href === '' || event.button !== 0 || event.defaultPrevented) {
28
+ return;
29
+ }
30
+ const cell = event
31
+ .composedPath()
32
+ .find((node) => node instanceof Element && node.parentElement === this && 'isTableCell' in node);
33
+ if (pressedOwnControl(event, cell ?? this)) {
34
+ return;
35
+ }
36
+ if (globalThis.getSelection?.()?.toString()) {
37
+ return;
38
+ }
39
+ followLink(this.ownerDocument, { href: this.href, rel: this.rel, target: this.target }, event);
40
+ };
21
41
  this.handleSlotChange = () => {
22
42
  for (const cell of this.children) {
23
43
  if ('isTableCell' in cell) {
@@ -41,15 +61,30 @@ let HelixHeadlessTableRow = class HelixHeadlessTableRow extends HelixElement {
41
61
  willUpdate(changed) {
42
62
  super.willUpdate(changed);
43
63
  hostAria(this.internals, { role: 'row' });
64
+ this.internals.ariaSelected = this.gridCell && this.selectable ? String(this.selected) : null;
44
65
  this.toggleState('selected', this.selectable && this.selected);
66
+ this.toggleState('link', this.href !== '');
67
+ }
68
+ connectedCallback() {
69
+ super.connectedCallback();
70
+ this.addEventListener('click', this.handleClick);
71
+ }
72
+ disconnectedCallback() {
73
+ super.disconnectedCallback();
74
+ this.removeEventListener('click', this.handleClick);
45
75
  }
46
76
  renderSelect() {
47
77
  if (!this.selectable) {
48
78
  return nothing;
49
79
  }
50
80
  const checkbox = this.tag('checkbox');
51
- return html `<span part="select${this.selected ? ' select-selected' : ''}" role="cell"
81
+ const grid = this.gridCell;
82
+ return html `<span
83
+ part="select${this.selected ? ' select-selected' : ''}"
84
+ role=${grid ? 'gridcell' : 'cell'}
85
+ tabindex=${grid ? (this.selectStop ? '0' : '-1') : nothing}
52
86
  ><${checkbox}
87
+ tabindex=${grid ? '-1' : nothing}
53
88
  part="checkbox"
54
89
  exportparts="box: checkbox-box, control: checkbox-control, feedback: checkbox-feedback,
55
90
  field: checkbox-field, hint: checkbox-hint, label: checkbox-label, mark: checkbox-mark,
@@ -64,6 +99,15 @@ let HelixHeadlessTableRow = class HelixHeadlessTableRow extends HelixElement {
64
99
  return html `${this.renderSelect()}<slot @slotchange=${this.handleSlotChange}></slot>`;
65
100
  }
66
101
  };
102
+ __decorate([
103
+ property()
104
+ ], HelixHeadlessTableRow.prototype, "href", void 0);
105
+ __decorate([
106
+ property()
107
+ ], HelixHeadlessTableRow.prototype, "rel", void 0);
108
+ __decorate([
109
+ property()
110
+ ], HelixHeadlessTableRow.prototype, "target", void 0);
67
111
  __decorate([
68
112
  property()
69
113
  ], HelixHeadlessTableRow.prototype, "value", void 0);
@@ -76,6 +120,12 @@ __decorate([
76
120
  __decorate([
77
121
  state()
78
122
  ], HelixHeadlessTableRow.prototype, "selectLabel", void 0);
123
+ __decorate([
124
+ state()
125
+ ], HelixHeadlessTableRow.prototype, "gridCell", void 0);
126
+ __decorate([
127
+ state()
128
+ ], HelixHeadlessTableRow.prototype, "selectStop", void 0);
79
129
  HelixHeadlessTableRow = __decorate([
80
130
  customElement('helix-headless-table-row')
81
131
  ], HelixHeadlessTableRow);
@@ -21,9 +21,11 @@ declare const HelixHeadlessTabs_base: (new (...args: any[]) => import("@fusion.d
21
21
  * between tabs either way.
22
22
  *
23
23
  * A tab with an `href` is a link, for tabs that are pages of a site. Pressing
24
- * it follows the link, and the arrow keys move focus without choosing, so
25
- * arrowing past a tab never leaves the page. Mark the tab of the page you are
26
- * on with `selected`, or set `active` to its value.
24
+ * it follows the link. Where any tab is a link, the arrow keys move focus
25
+ * without choosing on every tab of the list, as under `manual`, so arrowing
26
+ * past a tab never leaves the page and the list answers the keys one way.
27
+ * Mark the tab of the page you are on with `selected`, or set `active` to its
28
+ * value.
27
29
  *
28
30
  * Each tab says which panel it controls through `aria-controls`, set as an
29
31
  * element reference to the panel's host, where the engine has reflection.
@@ -22,12 +22,14 @@ export type TagSelectionMode = SelectionMode;
22
22
  * that is removed leaves `value`, which then sends `change`.
23
23
  *
24
24
  * Name the set with `label`. Each tag is named by its words alone, without
25
- * its remove button.
25
+ * its remove button. `value` takes an array of values on the property as
26
+ * well, as React sets `value={['Apple']}`; a press writes it back as a
27
+ * string.
26
28
  *
27
29
  * **Removing the last tag keeps focus in the group.** With no tags left the
28
30
  * set is a `group`, and focus moves to its `empty` part,
29
31
  * which holds the `empty` slot: put words there such as "No filters" for a
30
- * reader to hear.
32
+ * reader to hear. With nothing slotted it says `empty-label`, "No tags".
31
33
  *
32
34
  * @since 0.1.0
33
35
  * @status stable
@@ -35,7 +37,7 @@ export type TagSelectionMode = SelectionMode;
35
37
  * @documentation https://fusion.dev/helix/components/tag
36
38
  *
37
39
  * @slot - The tags, in the order they are read.
38
- * @slot empty - Shown in place of the tags while there are none, such as "No filters".
40
+ * @slot empty - Shown in place of the tags while there are none, such as "No filters". Its fallback is `empty-label`.
39
41
  *
40
42
  * @event {Event} change - Fired once a press has changed which tags are selected.
41
43
  * @event {HelixBeforeChangeEvent} helix-before-change - Fired before a press changes which tags are selected, with the `value` it would leave. Cancelable.
@@ -44,6 +46,11 @@ export type TagSelectionMode = SelectionMode;
44
46
  * @csspart empty - Holds the `empty` slot while the group has no tags, rendered only then. Takes focus when the last tag is removed.
45
47
  */
46
48
  export declare class HelixHeadlessTagGroup extends HelixElement {
49
+ /**
50
+ * The words the group shows and says once its last tag is removed, where
51
+ * nothing is in the `empty` slot.
52
+ */
53
+ emptyLabel: string;
47
54
  /**
48
55
  * The name of the set, such as "Filters", which a screen reader announces
49
56
  * before its tags.
@@ -62,7 +69,7 @@ export declare class HelixHeadlessTagGroup extends HelixElement {
62
69
  * Set it to start with tags selected. A tag's value is its `value`, or its
63
70
  * words where it has none.
64
71
  */
65
- value: string;
72
+ value: string | readonly string[];
66
73
  /** The tag the reader was last on, which keeps the tab stop. */
67
74
  private last;
68
75
  /**
@@ -72,6 +79,11 @@ export declare class HelixHeadlessTagGroup extends HelixElement {
72
79
  * a list of tags has a first and a last.
73
80
  */
74
81
  protected readonly keys: KeyboardNavigationController;
82
+ /**
83
+ * `value` as one written list, separated by commas, however it was set:
84
+ * an array of values is joined.
85
+ */
86
+ private get written();
75
87
  /** The tags the group holds, in order. */
76
88
  get tags(): HelixHeadlessTag[];
77
89
  /** The tags a key can land on, which are the ones that are not disabled. */
@@ -4,20 +4,21 @@ 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 { commaList, customElement, deepActiveElement, deepContains, HelixBeforeChangeEvent, HelixElement, hostAria, KeyboardNavigationController, pressedValue, prunedValue, requestChange, rovingStop, slottedWords, typeaheadBy, whenHydrated, } from '@fusion.dev/helix-core';
7
+ import { commaList, customElement, deepActiveElement, deepContains, focusItemOf, HelixElement, hostAria, KeyboardNavigationController, pressedValue, prunedValue, requestValue, rovingStop, slottedWords, typeaheadByWords, whenHydrated, } from '@fusion.dev/helix-core';
8
8
  import { html, nothing } from 'lit';
9
9
  import { property } from 'lit/decorators.js';
10
10
  import { HelixHeadlessTag } from '../root/tag-root.js';
11
11
  let HelixHeadlessTagGroup = class HelixHeadlessTagGroup extends HelixElement {
12
12
  constructor() {
13
13
  super(...arguments);
14
+ this.emptyLabel = 'No tags';
14
15
  this.label = '';
15
16
  this.value = '';
16
17
  this.keys = new KeyboardNavigationController(this, {
17
18
  items: () => this.reachable.map((tag) => this.navigable(tag)),
18
19
  origin: 'focus',
19
20
  selects: () => false,
20
- typeahead: typeaheadBy((item) => item.words),
21
+ typeahead: typeaheadByWords(),
21
22
  wrap: false,
22
23
  });
23
24
  this.handleKeydown = (event) => {
@@ -63,8 +64,8 @@ let HelixHeadlessTagGroup = class HelixHeadlessTagGroup extends HelixElement {
63
64
  return;
64
65
  }
65
66
  const left = this.tags.map((one) => this.valueFor(one));
66
- const pruned = prunedValue(this.value, this.valueFor(tag), left);
67
- if (pruned !== this.value) {
67
+ const pruned = prunedValue(this.written, this.valueFor(tag), left);
68
+ if (pruned !== this.written) {
68
69
  this.value = pruned;
69
70
  this.dispatchEvent(new Event('change', { bubbles: true, composed: true }));
70
71
  }
@@ -91,6 +92,14 @@ let HelixHeadlessTagGroup = class HelixHeadlessTagGroup extends HelixElement {
91
92
  }
92
93
  };
93
94
  }
95
+ get written() {
96
+ return typeof this.value === 'string'
97
+ ? this.value
98
+ : this.value
99
+ .map((one) => String(one).trim())
100
+ .filter((one) => one !== '')
101
+ .join(', ');
102
+ }
94
103
  get tags() {
95
104
  return [...(this.children ?? [])].filter((child) => child instanceof HelixHeadlessTag);
96
105
  }
@@ -98,21 +107,18 @@ let HelixHeadlessTagGroup = class HelixHeadlessTagGroup extends HelixElement {
98
107
  return this.tags.filter((tag) => !tag.disabled);
99
108
  }
100
109
  navigable(tag) {
101
- return {
102
- contains: (node) => tag.contains(node),
110
+ return focusItemOf(tag, {
103
111
  disabled: tag.disabled,
104
- focusItem: () => tag.focusItem(),
105
- select: () => { },
106
- selected: false,
112
+ focus: () => tag.focusItem(),
107
113
  words: tag.words,
108
- };
114
+ });
109
115
  }
110
116
  valueFor(tag) {
111
117
  return tag.value || slottedWords(tag, ['start', '']);
112
118
  }
113
119
  sync() {
114
120
  const mode = this.selectionMode ?? 'none';
115
- const chosen = new Set(commaList(this.value));
121
+ const chosen = new Set(commaList(this.written));
116
122
  const tags = this.tags;
117
123
  const items = tags.map((tag) => ({
118
124
  disabled: tag.disabled,
@@ -137,14 +143,8 @@ let HelixHeadlessTagGroup = class HelixHeadlessTagGroup extends HelixElement {
137
143
  if (mode === 'none' || tag.disabled) {
138
144
  return;
139
145
  }
140
- requestChange({
141
- apply: (value) => {
142
- this.value = value;
143
- this.dispatchEvent(new Event('change', { bubbles: true, composed: true }));
144
- },
145
- event: (value) => new HelixBeforeChangeEvent({ value }),
146
- host: this,
147
- next: pressedValue(mode, this.value, this.valueFor(tag)),
146
+ requestValue(this, pressedValue(mode, this.written, this.valueFor(tag)), (value) => {
147
+ this.value = value;
148
148
  });
149
149
  }
150
150
  connectedCallback() {
@@ -176,11 +176,14 @@ let HelixHeadlessTagGroup = class HelixHeadlessTagGroup extends HelixElement {
176
176
  }
177
177
  render() {
178
178
  const empty = this.empty
179
- ? html `<div part="empty" tabindex="-1"><slot name="empty"></slot></div>`
179
+ ? html `<div part="empty" tabindex="-1"><slot name="empty">${this.emptyLabel}</slot></div>`
180
180
  : nothing;
181
181
  return html `<slot @slotchange=${this.handleSlotchange}></slot>${empty}`;
182
182
  }
183
183
  };
184
+ __decorate([
185
+ property({ attribute: 'empty-label' })
186
+ ], HelixHeadlessTagGroup.prototype, "emptyLabel", void 0);
184
187
  __decorate([
185
188
  property()
186
189
  ], HelixHeadlessTagGroup.prototype, "label", void 0);
@@ -1,4 +1,4 @@
1
- import { AriaForwardController, HelixFormElement } from '@fusion.dev/helix-core';
1
+ import { AriaForwardController, HelixFormElement, type OwnRule } from '@fusion.dev/helix-core';
2
2
  import { type PropertyValues, type TemplateResult } from 'lit';
3
3
  declare const HelixHeadlessTextarea_base: (new (...args: any[]) => import("@fusion.dev/helix-core").MixinControllerValueInterface) & (new (...args: any[]) => import("@fusion.dev/helix-core").MixinFieldInterface) & typeof HelixFormElement;
4
4
  /**
@@ -22,12 +22,22 @@ declare const HelixHeadlessTextarea_base: (new (...args: any[]) => import("@fusi
22
22
  * every change once the browser finds nothing wrong, as React Aria's
23
23
  * TextField `validate` does.
24
24
  *
25
+ * **Keyboard.** The field's own keys are the platform's, and Enter starts a
26
+ * new line. The clear button under `clearable` is a tab stop of its own after
27
+ * the field.
28
+ *
29
+ * The inner textarea is named by `label`, or by a host `aria-label`,
30
+ * `aria-labelledby` or `<label for>`, and is described by the hint and the
31
+ * message, with `aria-invalid` while a message shows. The clear button is
32
+ * named `clear-label`.
33
+ *
25
34
  * @since 0.1.0
26
35
  * @status stable
27
36
  * @category forms
28
37
  * @aliases Multiline, TextArea
29
38
  * @documentation https://fusion.dev/helix/components/textarea
30
39
  *
40
+ * @slot clear-icon - Replaces the cross on the clear button, under `clearable`.
31
41
  * @slot end - After the text, for an icon or an action beside it.
32
42
  * @slot feedback - The message that says what is wrong, for content richer than a string. It shows while there is a message.
33
43
  * @slot hint - Help under the control, for content richer than the `hint` text.
@@ -238,12 +248,14 @@ export declare class HelixHeadlessTextarea extends HelixHeadlessTextarea_base {
238
248
  * nothing wrong. Return a message, or a list of them, to mark the field
239
249
  * invalid, and `true`, `null`, or nothing to accept the value.
240
250
  */
241
- validate?: (value: string) => string | string[] | true | null | undefined;
251
+ validate?: OwnRule;
242
252
  /**
243
253
  * How the browser wraps the text, and whether the breaks are submitted with
244
254
  * it.
245
255
  */
246
256
  wrap: 'hard' | 'off' | 'soft';
257
+ /** The cross on the clear button, behind a seam a tier can move. */
258
+ protected renderClearIcon(): TemplateResult;
247
259
  protected render(): TemplateResult;
248
260
  }
249
261
  declare global {