@fusion.dev/helix-headless 0.0.0-dev → 0.0.2

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 (210) hide show
  1. package/custom-elements.json +4513 -4483
  2. package/dist/accordion/item/accordion-item.d.ts +13 -15
  3. package/dist/accordion/item/accordion-item.js +15 -17
  4. package/dist/announcement/root/announcement-root.d.ts +7 -25
  5. package/dist/announcement/root/announcement-root.js +7 -20
  6. package/dist/app-header/root/app-header-root.d.ts +10 -17
  7. package/dist/app-header/root/app-header-root.js +9 -18
  8. package/dist/avatar/group/avatar-group.d.ts +10 -19
  9. package/dist/avatar/group/avatar-group.js +12 -17
  10. package/dist/avatar/root/avatar-root.d.ts +8 -8
  11. package/dist/avatar/root/avatar-root.js +19 -20
  12. package/dist/badge/root/badge-root.d.ts +6 -6
  13. package/dist/badge/root/badge-root.js +13 -13
  14. package/dist/bar-chart/root/bar-chart-root.d.ts +21 -29
  15. package/dist/bar-chart/root/bar-chart-root.js +42 -57
  16. package/dist/breadcrumbs/breadcrumb/breadcrumb.d.ts +12 -18
  17. package/dist/breadcrumbs/breadcrumb/breadcrumb.js +13 -16
  18. package/dist/breadcrumbs/root/breadcrumbs-root.d.ts +9 -28
  19. package/dist/breadcrumbs/root/breadcrumbs-root.js +9 -28
  20. package/dist/button/root/button-root.d.ts +84 -94
  21. package/dist/button/root/button-root.js +82 -92
  22. package/dist/callout/root/callout-root.d.ts +4 -5
  23. package/dist/carousel/root/carousel-root.d.ts +59 -71
  24. package/dist/carousel/root/carousel-root.js +73 -101
  25. package/dist/chat/composer/chat-composer.d.ts +29 -33
  26. package/dist/chat/composer/chat-composer.js +40 -44
  27. package/dist/chat/message/chat-message.d.ts +25 -25
  28. package/dist/chat/message/chat-message.js +26 -26
  29. package/dist/chat/root/chat-root.d.ts +28 -41
  30. package/dist/chat/root/chat-root.js +27 -40
  31. package/dist/checkbox/root/checkbox-root.d.ts +10 -12
  32. package/dist/checkbox/root/checkbox-root.js +29 -35
  33. package/dist/checkbox-group/root/checkbox-group-root.d.ts +32 -45
  34. package/dist/checkbox-group/root/checkbox-group-root.js +53 -79
  35. package/dist/code-block/root/code-block-root.d.ts +3 -4
  36. package/dist/code-block/root/code-block-root.js +8 -12
  37. package/dist/color-input/root/color-input-root.d.ts +36 -37
  38. package/dist/color-input/root/color-input-root.js +29 -34
  39. package/dist/color-picker/color.d.ts +7 -8
  40. package/dist/color-picker/color.js +7 -8
  41. package/dist/color-picker/root/color-picker-root.d.ts +55 -57
  42. package/dist/color-picker/root/color-picker-root.js +60 -64
  43. package/dist/combobox/root/combobox-root.d.ts +53 -58
  44. package/dist/combobox/root/combobox-root.js +85 -94
  45. package/dist/command/root/command-root.d.ts +8 -8
  46. package/dist/command/root/command-root.js +29 -33
  47. package/dist/copy-button/root/copy-button-root.d.ts +21 -24
  48. package/dist/copy-button/root/copy-button-root.js +25 -35
  49. package/dist/data-table/root/data-table-root.d.ts +77 -76
  50. package/dist/data-table/root/data-table-root.js +95 -84
  51. package/dist/data-table/root/order.d.ts +2 -2
  52. package/dist/data-table/root/order.js +1 -3
  53. package/dist/date-input/root/date-input-root.d.ts +88 -93
  54. package/dist/date-input/root/date-input-root.js +147 -158
  55. package/dist/date-picker/root/date-picker-root.d.ts +75 -83
  56. package/dist/date-picker/root/date-picker-root.js +120 -143
  57. package/dist/dialog/root/dialog-root.d.ts +41 -24
  58. package/dist/dialog/root/dialog-root.js +47 -24
  59. package/dist/divider/root/divider-root.d.ts +5 -6
  60. package/dist/divider/root/divider-root.js +4 -5
  61. package/dist/donut-chart/root/donut-chart-root.d.ts +22 -25
  62. package/dist/donut-chart/root/donut-chart-root.js +37 -51
  63. package/dist/drawer/root/drawer-root.d.ts +24 -29
  64. package/dist/drawer/root/drawer-root.js +15 -22
  65. package/dist/drilldown/item/drilldown-item.d.ts +14 -14
  66. package/dist/drilldown/item/drilldown-item.js +24 -26
  67. package/dist/drilldown/root/drilldown-root.d.ts +8 -10
  68. package/dist/drilldown/root/drilldown-root.js +6 -7
  69. package/dist/element-events.generated.js +1 -1
  70. package/dist/file-input/root/file-input-root.d.ts +20 -24
  71. package/dist/file-input/root/file-input-root.js +42 -57
  72. package/dist/format-date/root/format-date-root.js +1 -1
  73. package/dist/heatmap/root/buckets.d.ts +8 -8
  74. package/dist/heatmap/root/buckets.js +8 -8
  75. package/dist/heatmap/root/heatmap-root.d.ts +57 -63
  76. package/dist/heatmap/root/heatmap-root.js +72 -83
  77. package/dist/icon/root/icon-root.d.ts +4 -4
  78. package/dist/icon/root/icon-root.js +9 -9
  79. package/dist/icon-button/root/icon-button-root.d.ts +4 -6
  80. package/dist/icon-button/root/icon-button-root.js +4 -6
  81. package/dist/image/root/image-root.d.ts +49 -59
  82. package/dist/image/root/image-root.js +55 -65
  83. package/dist/index.d.ts +5 -5
  84. package/dist/index.js +5 -5
  85. package/dist/input/root/input-root.d.ts +61 -85
  86. package/dist/input/root/input-root.js +79 -106
  87. package/dist/kbd/root/kbd-root.d.ts +8 -7
  88. package/dist/kbd/root/kbd-root.js +71 -11
  89. package/dist/legend/root/legend-root.d.ts +1 -1
  90. package/dist/legend/root/legend-root.js +4 -5
  91. package/dist/line-chart/root/line-chart-root.d.ts +26 -30
  92. package/dist/line-chart/root/line-chart-root.js +10 -10
  93. package/dist/list/item/list-item.d.ts +14 -18
  94. package/dist/list/item/list-item.js +18 -22
  95. package/dist/list/root/list-root.d.ts +4 -4
  96. package/dist/list/root/list-root.js +3 -3
  97. package/dist/listbox/root/listbox-root.d.ts +31 -58
  98. package/dist/listbox/root/listbox-root.js +66 -109
  99. package/dist/megamenu/root/megamenu-root.d.ts +34 -35
  100. package/dist/megamenu/root/megamenu-root.js +53 -58
  101. package/dist/menu/item/menu-item.d.ts +39 -53
  102. package/dist/menu/item/menu-item.js +50 -64
  103. package/dist/menu/root/menu-root.d.ts +30 -40
  104. package/dist/menu/root/menu-root.js +49 -82
  105. package/dist/meter/root/meter-root.d.ts +49 -53
  106. package/dist/meter/root/meter-root.js +22 -27
  107. package/dist/navigation/root/navigation-root.js +11 -19
  108. package/dist/notifications/notification/notification.d.ts +16 -22
  109. package/dist/notifications/notification/notification.js +21 -27
  110. package/dist/notifications/root/notifications-root.d.ts +31 -39
  111. package/dist/notifications/root/notifications-root.js +41 -52
  112. package/dist/number-input/root/number-input-root.d.ts +31 -33
  113. package/dist/number-input/root/number-input-root.js +37 -39
  114. package/dist/option/root/option-root.d.ts +73 -74
  115. package/dist/option/root/option-root.js +62 -64
  116. package/dist/outline/root/outline-root.d.ts +38 -44
  117. package/dist/outline/root/outline-root.js +66 -82
  118. package/dist/pagination/root/pagination-root.d.ts +87 -92
  119. package/dist/pagination/root/pagination-root.js +116 -123
  120. package/dist/pagination/size/pagination-size.d.ts +31 -50
  121. package/dist/pagination/size/pagination-size.js +35 -55
  122. package/dist/pagination/summary/pagination-summary.d.ts +12 -12
  123. package/dist/pagination/summary/pagination-summary.js +18 -18
  124. package/dist/pin-input/root/pin-input-root.d.ts +53 -70
  125. package/dist/pin-input/root/pin-input-root.js +74 -94
  126. package/dist/popover/root/popover-root.d.ts +15 -20
  127. package/dist/popover/root/popover-root.js +19 -36
  128. package/dist/progress/root/progress-root.d.ts +12 -14
  129. package/dist/progress/root/progress-root.js +22 -25
  130. package/dist/qr-code/root/qr-code-root.d.ts +11 -11
  131. package/dist/qr-code/root/qr-code-root.js +12 -14
  132. package/dist/radio/group/radio-group.js +19 -26
  133. package/dist/radio/root/radio-root.d.ts +12 -13
  134. package/dist/radio/root/radio-root.js +12 -13
  135. package/dist/rating/root/rating-root.d.ts +25 -30
  136. package/dist/rating/root/rating-root.js +43 -50
  137. package/dist/scroll-area/root/scroll-area-root.d.ts +11 -14
  138. package/dist/scroll-area/root/scroll-area-root.js +39 -33
  139. package/dist/select/root/select-root.d.ts +7 -12
  140. package/dist/select/root/select-root.js +40 -55
  141. package/dist/slider/root/slider-root.d.ts +53 -60
  142. package/dist/slider/root/slider-root.js +74 -85
  143. package/dist/sparkline/root/sparkline-root.d.ts +43 -47
  144. package/dist/sparkline/root/sparkline-root.js +23 -32
  145. package/dist/speed-dial/item/speed-dial-item.d.ts +6 -6
  146. package/dist/speed-dial/item/speed-dial-item.js +9 -9
  147. package/dist/speed-dial/root/speed-dial-root.d.ts +21 -25
  148. package/dist/speed-dial/root/speed-dial-root.js +32 -40
  149. package/dist/splitter/root/splitter-root.d.ts +98 -111
  150. package/dist/splitter/root/splitter-root.js +96 -123
  151. package/dist/stat/root/stat-root.d.ts +2 -7
  152. package/dist/stat/root/stat-root.js +0 -5
  153. package/dist/steps/step/step.d.ts +19 -24
  154. package/dist/steps/step/step.js +27 -32
  155. package/dist/switch/root/switch-root.js +2 -2
  156. package/dist/table/column/table-column.d.ts +54 -60
  157. package/dist/table/column/table-column.js +95 -68
  158. package/dist/table/root/table-root.d.ts +5 -6
  159. package/dist/table/root/table-root.js +7 -10
  160. package/dist/tabs/panel/tab-panel.d.ts +21 -25
  161. package/dist/tabs/panel/tab-panel.js +25 -29
  162. package/dist/tabs/root/tabs-root.d.ts +25 -34
  163. package/dist/tabs/root/tabs-root.js +22 -28
  164. package/dist/tabs/tab/tab.d.ts +12 -12
  165. package/dist/tabs/tab/tab.js +19 -20
  166. package/dist/textarea/root/textarea-root.d.ts +36 -36
  167. package/dist/textarea/root/textarea-root.js +43 -47
  168. package/dist/time-input/root/time-input-root.d.ts +58 -68
  169. package/dist/time-input/root/time-input-root.js +62 -77
  170. package/dist/time-picker/root/time-picker-root.d.ts +73 -79
  171. package/dist/time-picker/root/time-picker-root.js +72 -84
  172. package/dist/timeline/item/timeline-item.d.ts +8 -11
  173. package/dist/timeline/item/timeline-item.js +8 -11
  174. package/dist/timeline/root/timeline-root.d.ts +5 -7
  175. package/dist/timeline/root/timeline-root.js +5 -7
  176. package/dist/toast/item/toast-item.d.ts +9 -27
  177. package/dist/toast/item/toast-item.js +19 -41
  178. package/dist/toast/root/toast-root.d.ts +10 -14
  179. package/dist/toast/root/toast-root.js +4 -5
  180. package/dist/toggle/group/toggle-group.d.ts +6 -15
  181. package/dist/toggle/group/toggle-group.js +21 -36
  182. package/dist/toggle/root/toggle-root.d.ts +26 -27
  183. package/dist/toggle/root/toggle-root.js +30 -31
  184. package/dist/toolbar/root/toolbar-root.d.ts +7 -10
  185. package/dist/toolbar/root/toolbar-root.js +10 -14
  186. package/dist/tooltip/root/tooltip-root.d.ts +52 -59
  187. package/dist/tooltip/root/tooltip-root.js +98 -93
  188. package/dist/tour/root/tour-root.d.ts +19 -23
  189. package/dist/tour/root/tour-root.js +31 -41
  190. package/dist/tour/stop/tour-stop.d.ts +14 -15
  191. package/dist/tour/stop/tour-stop.js +31 -34
  192. package/dist/tree/item/tree-item.d.ts +30 -35
  193. package/dist/tree/item/tree-item.js +43 -55
  194. package/dist/tree/root/tree-root.d.ts +7 -10
  195. package/dist/tree/root/tree-root.js +33 -42
  196. package/dist/trend/root/trend-root.d.ts +3 -5
  197. package/dist/trend/root/trend-root.js +5 -9
  198. package/dist/video/root/video-root.d.ts +100 -124
  199. package/dist/video/root/video-root.js +142 -176
  200. package/dist/video-playlist/item/video-playlist-item.d.ts +16 -16
  201. package/dist/video-playlist/item/video-playlist-item.js +24 -24
  202. package/dist/video-playlist/menu/video-playlist-menu.d.ts +5 -8
  203. package/dist/video-playlist/menu/video-playlist-menu.js +20 -29
  204. package/dist/video-playlist/root/video-playlist-root.d.ts +16 -11
  205. package/dist/video-playlist/root/video-playlist-root.js +21 -25
  206. package/dist/virtual-list/root/virtual-list-root.d.ts +8 -12
  207. package/dist/virtual-list/root/virtual-list-root.js +11 -16
  208. package/jsx.d.ts +9797 -12561
  209. package/package.json +6 -6
  210. package/vue.d.ts +2684 -3228
