@fusion.dev/helix-core 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 (56) hide show
  1. package/custom-elements.json +4 -4
  2. package/dist/controllers/aria-forward-controller/aria-forward-controller.js +0 -105
  3. package/dist/controllers/chart-pointer-controller/chart-pointer-controller.js +0 -71
  4. package/dist/controllers/command-controller/command-controller.js +0 -62
  5. package/dist/controllers/copy-controller/copy-controller.js +0 -63
  6. package/dist/controllers/disabled-cascade-controller/disabled-cascade-controller.js +0 -40
  7. package/dist/controllers/dismiss-controller/dismiss-controller.js +0 -124
  8. package/dist/controllers/drilldown-controller/drilldown-controller.js +0 -87
  9. package/dist/controllers/floating-controller/floating-controller.js +0 -152
  10. package/dist/controllers/focus-trap-controller/focus-trap-controller.js +0 -35
  11. package/dist/controllers/indicator-controller/indicator-controller.js +0 -82
  12. package/dist/controllers/keyboard-navigation-controller/keyboard-navigation-controller.js +0 -46
  13. package/dist/controllers/popover-controller/popover-controller.js +0 -72
  14. package/dist/controllers/source-controller/source-controller.js +0 -38
  15. package/dist/controllers/token-color-controller/token-color-controller.js +0 -51
  16. package/dist/controllers/virtualize-controller/virtualize-controller.js +0 -128
  17. package/dist/events/element-events.js +0 -22
  18. package/dist/events/events.js +0 -386
  19. package/dist/helix-element/helix-element.d.ts +10 -17
  20. package/dist/helix-element/helix-element.js +0 -505
  21. package/dist/helix-form-element/helix-form-element.js +0 -140
  22. package/dist/mixins/mixin-chart-source/mixin-chart-source.js +0 -77
  23. package/dist/mixins/mixin-collection/mixin-collection.js +0 -83
  24. package/dist/mixins/mixin-controller-active/mixin-controller-active.js +0 -82
  25. package/dist/mixins/mixin-controller-checked/mixin-controller-checked.js +0 -78
  26. package/dist/mixins/mixin-controller-open/mixin-controller-open.js +0 -93
  27. package/dist/mixins/mixin-controller-value/mixin-controller-value.js +0 -87
  28. package/dist/mixins/mixin-dismissible/mixin-dismissible.js +0 -38
  29. package/dist/mixins/mixin-field/mixin-field.js +0 -277
  30. package/dist/utils/anchor-element/anchor-element.js +0 -23
  31. package/dist/utils/capture-pointer/capture-pointer.js +0 -18
  32. package/dist/utils/closest-instance/closest-instance.js +0 -20
  33. package/dist/utils/create-sheet/create-sheet.js +0 -14
  34. package/dist/utils/custom-element/custom-element.js +0 -83
  35. package/dist/utils/draw-icon/draw-icon.js +0 -28
  36. package/dist/utils/draw-tooltip/draw-tooltip.js +1 -50
  37. package/dist/utils/elapsed-time/elapsed-time.js +0 -51
  38. package/dist/utils/focusable-elements/focusable-elements.js +1 -59
  39. package/dist/utils/format-numbers/format-numbers.js +0 -16
  40. package/dist/utils/host-aria/host-aria.js +0 -26
  41. package/dist/utils/inherit-disabled/inherit-disabled.js +0 -36
  42. package/dist/utils/line-path/line-path.js +0 -36
  43. package/dist/utils/on-unless-false/on-unless-false.js +0 -23
  44. package/dist/utils/read-series/read-series.js +0 -71
  45. package/dist/utils/relative-time/relative-time.js +0 -43
  46. package/dist/utils/resolve-active-item/resolve-active-item.js +0 -20
  47. package/dist/utils/restore-value/restore-value.js +0 -54
  48. package/dist/utils/scale/scale.js +0 -19
  49. package/dist/utils/scale/ticks.js +0 -36
  50. package/dist/utils/scroll-item-into-view/scroll-item-into-view.js +0 -53
  51. package/dist/utils/slot-filled/slot-filled.js +0 -23
  52. package/dist/utils/tell-disclosure/tell-disclosure.js +0 -53
  53. package/dist/utils/ticker/ticker.js +0 -22
  54. package/dist/utils/tone-marks/tone-marks.js +0 -24
  55. package/dist/utils/value-as/value-as.js +0 -56
  56. package/package.json +5 -5
@@ -7,63 +7,13 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
7
7
  import { property } from 'lit/decorators.js';
8
8
  import { HelixBeforeCloseEvent, HelixBeforeOpenEvent } from '../../events/events.js';
9
9
  import { requestChange } from '../../utils/request-change/request-change.js';
