@fusion.dev/helix-headless 0.2.0 → 0.3.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 (127) hide show
  1. package/custom-elements.json +234 -234
  2. package/dist/accordion/item/accordion-item.js +0 -108
  3. package/dist/accordion/root/accordion-root.js +0 -33
  4. package/dist/announcement/root/announcement-root.js +1 -76
  5. package/dist/app-header/root/app-header-root.js +0 -84
  6. package/dist/avatar/group/avatar-group.js +0 -77
  7. package/dist/avatar/root/avatar-root.js +0 -72
  8. package/dist/badge/root/badge-root.js +0 -67
  9. package/dist/bar-chart/root/bar-chart-root.js +3 -263
  10. package/dist/blockquote/root/blockquote-root.js +0 -46
  11. package/dist/breadcrumbs/breadcrumb/breadcrumb.js +0 -72
  12. package/dist/breadcrumbs/root/breadcrumbs-root.js +0 -52
  13. package/dist/button/root/button-root.js +0 -215
  14. package/dist/button-group/root/button-group-root.js +0 -30
  15. package/dist/callout/root/callout-root.js +0 -52
  16. package/dist/card/root/card-root.js +0 -41
  17. package/dist/carousel/root/carousel-root.d.ts +2 -2
  18. package/dist/carousel/root/carousel-root.js +2 -362
  19. package/dist/chat/composer/chat-composer.js +0 -131
  20. package/dist/chat/message/chat-message.js +0 -137
  21. package/dist/chat/root/chat-root.js +0 -193
  22. package/dist/checkbox/root/checkbox-root.js +0 -113
  23. package/dist/checkbox-group/root/checkbox-group-root.js +1 -157
  24. package/dist/code/root/code-root.js +0 -26
  25. package/dist/code-block/root/code-block-root.js +0 -100
  26. package/dist/color-input/root/color-input-root.js +0 -217
  27. package/dist/color-picker/color.js +0 -69
  28. package/dist/color-picker/root/color-picker-root.js +0 -272
  29. package/dist/combobox/root/combobox-root.js +0 -428
  30. package/dist/command/root/command-root.js +0 -177
  31. package/dist/copy-button/root/copy-button-root.js +0 -134
  32. package/dist/data-table/root/data-table-root.js +0 -336
  33. package/dist/data-table/root/order.js +0 -100
  34. package/dist/date-input/root/date-input-root.js +1 -398
  35. package/dist/date-picker/root/date-picker-root.js +0 -358
  36. package/dist/dialog/root/dialog-root.js +0 -189
  37. package/dist/divider/root/divider-root.js +0 -71
  38. package/dist/donut-chart/root/donut-chart-root.js +0 -214
  39. package/dist/drawer/root/drawer-root.js +0 -116
  40. package/dist/drilldown/item/drilldown-item.js +0 -82
  41. package/dist/drilldown/root/drilldown-root.js +0 -91
  42. package/dist/element-events.generated.js +0 -5
  43. package/dist/empty/root/empty-root.js +0 -35
  44. package/dist/file-input/root/file-input-root.js +0 -232
  45. package/dist/format-date/root/format-date-root.js +0 -95
  46. package/dist/heatmap/root/buckets.js +0 -57
  47. package/dist/heatmap/root/heatmap-root.js +0 -313
  48. package/dist/icon/root/icon-root.js +0 -48
  49. package/dist/icon-button/root/icon-button-root.js +0 -30
  50. package/dist/image/root/image-root.js +0 -174
  51. package/dist/index.js +0 -9
  52. package/dist/input/root/input-root.js +0 -228
  53. package/dist/kbd/root/kbd-root.js +0 -117
  54. package/dist/legend/root/legend-root.js +0 -73
  55. package/dist/line-chart/root/line-chart-root.js +0 -172
  56. package/dist/list/item/list-item.js +0 -92
  57. package/dist/list/root/list-root.js +0 -26
  58. package/dist/listbox/root/listbox-root.js +2 -429
  59. package/dist/loader/root/loader-root.js +0 -40
  60. package/dist/megamenu/root/megamenu-root.js +0 -284
  61. package/dist/menu/item/menu-item.js +1 -221
  62. package/dist/menu/root/menu-root.js +1 -171
  63. package/dist/meter/root/meter-root.js +1 -152
  64. package/dist/navigation/root/navigation-root.js +0 -56
  65. package/dist/notifications/notification/notification.js +0 -159
  66. package/dist/notifications/root/notifications-root.js +0 -148
  67. package/dist/number-input/root/number-input-root.js +1 -263
  68. package/dist/option/group/option-group.js +0 -26
  69. package/dist/option/root/option-root.js +0 -157
  70. package/dist/outline/root/outline-root.js +0 -292
  71. package/dist/pagination/root/pagination-root.js +0 -361
  72. package/dist/pagination/size/pagination-size.js +0 -104
  73. package/dist/pagination/summary/pagination-summary.js +0 -90
  74. package/dist/pin-input/root/pin-input-root.js +0 -276
  75. package/dist/popover/root/popover-root.js +0 -103
  76. package/dist/progress/root/progress-root.js +1 -133
  77. package/dist/qr-code/root/qr-code-root.js +0 -96
  78. package/dist/quote/root/quote-root.js +0 -25
  79. package/dist/radio/group/radio-group.js +0 -81
  80. package/dist/radio/root/radio-root.js +0 -85
  81. package/dist/rating/root/rating-root.js +0 -220
  82. package/dist/scroll-area/root/scroll-area-root.js +0 -100
  83. package/dist/select/root/select-root.js +2 -218
  84. package/dist/skeleton/root/skeleton-root.js +0 -20
  85. package/dist/slider/root/slider-root.js +1 -267
  86. package/dist/sparkline/root/sparkline-root.js +3 -164
  87. package/dist/speed-dial/item/speed-dial-item.js +0 -52
  88. package/dist/speed-dial/root/speed-dial-root.js +1 -116
  89. package/dist/splitter/root/splitter-root.js +0 -489
  90. package/dist/stat/group/stat-group.js +0 -18
  91. package/dist/stat/root/stat-root.js +0 -23
  92. package/dist/steps/root/steps-root.js +0 -62
  93. package/dist/steps/step/step.js +0 -131
  94. package/dist/switch/root/switch-root.js +0 -80
  95. package/dist/table/cell/table-cell.js +0 -23
  96. package/dist/table/column/table-column.js +0 -158
  97. package/dist/table/root/table-root.js +0 -82
  98. package/dist/table/row/table-row.js +0 -21
  99. package/dist/tabs/panel/tab-panel.js +0 -49
  100. package/dist/tabs/root/tabs-root.js +0 -98
  101. package/dist/tabs/tab/tab.js +0 -59
  102. package/dist/tag/root/tag-root.js +0 -31
  103. package/dist/textarea/root/textarea-root.js +0 -162
  104. package/dist/time-input/root/time-input-root.js +0 -283
  105. package/dist/time-picker/root/time-picker-root.js +0 -326
  106. package/dist/timeline/item/timeline-item.js +0 -66
  107. package/dist/timeline/root/timeline-root.js +0 -41
  108. package/dist/toast/item/toast-item.js +0 -165
  109. package/dist/toast/root/toast-root.js +0 -51
  110. package/dist/toggle/group/toggle-group.js +0 -150
  111. package/dist/toggle/root/toggle-root.js +0 -78
  112. package/dist/toolbar/root/toolbar-root.js +0 -116
  113. package/dist/tooltip/root/tooltip-root.js +0 -427
  114. package/dist/tour/root/tour-root.js +0 -130
  115. package/dist/tour/stop/tour-stop.js +1 -127
  116. package/dist/tree/item/tree-item.js +0 -198
  117. package/dist/tree/root/tree-root.js +0 -97
  118. package/dist/trend/root/trend-root.js +0 -53
  119. package/dist/video/root/video-root.d.ts +8 -12
  120. package/dist/video/root/video-root.js +5 -756
  121. package/dist/video-playlist/item/video-playlist-item.js +1 -90
  122. package/dist/video-playlist/menu/video-playlist-menu.js +1 -132
  123. package/dist/video-playlist/root/video-playlist-root.js +0 -113
  124. package/dist/virtual-list/root/virtual-list-root.js +0 -105
  125. package/jsx.d.ts +1408 -2576
  126. package/package.json +6 -6
  127. package/vue.d.ts +1 -1