@@ -14,20 +14,12 @@ export type CellReader = (row: Readonly<Record<string, unknown>>) => unknown;
14
14
  * @summary One column of a table: its heading, how wide it is, and what it reads.
15
15
  *
16
16
  * @description
17
- * A column is a heading and a width, declared together, because they are two
18
- * facts about one thing and keeping them apart is what went wrong before.
19
- *
20
- * **This replaces a `columns` string on the table.** That property took a CSS
21
- * track list, so the headings lived in a row of cells and the widths lived in
22
- * an attribute, and nothing tied the two together: a table with three headings
23
- * and a two-track list rendered without complaint. Worse, handing it the
24
- * headings instead of a track list produced invalid CSS, which the grid
25
- * silently ignored, so the whole table collapsed into one column and every cell
26
- * stacked. That happened, in this library's own example, and the failure said
27
- * nothing at all.
28
- *
29
- * Now the column is the source of both. Add one and the table has another
30
- * track; remove one and it does not.
17
+ * **The column is the source of both its heading and its track.** Add one and
18
+ * the table has another track; remove one and it does not. Declaring the widths
19
+ * separately, as a CSS track list on the table, leaves nothing tying the two
20
+ * together: a table with three headings and a two-track list renders without
21
+ * complaint, and a track list that is accidentally the headings is invalid CSS
22
+ * the grid silently ignores, collapsing the whole table into one column.
31
23
  *
