@fusion.dev/helix-headless 0.157.0 → 0.158.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.
@@ -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 { AriaForwardController, appleTouch, valueAsNumber as asNumber, customElement, formatNumber, formatWords, numberAsValue as fromNumber, HelixFormElement, holdCaret, MixinControllerValue, MixinField, parseNumber, restoreValue, submitImplicitly, words, wordsLocale, } from '@fusion.dev/helix-core';
7
+ import { AriaForwardController, appleTouch, customElement, formatNumber, formatWords, numberAsValue as fromNumber, HelixFormElement, holdCaret, MixinControllerValue, MixinField, parseNumber, restoreValue, submitImplicitly, words, wordsLocale, } from '@fusion.dev/helix-core';
8
8
  import { minus, plus } from '@fusion.dev/helix-icons';
9
9
  import { html, nothing } from 'lit';
10
10
  import { property, state } from 'lit/decorators.js';
@@ -410,7 +410,7 @@ let HelixHeadlessNumberInput = class HelixHeadlessNumberInput extends MixinContr
410
410
  const atMin = parsed !== null && this.min !== undefined && parsed <= this.min;
411
411
  const atMax = parsed !== null && this.max !== undefined && parsed >= this.max;
412
412
  return html `${this.renderLabel()}
413
- <div part="field" role="group">
413
+ <div part="field" role="group" aria-labelledby=${this.labeled ? this.labelId : nothing}>
414
414
  <button
415
415
  part="decrement"
416
416
  type="button"
@@ -484,7 +484,7 @@ let HelixHeadlessNumberInput = class HelixHeadlessNumberInput extends MixinContr
484
484
  ${this.renderHint()}${this.renderFeedback()}`;
485
485
  }
486
486
  get valueAsNumber() {
487
- return asNumber(this.value);
487
+ return this.numeric ?? Number.NaN;
488
488
  }