@@ -7,122 +7,33 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
7
7
  import { AriaForwardController, customElement, HelixFormElement, holdCaret, MixinControllerValue, MixinField, restoreValue, } from '@fusion.dev/helix-core';
8
8
  import { html, nothing } from 'lit';
9
9
  import { property } from 'lit/decorators.js';
10
- /**
11
- * @summary Several lines of text a reader types into.
12
- *
13
- * @description
14
- * A real `<textarea>`, so the caret, the selection, spellcheck, the resize
15
- * handle and the keyboard a phone chooses are all the platform's, and it
16
- * serializes into the server's markup so the field is usable before any script
17
- * loads.
18
- *
19
- * **Not an Input with a taller box.** The difference is the Enter key: in a
20
- * single-line field it submits the form, and here it inserts a line. That is a
21
- * behavioral difference the platform owns and cannot be styled into existence,
22
- * which is why this is its own element rather than `Input` with a property.
23
- *
24
- * `rows` sets the height it starts at, and `auto-grow` lets it follow its own
25
- * content. They are not alternatives: `rows` is where an empty field begins and
26
- * `auto-grow` is what happens after, so a field that grows still has to start
27
- * somewhere.
28
- *
29
- * @since 0.1.0
30
- * @status stable
31
- * @category forms
32
- * @aliases Multiline, TextArea
33
- * @documentation https://helix.fusion.dev/components/textarea
34
- *
35
- * @event {Event} change - Relayed from the textarea once the reader has finished.
36
- * @event {HelixBeforeChangeEvent} helix-before-change - Fired as the text changes, and cancelable.
37
- * @event {Event} input - Announced once the value has moved.
38
- *
39
- * @csspart control - The textarea itself.
40
- * @csspart feedback - What is wrong with it.
41
- * @csspart field - The box holding the control.
42
- * @csspart hint - Help under the field, while nothing is wrong.
43
- * @csspart label - The question, over the field.
44
- */
45
10
  let HelixHeadlessTextarea = class HelixHeadlessTextarea extends MixinControllerValue(MixinField(HelixFormElement)) {
46
11
  constructor() {
47
12
  super(...arguments);
48
- /* A consumer's `aria-describedby` names ids in their own tree and the control
49
- is in this shadow root, so the reference has to be carried down as an
50
- element rather than copied as an id. See `AriaForwardController`: measured
51
- in Chrome's own tree, the host held the description and the control the
52
- reader is actually on was exposed without it. */
53
13
  this.aria = new AriaForwardController(this, {
54
14
  target: () => this.renderRoot?.querySelector('[part="control"]') ?? null,
55
15
  });
56
- /** Typed or dragged, so every edit is announced. See `announcesInput`. */
57
16
  this.announcesInput = true;
58
- /**
59
- * What the browser may autofill here, as one of the platform's own tokens.
60
- *
61
- * Empty leaves the attribute off, which is the browser's default. Set it to
62
- * a token like `email` or `bday` to ask for autofill, or to `off` to refuse.
63
- */
64
17
  this.autocomplete = '';
65
- /**
66
- * Whether the box follows its own content rather than scrolling.
67
- */
68
18
  this.autoGrow = false;
69
- /**
70
- * The name a second entry carries, holding which way the text runs.
71
- *
72
- * **Submitted through `setFormValue`, because the inner control's own
73
- * `dirname` cannot reach the form.** This host is form-associated and reports
74
- * its value itself, so the `<textarea>` inside the shadow root participates in
75
- * no form at all and forwarding the attribute would have looked right and
76
- * submitted nothing. `ElementInternals` takes a `FormData`, which is how one
77
- * element sends two entries, and that is what this does.
78
- */
79
19
  this.dirName = '';
80
- /**
81
- * Shown while the field is empty.
82
- *
83
- * Not a label: it goes when typing starts.
84
- */
85
20
  this.placeholder = '';
86
- /**
87
- * Whether the field refuses input while still submitting its value.
88
- */
89
21
  this.readOnly = false;
90
- /**
91
- * Every keystroke, cancelable, and put back where it is refused.
92
- *
93
- * The control has already taken the character by the time this runs, so
94
- * refusing has to restore it, or what is on screen and what the form would
95
- * submit disagree.
96
- */
97
22
  this.handleInput = (event) => {
98
- // Stopped for the reason `Input.handleInput` gives: the inner control's own
99
- // `input` is composed and would reach a consumer beside this element's.
100
23
  event.stopPropagation();
101
24
  const control = event.target;
102
25
  const next = control.value;
103
- /* Through the mixin, which announces and then applies only if the value is
104
- the element's to move. The native control has already changed either way,
105
- so wherever the answer does not follow it has to be put back. */
106
26
  this.requestValue(next);
107
27
  restoreValue(control, this.value);
108
28
  this.grow();
109
29
  };
110
- /** Relayed, because `change` does not cross a shadow boundary on its own. */
111
30
  this.handleChange = (event) => {
112
31
  event.stopPropagation();
113
32
  this.dispatchEvent(new Event('change', { bubbles: true, composed: false }));
114
33
  };
115
- /**
116
- * How many lines the box is before anything is typed.
117
- */
118
34
  this.rows = 3;
119
- /**
120
- * How the browser wraps the text, and whether the breaks are submitted with
121
- * it.
122
- */
123
35
  this.wrap = 'soft';
124
36
  }
125
- /** Focus is delegated to the control, so the host is never the target. */
126
37
  static { this.shadowRootOptions = {
127
38
  ...HelixFormElement.shadowRootOptions,
128
39
  delegatesFocus: true,
@@ -130,49 +41,18 @@ let HelixHeadlessTextarea = class HelixHeadlessTextarea extends MixinControllerV
130
41
  get control() {
131
42
  return this.renderRoot.querySelector('[part="control"]');
132
43
  }
133
- /**
134
- * Follows the content, by measuring rather than by counting.
135
- *
136
- * `scrollHeight` is what the text actually needs, which no arithmetic over
137
- * line count and line height gets right: a wrapped line, a pasted paragraph
138
- * and a font that has not loaded yet all break the arithmetic and none of
139
- * them break the measurement.
140
- *
141
- * Reset to `auto` first, because `scrollHeight` of an element already sized to
142
- * its content is that size, so without the reset the box can only ever grow.
143
- */
144
44
  grow() {
145
45
  const control = this.control;
146
46
  if (!this.autoGrow || !control) {
147
47
  return;
148
48
  }
149
49
  control.style.blockSize = 'auto';
150
- /* Zero is not a height, it is the absence of a layout box.
151
- *
152
- * An element with `display: none` anywhere above it reports `scrollHeight`
153
- * as zero. Written back as a fixed `block-size` it pins the field there,
154
- * since every later call then measures a control at zero and measures zero
155
- * again: a textarea inside a tab panel, an accordion, or anything else that
156
- * renders shut and opens later comes out as a hairline with the text hidden
157
- * behind it. `tabs-root` refuses zero for the same reason.
158
- *
159
- * The reset to `auto` above has already been written by this point, which
160
- * is the right state to leave it in: an ungrown auto-grow field is the
161
- * browser's own height, not a stale number from the last time it had one. */
162
50
  const next = control.scrollHeight;
163
51
  if (next === 0) {
164
52
  return;
165
53
  }
166
54
  control.style.blockSize = `${next}px`;
167
55
  }
168
- /**
169
- * What the form receives, which is two entries where `dirName` asks for it.
170
- *
171
- * A plain string otherwise, because that is the common case and a `FormData`
172
- * of one entry says the same thing at more cost. The direction is read off
173
- * the control rather than assumed, so a field a consumer set `dir="rtl"` on,
174
- * or one inside an RTL document, submits what the reader actually saw.
175
- */
176
56
  formValue() {
177
57
  const control = this.control;
178
58
  if (!this.dirName || !this.name || !control) {
@@ -183,19 +63,6 @@ let HelixHeadlessTextarea = class HelixHeadlessTextarea extends MixinControllerV
183
63
  data.append(this.dirName, getComputedStyle(control).direction === 'rtl' ? 'rtl' : 'ltr');
184
64
  return data;
185
65
  }
186
- /**
187
- * The caret and the selection, under the platform's own names.
188
- *
189
- * **The whole reason this renders a real `<textarea>` is the caret**, and the
190
- * control is inside this shadow root, so `querySelector` does not find it and
191
- * a consumer has no other way to ask where the selection is, let alone move
192
- * it. A field that cannot be scripted at the caret cannot do an
193
- * insert-at-cursor toolbar, which is the first thing anybody builds on a
194
- * textarea.
195
- *
196
- * Written through to the control, and answering zero before there is one,
197
- * which is where an empty field's caret would be anyway.
198
- */
199
66
  get selectionDirection() {
200
67
  return this.control?.selectionDirection ?? 'none';
201
68
  }
@@ -205,7 +72,6 @@ let HelixHeadlessTextarea = class HelixHeadlessTextarea extends MixinControllerV
205
72
  control.selectionDirection = direction;
206
73
  }
207
74
  }
208
- /** Where the selection ends, as an offset into the value. */
209
75
  get selectionEnd() {
210
76
  return this.control?.selectionEnd ?? 0;
211
77
  }
@@ -215,7 +81,6 @@ let HelixHeadlessTextarea = class HelixHeadlessTextarea extends MixinControllerV
215
81
  control.selectionEnd = at;
216
82
  }
217
83
  }