32
24
  * **It is also where every per-column fact goes**, which is the reason
33
25
  * `helix-data-table` needs no column config object. `field` names the key the
@@ -56,34 +48,32 @@ export type CellReader = (row: Readonly<Record<string, unknown>>) => unknown;
56
48
  */
57
49
  export declare class HelixHeadlessTableColumn extends HelixElement {
58
50
  /**
59
- * The track this column takes, as CSS.
60
- *
61
- * A single track value, so anything valid in `grid-template-columns` works:
62
- * `16rem`, `auto`, `minmax(0, 2fr)`. Left unset the column shares what is
63
- * left over equally, as `minmax(max-content, 1fr)`.
51
+ * Which edge the values line up against.
64
52
  *
65
- * **The floor was `0` and that is what broke a narrow table.** A zero floor
66
- * lets a track shrink under its own content, so at 375 the columns were
67
- * squeezed to 75px and `eu-central-1` wrapped across lines, which reads as
68
- * corrupt data rather than as a table that ran out of room. The zero was
69
- * chosen to stop one long value pushing the table past its container, and
70
- * that was the right worry with nowhere for the overflow to go.
53
+ * `end` is what a column of numbers wants, so digits of the same magnitude sit
54
+ * above each other. Left unset the cell inherits the table's own alignment,
55
+ * which is `start` for text in either writing direction.
56
+ */
57
+ align: 'center' | 'end' | 'start' | '';
58
+ /**
59
+ * How to read the cell, where the field alone will not do.
71
60
  *
72
- * Somewhere now exists: `@fusion.dev/helix` scrolls the table's own box. So a
73
- * long value pushes past the container as the old comment feared, and the
74
- * table scrolls instead of the value being destroyed. Measured at 375: tracks
75
- * of 192, 89 and 102 against a 343 box, so the table scrolls 384 and the page
76
- * does not move.
61
+ * A property and not an attribute, because it is a function. Set it from a Lit
62
+ * template with `.cell=${...}`, or assign it in script. A column with neither
63
+ * this nor a `field` renders an empty cell rather than the whole row stringified,
64
+ * which is the failure mode of guessing.
65
+ */
66
+ cell: CellReader | undefined;
67
+ /**
68
+ * How to read the value that gets sorted and filtered, where it is not the cell.
77
69
  *
78
- * **`max-content` and not `min-content`, because a hyphen is a wrap
79
- * opportunity.** A `min-content` floor still broke `eu-central-1` at its
80
- * hyphens, which is the whole of the reported fault. The cost is that a
81
- * column of prose asks for its longest paragraph on one line, so a column
82
- * holding sentences rather than values wants `width="minmax(0, 1fr)"` to opt
83
- * back into wrapping. A headless consumer owns the overflow either way, that
84
- * being paint, and gets the honest track list.
70
+ * **The one that is easy to leave out and expensive to add later.** A cell
71
+ * showing `2.4 MB` sorts as a string unless something says the underlying value
72
+ * is a number, so `12 kB` sorts above `2.4 MB` and the column looks broken
73
+ * while every value in it is right. Left unset this is the field, which is the
74
+ * correct default: the raw value is what an API sorted by.
85
75
  */
86
- width: string;
76
+ compare: CellReader | undefined;
87
77
  /**
88
78
  * The key this column reads out of a row.
89
79
  *
@@ -109,38 +99,42 @@ export declare class HelixHeadlessTableColumn extends HelixElement {
109
99
  */
110
100
  sortable: boolean;
111
101
  /**
112
- * Which edge the values line up against.
102
+ * The track this column takes, as CSS.
113
103
  *
114
- * `end` is what a column of numbers wants, so digits of the same magnitude sit
115
- * above each other. Left unset the cell inherits the table's own alignment,
116
- * which is `start` for text in either writing direction.
117
- */
118
- align: 'center' | 'end' | 'start' | '';
119
- /**
120
- * How to read the cell, where the field alone will not do.
104
+ * A single track value, so anything valid in `grid-template-columns` works:
105
+ * `16rem`, `auto`, `minmax(0, 2fr)`. Left unset the column shares what is
106
+ * left over equally, as `minmax(max-content, 1fr)`.
121
107
  *
122
- * A property and not an attribute, because it is a function. Set it from a Lit
123
- * template with `.cell=${...}`, or assign it in script. A column with neither
124
- * this nor a `field` renders an empty cell rather than the whole row stringified,
125
- * which is the failure mode of guessing.
126
- */
127
- cell: CellReader | undefined;
128
- /**
129
- * How to read the value that gets sorted and filtered, where it is not the cell.
108
+ * **The floor is `max-content`, never `0` and never `min-content`.** A zero
109
+ * floor lets a track shrink under its own content: at 375 the columns squeeze
110
+ * to 75px and `eu-central-1` wraps across lines, which reads as corrupt data
111
+ * rather than as a table that ran out of room. A `min-content` floor still
112
+ * breaks it, a hyphen being a wrap opportunity.
130
113
  *
131
- * **The one that is easy to leave out and expensive to add later.** A cell
132
- * showing `2.4 MB` sorts as a string unless something says the underlying value
133
- * is a number, so `12 kB` sorts above `2.4 MB` and the column looks broken
134
- * while every value in it is right. Left unset this is the field, which is the
135
- * correct default: the raw value is what an API sorted by.
114
+ * The overflow has somewhere to go: `@fusion.dev/helix` scrolls the table's
115
+ * own box, so a long value pushes past the container and the table scrolls
116
+ * instead of the value being destroyed. Measured at 375: tracks of 192, 89 and
117
+ * 102 against a 343 box, so the table scrolls 384 and the page does not move.
118
+ *
119
+ * The cost is that a column of prose asks for its longest paragraph on one
120
+ * line, so a column holding sentences rather than values wants
121
+ * `width="minmax(0, 1fr)"` to opt back into wrapping. A headless consumer owns
122
+ * the overflow either way, that being paint, and gets the honest track list.
136
123
  */
137
- compare: CellReader | undefined;
124
+ width: string;
138
125
  /**
139
126
  * @internal Read by a parent to identify its children across the light DOM,
140
127
  * which is cheaper than `instanceof` and is why this is public rather than
141
128
  * protected. Not a consumer's to read or set.
142
129
  */
143
130
  readonly isTableColumn = true;
131
+ /**
132
+ * @internal Which way this column is currently ordered, written by the table
133
+ * that owns the sort. Not a consumer's to set: the sort lives on the table,
134
+ * and a column that disagreed with it would announce an order the rows are
135
+ * not in.
136
+ */
137
+ sorted: 'ascending' | 'descending' | undefined;
144
138
  /** The track this column contributes, resolved. */
145
139
  get track(): string;
146
140
  /** Whether a reader can actually reorder by this column. */
@@ -6,7 +6,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
6
6
  };
