@fusion.dev/helix 0.144.0 → 0.146.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 (213) hide show
  1. package/custom-elements.json +17914 -4368
  2. package/dist/accordion/item/accordion-item.css.js +25 -10
  3. package/dist/accordion/item/accordion-item.d.ts +10 -0
  4. package/dist/aura/palette.d.ts +38 -0
  5. package/dist/aura/palette.js +22 -0
  6. package/dist/aura/root/aura-root.css.js +27 -3
  7. package/dist/aura/root/aura-root.d.ts +61 -14
  8. package/dist/aura/root/aura-root.js +40 -23
  9. package/dist/badge/root/badge-root.css.js +86 -16
  10. package/dist/badge/root/badge-root.d.ts +18 -0
  11. package/dist/badge/root/badge-root.js +6 -0
  12. package/dist/blockquote/root/blockquote-root.css.js +2 -2
  13. package/dist/blockquote/root/blockquote-root.d.ts +2 -0
  14. package/dist/breadcrumbs/breadcrumb/breadcrumb.css.js +7 -7
  15. package/dist/breadcrumbs/breadcrumb/breadcrumb.d.ts +5 -0
  16. package/dist/breadcrumbs/root/breadcrumbs-root.css.js +24 -1
  17. package/dist/breadcrumbs/root/breadcrumbs-root.d.ts +4 -0
  18. package/dist/breadcrumbs/root/breadcrumbs-root.js +2 -0
  19. package/dist/button/root/button-root.css.js +4 -3
  20. package/dist/button/root/button-root.d.ts +2 -0
  21. package/dist/button-group/root/button-group-root.d.ts +3 -0
  22. package/dist/callout/root/callout-root.css.js +4 -3
  23. package/dist/callout/root/callout-root.d.ts +6 -2
  24. package/dist/canvas/root/canvas-root.css.js +1 -0
  25. package/dist/card/root/card-root.d.ts +6 -0
  26. package/dist/carousel/root/carousel-root.css.js +17 -1
  27. package/dist/chat/message/chat-message.css.js +0 -62
  28. package/dist/chat/message/chat-message.js +2 -1
  29. package/dist/chat/root/chat-root.css.js +7 -0
  30. package/dist/chat/root/chat-root.d.ts +2 -0
  31. package/dist/chat/root/chat-root.js +2 -1
  32. package/dist/chat/typing.css.d.ts +1 -0
  33. package/dist/chat/typing.css.js +62 -0
  34. package/dist/checkbox/root/checkbox-root.css.js +15 -0
  35. package/dist/checkbox/root/checkbox-root.d.ts +2 -1
  36. package/dist/code/root/code-root.css.js +2 -2
  37. package/dist/code/root/code-root.d.ts +2 -0
  38. package/dist/code-block/root/code-block-root.css.js +24 -0
  39. package/dist/code-block/root/code-block-root.d.ts +2 -1
  40. package/dist/color-input/root/color-input-root.css.js +10 -0
  41. package/dist/color-picker/root/color-picker-root.css.js +8 -0
  42. package/dist/color-picker/root/color-picker-root.d.ts +1 -0
  43. package/dist/copy-button/root/copy-button-root.css.js +15 -6
  44. package/dist/copy-button/root/copy-button-root.d.ts +7 -0
  45. package/dist/data-table/root/data-table-root.css.js +70 -0
  46. package/dist/data-table/root/data-table-root.d.ts +6 -0
  47. package/dist/date-input/root/date-input-root.css.js +10 -0
  48. package/dist/description-list/item/description-list-item.css.js +11 -0
  49. package/dist/donut-chart/root/donut-chart-root.css.js +19 -0
  50. package/dist/donut-chart/root/donut-chart-root.d.ts +3 -0
  51. package/dist/drawer/root/drawer-root.css.js +47 -0
  52. package/dist/drawer/root/drawer-root.d.ts +5 -0
  53. package/dist/drilldown/item/drilldown-item.css.js +8 -7
  54. package/dist/drilldown/item/drilldown-item.d.ts +6 -0
  55. package/dist/drilldown/root/drilldown-root.css.js +27 -13
  56. package/dist/drilldown/root/drilldown-root.d.ts +10 -0
  57. package/dist/element-events.generated.js +72 -13
  58. package/dist/file-input/root/file-input-root.css.js +12 -11
  59. package/dist/file-input/root/file-input-root.d.ts +11 -0
  60. package/dist/filter-input/root/filter-input-root.css.js +6 -5
  61. package/dist/filter-input/root/filter-input-root.d.ts +5 -0
  62. package/dist/flex/root/flex-root.css.js +143 -9
  63. package/dist/flex/root/flex-root.d.ts +62 -5
  64. package/dist/flex/root/flex-root.js +17 -1
  65. package/dist/graph/root/graph-root.css.js +11 -8
  66. package/dist/graph/root/graph-root.d.ts +8 -0
  67. package/dist/grid/root/grid-root.css.js +114 -11
  68. package/dist/grid/root/grid-root.d.ts +40 -0
  69. package/dist/grid/root/grid-root.js +13 -1
  70. package/dist/heatmap/root/heatmap-root.css.js +2 -1
  71. package/dist/icon-button/root/icon-button-root.css.js +68 -13
  72. package/dist/icon-button/root/icon-button-root.d.ts +4 -0
  73. package/dist/kbd/root/kbd-root.css.js +27 -0
  74. package/dist/kbd/root/kbd-root.d.ts +2 -0
  75. package/dist/lightbox/item/lightbox-item.css.js +4 -0
  76. package/dist/lightbox/root/lightbox-root.css.js +41 -0
  77. package/dist/line-chart/root/line-chart-root.css.js +16 -0
  78. package/dist/line-chart/root/line-chart-root.d.ts +2 -0
  79. package/dist/list/item/list-item.css.js +21 -1
  80. package/dist/list/item/list-item.d.ts +3 -0
  81. package/dist/list/root/list-root.css.js +13 -1
  82. package/dist/listbox/root/listbox-root.css.js +9 -0
  83. package/dist/listbox/root/listbox-root.d.ts +1 -0
  84. package/dist/loader/root/loader-root.css.js +3 -3
  85. package/dist/loader/root/loader-root.d.ts +2 -0
  86. package/dist/megamenu/root/megamenu-root.css.js +16 -13
  87. package/dist/megamenu/root/megamenu-root.d.ts +11 -0
  88. package/dist/menu/index.d.ts +1 -0
  89. package/dist/menu/index.js +1 -0
  90. package/dist/menu/item/menu-item.css.js +39 -4
  91. package/dist/menu/item/menu-item.d.ts +4 -0
  92. package/dist/menu/item/menu-item.js +2 -0
  93. package/dist/menu/section/menu-section.css.d.ts +1 -0
  94. package/dist/menu/section/menu-section.css.js +14 -0
  95. package/dist/menu/section/menu-section.d.ts +24 -0
  96. package/dist/menu/section/menu-section.js +16 -0
  97. package/dist/meter/root/meter-root.css.js +6 -3
  98. package/dist/meter/root/meter-root.d.ts +1 -0
  99. package/dist/navigation/root/navigation-root.css.js +3 -2
  100. package/dist/navigation/root/navigation-root.d.ts +13 -0
  101. package/dist/notifications/root/notifications-root.css.js +30 -1
  102. package/dist/notifications/root/notifications-root.d.ts +1 -0
  103. package/dist/number-input/root/number-input-root.css.js +12 -9
  104. package/dist/number-input/root/number-input-root.d.ts +8 -0
  105. package/dist/object-inspector/root/object-inspector-root.css.js +38 -7
  106. package/dist/object-inspector/root/object-inspector-root.d.ts +4 -1
  107. package/dist/object-inspector/root/object-inspector-root.js +2 -1
  108. package/dist/option/root/option-root.css.js +1 -1
  109. package/dist/orb/index.d.ts +1 -1
  110. package/dist/orb/index.js +1 -1
  111. package/dist/orb/root/orb-root.d.ts +40 -6
  112. package/dist/orb/root/orb-root.js +29 -11
  113. package/dist/outline/root/outline-root.css.js +10 -0
  114. package/dist/outline/root/outline-root.d.ts +7 -0
  115. package/dist/pin-input/root/pin-input-root.css.js +4 -4
  116. package/dist/pin-input/root/pin-input-root.d.ts +4 -0
  117. package/dist/progress/root/progress-root.css.js +4 -2
  118. package/dist/progress/root/progress-root.d.ts +1 -0
  119. package/dist/qr-code/root/qr-code-root.css.js +11 -0
  120. package/dist/quote/root/quote-root.css.js +3 -0
  121. package/dist/quote/root/quote-root.d.ts +2 -0
  122. package/dist/radio/root/radio-root.css.js +16 -0
  123. package/dist/radio/root/radio-root.d.ts +2 -1
  124. package/dist/sandbox/frame.d.ts +64 -0
  125. package/dist/sandbox/frame.js +146 -0
  126. package/dist/sandbox/index.d.ts +2 -0
  127. package/dist/sandbox/index.js +1 -0
  128. package/dist/sandbox/levels.d.ts +10 -0
  129. package/dist/sandbox/levels.js +5 -0
  130. package/dist/sandbox/root/sandbox-root.d.ts +3 -0
  131. package/dist/sandbox/root/sandbox-root.js +13 -3
  132. package/dist/sandbox/source/sandbox-source.css.js +70 -0
  133. package/dist/sandbox/source/sandbox-source.d.ts +35 -0
  134. package/dist/sandbox/source/sandbox-source.js +22 -3
  135. package/dist/sandbox/terminal/sandbox-terminal.css.js +39 -0
  136. package/dist/sandbox/terminal/sandbox-terminal.d.ts +50 -1
  137. package/dist/sandbox/terminal/sandbox-terminal.js +61 -4
  138. package/dist/sandbox/tokens.d.ts +39 -0
  139. package/dist/sandbox/tokens.js +9 -0
  140. package/dist/scatter-chart/root/scatter-chart-root.css.js +9 -0
  141. package/dist/scatter-chart/root/scatter-chart-root.d.ts +2 -0
  142. package/dist/scroll-area/root/scroll-area-root.css.js +83 -1
  143. package/dist/scroll-area/root/scroll-area-root.d.ts +6 -0
  144. package/dist/skeleton/root/skeleton-root.css.js +11 -11
  145. package/dist/skeleton/root/skeleton-root.d.ts +1 -0
  146. package/dist/skip-link/root/skip-link-root.css.js +20 -8
  147. package/dist/skip-link/root/skip-link-root.d.ts +12 -3
  148. package/dist/slider/root/slider-root.css.js +26 -0
  149. package/dist/sparkline/root/sparkline-root.css.js +49 -0
  150. package/dist/sparkline/root/sparkline-root.d.ts +6 -0
  151. package/dist/sparkline/root/sparkline-root.js +2 -1
  152. package/dist/speed-dial/item/speed-dial-item.css.js +18 -10
  153. package/dist/speed-dial/item/speed-dial-item.d.ts +7 -0
  154. package/dist/speed-dial/root/speed-dial-root.css.js +17 -8
  155. package/dist/speed-dial/root/speed-dial-root.d.ts +16 -1
  156. package/dist/speed-dial/root/speed-dial-root.js +4 -1
  157. package/dist/stat/root/stat-root.css.js +4 -0
  158. package/dist/steps/root/steps-root.css.js +28 -0
  159. package/dist/steps/root/steps-root.d.ts +5 -0
  160. package/dist/steps/step/step.js +2 -1
  161. package/dist/table/root/table-root.css.js +18 -0
  162. package/dist/table/root/table-root.d.ts +6 -0
  163. package/dist/table/root/table-root.js +2 -0
  164. package/dist/table/row/table-row.css.js +18 -0
  165. package/dist/table/row/table-row.d.ts +2 -0
  166. package/dist/table/row/table-row.js +2 -0
  167. package/dist/tabs/panel/tab-panel.css.js +5 -1
  168. package/dist/tabs/root/tabs-root.css.js +58 -3
  169. package/dist/tabs/root/tabs-root.d.ts +4 -0
  170. package/dist/tabs/tab/tab.css.js +21 -10
  171. package/dist/tabs/tab/tab.d.ts +7 -0
  172. package/dist/tag/group/tag-group.css.js +6 -0
  173. package/dist/text/clamp.d.ts +11 -0
  174. package/dist/text/clamp.js +3 -0
  175. package/dist/text/root/text-root.css.js +79 -45
  176. package/dist/text/root/text-root.d.ts +49 -7
  177. package/dist/text/root/text-root.js +17 -11
  178. package/dist/textarea/root/textarea-root.css.js +27 -0
  179. package/dist/time-input/root/time-input-root.css.js +12 -0
  180. package/dist/time-picker/root/time-picker-root.css.js +1 -1
  181. package/dist/timeline/group/timeline-group.css.d.ts +1 -0
  182. package/dist/timeline/group/timeline-group.css.js +32 -0
  183. package/dist/timeline/group/timeline-group.d.ts +25 -0
  184. package/dist/timeline/group/timeline-group.js +16 -0
  185. package/dist/timeline/index.d.ts +1 -0
  186. package/dist/timeline/index.js +1 -0
  187. package/dist/timeline/item/timeline-item.css.js +43 -16
  188. package/dist/timeline/root/timeline-root.css.js +56 -0
  189. package/dist/timeline/root/timeline-root.d.ts +26 -0
  190. package/dist/timeline/root/timeline-root.js +7 -0
  191. package/dist/toast/item/toast-item.css.js +10 -0
  192. package/dist/toast/root/toast-root.d.ts +1 -0
  193. package/dist/toast/root/toast-root.js +1 -0
  194. package/dist/toggle/group/toggle-group.css.js +10 -7
  195. package/dist/toggle/group/toggle-group.d.ts +6 -1
  196. package/dist/toggle/root/toggle-root.d.ts +6 -0
  197. package/dist/toolbar/root/toolbar-root.css.js +4 -0
  198. package/dist/toolbar/root/toolbar-root.d.ts +5 -0
  199. package/dist/tooltip/root/tooltip-root.css.js +5 -5
  200. package/dist/tooltip/root/tooltip-root.d.ts +4 -0
  201. package/dist/tree/item/tree-item.css.js +89 -7
  202. package/dist/tree/item/tree-item.d.ts +19 -0
  203. package/dist/trend/root/trend-root.css.js +3 -5
  204. package/dist/trend/root/trend-root.d.ts +2 -2
  205. package/dist/video/root/video-root.css.js +6 -0
  206. package/dist/video/root/video-root.d.ts +3 -0
  207. package/dist/virtual-list/root/virtual-list-root.css.js +19 -0
  208. package/dist/virtual-list/root/virtual-list-root.d.ts +10 -3
  209. package/lint.json +1 -1
  210. package/package.json +9 -9
  211. package/types/jsx.d.ts +8253 -1233
  212. package/types/svelte.d.ts +2 -0
  213. package/types/vue.d.ts +2357 -312