218
- /** Where the selection starts, as an offset into the value. */
219
84
  get selectionStart() {
220
85
  return this.control?.selectionStart ?? 0;
221
86
  }
@@ -225,49 +90,27 @@ let HelixHeadlessTextarea = class HelixHeadlessTextarea extends MixinControllerV
225
90
  control.selectionStart = at;
226
91
  }
227
92
  }
228
- /**
229
- * Selects a range, which is the one operation the three accessors above
230
- * cannot express between them.
231
- *
232
- * Setting `selectionStart` past the current `selectionEnd` drags the end
233
- * along, so the two writes a consumer would make in sequence do not compose
234
- * into the range they asked for. The platform has this method for that reason
235
- * and so does this.
236
- */
237
93
  setSelectionRange(start, end, direction) {
238
94
  this.control?.setSelectionRange(start, end, direction);
239
95
  }
240
- /** How many characters the value holds. */
241
96
  get textLength() {
242
97
  return this.value.length;
243
98
  }
244
- /** What kind of control this is, which for a textarea is always the one word. */
245
99
  get type() {
246
100
  return 'textarea';
247
101
  }
248
- /** Puts the caret in the field, the way a label pointing at one would. */
249
102
  focus(options) {
250
103
  this.control?.focus(options);
251
104
  }