7
7
  import { customElement, HelixElement, hostAria } from '@fusion.dev/helix-core';
8
8
  import { html } from 'lit';
9
- import { property } from 'lit/decorators.js';
9
+ import { property, state } from 'lit/decorators.js';
10
10
  /**
11
11
  * A dot path resolved against a row.
12
12
  *
@@ -36,20 +36,12 @@ const at = (row, path) => {
36
36
  * @summary One column of a table: its heading, how wide it is, and what it reads.
37
37
  *
38
38
  * @description
39
- * A column is a heading and a width, declared together, because they are two
40
- * facts about one thing and keeping them apart is what went wrong before.
41
- *
42
- * **This replaces a `columns` string on the table.** That property took a CSS
43
- * track list, so the headings lived in a row of cells and the widths lived in
44
- * an attribute, and nothing tied the two together: a table with three headings
45
- * and a two-track list rendered without complaint. Worse, handing it the
46
- * headings instead of a track list produced invalid CSS, which the grid
47
- * silently ignored, so the whole table collapsed into one column and every cell
48
- * stacked. That happened, in this library's own example, and the failure said
49
- * nothing at all.
50
- *
51
- * Now the column is the source of both. Add one and the table has another
52
- * track; remove one and it does not.
39
+ * **The column is the source of both its heading and its track.** Add one and
40
+ * the table has another track; remove one and it does not. Declaring the widths
41
+ * separately, as a CSS track list on the table, leaves nothing tying the two
42
+ * together: a table with three headings and a two-track list renders without
43
+ * complaint, and a track list that is accidentally the headings is invalid CSS
44
+ * the grid silently ignores, collapsing the whole table into one column.
53
45
  *
54
46
  * **It is also where every per-column fact goes**, which is the reason
55
47
  * `helix-data-table` needs no column config object. `field` names the key the
@@ -80,34 +72,32 @@ let HelixHeadlessTableColumn = class HelixHeadlessTableColumn extends HelixEleme
80
72
  constructor() {
81
73
  super(...arguments);
82
74
  /**
83
- * The track this column takes, as CSS.
84
- *
85
- * A single track value, so anything valid in `grid-template-columns` works:
86
- * `16rem`, `auto`, `minmax(0, 2fr)`. Left unset the column shares what is
87
- * left over equally, as `minmax(max-content, 1fr)`.
75
+ * Which edge the values line up against.
88
76
  *
89
- * **The floor was `0` and that is what broke a narrow table.** A zero floor
90
- * lets a track shrink under its own content, so at 375 the columns were
91
- * squeezed to 75px and `eu-central-1` wrapped across lines, which reads as
92
- * corrupt data rather than as a table that ran out of room. The zero was
93
- * chosen to stop one long value pushing the table past its container, and
94
- * that was the right worry with nowhere for the overflow to go.
77
+ * `end` is what a column of numbers wants, so digits of the same magnitude sit
78
+ * above each other. Left unset the cell inherits the table's own alignment,
79
+ * which is `start` for text in either writing direction.
80
+ */
81
+ this.align = '';
82
+ /**
83
+ * How to read the cell, where the field alone will not do.
95
84
  *
96
- * Somewhere now exists: `@fusion.dev/helix` scrolls the table's own box. So a
97
- * long value pushes past the container as the old comment feared, and the
98
- * table scrolls instead of the value being destroyed. Measured at 375: tracks
99
- * of 192, 89 and 102 against a 343 box, so the table scrolls 384 and the page
100
- * does not move.
85
+ * A property and not an attribute, because it is a function. Set it from a Lit
86
+ * template with `.cell=${...}`, or assign it in script. A column with neither
87
+ * this nor a `field` renders an empty cell rather than the whole row stringified,
88
+ * which is the failure mode of guessing.
89
+ */
90
+ this.cell = undefined;
91
+ /**
92
+ * How to read the value that gets sorted and filtered, where it is not the cell.
101
93
  *
102
- * **`max-content` and not `min-content`, because a hyphen is a wrap
103
- * opportunity.** A `min-content` floor still broke `eu-central-1` at its
104
- * hyphens, which is the whole of the reported fault. The cost is that a
105
- * column of prose asks for its longest paragraph on one line, so a column
106
- * holding sentences rather than values wants `width="minmax(0, 1fr)"` to opt
107
- * back into wrapping. A headless consumer owns the overflow either way, that
108
- * being paint, and gets the honest track list.
94
+ * **The one that is easy to leave out and expensive to add later.** A cell
95
+ * showing `2.4 MB` sorts as a string unless something says the underlying value
96
+ * is a number, so `12 kB` sorts above `2.4 MB` and the column looks broken
97
+ * while every value in it is right. Left unset this is the field, which is the
98
+ * correct default: the raw value is what an API sorted by.
109
99
  */