10
- /**
11
- * Grafts open state onto a base class, and says so twice.
12
- *
13
- * `helix-before-open` and `helix-before-close` announce the change while it is
14
- * still a request, so `preventDefault()` refuses it and nothing moves. Native
15
- * `toggle` announces it afterwards, once the state has actually gone, carrying
16
- * `newState` and `oldState` the way the platform does on `<details>` and on a
17
- * popover. The first is how a consumer takes the decision; the second is what
18
- * they bind when they only want to know.
19
- *
20
- * `open` is a seed and a correction rather than a claim: the element applies
21
- * its own changes from wherever markup started it, and `defaultOpen` is what a
22
- * reset returns to.
23
- *
24
- * Records `:state(open)` whenever the element is open. Styled tiers select on
25
- * that rather than on `[open]`, which is absent until somebody writes it.
26
- */
27
10
  export const MixinControllerOpen = (Base) => {
28
- // JSDoc is duplicated from MixinControllerOpenInterface deliberately. The interface is
29
- // what TypeScript consumers see; this class is what the manifest analyzer
30
- // reads when resolving inherited members into dependent packages.
31
11
  class OpenElement extends Base {
32
12
  constructor() {
33
13
  super(...arguments);
34
- /**
35
- * Initial open state for uncontrolled use, where nothing declared one.
36
- */
37
14
  this.defaultOpen = false;
38
- /**
39
- * The state, whoever set it, and `undefined` until somebody has.
40
- *
41
- * Prefixed, and it has to be. These mixins compose onto one prototype
42
- * chain, `Select` takes this one and `MixinControllerValue` together, and
43
- * TypeScript's `private` is a compile-time fiction: two mixins with a field
44
- * called `state` share one property on the instance, and the second one
45
- * silently overwrites the first. Measured, as a select whose `value` came
46
- * back holding its `open` boolean.
47
- *
48
- * One field and not two. Writing always applies, the way a native control
49
- * does when a script assigns to it.
50
- */
51
15
  this.openState = undefined;
52
16
  }
53
- /**
54
- * Whether the element is open.
55
- *
56
- * One property, not two, so `dialog.open` answers the question anyone
57
- * asking it meant. Writing always applies; `<helix-dialog open>` is the
58
- * same statement in markup.
59
- *
60
- * **Not reflected, and that is required rather than tidy.** Reflection
61
- * writes the resolved state back as an attribute, so an element that opened
62
- * itself would put `open` on its own host: cloned, serialized for
63
- * hydration, or diffed by a framework, it comes back holding whatever the
64
- * last reader did rather than what the author wrote. `:state(open)` carries
65
- * the resolved state for stylesheets, which is what the mirror is for.
66
- */
67
17
  get open() {
68
18
  return this.openState ?? this.defaultOpen;
69
19
  }
@@ -72,31 +22,10 @@ export const MixinControllerOpen = (Base) => {
72
22
  this.openState = next;
73
23
  this.requestUpdate('open', previous);
74
24
  }
75
- /**
76
- * Records the resolved state as the custom state `open`.
77
- *
78
- * **A custom state and never `data-open`.** An attribute mirror is in the
79
- * DOM, so an `<helix-accordion-item default-open>` served without it gains
80
- * it on upgrade, which is a hydration mismatch a React consumer reports.
81
- * See `HelixElement.toggleState`, and see `Toast.Item` for the other answer
82
- * to the same fault: inverting the hook so the write falls on the side that
83
- * only happens after somebody acts. Inversion works where the resting state
84
- * is the loud one and cannot help here, `checked` and `open` being true
85
- * only because a consumer asked for them.
86
- */
87
25
  willUpdate(changed) {
88
26
  super.willUpdate(changed);
89
27
  this.toggleState('open', this.open);
90
28
  }
91
- /**
92
- * Requests an open-state change, and reports whether it was applied.
93
- *
94
- * Announces before it acts, so `preventDefault()` on the `helix-before-open` or
95
- * `helix-before-close` is a refusal and nothing moves. Nobody refusing means the
96
- * element opens or closes itself, whether or not a consumer declared
97
- * `open`: a declared property is a seed and a correction, and a consumer
98
- * who wants the decision for themselves refuses it and assigns their own.
99
- */
100
29
  requestOpen(next) {
101
30
  if (this.open === next) {
102
31
  return true;
@@ -116,27 +45,6 @@ export const MixinControllerOpen = (Base) => {
116
45
  }
117
46
  return applied;
118
47
  }
119
- /**
120
- * Says the state moved, under the platform's own name and in its shape.
121
- *
122
- * **A native `toggle` from inside a shadow root reaches nobody**, because
123
- * it neither bubbles nor composes, so the ten families showing a
124
- * `popover="manual"` panel and the two rendering a real `<dialog>` announce
125
- * nothing to a consumer. The disclosures have no native element to fire
126
- * anything at all: `AccordionItem` and `TreeItem` are `aria-expanded` and
127
- * `hidden` written by hand, which is `<details>`'s job done manually.
128
- *
129
- * **From here rather than from `PopoverController`.** The controller covers
130
- * eleven families and the mixin covers sixteen, so announcing from both
131
- * would announce twice on the ten they share. What `toggle` reports is the
132
- * *state*, and the state is this mixin's; the controller is a way of
133
- * putting a panel on the screen.
134
- *
135
- * **`newState` and `oldState`, because that is the platform's shape**, so a
136
- * consumer arriving from `<details>` reads the same two words. Not
137
- * cancelable: the before events are the request, and a second cancelable
138
- * event for one transition is two answers to one question.
139
- */
140
48
  announceToggle(open) {
141
49
  const event = new Event('toggle', { bubbles: false, cancelable: false, composed: false });
142
50
  Object.assign(event, {
@@ -145,7 +53,6 @@ export const MixinControllerOpen = (Base) => {
145
53
  });
146
54
  this.dispatchEvent(event);
147
55
  }
148
- /** Requests the opposite of the current state. */
149
56
  toggleOpen() {
150
57
  return this.requestOpen(!this.open);
151
58
  }
@@ -7,64 +7,14 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
7
7
  import { property } from 'lit/decorators.js';
8
8
  import { HelixBeforeChangeEvent } from '../../events/events.js';
9
9
  import { requestChange } from '../../utils/request-change/request-change.js';
10
- /**
11
- * Grafts `value`, `defaultValue`, and the two callbacks that answer a form.
12
- *
13
- * **Derived on read, never seeded in a lifecycle hook.** `value` falls back to
14
- * `defaultValue`, so the server and the client agree without either running a
15
- * hook. Seeding in `connectedCallback` is the trap: SSR never calls it, so a
16
- * control with a `default-value` would serve empty and fill itself at
17
- * hydration, a flash for a reader and a mismatch for React.
18
- *
19
- * **What it does not own is reporting.** `setFormValue` stays with the
20
- * component, because what an empty value means is the component's business: a
21
- * text field submits its emptiness, since `""` is an answer and the field was
22
- * on the form, while a group with nothing chosen submits nothing at all.
23
- *
24
- * `Checkbox` deliberately does not take this. Its `value` is what it submits
25
- * *when it is on* rather than what it holds, so it is configuration rather than
26
- * state, and the state it does have is `checked`, which is
27
- * `MixinControllerChecked`'s.
28
- */
29
10
  export const MixinControllerValue = (Base) => {
30
- // JSDoc is duplicated from the interface deliberately. The interface is what
31
- // TypeScript consumers see; this class is what the manifest analyzer reads
32
- // when resolving inherited members into dependent packages.
33
11
  class ValueElement extends Base {
34
12
  constructor() {
35
13
  super(...arguments);
36
- /**
37
- * The value the markup declared, which is where a reset returns to.
38
- */
39
14
  this.defaultValue = '';
40
- /**
41
- * The state, whoever set it, and `undefined` until somebody has.
42
- *
43
- * One field and not two. Writing always applies, the way a native control
44
- * does when a script assigns to it.
45
- */
46
15
  this.valueState = undefined;
47
- /**
48
- * Whether a reader edits this continuously, which decides the native name.
49
- *
50
- * The request event is `helix-before-change` whatever the answer; this
51
- * decides which native event announces the result, `input` while a reader
52
- * is editing against `change` when they are done, which is the distinction
53
- * the platform already draws.
54
- *
55
- * Discrete by default: only a control the reader edits continuously says
56
- * otherwise.
57
- */
58
16
  this.announcesInput = false;
59
17
  }
60
- /**
61
- * What the control holds now, and what its form submits.
62
- *
63
- * One property, not two, so `input.value` answers the question anyone
64
- * asking it meant. Writing always applies; `<helix-input value="x">` is the
65
- * same statement in markup, and `default-value` is how markup seeds a value
66
- * a reset should return to.
67
- */
68
18
  get value() {
69
19
  return this.valueState ?? this.defaultValue;
70
20
  }
@@ -73,35 +23,12 @@ export const MixinControllerValue = (Base) => {
73
23
  this.valueState = next;
74
24
  this.requestUpdate('value', previous);
75
25
  }
76
- /**
77
- * Announces the applied value under the platform's own name.
78
- *
79
- * **After `apply`, never before**, which is the whole reason this is
80
- * separate from the request event: a native handler reads
81
- * `event.target.value`, and it has to be the value that was just applied.
82
- *
83
- * **Both, for a discrete control, because that is what the platform does.**
84
- * A native `<select>` sends `input` and then `change` from one choice: the
85
- * value moved, and the reader is also done. A continuous control announces
86
- * `input` here and relays `change` from its inner control when the reader
87
- * is done, so the pair keeps the platform's timings rather than reporting a
88
- * commit on every keystroke.
89
- */
90
26
  announceNatively() {
91
27
  this.dispatchEvent(new Event('input', { bubbles: true, composed: true }));
92
28
  if (!this.announcesInput) {
93
29
  this.dispatchEvent(new Event('change', { bubbles: true, composed: false }));
94
30
  }
95
31
  }
96
- /**
97
- * Requests a new value, and reports whether the request stood.
98
- *
99
- * Announces before it acts, so `preventDefault()` on the `helix-before-change` is
100
- * a refusal and nothing moves. Nobody refusing means the control updates
101
- * itself, whether or not a consumer declared `value`: a declared property
102
- * is a seed and a correction, the way `<input value>` is, and a consumer
103
- * who wants the change for themselves refuses it and assigns their own.
104
- */
105
32
  requestValue(next) {
106
33
  if (this.value === next) {
107
34
  return true;
@@ -121,25 +48,11 @@ export const MixinControllerValue = (Base) => {
121
48
  }
122
49
  return applied;
123
50
  }
124
- /**
125
- * Returns the control to the value its markup declared.
126
- *
127
- * Both halves are dropped, the consumer's and the control's, because a
128
- * reset means the form is as it was served. Clearing only the internal one
129
- * would leave a control that had been written to stuck at that value.
130
- */
131
51
  formResetCallback() {
132
52
  const previous = this.value;
133
53
  this.valueState = undefined;
134
54
  this.requestUpdate('value', previous);
135
55
  }
136
- /**
137
- * Restores the value when the browser brings a form back.
138
- *
139
- * Falling back to `defaultValue` rather than to empty, because a restore
140
- * with no state is a form the browser has nothing recorded for, which is
141
- * the same situation as a fresh one.
142
- */
143
56
  formStateRestoreCallback(state) {
144
57
  const previous = this.value;
145
58
  this.valueState = state ?? undefined;
@@ -6,58 +6,20 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
6
6
  };
7
7
  import { property } from 'lit/decorators.js';
8
8
  import { HelixDismissEvent } from '../../events/events.js';
9
- /**
10
- * Grafts `dismissible`, its label, and the event that says so.
11
- *
12
- * **The label reads the default slot, never `this.textContent`**, which is
13
- * every light-DOM descendant including the ones assigned elsewhere. On
14
- * `Announcement` and `Tag` the two are the same thing, because they have one
15
- * slot. On `Toast.Item` the second sweeps in the actions: a message reading
16
- * "Could not reach the server" with a `Retry` button announces itself as "Could
17
- * not reach the server Retry", and the consumer removing it from their list
18
- * gets that string to match on.
19
- *
20
- * **`dismissEvent()` is separate from `dismiss()` for the one that needs it.**
21
- * `Announcement` and `Tag` dispatch and are done: they own no state, so a
22
- * refusal is the whole of the consumer's answer. `Toast.Item` holds an `open`
23
- * and applies the change itself, so its event goes through `requestChange` with
24
- * an `apply` beside it. Giving it the event rather than the method lets it keep
25
- * the contract and skip the default.
26
- */
27
9
  export const MixinDismissible = (Base) => {
28
10
  class Dismissible extends Base {
29
11
  constructor() {
30
12
  super(...arguments);
31
- /**
32
- * Whether it offers a control to take it away.
33
- */
34
13
  this.dismissible = false;
35
- /**
36
- * Accessible name for that control.
37
- *
38
- * `attribute` is spelled out because Lit lowercases a property name to
39
- * derive one rather than dash-casing it, so this would otherwise be
40
- * reachable only as `dismisslabel`, which nobody would guess and no linter
41
- * would catch.
42
- */
43
14
  this.dismissLabel = 'Dismiss';
44
15
  }
45
- /**
46
- * The event, built and not dispatched.
47
- *
48
- * Reading text is safe here: nothing calls this on a server, because the
49
- * only things that do are a press and a timer.
50
- */
51
16
  dismissEvent() {
52
- /* Default slot only. A node assigned to a named slot belongs to another
53
- region and is not what this surface is called. */
54
17
  const own = [...this.childNodes]
55
18
  .filter((node) => !(node instanceof Element) || !node.slot)
56
19
  .map((node) => node.textContent ?? '')
57
20
  .join('');
58
21
  return new HelixDismissEvent({ label: own.trim() });
59
22
  }
60
- /** Announces that it should go, and reports whether the request stood. */
61
23
  dismiss() {
62
24
  const event = this.dismissEvent();
63
25
  this.dispatchEvent(event);