489
489
  set valueAsNumber(count) {
490
490
  this.value = fromNumber(count);
@@ -51,7 +51,7 @@ let HelixHeadlessProgress = class HelixHeadlessProgress extends HelixElement {
51
51
  this.internals.ariaValueMax = String(max);
52
52
  this.internals.ariaValueNow = this.indeterminate
53
53
  ? null
54
- : String(Math.min(Math.max(this.value || min, min), max));
54
+ : String(Math.min(Math.max(Number.isNaN(this.value) ? min : this.value, min), max));
55
55
  const shown = this.valueText || slottedWords(this, ['']);
56
56
  this.internals.ariaValueText = this.indeterminate ? shown || null : shown || this.text;
57
57
  this.toggleState('complete', this.complete);
@@ -19,7 +19,9 @@ declare const HelixHeadlessSelect_base: (new (...args: any[]) => import("@fusion
19
19
  * whole set.
20
20
  *
21
21
  * `Select` owns the value, passes it down to the listbox, and takes changes
22
- * back, so the value lives in one place.
22
+ * back, so the value lives in one place. With `multiple`, the value is the
23
+ * chosen values joined with commas, and the form receives one entry for each.
24
+ * An option's value may hold a comma, and it is read as one value.
23
25
  *
24
26
  * Set `valueContent` to draw the trigger's content from the chosen options,
25
27
  * and several chosen options are written as a list in the reader's language.
@@ -291,6 +293,11 @@ export declare class HelixHeadlessSelect extends HelixHeadlessSelect_base {
291
293
  private get display();
292
294
  /** The chosen options, in the order they appear. None on a server or while hydrating, and none for `items`. */
293
295
  private get chosenOptions();
296
+ /**
297
+ * The chosen values, read against the options' values, so an option whose
298
+ * value holds a comma is one value. See `chosenValues`.
299
+ */
300
+ private get chosen();
294
301
  /** `items` as the list reads them, built once per array. */
295
302
  private data;
296
303
  /**
@@ -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 { AriaForwardController, afterLinkFollowed, customElement, dataOptions, drawAutofill, drawStatus, HelixFormElement, hostAria, hostWords, isRtl, MixinControllerOpen, MixinControllerValue, MixinField, onApple, PopoverController, reportValues, StatusController, sideOf, typesCharacter, words, wordsLocale, } from '@fusion.dev/helix-core';
7
+ import { AriaForwardController, afterLinkFollowed, chosenValues, customElement, dataOptions, drawAutofill, drawStatus, HelixFormElement, hostAria, hostWords, isRtl, MixinControllerOpen, MixinControllerValue, MixinField, onApple, PopoverController, reportValues, StatusController, sideOf, typesCharacter, words, wordsLocale, } from '@fusion.dev/helix-core';
8
8
  import { caretDown } from '@fusion.dev/helix-icons';
9
9
  import { nothing } from 'lit';
10
10
  import { property } from 'lit/decorators.js';
@@ -173,7 +173,7 @@ let HelixHeadlessSelect = class HelixHeadlessSelect extends MixinControllerOpen(
173
173
  return this.partNamed('listbox');
174
174
  }
175
175
  get display() {
176
- const chosen = new Set(this.value === '' ? [] : this.value.split(','));
176
+ const chosen = new Set(this.chosen);
177
177
  const words = this.entries.filter((option) => chosen.has(option.value)).map((one) => one.text);
178
178
  if (words.length > 0) {
179
179
  return new Intl.ListFormat(wordsLocale(this), { style: 'short', type: 'unit' }).format(words);
@@ -184,9 +184,12 @@ let HelixHeadlessSelect = class HelixHeadlessSelect extends MixinControllerOpen(
184
184
  if (this.items) {
185
185
  return [];
186
186
  }
187
- const chosen = new Set(this.value === '' ? [] : this.value.split(','));
187
+ const chosen = new Set(this.chosen);
188
188
  return optionsAmong(this.knownChildren).filter((option) => chosen.has(option.value));
189
189
  }
190
+ get chosen() {
191
+ return chosenValues(this.value, new Set(this.entries.map((option) => option.value)), this.multiple);
192
+ }
190
193
  get entries() {
191
194
  if (!this.items) {
192
195
  return optionsAmong(this.knownChildren);
@@ -257,7 +260,7 @@ let HelixHeadlessSelect = class HelixHeadlessSelect extends MixinControllerOpen(
257
260
  }
258
261
  }
259
262
  const present = new Set(options.map((option) => option.value));
260
- const held = this.value === '' ? [] : this.value.split(',');
263
+ const held = chosenValues(this.value, new Set([...present, ...this.seen]), this.multiple);
261
264
  const gone = held.filter((value) => this.seen.has(value) && !present.has(value));
262
265
  this.seen = present;
263
266
  if (gone.length > 0) {
@@ -266,7 +269,7 @@ let HelixHeadlessSelect = class HelixHeadlessSelect extends MixinControllerOpen(
266
269
  }
267
270
  sync() {
268
271
  if (this.multiple) {
269
- reportValues(this.internals, this.name, this.value === '' ? [] : this.value.split(','));
272
+ reportValues(this.internals, this.name, this.chosen);
270
273
  }
271
274
  else {
272
275
  this.internals.setFormValue(this.value === '' ? null : this.value);
@@ -41,7 +41,8 @@ export declare class HelixHeadlessSkeleton extends HelixElement {
41
41
  * What is loading, read out as the placeholder's name, such as "Loading
42
42
  * profile".
43
43
  *
44
- * Absent hides the placeholder from screen readers.
44
+ * Absent hides the placeholder from screen readers. Around content, the name
45
+ * is read while `loading` is set, and the loaded content is read as it is.
45
46
  */
46
47
  label: string;
47
48
  /**
@@ -22,7 +22,7 @@ let HelixHeadlessSkeleton = class HelixHeadlessSkeleton extends HelixElement {
22
22
  const wraps = this.wraps;
23
23
  this.toggleState('wrapping', wraps);
24
24
  this.internals.ariaBusy = this.loading ? 'true' : null;
25
- if (this.label) {
25
+ if (this.label && (this.loading || !wraps)) {
26
26
  hostAria(this.internals, { label: this.label, role: 'progressbar' });
27
27
  this.internals.ariaHidden = null;
28
28
  }