110
- this.width = '';
100
+ this.compare = undefined;
111
101
  /**
112
102
  * The key this column reads out of a row.
113
103
  *
@@ -133,38 +123,42 @@ let HelixHeadlessTableColumn = class HelixHeadlessTableColumn extends HelixEleme
133
123
  */
134
124
  this.sortable = false;
135
125
  /**
136
- * Which edge the values line up against.
126
+ * The track this column takes, as CSS.
137
127
  *
138
- * `end` is what a column of numbers wants, so digits of the same magnitude sit
139
- * above each other. Left unset the cell inherits the table's own alignment,
140
- * which is `start` for text in either writing direction.
141
- */
142
- this.align = '';
143
- /**
144
- * How to read the cell, where the field alone will not do.
128
+ * A single track value, so anything valid in `grid-template-columns` works:
129
+ * `16rem`, `auto`, `minmax(0, 2fr)`. Left unset the column shares what is
130
+ * left over equally, as `minmax(max-content, 1fr)`.
145
131
  *
146
- * A property and not an attribute, because it is a function. Set it from a Lit
147
- * template with `.cell=${...}`, or assign it in script. A column with neither
148
- * this nor a `field` renders an empty cell rather than the whole row stringified,
149
- * which is the failure mode of guessing.
150
- */
151
- this.cell = undefined;
152
- /**
153
- * How to read the value that gets sorted and filtered, where it is not the cell.
132
+ * **The floor is `max-content`, never `0` and never `min-content`.** A zero
133
+ * floor lets a track shrink under its own content: at 375 the columns squeeze
134
+ * to 75px and `eu-central-1` wraps across lines, which reads as corrupt data
135
+ * rather than as a table that ran out of room. A `min-content` floor still
136
+ * breaks it, a hyphen being a wrap opportunity.
154
137
  *
155
- * **The one that is easy to leave out and expensive to add later.** A cell
156
- * showing `2.4 MB` sorts as a string unless something says the underlying value
157
- * is a number, so `12 kB` sorts above `2.4 MB` and the column looks broken
158
- * while every value in it is right. Left unset this is the field, which is the
159
- * correct default: the raw value is what an API sorted by.
138
+ * The overflow has somewhere to go: `@fusion.dev/helix` scrolls the table's
139
+ * own box, so a long value pushes past the container and the table scrolls
140
+ * instead of the value being destroyed. Measured at 375: tracks of 192, 89 and
141
+ * 102 against a 343 box, so the table scrolls 384 and the page does not move.
142
+ *
143
+ * The cost is that a column of prose asks for its longest paragraph on one
144
+ * line, so a column holding sentences rather than values wants
145
+ * `width="minmax(0, 1fr)"` to opt back into wrapping. A headless consumer owns
146
+ * the overflow either way, that being paint, and gets the honest track list.
160
147
  */