252
- /** Reports the value and the validity the host stands behind. */
253
105
  sync() {
254
106
  this.internals.setFormValue(this.formValue());
255
107
  const control = this.control;
256
108
  if (!control) {
257
109
  return;
258
110
  }
259
- // The platform's verdict, copied rather than recomputed, with the control as
260
- // the anchor so a validity bubble points at the text and not at the host.
261
111
  this.internals.setValidity(control.validity, control.validationMessage, control);
262
112
  this.refreshFeedback();
263
113
  }
264
- /* Rebuilt on reconnection, because nothing else does it.
265
- *
266
- * `firstUpdated` runs once for the life of the element and
267
- * `disconnectedCallback` runs every time it moves, so without this a
268
- * framework reordering a list leaves the observer gone with nothing to
269
- * rebuild it. Guarded on `hasUpdated`, because the first connection happens
270
- * before the first render and there is nothing to watch yet. */
271
114
  connectedCallback() {
272
115
  super.connectedCallback();
273
116
  if (this.hasUpdated) {
@@ -283,7 +126,6 @@ let HelixHeadlessTextarea = class HelixHeadlessTextarea extends MixinControllerV
283
126
  super.firstUpdated(changed);
284
127
  this.watchControl();
285
128
  }
286
- /** Watches the control so the box grows with what is typed into it. */
287
129
  watchControl() {
288
130
  const control = this.control;
289
131
  if (!control) {
@@ -295,10 +137,6 @@ let HelixHeadlessTextarea = class HelixHeadlessTextarea extends MixinControllerV
295
137
  }
296
138
  willUpdate(changed) {
297
139
  super.willUpdate(changed);
298
- /* Never before the first update, which is the one the server does: there is
299
- no render root to query there, and `querySelector` is not merely empty on
300
- Lit's element shim, it is undefined. There is also no caret to keep before
301
- anything has rendered. */
302
140
  if (!this.hasUpdated) {
303
141
  return;
304
142
  }