@@ -9,7 +9,9 @@ import '../../copy-button/index.js';
9
9
  * The styled tier draws the tree in the Code Block frame. Keys and each type of
10
10
  * value take their colors from the syntax colors code blocks use. Each row is
11
11
  * one line, and a long string ends in an ellipsis, so every row has the same
12
- * height and a windowed tree does not measure rows one by one.
12
+ * height and a windowed tree does not measure rows one by one. A filter's
13
+ * matches take a tinted ground, and the filter field is a band of the same
14
+ * frame, under the label.
13
15
  *
14
16
  * @since 0.1.0
15
17
  * @status stable
@@ -21,6 +23,7 @@ import '../../copy-button/index.js';
21
23
  * @cssproperty --object-inspector-block-size - The height of the scrolling box when `windowed` is set.
22
24
  * @cssproperty --object-inspector-border-color - The color of the edge around the tree and its header.
23
25
  * @cssproperty --object-inspector-header-background-color - The background of the bar that holds the label.
26
+ * @cssproperty --object-inspector-match-background-color - The background of an entry a filter matched.
24
27
  * @cssproperty --object-inspector-radius - The corner radius of the tree.
25
28
  */
26
29
  export declare class HelixObjectInspector extends HelixHeadlessObjectInspector {
@@ -6,11 +6,12 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
6
6
  };