161
- this.compare = undefined;
148
+ this.width = '';
162
149
  /**
163
150
  * @internal Read by a parent to identify its children across the light DOM,
164
151
  * which is cheaper than `instanceof` and is why this is public rather than
165
152
  * protected. Not a consumer's to read or set.
166
153
  */
167
154
  this.isTableColumn = true;
155
+ /**
156
+ * @internal Which way this column is currently ordered, written by the table
157
+ * that owns the sort. Not a consumer's to set: the sort lives on the table,
158
+ * and a column that disagreed with it would announce an order the rows are
159
+ * not in.
160
+ */
161
+ this.sorted = undefined;
168
162
  }
169
163
  /** The track this column contributes, resolved. */
170
164
  get track() {
@@ -192,7 +186,37 @@ let HelixHeadlessTableColumn = class HelixHeadlessTableColumn extends HelixEleme
192
186
  }
193
187
  willUpdate(changed) {
194
188
  super.willUpdate(changed);
189
+ /* **`aria-sort` is not decoration.** A `columnheader` a reader can reorder
190
+ by has to say which way it is ordered and which headers are orderable at
191
+ all, or the whole affordance exists only for a reader who can see the rows
192
+ move. `none` on the sortable ones that are not currently the sort is the
193
+ part that carries the second half: it is what tells a screen reader this
194
+ column can be sorted, where an absent attribute says nothing.
195
+
196
+ Off the internals rather than the attribute, for the same reason the role
197
+ is: it is this element's own semantics rather than markup a consumer
198
+ wrote, and an attribute here is one more thing hydration can disagree
199
+ about. */
195
200
  hostAria(this.internals, { role: 'columnheader' });
201
+ /* Set here rather than through `hostAria`, which carries the four semantics
202
+ every family needs and not this one. */
203
+ this.internals.ariaSort = this.canSort ? (this.sorted ?? 'none') : null;
204
+ /* And the same fact as a custom state, because ARIA is not a style hook.
205
+ Whoever draws this column draws the caret, and had nothing to draw it
206
+ from: no state and no part told the sorted column from the rest, so the
207
+ only way to it was listening for `helix-sort` and reading the order back a
208
+ microtask later, which is a lot of machinery for one glyph. */
209
+ for (const [name, on] of [
210
+ ['sorted-ascending', this.sorted === 'ascending'],
211
+ ['sorted-descending', this.sorted === 'descending'],
212
+ ]) {
213
+ /* Through `toggleState`, which carries the feature test, the way
214
+ `pagination-root.ts` does in this same hook. Safari below 17.4 and
215
+ Firefox below 126 have no `CustomStateSet`, and there
216
+ `internals.states.delete` is a `TypeError` thrown from `willUpdate`:
217
+ the column would fail to render rather than render without a caret. */
218
+ this.toggleState(name, on);
219
+ }
196
220
  }
197
221
  render() {
198
222
  return html `<span part="column"><slot></slot></span>`;
@@ -200,7 +224,13 @@ let HelixHeadlessTableColumn = class HelixHeadlessTableColumn extends HelixEleme
200
224
  };
201
225
  __decorate([
202
226
  property()
203
- ], HelixHeadlessTableColumn.prototype, "width", void 0);
227
+ ], HelixHeadlessTableColumn.prototype, "align", void 0);
228
+ __decorate([
229
+ property({ attribute: false })
230
+ ], HelixHeadlessTableColumn.prototype, "cell", void 0);
231
+ __decorate([
232
+ property({ attribute: false })
233
+ ], HelixHeadlessTableColumn.prototype, "compare", void 0);
204
234
  __decorate([
205
235
  property()
206
236
  ], HelixHeadlessTableColumn.prototype, "field", void 0);
@@ -209,13 +239,10 @@ __decorate([
209
239
  ], HelixHeadlessTableColumn.prototype, "sortable", void 0);
210
240
  __decorate([
211
241
  property()
212
- ], HelixHeadlessTableColumn.prototype, "align", void 0);
213
- __decorate([
214
- property({ attribute: false })
215
- ], HelixHeadlessTableColumn.prototype, "cell", void 0);
242
+ ], HelixHeadlessTableColumn.prototype, "width", void 0);
216
243
  __decorate([
217
- property({ attribute: false })
218
- ], HelixHeadlessTableColumn.prototype, "compare", void 0);
244
+ state()
245
+ ], HelixHeadlessTableColumn.prototype, "sorted", void 0);
219
246
  HelixHeadlessTableColumn = __decorate([
220
247
  customElement('helix-headless-table-column')
221
248
  ], HelixHeadlessTableColumn);
@@ -69,12 +69,11 @@ export declare class HelixHeadlessTable extends HelixHeadlessTable_base {
69
69
  /**
70
70
  * Nothing is assigned by name, so the columns can be put in a row.
71
71
  *
72
- * `role="columnheader"` was landing directly under `role="table"` with no
73
- * owning `row`, which is invalid: the table pattern is `table > row >
74
- * columnheader`, and a header cell with no row is a cell belonging to
75
- * nothing. The columns are ordinary children the consumer writes with no
76
- * `slot`, so the only way to put a wrapper around them without changing what
77
- * a consumer writes is to assign them here.
72
+ * The table pattern is `table > row > columnheader`, and a header cell
73
+ * landing directly under `role="table"` with no owning row is invalid: it is
74
+ * a cell belonging to nothing. The columns are ordinary children the consumer
75
+ * writes with no `slot`, so the only way to put a wrapper around them without
76
+ * changing what a consumer writes is to assign them here.
78
77
  *
79
78
  * Manual rather than a `slot` attribute this element would set on the
80
79
  * consumer's own markup, which is the change a React consumer's hydration
@@ -71,10 +71,8 @@ let HelixHeadlessTable = class HelixHeadlessTable extends MixinCollection(HelixE
71
71
  get tableColumns() {
72
72
  /* `?? []` is the server. Lit's element shim carries attributes and not a
73
73
  tree, so `children` is undefined there, and this getter is reached from
74
- `template`, which is read during `render`: spreading it threw and the
75
- whole SSR suite died on an unhandled error. The same fault the menu item
76
- had, in code written after it was fixed there, which is the argument for
77
- the SSR specs existing at all. */
74
+ `template`, which is read during `render`: spreading it throws and takes
75
+ the whole SSR render down with it. */
78
76
  return [...(this.children ?? [])].filter((child) => 'isTableColumn' in child && child.isTableColumn === true);
79
77
  }
80
78
  /**
@@ -95,12 +93,11 @@ let HelixHeadlessTable = class HelixHeadlessTable extends MixinCollection(HelixE
95
93
  /**
96
94
  * Nothing is assigned by name, so the columns can be put in a row.
97
95
  *
98
- * `role="columnheader"` was landing directly under `role="table"` with no
99
- * owning `row`, which is invalid: the table pattern is `table > row >
100
- * columnheader`, and a header cell with no row is a cell belonging to
101
- * nothing. The columns are ordinary children the consumer writes with no
102
- * `slot`, so the only way to put a wrapper around them without changing what
103
- * a consumer writes is to assign them here.
96
+ * The table pattern is `table > row > columnheader`, and a header cell
97
+ * landing directly under `role="table"` with no owning row is invalid: it is
98
+ * a cell belonging to nothing. The columns are ordinary children the consumer
99
+ * writes with no `slot`, so the only way to put a wrapper around them without
100
+ * changing what a consumer writes is to assign them here.
104
101
  *
105
102
  * Manual rather than a `slot` attribute this element would set on the
106
103
  * consumer's own markup, which is the change a React consumer's hydration
@@ -18,14 +18,6 @@ import { type PropertyValues, type TemplateResult } from 'lit';
18
18
  * @csspart panel - The panel container.
19
19
  */