7
7
  import { customElement } from '@fusion.dev/helix-core';
8
8
  import { HelixHeadlessObjectInspector } from '@fusion.dev/helix-headless/object-inspector';
9
+ import { styles as liveStyles } from '../../shared/live/live.css.js';
9
10
  import { styles } from './object-inspector-root.css.js';
10
11
  import '../../copy-button/index.js';
11
12
  let HelixObjectInspector = class HelixObjectInspector extends HelixHeadlessObjectInspector {
12
13
  static { this.tier = 'helix-'; }
13
- static { this.styles = styles; }
14
+ static { this.styles = [liveStyles, styles]; }
14
15
  };
15
16
  HelixObjectInspector = __decorate([
16
17
  customElement('helix-object-inspector')
@@ -67,7 +67,7 @@ mask-repeat: no-repeat;
67
67
  mask-size: contain;
68
68
  }
69
69
 
70
- :host([data-active]) [part~="item"],
70
+ :host(:state(active)) [part~="item"],
71
71
  :host(:not([disabled])) [part~="item"]:hover {
72
72
 
73
73
  background-color: var(
@@ -1,2 +1,2 @@
1
1
  export * from './root/orb-root.js';
2
- export * from './shapes.js';
2
+ export { ORB_STATES, type OrbState } from './shapes.js';
package/dist/orb/index.js CHANGED
@@ -1,2 +1,2 @@
1
1
  export * from './root/orb-root.js';
2
- export * from './shapes.js';
2
+ export { ORB_STATES } from './shapes.js';
@@ -31,11 +31,16 @@ import { type OrbState } from '../shapes.js';
31
31
  * `prefers-reduced-motion`, it draws one still frame.
32
32
  *
33
33
  * The orb is styled only and has behavior, which the tier split does not
34
- * otherwise allow. Its role, name and busy state follow `state`, and the rest
34
+ * otherwise allow. Its role, name and busy state follow `state`, unless
35
+ * `announce` makes it a status region, and the rest
35
36
  * is drawing dots to a canvas, so there is no structure to restyle. For a
36
37
  * drawing of your own, the headless `Loader` holds the same busy progress bar
37
38
  * and its name.
38
39
  *
40
+ * Each state is also a custom state, such as `:state(thinking)` or
41
+ * `:state(done)`, so a page can style what sits around an orb by what it shows,
42
+ * whether the state was written as an attribute or set from script.
43
+ *
39
44
  * @since 0.8.0
40
45
  * @status stable
41
46
  * @category feedback
@@ -43,13 +48,36 @@ import { type OrbState } from '../shapes.js';
43
48
  * @documentation https://fusion.dev/helix/components/orb
44
49
  *
45
50
  * @csspart canvas - The canvas the dots are drawn on.
51
+ * @csspart live - The word for the state, which the orb says as it changes when `announce` is set. Rendered only then, and clipped out of view.
46
52
  *
47
53
  * @cssproperty --orb-color - The color of the nearest dots. Defaults to `currentColor`.
48
54
  * @cssproperty --orb-ground - The color the farthest dots fade toward. Defaults to the page's background.
49
55
  * @cssproperty --orb-size - The diameter. Overrides `size`.
56
+ *
57
+ * @cssstate connecting - The orb shows `connecting`.
58
+ * @cssstate done - The orb shows `done`.
59
+ * @cssstate fetching - The orb shows `fetching`.
60
+ * @cssstate listening - The orb shows `listening`.
61
+ * @cssstate thinking - The orb shows `thinking`, which is also what a state it does not draw shows.
62
+ * @cssstate waiting - The orb shows `waiting`.
63
+ * @cssstate working - The orb shows `working`.
50
64
  */
51
65
  export declare class HelixOrb extends HelixElement {
52
66
  static styles: CSSResultGroup;
67
+ /**
68
+ * Says each new state politely, such as "Working" and then "Done".
69
+ *
70
+ * **The orb becomes the live region**: its role is `status` rather than
71
+ * `progressbar` or `img`, and it holds the state's word. A region inside a
72
+ * progress bar or an image may never be heard, because assistive technology
73
+ * treats what those two hold as presentation. The name is still `label` or
74
+ * the state's word.
75
+ *
76
+ * Off by default, because the name and the busy state already change with
77
+ * the state, and an orb beside a stream of messages would otherwise talk
78
+ * over them. Set it on an orb that is the only sign of progress on the page.
79
+ */
80
+ announce: boolean;
53
81
  /**
54
82
  * The name read by screen readers. Defaults to the name of the state, such
55
83
  * as "Thinking".
@@ -82,16 +110,18 @@ export declare class HelixOrb extends HelixElement {
82
110
  * verb we have not made a shape for should cost a reader a less specific
83
111
  * indicator, not an empty box where the indicator was.
84
112
  *
85
- * Not reflected: no rule selects on it, because the state is drawn rather than
86
- * styled. A consumer writing the attribute can still select on their own
87
- * markup.
113
+ * Not reflected, because a state set from script would then write an
114
+ * attribute onto the host after a server sent it without one. Each state is
115
+ * a custom state instead, such as `:state(working)`.
88
116
  */
89
117
  state: OrbState;
90
118
  /**
91
119
  * The word for each state, for a page in another language.
92
120
  *
93
- * A state left out keeps its English word, and `label` wins over both. It is
94
- * a property with no attribute, keyed by state, such as `{ thinking: '…' }`.
121
+ * A state left out keeps its English word, and `label` wins over both.
122
+ * Keyed by state, such as `{ thinking: '…' }`. As an attribute it is that
123
+ * object as JSON, such as `state-labels='{"done":"Terminé"}'`, so server
124
+ * markup and plain HTML can carry the words too.
95
125
  */
96
126
  stateLabels: Partial<Record<OrbState, string>>;
97
127
  private canvas;
@@ -135,6 +165,10 @@ export declare class HelixOrb extends HelixElement {
135
165
  */
136
166
  private phase;
137
167
  protected willUpdate(changed: PropertyValues): void;
168
+ /** The state drawn: `state`, or `thinking` for one it does not draw. */
169
+ private get shown();
170
+ /** The word for the state drawn, in the page's words where it gave them. */
171
+ private get word();
138
172
  protected render(): TemplateResult;
139
173
  protected firstUpdated(changed: PropertyValues): void;
140
174
  connectedCallback(): void;
@@ -4,9 +4,10 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
4
4
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
5
  return c > 3 && r && Object.defineProperty(target, key, r), r;
6
6
  };
7
- import { customElement, HelixElement, hostAria, PaintGateController, readColor, } from '@fusion.dev/helix-core';
8
- import { html } from 'lit';
7
+ import { customElement, HelixElement, hostAria, PaintGateController, readColor, wordsConverter, } from '@fusion.dev/helix-core';
8
+ import { html, nothing } from 'lit';
9
9
  import { property } from 'lit/decorators.js';
10
+ import { styles as liveStyles } from '../../shared/live/live.css.js';
10
11
  import { blendStaged, evenSphere, fibonacci, meshFor, ORB_STATES, orbPoint, paramsFor, project, smoother, stateDistance, TRAIL, } from '../shapes.js';
11
12
  import { styles } from './orb-root.css.js';
12
13
  const MORPH_NEAR = 380;
@@ -26,6 +27,7 @@ const GRAY = [128, 128, 128];
26
27
  let HelixOrb = class HelixOrb extends HelixElement {
27
28
  constructor() {
28
29
  super(...arguments);
30
+ this.announce = false;
29
31
  this.label = '';
30
32
  this.state = 'thinking';
31
33
  this.stateLabels = {};
@@ -67,23 +69,36 @@ let HelixOrb = class HelixOrb extends HelixElement {
67
69
  this.gate.play();
68
70
  };
69
71
  }
70
- static { this.styles = styles; }
72
+ static { this.styles = [liveStyles, styles]; }
71
73
  willUpdate(changed) {
72
74
  super.willUpdate(changed);
73
- const state = ORB_STATES.includes(this.state)
74
- ? this.state
75
- : 'thinking';
75
+ const state = this.shown;
76
76
  hostAria(this.internals, {
77
- label: this.label || this.stateLabels[state] || LABELS[state],
78
- role: state === 'done' ? 'img' : 'progressbar',
77
+ label: this.label || this.word,
78
+ role: this.announce ? 'status' : state === 'done' ? 'img' : 'progressbar',
79
79
  });
80
- this.internals.ariaBusy = state === 'done' ? 'false' : 'true';
80
+ this.internals.ariaBusy = this.announce ? null : state === 'done' ? 'false' : 'true';
81
+ this.toggleState('connecting', state === 'connecting');
82
+ this.toggleState('done', state === 'done');
83
+ this.toggleState('fetching', state === 'fetching');
84
+ this.toggleState('listening', state === 'listening');
85
+ this.toggleState('thinking', state === 'thinking');
86
+ this.toggleState('waiting', state === 'waiting');
87
+ this.toggleState('working', state === 'working');
81
88
  if (changed.has('state') && changed.get('state') !== undefined) {
82
89
  this.turn();
83
90
  }
84
91
  }
92
+ get shown() {
93
+ return ORB_STATES.includes(this.state)
94
+ ? this.state
95
+ : 'thinking';
96
+ }
97
+ get word() {
98
+ return this.stateLabels?.[this.shown] || LABELS[this.shown];
99
+ }
85
100
  render() {
86
- return html `<canvas part="canvas" aria-hidden="true"></canvas>`;
101
+ return html `<canvas part="canvas" aria-hidden="true"></canvas>${this.announce ? html `<span part="live">${this.word}</span>` : nothing}`;
87
102
  }
88
103
  firstUpdated(changed) {
89
104
  super.firstUpdated(changed);
@@ -236,6 +251,9 @@ let HelixOrb = class HelixOrb extends HelixElement {
236
251
  }
237
252
  }
238
253
  };
254
+ __decorate([
255
+ property({ type: Boolean })
256
+ ], HelixOrb.prototype, "announce", void 0);
239
257
  __decorate([
240
258
  property()
241
259
  ], HelixOrb.prototype, "label", void 0);
@@ -246,7 +264,7 @@ __decorate([
246
264
  property()
247
265
  ], HelixOrb.prototype, "state", void 0);
248
266
  __decorate([
249
- property({ attribute: false })
267
+ property({ attribute: 'state-labels', converter: wordsConverter })
250
268
  ], HelixOrb.prototype, "stateLabels", void 0);
251
269
  HelixOrb = __decorate([
252
270
  customElement('helix-orb')
@@ -123,6 +123,16 @@ var(--outline-indent, var(--helix-space-sm))
123
123
  );
124
124
  }
125
125
 
126
+ ::slotted([slot="heading"]) {
127
+ color: var(--helix-color-foreground);
128
+ font-size: var(--helix-text-xs);
129
+ font-weight: var(--helix-weight-semibold);
130
+ line-height: var(--helix-leading-normal);
131
+ margin-block: 0 var(--helix-space-xs);
132
+ margin-inline: 0;
133
+ padding-inline-start: calc(var(--outline-rail) + var(--helix-space-sm));
134
+ }
135
+
126
136
  @media print {
127
137
  :host {
128
138
  print-color-adjust: economy;
@@ -12,6 +12,13 @@ import type { CSSResultGroup } from 'lit';
12
12
  * `data-level` is at the top level. The outline does not read heading levels
13
13
  * from the document, because the headings are not always in the document.
14
14
  *
15
+ * Links in a nested `<ul>` take their indentation from your own stylesheet:
16
+ * the outline's styles reach the elements slotted into it and nothing inside
17
+ * them. Write the links flat with `data-level` for the indentation drawn here,
18
+ * and screen readers still hear them as nested lists.
19
+ *
20
+ * A heading slotted into `heading` is set above the links, lined up with them.
21
+ *
15
22
  * @since 0.1.0
16
23
  * @status stable
17
24
  * @category navigation
@@ -19,9 +19,9 @@ border: var(--helix-border-thin) solid
19
19
  var(--pin-input-cell-border-color, var(--helix-color-border));
20
20
  border-radius: var(--pin-input-cell-radius, var(--helix-radii-sm));
21
21
  box-sizing: border-box;
22
- color: var(--helix-color-foreground);
22
+ color: var(--pin-input-cell-color, var(--helix-color-foreground));
23
23
  font-family: var(--helix-font-sans);
24
- font-size: var(--helix-text-lg);
24
+ font-size: var(--pin-input-cell-font-size, var(--helix-text-lg));
25
25
 
26
26
  font-variant-numeric: tabular-nums;
27
27
  font-weight: var(--helix-weight-medium);
@@ -35,7 +35,7 @@ border-color: var(--helix-color-foreground-muted);
35
35
  }
36
36
 
37
37
  [part="cell"]:focus-visible {
38
- border-color: var(--helix-color-primary);
38
+ border-color: var(--pin-input-cell-border-color-focus, var(--helix-color-primary));
39
39
  outline: var(--helix-size-focus-ring) solid var(--helix-color-focus-ring);
40
40
  outline-offset: 0;
41
41
  }
@@ -59,7 +59,7 @@ font-size: var(--helix-text-xl);
59
59
 
60
60
  [part="separator"] {
61
61
  align-self: center;
62
- color: var(--helix-color-foreground-muted);
62
+ color: var(--pin-input-separator-color, var(--helix-color-foreground-muted));
63
63
  font-size: var(--helix-text-lg);
64
64
  }
65
65
 
@@ -25,9 +25,13 @@ import type { CSSResultGroup } from 'lit';
25
25
  *
26
26
  * @cssproperty --pin-input-cell-background-color - Fill behind each box.
27
27
  * @cssproperty --pin-input-cell-border-color - Edge of each box at rest. Hover, focus and an error still draw their own.
28
+ * @cssproperty --pin-input-cell-border-color-focus - Edge of the box holding focus.
29
+ * @cssproperty --pin-input-cell-color - The color of a typed character.
30
+ * @cssproperty --pin-input-cell-font-size - The size of a typed character.
28
31
  * @cssproperty --pin-input-cell-radius - Corner radius of each box.
29
32
  * @cssproperty --pin-input-cell-size - Width and height of each box.
30
33
  * @cssproperty --pin-input-gap - The space between one box and the next.
34
+ * @cssproperty --pin-input-separator-color - The color of the text `format` draws between boxes.
31
35
  */
32
36
  export declare class HelixPinInput extends HelixHeadlessPinInput {
33
37
  static styles: CSSResultGroup;
@@ -55,7 +55,8 @@ border-radius: inherit;
55
55
  inline-size: 100%;
56
56
  scale: var(--progress-fraction, 0) 1;
57
57
  transform-origin: left center;
58
- transition: scale var(--helix-duration-normal) var(--helix-easing-decelerate);
58
+ transition: scale var(--progress-transition-duration, var(--helix-duration-normal))
59
+ var(--helix-easing-decelerate);
59
60
  }
60
61
 
61
62
  :host(:dir(rtl)) [part="indicator"] {
@@ -150,7 +151,8 @@ scale: none;
150
151
  stroke: var(--progress-color, var(--helix-color-primary));
151
152
  stroke-dasharray: calc(var(--progress-fraction) * 100) 100;
152
153
  stroke-linecap: round;
153
- transition: stroke-dasharray var(--helix-duration-normal) var(--helix-easing-decelerate);
154
+ transition: stroke-dasharray var(--progress-transition-duration, var(--helix-duration-normal))
155
+ var(--helix-easing-decelerate);
154
156
  }
155
157
 
156
158
  :host([shape="ring"][show-value]) {
@@ -28,6 +28,7 @@ import type { CSSResultGroup } from 'lit';
28
28
  * @cssproperty --progress-ring-width - Thickness of the ring's stroke.
29
29
  * @cssproperty --progress-size - Thickness of the bar.
30
30
  * @cssproperty --progress-track-color - Fill of the part that is not done.
31
+ * @cssproperty --progress-transition-duration - How long the fill takes to move to a new value. `0s` moves it at once.
31
32
  */
32
33
  export declare class HelixProgress extends HelixHeadlessProgress {
33
34
  /**
@@ -17,6 +17,17 @@ display: block;
17
17
  inline-size: 100%;
18
18
  }
19
19
 
20
+ [part="fallback"] {
21
+ align-items: center;
22
+ block-size: 100%;
23
+ box-sizing: border-box;
24
+ display: flex;
25
+ justify-content: center;
26
+ overflow-wrap: anywhere;
27
+ padding: var(--helix-space-md);
28
+ text-align: center;
29
+ }
30
+
20
31
  [part="finders"] {
21
32
  fill: var(--qr-code-finder-color, currentColor);
22
33
  }
@@ -8,7 +8,10 @@ font: inherit;
8
8
 
9
9
  color: var(--quote-color, var(--helix-color-foreground-muted));
10
10
  font: inherit;
11
+
12
+ font-family: var(--quote-font-family, inherit);
11
13
  font-style: var(--quote-font-style, italic);
14
+ font-weight: var(--quote-font-weight, inherit);
12
15
  }
13
16
 
14
17
  @media print {
@@ -14,7 +14,9 @@ import type { CSSResultGroup } from 'lit';
14
14
  * @documentation https://fusion.dev/helix/components/quote
15
15
  *
16
16
  * @cssproperty --quote-color - Color of the quoted text.
17
+ * @cssproperty --quote-font-family - The typeface of the quoted text, the paragraph's own by default.
17
18
  * @cssproperty --quote-font-style - The slant of the quoted text, `italic` by default. Set `normal` for a face whose italic is too loud, or `oblique` for one with no italic of its own.
19
+ * @cssproperty --quote-font-weight - The weight of the quoted text, the paragraph's own by default.
18
20
  */
19
21
  export declare class HelixQuote extends HelixHeadlessQuote {
20
22
  static styles: CSSResultGroup;
@@ -58,6 +58,22 @@ transition: scale var(--helix-duration-fast) var(--helix-easing-emphasized);
58
58
  scale: 1;
59
59
  }
60
60
 
61
+ :host(:state(has-indicator)) [part="box"]::after {
62
+ content: none;
63
+ }
64
+
65
+ slot[name="indicator"]::slotted(*) {
66
+ block-size: var(--radio-indicator-size, calc(var(--_radio-size) * 0.75));
67
+ color: var(--radio-mark-color, var(--helix-color-foreground));
68
+ inline-size: var(--radio-indicator-size, calc(var(--_radio-size) * 0.75));
69
+ scale: 0;
70
+ transition: scale var(--helix-duration-fast) var(--helix-easing-emphasized);
71
+ }
72
+
73
+ :host(:state(selected)) slot[name="indicator"]::slotted(*) {
74
+ scale: 1;
75
+ }
76
+
61
77
  [part="item"]:focus-visible [part="box"] {
62
78
  outline: var(--helix-size-focus-ring) solid var(--helix-color-focus-ring);
63
79
  outline-offset: var(--helix-size-focus-offset);
@@ -23,7 +23,8 @@ import type { CSSResultGroup } from 'lit';
23
23
  * @cssproperty --radio-card-border-color - The border color of a card-shaped choice.
24
24
  * @cssproperty --radio-card-padding - The padding inside a card-shaped choice.
25
25
  * @cssproperty --radio-chip-size - The diameter of a chip.
26
- * @cssproperty --radio-mark-color - The color of the dot.
26
+ * @cssproperty --radio-indicator-size - The width and height of an icon slotted into `indicator`. Three quarters of the circle by default.
27
+ * @cssproperty --radio-mark-color - The color of the dot, or of an icon slotted into `indicator`.
27
28
  * @cssproperty --radio-size - The diameter of the circle.
28
29
  */
29
30
  export declare class HelixRadio extends HelixHeadlessRadio {
@@ -0,0 +1,64 @@
1
+ import type { PreviewRender } from './preview/sandbox-preview.js';
2
+ /** How `servePreview` serves a frame document. */
3
+ export interface ServePreviewOptions {
4
+ /**
5
+ * The element each example is written into. Defaults to `#preview-root`,
6
+ * and to the body where there is none.
7
+ */
8
+ root?: HTMLElement;
9
+ /**
10
+ * Whether the frame adds the rules for the four `layout` values, `padded`,
11
+ * `centered`, `hug` and `fullscreen`, to its own head. Defaults to `true`.
12
+ * Set `false` where your frame's stylesheet places the root itself.
13
+ */
14
+ layouts?: boolean;
15
+ /** Called before new markup replaces the old, to take down what it mounted. */
16
+ onReplace?: (root: HTMLElement) => void;
17
+ /** Called after each render, with whether the markup was new or only restyled. */
18
+ onRender?: (root: HTMLElement, fresh: boolean) => void;
19
+ }
20
+ /**
21
+ * The rules that place the root for each `layout` a preview sends.
22
+ *
23
+ * `centered` gives the example a measure and centers that box, and `hug`
24
+ * shrinks each top-level child to its own content and centers it, which is
25
+ * the difference for a component whose root is a full-width block. They
26
+ * select the root by its `data-preview-root` attribute, so they reach nothing
27
+ * an example draws inside it. The three that fill the viewport count their
28
+ * padding inside that height, so the root never overflows the frame.
29
+ */
30
+ export declare const LAYOUT_RULES = "\n:root { --preview-measure: 48rem; }\n[data-preview-root][data-layout=\"padded\"] { padding: var(--helix-space-lg, 1.5rem); }\n[data-preview-root][data-layout=\"centered\"], [data-preview-root][data-layout=\"hug\"] {\n align-content: center; box-sizing: border-box; display: block;\n inline-size: min(100%, var(--preview-measure)); margin-inline: auto; min-block-size: 100dvh;\n padding: var(--helix-space-lg, 1.5rem);\n}\n[data-preview-root][data-layout=\"centered\"] { text-align: center; }\n[data-preview-root][data-layout=\"centered\"] > * { margin-inline: auto; text-align: start; }\n[data-preview-root][data-layout=\"hug\"] > * {\n inline-size: fit-content; margin-inline: auto; max-inline-size: 100%;\n}\n[data-preview-root][data-layout=\"fullscreen\"] { box-sizing: border-box; min-block-size: 100dvh; padding: 0; }\n";
31
+ /** Whether `data` is a render message, as the preview sends one. */
32
+ export declare const isRender: (data: unknown) => data is PreviewRender;
33
+ /**
34
+ * The markup an example renders, without the stylesheet links it carries.
35
+ *
36
+ * An example that needs CSS says so the way a consumer would, with a `<link>`
37
+ * beside it, and the stylesheet arrives in the render message already read.
38
+ * The frame is on an opaque origin, so a request for the link would fail and
39
+ * log an error into the reader's console on every render.
40
+ */
41
+ export declare const withoutStylesheets: (source: string) => string;
42
+ /** A logged value as text, without throwing on a cycle. */
43
+ export declare const loggedText: (value: unknown) => string;
44
+ /**
45
+ * Serves the frame side of a sandbox preview, in the document its `src` loads.
46
+ *
47
+ * Call it once from that document, after the elements your examples use are
48
+ * defined. It does what the preview's protocol asks of a frame:
49
+ *
50
+ * - Posts `helix-preview-ready` once it listens.
51
+ * - Writes each `helix-preview-render` into the root: the markup, the
52
+ * stylesheet, the direction, the layout and the color mode. Scripts in the
53
+ * markup run.
54
+ * - Posts every console call and uncaught error as `helix-preview-console`.
55
+ * - Posts `helix-preview-size` whenever what was drawn changes height.
56
+ * - Posts `helix-preview-press` on every press, so menus outside close.
57
+ *
58
+ * Only a message from the parent window is rendered. Answers go to `*`, which
59
+ * is the only target a sandboxed frame can name, and carry only what the
60
+ * example itself wrote.
61
+ *
62
+ * @returns A function that stops serving and puts the console back.
63
+ */
64
+ export declare const servePreview: (options?: ServePreviewOptions) => (() => void);
@@ -0,0 +1,146 @@
1
+ export const LAYOUT_RULES = `
2
+ :root { --preview-measure: 48rem; }
3
+ [data-preview-root][data-layout="padded"] { padding: var(--helix-space-lg, 1.5rem); }
4
+ [data-preview-root][data-layout="centered"], [data-preview-root][data-layout="hug"] {
5
+ align-content: center; box-sizing: border-box; display: block;
6
+ inline-size: min(100%, var(--preview-measure)); margin-inline: auto; min-block-size: 100dvh;
7
+ padding: var(--helix-space-lg, 1.5rem);
8
+ }
9
+ [data-preview-root][data-layout="centered"] { text-align: center; }
10
+ [data-preview-root][data-layout="centered"] > * { margin-inline: auto; text-align: start; }
11
+ [data-preview-root][data-layout="hug"] > * {
12
+ inline-size: fit-content; margin-inline: auto; max-inline-size: 100%;
13
+ }
14
+ [data-preview-root][data-layout="fullscreen"] { box-sizing: border-box; min-block-size: 100dvh; padding: 0; }
15
+ `;
16
+ export const isRender = (data) => typeof data === 'object' &&
17
+ data !== null &&
18
+ data.type === 'helix-preview-render';
19
+ export const withoutStylesheets = (source) => source.replace(/<link\b[^>]*\brel=(["'])stylesheet\1[^>]*>\s*/gi, '');
20
+ export const loggedText = (value) => {
21
+ if (typeof value === 'string') {
22
+ return value;
23
+ }
24
+ try {
25
+ return JSON.stringify(value) ?? String(value);
26
+ }
27
+ catch {
28
+ return String(value);
29
+ }
30
+ };
31
+ const runScripts = (root) => {
32
+ for (const original of [...root.querySelectorAll('script')]) {
33
+ const script = document.createElement('script');
34
+ for (const { name, value } of original.attributes) {
35
+ script.setAttribute(name, value);
36
+ }
37
+ if (!script.type) {
38
+ script.type = 'module';
39
+ }
40
+ script.text = original.text;
41
+ original.replaceWith(script);
42
+ }
43
+ };
44
+ const drawn = (child) => {
45
+ const own = child.getBoundingClientRect();
46
+ if (own.width > 0 || own.height > 0) {
47
+ return [own];
48
+ }
49
+ return [...child.querySelectorAll('*')]
50
+ .filter((node) => getComputedStyle(node).position !== 'fixed')
51
+ .map((node) => node.getBoundingClientRect())
52
+ .filter((box) => box.width > 0 || box.height > 0);
53
+ };
54
+ export const servePreview = (options = {}) => {
55
+ const root = options.root ?? document.getElementById('preview-root') ?? document.body;
56
+ root.toggleAttribute('data-preview-root', true);
57
+ root.dataset.layout ??= 'padded';
58
+ if (options.layouts !== false) {
59
+ const rules = document.createElement('style');
60
+ rules.textContent = LAYOUT_RULES;
61
+ document.head.prepend(rules);
62
+ }
63
+ const post = (message) => window.parent?.postMessage(message, '*');
64
+ const levels = ['log', 'info', 'warn', 'error'];
65
+ const originals = levels.map((level) => console[level]);
66
+ for (const level of levels) {
67
+ const original = console[level];
68
+ console[level] = (...args) => {
69
+ original(...args);
70
+ post({ level, text: args.map(loggedText).join(' '), type: 'helix-preview-console' });
71
+ };
72
+ }
73
+ const failed = (event) => {
74
+ post({ level: 'error', text: event.message, type: 'helix-preview-console' });
75
+ };
76
+ const measure = () => {
77
+ const boxes = [...root.children].flatMap(drawn);
78
+ if (boxes.length === 0) {
79
+ return;
80
+ }
81
+ const top = Math.min(...boxes.map((box) => box.top));
82
+ const bottom = Math.max(...boxes.map((box) => box.bottom));
83
+ const style = getComputedStyle(root);
84
+ const padding = (Number.parseFloat(style.paddingBlockStart) || 0) +
85
+ (Number.parseFloat(style.paddingBlockEnd) || 0);
86
+ post({ size: Math.ceil(bottom - top + padding), type: 'helix-preview-size' });
87
+ };
88
+ let rendered;
89
+ const render = (event) => {
90
+ if (!isRender(event.data) || event.source !== window.parent) {
91
+ return;
92
+ }
93
+ const { colorMode, direction = 'ltr', layout = 'padded', source = '', styles = '' } = event.data;
94
+ document.documentElement.dir = direction;
95
+ root.dataset.layout = layout;
96
+ if (colorMode) {
97
+ document.documentElement.dataset.colorMode = colorMode;
98
+ document.documentElement.style.colorScheme = colorMode;
99
+ }
100
+ const fresh = source !== rendered;
101
+ if (fresh) {
102
+ options.onReplace?.(root);
103
+ root.innerHTML = withoutStylesheets(source);
104
+ runScripts(root);
105
+ rendered = source;
106
+ }
107
+ let sheet = document.getElementById('preview-styles');
108
+ if (!sheet) {
109
+ sheet = document.createElement('style');
110
+ sheet.id = 'preview-styles';
111
+ document.head.append(sheet);
112
+ }
113
+ sheet.textContent = styles;
114
+ options.onRender?.(root, fresh);
115
+ measure();
116
+ };
117
+ const watcher = new ResizeObserver(measure);
118
+ const watch = () => {
119
+ watcher.disconnect();
120
+ watcher.observe(root);
121
+ for (const child of root.children) {
122
+ const placed = getComputedStyle(child).display === 'contents' ? child.children : [child];
123
+ for (const box of placed) {
124
+ watcher.observe(box);
125
+ }
126
+ }
127
+ };
128
+ const children = new MutationObserver(watch);
129
+ children.observe(root, { childList: true });
130
+ watch();
131
+ const press = () => post({ type: 'helix-preview-press' });
132
+ window.addEventListener('error', failed);
133
+ window.addEventListener('message', render);
134
+ document.addEventListener('pointerdown', press, { capture: true, passive: true });
135
+ post({ type: 'helix-preview-ready' });
136
+ return () => {
137
+ levels.forEach((level, index) => {
138
+ console[level] = originals[index];
139
+ });
140
+ watcher.disconnect();
141
+ children.disconnect();
142
+ window.removeEventListener('error', failed);
143
+ window.removeEventListener('message', render);
144
+ document.removeEventListener('pointerdown', press, { capture: true });
145
+ };
146
+ };
@@ -12,9 +12,11 @@
12
12
  * hardcodes `sandbox="allow-scripts allow-forms"` on its frame and never
13
13
  * `allow-same-origin`, which is the pairing that would undo it.
14
14
  */
15
+ export { isRender, LAYOUT_RULES, loggedText, type ServePreviewOptions, servePreview, withoutStylesheets, } from './frame.js';
15
16
  export * from './preview/sandbox-preview.js';
16
17
  export * from './root/sandbox-root.js';
17
18
  export * from './source/sandbox-source.js';
18
19
  export * from './status-bar/sandbox-status-bar.js';
19
20
  export * from './terminal/sandbox-terminal.js';
21
+ export type { SandboxHighlight, SandboxToken } from './tokens.js';
20
22
  export * from './toolbar/sandbox-toolbar.js';
@@ -1,3 +1,4 @@
1
+ export { isRender, LAYOUT_RULES, loggedText, servePreview, withoutStylesheets, } from './frame.js';
1
2
  export * from './preview/sandbox-preview.js';
2
3
  export * from './root/sandbox-root.js';
3
4
  export * from './source/sandbox-source.js';
@@ -0,0 +1,10 @@
1
+ import type { ConsoleDetail } from '@fusion.dev/helix-core';
2
+ /** A console level, from the quietest to the loudest. */
3
+ export type ConsoleLevel = ConsoleDetail['level'];
4
+ /** The four levels in order, the quietest first. */
5
+ export declare const LEVELS: readonly ConsoleLevel[];
6
+ /**
7
+ * Whether a line at `level` shows under a terminal's `level`, which is the
8
+ * quietest it shows. No floor, or one that names no level, shows every line.
9
+ */
10
+ export declare const shows: (level: ConsoleLevel, floor: string | undefined) => boolean;