20
20
  export declare class HelixHeadlessTabPanel extends HelixElement {
21
- /**
22
- * Pairs the panel with the tab of the same value.
23
- */
24
- value: string;
25
- /**
26
- * Whether this panel is the visible one.
27
- */
28
- selected: boolean;
29
21
  /**
30
22
  * The name of the panel, which is the text of the tab that opens it.
31
23
  *
@@ -33,29 +25,33 @@ export declare class HelixHeadlessTabPanel extends HelixElement {
33
25
  * because it is coordination between elements rather than anything a consumer
34
26
  * writes: the tab already says it.
35
27
  *
36
- * A string where the markup wanted a reference. `aria-labelledby` named
37
- * `tab-${value}`, an id inside the *tab's* own shadow root, and an IDREF
38
- * resolves only in the tree it is written in, so the panel had no accessible
39
- * name at all. An element reference cannot reach there either, a sibling
40
- * shadow tree being neither the same tree nor an ancestor of it. A name is
41
- * the one form that crosses, and `aria-label` on a `tabpanel` is how the
42
- * pattern names one anyway.
28
+ * A string and not a reference: an IDREF resolves only in the tree it is
29
+ * written in, and an element reference cannot reach a sibling shadow tree
30
+ * either, so `aria-labelledby` to the tab's own id leaves the panel with no
31
+ * accessible name. `aria-label` on a `tabpanel` is how the pattern names one
32
+ * anyway.
43
33
  */
44
34
  label: string;
35
+ /**
36
+ * Whether this panel is the visible one.
37
+ */
38
+ selected: boolean;
39
+ /**
40
+ * Pairs the panel with the tab of the same value.
41
+ */
42
+ value: string;
45
43
  /**
46
44
  * Mirrors the chosen state where a stylesheet can select on it.
47
45
  *
48
- * **A custom state and not the `selected` attribute it used to reflect.** The
49
- * parent writes this: a listbox choosing a row, a tab strip moving the tab, a
50
- * radio group answering for its set. Reflected, that put the element's own
51
- * bookkeeping onto markup a consumer wrote and a consumer's server never sent,
52
- * which React reconciles and reports as a mismatch, and which a serialized
53
- * element pasted back declares as a choice nobody made. `ElementInternals`
54
- * holds it instead, where it is not in the DOM at all.
46
+ * **A custom state, never a reflected `selected` attribute.** The parent
47
+ * writes this, so reflecting it would put the element's own bookkeeping onto
48
+ * markup a consumer wrote and their server never sent, which React reports as
49
+ * a hydration mismatch and which a serialized element pasted back declares as
50
+ * a choice nobody made. `ElementInternals` holds it instead.
55
51
  *
56
- * Reading `selected` is unaffected and so is writing it: the attribute still
57
- * seeds the property, which is what `<helix-tab-panel selected>` in a consumer's
58
- * markup means. What stops is the write back. See 302 and 304.
52
+ * The attribute still seeds the property, which is what
53
+ * `<helix-tab-panel selected>` in a consumer's markup means. Only the write
54
+ * back is gone.
59
55
  */
60
56
  protected willUpdate(changed: PropertyValues): void;
61
57
  protected render(): TemplateResult;
@@ -27,14 +27,6 @@ import { property } from 'lit/decorators.js';
27
27
  let HelixHeadlessTabPanel = class HelixHeadlessTabPanel extends HelixElement {
28
28
  constructor() {
29
29
  super(...arguments);
30
- /**
31
- * Pairs the panel with the tab of the same value.
32
- */
33
- this.value = '';
34
- /**
35
- * Whether this panel is the visible one.
36
- */
37
- this.selected = false;
38
30
  /**
39
31
  * The name of the panel, which is the text of the tab that opens it.
40
32
  *
@@ -42,30 +34,34 @@ let HelixHeadlessTabPanel = class HelixHeadlessTabPanel extends HelixElement {
42
34
  * because it is coordination between elements rather than anything a consumer
43
35
  * writes: the tab already says it.
44
36
  *
45
- * A string where the markup wanted a reference. `aria-labelledby` named
46
- * `tab-${value}`, an id inside the *tab's* own shadow root, and an IDREF
47
- * resolves only in the tree it is written in, so the panel had no accessible
48
- * name at all. An element reference cannot reach there either, a sibling
49
- * shadow tree being neither the same tree nor an ancestor of it. A name is
50
- * the one form that crosses, and `aria-label` on a `tabpanel` is how the
51
- * pattern names one anyway.
37
+ * A string and not a reference: an IDREF resolves only in the tree it is
38
+ * written in, and an element reference cannot reach a sibling shadow tree
39
+ * either, so `aria-labelledby` to the tab's own id leaves the panel with no
40
+ * accessible name. `aria-label` on a `tabpanel` is how the pattern names one
41
+ * anyway.
52
42
  */
53
43
  this.label = '';
44
+ /**
45
+ * Whether this panel is the visible one.
46
+ */
47
+ this.selected = false;
48
+ /**
49
+ * Pairs the panel with the tab of the same value.
50
+ */
51
+ this.value = '';
54
52
  }
55
53
  /**
56
54
  * Mirrors the chosen state where a stylesheet can select on it.
57
55
  *
58
- * **A custom state and not the `selected` attribute it used to reflect.** The
59
- * parent writes this: a listbox choosing a row, a tab strip moving the tab, a
60
- * radio group answering for its set. Reflected, that put the element's own
61
- * bookkeeping onto markup a consumer wrote and a consumer's server never sent,
62
- * which React reconciles and reports as a mismatch, and which a serialized
63
- * element pasted back declares as a choice nobody made. `ElementInternals`
64
- * holds it instead, where it is not in the DOM at all.
56
+ * **A custom state, never a reflected `selected` attribute.** The parent
57
+ * writes this, so reflecting it would put the element's own bookkeeping onto
58
+ * markup a consumer wrote and their server never sent, which React reports as
59
+ * a hydration mismatch and which a serialized element pasted back declares as
60
+ * a choice nobody made. `ElementInternals` holds it instead.
65
61
  *
66
- * Reading `selected` is unaffected and so is writing it: the attribute still
67
- * seeds the property, which is what `<helix-tab-panel selected>` in a consumer's
68
- * markup means. What stops is the write back. See 302 and 304.
62
+ * The attribute still seeds the property, which is what
63
+ * `<helix-tab-panel selected>` in a consumer's markup means. Only the write
64
+ * back is gone.
69
65
  */
70
66
  willUpdate(changed) {
71
67
  super.willUpdate(changed);
@@ -84,14 +80,14 @@ let HelixHeadlessTabPanel = class HelixHeadlessTabPanel extends HelixElement {
84
80
  }
85
81
  };
86
82
  __decorate([
87
- property()
88
- ], HelixHeadlessTabPanel.prototype, "value", void 0);
83
+ property({ attribute: false })
84
+ ], HelixHeadlessTabPanel.prototype, "label", void 0);
89
85
  __decorate([
90
86
  property({ type: Boolean })
91
87
  ], HelixHeadlessTabPanel.prototype, "selected", void 0);
92
88
  __decorate([
93
- property({ attribute: false })
94
- ], HelixHeadlessTabPanel.prototype, "label", void 0);
89
+ property()
90
+ ], HelixHeadlessTabPanel.prototype, "value", void 0);
95
91
  HelixHeadlessTabPanel = __decorate([
96
92
  customElement('helix-headless-tab-panel')
97
93
  ], HelixHeadlessTabPanel);