@fusion.dev/helix 0.143.0 → 0.145.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 (211) hide show
  1. package/custom-elements.json +19817 -1238
  2. package/dist/accordion/item/accordion-item.css.js +14 -3
  3. package/dist/accordion/item/accordion-item.d.ts +2 -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 +24 -3
  7. package/dist/aura/root/aura-root.d.ts +42 -7
  8. package/dist/aura/root/aura-root.js +31 -25
  9. package/dist/badge/root/badge-root.css.js +35 -0
  10. package/dist/badge/root/badge-root.d.ts +16 -0
  11. package/dist/badge/root/badge-root.js +3 -0
  12. package/dist/blockquote/root/blockquote-root.css.js +5 -5
  13. package/dist/blockquote/root/blockquote-root.d.ts +5 -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 +1 -1
  17. package/dist/breadcrumbs/root/breadcrumbs-root.d.ts +3 -0
  18. package/dist/breadcrumbs/root/breadcrumbs-root.js +2 -0
  19. package/dist/button/root/button-root.css.js +38 -1
  20. package/dist/button/root/button-root.d.ts +5 -0
  21. package/dist/button/root/button-root.js +2 -1
  22. package/dist/button-group/root/button-group-root.d.ts +3 -0
  23. package/dist/callout/root/callout-root.css.js +69 -11
  24. package/dist/callout/root/callout-root.d.ts +25 -2
  25. package/dist/callout/root/callout-root.js +4 -0
  26. package/dist/canvas/root/canvas-root.css.js +1 -0
  27. package/dist/card/root/card-root.css.js +26 -1
  28. package/dist/card/root/card-root.d.ts +11 -0
  29. package/dist/carousel/root/carousel-root.css.js +17 -1
  30. package/dist/checkbox-group/root/checkbox-group-root.d.ts +2 -0
  31. package/dist/checkbox-group/root/checkbox-group-root.js +2 -0
  32. package/dist/code-block/root/code-block-root.css.js +23 -0
  33. package/dist/code-block/root/code-block-root.d.ts +15 -0
  34. package/dist/code-block/root/code-block-root.js +8 -0
  35. package/dist/color-picker/root/color-picker-root.css.js +64 -0
  36. package/dist/color-picker/root/color-picker-root.d.ts +2 -0
  37. package/dist/copy-button/root/copy-button-root.css.js +5 -0
  38. package/dist/data-table/root/data-table-root.css.js +63 -0
  39. package/dist/data-table/root/data-table-root.d.ts +1 -0
  40. package/dist/date-input/root/date-input-root.css.js +19 -0
  41. package/dist/date-input/root/date-input-root.d.ts +8 -0
  42. package/dist/date-input/root/date-input-root.js +2 -0
  43. package/dist/date-picker/root/date-picker-root.css.js +68 -0
  44. package/dist/date-picker/root/date-picker-root.d.ts +1 -0
  45. package/dist/description-list/item/description-list-item.css.js +11 -0
  46. package/dist/dialog/root/dialog-root.css.js +47 -0
  47. package/dist/divider/root/divider-root.css.js +8 -3
  48. package/dist/divider/root/divider-root.d.ts +17 -1
  49. package/dist/divider/root/divider-root.js +4 -0
  50. package/dist/drawer/root/drawer-root.css.js +28 -1
  51. package/dist/drilldown/item/drilldown-item.css.js +2 -1
  52. package/dist/drilldown/root/drilldown-root.css.js +2 -1
  53. package/dist/element-events.generated.js +66 -14
  54. package/dist/empty/root/empty-root.css.js +9 -9
  55. package/dist/empty/root/empty-root.d.ts +9 -0
  56. package/dist/file-input/root/file-input-root.js +2 -0
  57. package/dist/filter-input/root/filter-input-root.js +2 -0
  58. package/dist/flex/root/flex-root.css.js +134 -9
  59. package/dist/flex/root/flex-root.d.ts +51 -5
  60. package/dist/flex/root/flex-root.js +17 -1
  61. package/dist/grid/root/grid-root.css.js +114 -11
  62. package/dist/grid/root/grid-root.d.ts +37 -0
  63. package/dist/grid/root/grid-root.js +13 -1
  64. package/dist/heatmap/root/heatmap-root.css.js +33 -5
  65. package/dist/heatmap/root/heatmap-root.d.ts +4 -1
  66. package/dist/icon/index.d.ts +1 -0
  67. package/dist/icon/index.js +1 -0
  68. package/dist/icon/root/icon-root.d.ts +1 -1
  69. package/dist/icon/root/icon-root.js +1 -1
  70. package/dist/icon/root/index.d.ts +2 -0
  71. package/dist/icon/root/index.js +2 -0
  72. package/dist/icon-button/root/icon-button-root.css.js +37 -0
  73. package/dist/icon-button/root/icon-button-root.d.ts +4 -0
  74. package/dist/icon-button/root/icon-button-root.js +2 -1
  75. package/dist/input/root/input-root.css.js +3 -3
  76. package/dist/input/root/input-root.d.ts +3 -0
  77. package/dist/legend/root/legend-root.css.js +40 -13
  78. package/dist/legend/root/legend-root.d.ts +6 -0
  79. package/dist/legend/root/legend-root.js +1 -1
  80. package/dist/lightbox/root/lightbox-root.css.js +84 -0
  81. package/dist/lightbox/root/lightbox-root.d.ts +1 -0
  82. package/dist/list/item/list-item.css.js +21 -1
  83. package/dist/list/item/list-item.d.ts +3 -0
  84. package/dist/list/root/list-root.css.js +13 -1
  85. package/dist/loader/root/loader-root.css.js +10 -0
  86. package/dist/loader/root/loader-root.d.ts +3 -0
  87. package/dist/menu/index.d.ts +1 -0
  88. package/dist/menu/index.js +1 -0
  89. package/dist/menu/item/menu-item.css.js +15 -1
  90. package/dist/menu/item/menu-item.d.ts +3 -0
  91. package/dist/menu/item/menu-item.js +2 -0
  92. package/dist/menu/section/menu-section.css.d.ts +1 -0
  93. package/dist/menu/section/menu-section.css.js +14 -0
  94. package/dist/menu/section/menu-section.d.ts +24 -0
  95. package/dist/menu/section/menu-section.js +16 -0
  96. package/dist/meter/root/meter-root.css.js +23 -1
  97. package/dist/meter/root/meter-root.d.ts +5 -0
  98. package/dist/navigation/root/navigation-root.css.js +3 -2
  99. package/dist/navigation/root/navigation-root.d.ts +6 -0
  100. package/dist/notifications/notification/notification.css.js +5 -0
  101. package/dist/notifications/root/notifications-root.css.js +24 -1
  102. package/dist/notifications/root/notifications-root.d.ts +1 -0
  103. package/dist/number-input/root/number-input-root.css.js +3 -3
  104. package/dist/number-input/root/number-input-root.d.ts +3 -0
  105. package/dist/object-inspector/root/object-inspector-root.css.js +36 -1
  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/orb/index.d.ts +1 -1
  109. package/dist/orb/index.js +1 -1
  110. package/dist/orb/root/orb-root.d.ts +31 -5
  111. package/dist/orb/root/orb-root.js +33 -4
  112. package/dist/outline/root/outline-root.css.js +10 -0
  113. package/dist/outline/root/outline-root.d.ts +7 -0
  114. package/dist/pin-input/root/pin-input-root.css.js +12 -5
  115. package/dist/pin-input/root/pin-input-root.d.ts +5 -0
  116. package/dist/popover/root/popover-root.css.js +36 -0
  117. package/dist/popover/root/popover-root.d.ts +1 -0
  118. package/dist/progress/root/progress-root.css.js +22 -1
  119. package/dist/progress/root/progress-root.d.ts +5 -0
  120. package/dist/quote/root/quote-root.css.js +1 -1
  121. package/dist/quote/root/quote-root.d.ts +1 -0
  122. package/dist/sandbox/frame.d.ts +63 -0
  123. package/dist/sandbox/frame.js +132 -0
  124. package/dist/sandbox/index.d.ts +1 -0
  125. package/dist/sandbox/index.js +1 -0
  126. package/dist/sandbox/levels.d.ts +10 -0
  127. package/dist/sandbox/levels.js +5 -0
  128. package/dist/sandbox/root/sandbox-root.d.ts +3 -0
  129. package/dist/sandbox/root/sandbox-root.js +13 -3
  130. package/dist/sandbox/source/sandbox-source.d.ts +1 -0
  131. package/dist/sandbox/source/sandbox-source.js +7 -3
  132. package/dist/sandbox/terminal/sandbox-terminal.css.js +39 -0
  133. package/dist/sandbox/terminal/sandbox-terminal.d.ts +42 -1
  134. package/dist/sandbox/terminal/sandbox-terminal.js +47 -3
  135. package/dist/scroll-area/root/scroll-area-root.css.js +83 -1
  136. package/dist/scroll-area/root/scroll-area-root.d.ts +6 -0
  137. package/dist/shared/chart/tooltip.css.js +25 -2
  138. package/dist/shared/field/field-segments.css.d.ts +1 -0
  139. package/dist/shared/field/field-segments.css.js +40 -0
  140. package/dist/skeleton/root/skeleton-root.css.js +56 -5
  141. package/dist/skeleton/root/skeleton-root.d.ts +17 -1
  142. package/dist/skeleton/root/skeleton-root.js +3 -0
  143. package/dist/skip-link/root/skip-link-root.css.js +8 -8
  144. package/dist/skip-link/root/skip-link-root.d.ts +9 -0
  145. package/dist/speed-dial/item/speed-dial-item.css.js +11 -4
  146. package/dist/speed-dial/item/speed-dial-item.d.ts +4 -0
  147. package/dist/speed-dial/root/speed-dial-root.css.js +7 -3
  148. package/dist/speed-dial/root/speed-dial-root.d.ts +9 -0
  149. package/dist/speed-dial/root/speed-dial-root.js +4 -0
  150. package/dist/stat/root/stat-root.css.js +7 -7
  151. package/dist/stat/root/stat-root.d.ts +8 -0
  152. package/dist/steps/step/step.js +2 -1
  153. package/dist/switch/root/switch-root.css.js +13 -5
  154. package/dist/switch/root/switch-root.d.ts +25 -1
  155. package/dist/switch/root/switch-root.js +7 -0
  156. package/dist/table/root/table-root.css.js +18 -0
  157. package/dist/table/root/table-root.d.ts +6 -0
  158. package/dist/table/root/table-root.js +2 -0
  159. package/dist/table/row/table-row.css.js +18 -0
  160. package/dist/table/row/table-row.d.ts +2 -0
  161. package/dist/table/row/table-row.js +2 -0
  162. package/dist/tabs/panel/tab-panel.css.js +5 -1
  163. package/dist/tabs/root/tabs-root.css.js +56 -1
  164. package/dist/tabs/tab/tab.css.js +5 -1
  165. package/dist/tag/group/tag-group.css.d.ts +1 -0
  166. package/dist/tag/group/tag-group.css.js +6 -0
  167. package/dist/tag/group/tag-group.d.ts +25 -0
  168. package/dist/tag/group/tag-group.js +16 -0
  169. package/dist/tag/index.d.ts +1 -0
  170. package/dist/tag/index.js +1 -0
  171. package/dist/tag/root/tag-root.css.js +50 -0
  172. package/dist/tag/root/tag-root.d.ts +4 -0
  173. package/dist/text/clamp.d.ts +8 -0
  174. package/dist/text/clamp.js +1 -0
  175. package/dist/text/root/text-root.css.js +85 -45
  176. package/dist/text/root/text-root.d.ts +48 -7
  177. package/dist/text/root/text-root.js +17 -11
  178. package/dist/textarea/root/textarea-root.css.js +12 -4
  179. package/dist/textarea/root/textarea-root.d.ts +4 -0
  180. package/dist/time-input/root/time-input-root.css.js +19 -0
  181. package/dist/time-input/root/time-input-root.d.ts +8 -0
  182. package/dist/time-input/root/time-input-root.js +2 -0
  183. package/dist/timeline/group/timeline-group.css.d.ts +1 -0
  184. package/dist/timeline/group/timeline-group.css.js +32 -0
  185. package/dist/timeline/group/timeline-group.d.ts +25 -0
  186. package/dist/timeline/group/timeline-group.js +16 -0
  187. package/dist/timeline/index.d.ts +1 -0
  188. package/dist/timeline/index.js +1 -0
  189. package/dist/timeline/item/timeline-item.css.js +43 -16
  190. package/dist/timeline/root/timeline-root.css.js +56 -0
  191. package/dist/timeline/root/timeline-root.d.ts +26 -0
  192. package/dist/timeline/root/timeline-root.js +7 -0
  193. package/dist/toast/item/toast-item.css.js +16 -0
  194. package/dist/toggle/group/toggle-group.css.js +16 -0
  195. package/dist/toolbar/root/toolbar-root.css.js +3 -0
  196. package/dist/toolbar/root/toolbar-root.d.ts +3 -0
  197. package/dist/tour/root/tour-root.css.js +8 -0
  198. package/dist/tour/stop/tour-stop.css.js +32 -0
  199. package/dist/tree/item/tree-item.css.js +72 -0
  200. package/dist/tree/item/tree-item.d.ts +10 -0
  201. package/dist/trend/root/trend-root.css.js +12 -5
  202. package/dist/trend/root/trend-root.d.ts +6 -1
  203. package/dist/video/root/video-root.css.js +6 -0
  204. package/dist/video/root/video-root.d.ts +3 -0
  205. package/dist/virtual-list/root/virtual-list-root.css.js +5 -0
  206. package/dist/virtual-list/root/virtual-list-root.d.ts +4 -3
  207. package/lint.json +1 -1
  208. package/package.json +6 -6
  209. package/types/jsx.d.ts +8620 -813
  210. package/types/svelte.d.ts +3 -0
  211. package/types/vue.d.ts +2372 -213
@@ -31,15 +31,26 @@ transform: scaleY(1);
31
31
  transition: transform var(--helix-duration-fast) var(--helix-easing-standard);
32
32
  }
33
33
 
34
- :host(:not([chevron-placement="start"])) [part="chevron"] {
34
+ ::slotted([slot="chevron"]) {
35
+ block-size: 1em;
36
+ color: var(--helix-color-foreground-subtle);
37
+ flex: 0 0 auto;
38
+ inline-size: 1em;
39
+ transition: transform var(--helix-duration-fast) var(--helix-easing-standard);
40
+ }
41
+
42
+ :host(:not([chevron-placement="start"])) [part="chevron"],
43
+ :host(:not([chevron-placement="start"])) ::slotted([slot="chevron"]) {
35
44
  margin-inline-start: auto;
36
45
  }
37
46
 
38
- :host(:state(open)) [part="chevron"] {
47
+ :host(:state(open)) [part="chevron"],
48
+ :host(:state(open)) ::slotted([slot="chevron"]) {
39
49
  transform: scaleY(-1);
40
50
  }
41
51
 
42
- [part="trigger"]:hover:not(:disabled) [part="chevron"] {
52
+ [part="trigger"]:hover:not(:disabled) [part="chevron"],
53
+ [part="trigger"]:hover:not(:disabled) ::slotted([slot="chevron"]) {
43
54
  color: var(--helix-color-foreground);
44
55
  }
45
56
 
@@ -16,6 +16,8 @@ import type { CSSResultGroup } from 'lit';
16
16
  * @documentation https://fusion.dev/helix/components/accordion
17
17
  *
18
18
  * @slot - The content shown when the section is open.
19
+ * @slot chevron - Replaces the open and close indicator. A slotted icon is sized, colored and
20
+ * turned like the drawn one.
19
21
  * @slot summary - The text of the button that opens and closes the section. Always shown.
20
22
  *
21
23
  * @csspart chevron - The open and close indicator.
@@ -0,0 +1,38 @@
1
+ import type { ColorBytes, TokenColor } from '@fusion.dev/helix-core';
2
+ /** The four ramp stops a shape is drawn through, as channels in `0..1`. */
3
+ export interface AuraPalette {
4
+ glow: TokenColor;
5
+ ground: TokenColor;
6
+ haze: TokenColor;
7
+ peak: TokenColor;
8
+ }
9
+ /** The computed colors the canvas carries, one per stop and two for the peak. */
10
+ export type PaletteStyle = Pick<CSSStyleDeclaration, 'caretColor' | 'color' | 'columnRuleColor' | 'outlineColor' | 'textDecorationColor'>;
11
+ /** The default theme's dark page, ink on black, which is drawn until a read. */
12
+ export declare const RESTING_PALETTE: AuraPalette;
13
+ /**
14
+ * The ramp, from the colors the canvas's stylesheet resolved for it.
15
+ *
16
+ * **Carried on color properties of the canvas, which a canvas never paints**,
17
+ * because a custom property is handed back as the text that was written and a
18
+ * color property is resolved by the engine first. Read there, each stop takes
19
+ * the `--aura-*` hook a page wrote anywhere above the aura, and the token
20
+ * otherwise, the same way the fallback gradient on the host does:
21
+ *
22
+ * - `color`: `--aura-glow`, or `primary`.
23
+ * - `text-decoration-color`: `--aura-haze`, or `primary-subtle`.
24
+ * - `outline-color`: `--aura-ground`, or the background.
25
+ * - `column-rule-color` and `caret-color`: `--aura-peak`, or the light and the
26
+ * dark page's own peak.
27
+ *
28
+ * **Light pages peak on the pressed `primary-active` and dark ones on the
29
+ * foreground**, and the ground is what says which: mixing a saturated hue
30
+ * toward near-black takes the chroma out of exactly the pixels carrying the
31
+ * most of it. Read from the ground's own luminance rather than asked of the
32
+ * color mode, which is a private token this tier may not reach for. A page
33
+ * that sets `--aura-peak` sets both, so its peak is used either way.
34
+ *
35
+ * @param style The canvas's computed style.
36
+ * @param read Turns a resolved color into bytes, `undefined` where it cannot.
37
+ */
38
+ export declare const paletteOf: (style: PaletteStyle, read: (value: string) => ColorBytes | undefined) => AuraPalette;
@@ -0,0 +1,22 @@
1
+ export const RESTING_PALETTE = {
2
+ glow: [0.88, 0.88, 0.88],
3
+ ground: [0, 0, 0],
4
+ haze: [0.16, 0.16, 0.16],
5
+ peak: [1, 1, 1],
6
+ };
7
+ export const paletteOf = (style, read) => {
8
+ const channels = (value, fallback) => {
9
+ const bytes = read(value);
10
+ return bytes ? [bytes[0] / 255, bytes[1] / 255, bytes[2] / 255] : [...fallback];
11
+ };
12
+ const ground = channels(style.outlineColor, RESTING_PALETTE.ground);
13
+ const light = ground[0] * 0.2126 + ground[1] * 0.7152 + ground[2] * 0.0722 > 0.5;
14
+ return {
15
+ glow: channels(style.color, RESTING_PALETTE.glow),
16
+ ground,
17
+ haze: channels(style.textDecorationColor, RESTING_PALETTE.haze),
18
+ peak: light
19
+ ? channels(style.columnRuleColor, [0.02, 0.02, 0.02])
20
+ : channels(style.caretColor, RESTING_PALETTE.peak),
21
+ };
22
+ };
@@ -1,5 +1,10 @@
1
1
  import { createSheet } from '@fusion.dev/helix-core';
2
2
  export const styles = createSheet(`:host {
3
+
4
+ --_aura-glow: var(--aura-glow, var(--helix-color-primary));
5
+ --_aura-ground: var(--aura-ground, var(--helix-color-background));
6
+ --_aura-haze: var(--aura-haze, var(--helix-color-primary-subtle));
7
+
3
8
  position: relative;
4
9
  display: block;
5
10
  inline-size: 100%;
@@ -7,9 +12,9 @@ block-size: 100%;
7
12
 
8
13
  background-image: radial-gradient(
9
14
  120% 90% at 62% 12%,
10
- color-mix(in oklab, var(--helix-color-primary) 38%, var(--helix-color-background)) 0%,
11
- var(--helix-color-primary-subtle) 38%,
12
- var(--helix-color-background) 78%
15
+ color-mix(in oklab, var(--_aura-glow) 38%, var(--_aura-ground)) 0%,
16
+ var(--_aura-haze) 38%,
17
+ var(--_aura-ground) 78%
13
18
  );
14
19
  }
15
20
 
@@ -25,6 +30,22 @@ pointer-events: auto;
25
30
  display: block;
26
31
  inline-size: 100%;
27
32
  block-size: 100%;
33
+
34
+ caret-color: var(--aura-peak, var(--helix-color-foreground));
35
+ color: var(--_aura-glow);
36
+ column-rule-color: var(--aura-peak, var(--helix-color-primary-active));
37
+ outline-color: var(--_aura-ground);
38
+ text-decoration-color: var(--_aura-haze);
39
+ }
40
+
41
+ [part="content"] {
42
+ inset: 0;
43
+ pointer-events: none;
44
+ position: absolute;
45
+ }
46
+
47
+ ::slotted(*) {
48
+ pointer-events: auto;
28
49
  }
29
50
 
30
51
  [part="canvas"][hidden] {
@@ -33,13 +33,37 @@ import type { CSSResultGroup, PropertyValues, TemplateResult } from 'lit';
33
33
  * allow. Its behavior is drawing to a canvas, so there is no structure for you
34
34
  * to restyle and nothing for a headless version to hold.
35
35
  *
36
+ * **Content placed inside sits over the field**, in a `content` part that
37
+ * covers the aura, so an interactive aura answers the pointer over the
38
+ * content too. Clicks still reach the content. Style `::part(content)` to
39
+ * place it, such as centering a hero's heading.
40
+ *
41
+ * **The colors are the theme's, and each has a hook**: `--aura-ground`,
42
+ * `--aura-haze`, `--aura-glow` and `--aura-peak`, read by the shader and by the
43
+ * fallback gradient alike, from wherever on the page you set them.
44
+ *
45
+ * Where the gradient shows in place of the shader, the aura matches
46
+ * `:state(fallback)` and sends `helix-aura-fallback` with the reason.
47
+ *
36
48
  * @since 0.1.0
37
49
  * @status stable
38
50
  * @category media
39
51
  * @aliases Backdrop, Background, Atmosphere, Gradient
40
52
  * @documentation https://fusion.dev/helix/components/aura
41
53
  *
54
+ * @slot - Content drawn over the field, such as a heading.
55
+ *
56
+ * @event {HelixAuraFallbackEvent} helix-aura-fallback - Fired each time the aura stops drawing its shader and shows its gradient, with the reason.
57
+ *
42
58
  * @csspart canvas - The surface the shader draws into.
59
+ * @csspart content - The box over the field that holds the content. It covers the aura.
60
+ *
61
+ * @cssproperty --aura-glow - The bright stop of the ramp. Defaults to `--helix-color-primary`.
62
+ * @cssproperty --aura-ground - The page the field fades into. Defaults to `--helix-color-background`.
63
+ * @cssproperty --aura-haze - The faint stop between the ground and the glow. Defaults to `--helix-color-primary-subtle`.
64
+ * @cssproperty --aura-peak - The hottest stop, at the center of a shape. Defaults to `--helix-color-primary-active` on a light page and `--helix-color-foreground` on a dark one.
65
+ *
66
+ * @cssstate fallback - The aura shows its gradient: the renderer draws on the CPU, there is no WebGL, or the browser took the context back. Cleared once the shader draws again.
43
67
  */
44
68
  export declare class HelixAura extends HelixElement {
45
69
  static styles: CSSResultGroup;
@@ -173,8 +197,7 @@ export declare class HelixAura extends HelixElement {
173
197
  * states.
174
198
  */
175
199
  variant?: 'aurora' | 'braid' | 'caustics' | 'flow' | 'fracture' | 'lattice' | 'particles' | 'rays' | 'streaks' | 'threads' | 'waves';
176
- /** Repaints when the palette moves, which no re-render would do on its own. */
177
- private readonly tokens;
200
+ constructor();
178
201
  /**
179
202
  * The four ramp stops, resolved.
180
203
  *
@@ -186,6 +209,10 @@ export declare class HelixAura extends HelixElement {
186
209
  * that happens, so this is filled from there and from the first paint.
187
210
  */
188
211
  private palette;
212
+ /** Why the gradient shows, while it does, or `undefined` while the shader draws. */
213
+ private fallback;
214
+ /** Why the last `build` drew nothing, for the fallback it leads to. */
215
+ private refused;
189
216
  private canvas;
190
217
  private gl;
191
218
  private program;
@@ -413,6 +440,15 @@ export declare class HelixAura extends HelixElement {
413
440
  * loss was canceled.
414
441
  */
415
442
  private readonly handleLost;
443
+ /**
444
+ * Shows the gradient, and says so once for each time it starts to.
445
+ *
446
+ * The state is what a stylesheet reads, and the event is what a script
447
+ * logs, such as to count how many readers see the gradient. Sent again only
448
+ * after the shader has drawn in between, so a context that is lost while
449
+ * the gradient already shows is not said twice.
450
+ */
451
+ private fallBack;
416
452
  /**
417
453
  * Draws again on the context the browser gave back.
418
454
  *
@@ -424,11 +460,10 @@ export declare class HelixAura extends HelixElement {
424
460
  /**
425
461
  * Resolves the ramp. Called when the palette moves, not when a frame draws.
426
462
  *
427
- * Light pages peak on the pressed `primary-active` and dark ones on the
428
- * foreground, and the ground is what says which: mixing a saturated hue
429
- * toward near-black takes the chroma out of exactly the pixels carrying the
430
- * most of it. Read from the ground's own luminance rather than asked of the
431
- * color mode, which is a private token this tier may not reach for.
463
+ * From the canvas's own computed style, which carries each stop on a color
464
+ * property: the `--aura-*` hook where a page set one, and the token
465
+ * otherwise. `paletteOf` says which property is which, and how the peak is
466
+ * chosen for a light page or a dark one.
432
467
  */
433
468
  private readPalette;
434
469
  private link;
@@ -5,10 +5,11 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
5
5
  return c > 3 && r && Object.defineProperty(target, key, r), r;
6
6
  };
7
7
  var HelixAura_1;
8
- import { customElement, HelixElement, MAX_FRAME_STEP, PaintGateController, TokenColorController, } from '@fusion.dev/helix-core';
8
+ import { customElement, HelixAuraFallbackEvent, HelixElement, MAX_FRAME_STEP, PaintGateController, readColor, TokenColorController, } from '@fusion.dev/helix-core';
9
9
  import { html } from 'lit';
10
10
  import { property } from 'lit/decorators.js';
11
11
  import { tiltFor } from '../axis.js';
12
+ import { paletteOf, RESTING_PALETTE } from '../palette.js';
12
13
  import { FRAGMENT, INTERACTIONS, SHAPES, VERTEX } from '../shader.js';
13
14
  import { styles } from './aura-root.css.js';
14
15
  const MAX_CANVAS_EDGE = 4096;
@@ -16,8 +17,10 @@ const MAX_CANVAS_PIXELS = 4_194_304;
16
17
  const OPENING_PATIENCE = 500;
17
18
  const SOFTWARE_RENDERER = /swiftshader|llvmpipe|softpipe|software rasterizer|basic render/i;
18
19
  let HelixAura = class HelixAura extends HelixElement {
20
+ static { HelixAura_1 = this; }
21
+ static { this.styles = styles; }
19
22
  constructor() {
20
- super(...arguments);
23
+ super();
21
24
  this.bloom = 0.5;
22
25
  this.drift = 0;
23
26
  this.gain = 1;
@@ -27,16 +30,8 @@ let HelixAura = class HelixAura extends HelixElement {
27
30
  this.speed = 1;
28
31
  this.tilt = 14;
29
32
  this.variance = 1;
30
- this.tokens = new TokenColorController(this, () => {
31
- this.readPalette();
32
- this.paintOnce();
33
- });
34
- this.palette = {
35
- glow: [0.88, 0.88, 0.88],
36
- ground: [0, 0, 0],
37
- haze: [0.16, 0.16, 0.16],
38
- peak: [1, 1, 1],
39
- };
33
+ this.palette = { ...RESTING_PALETTE };
34
+ this.refused = 'unavailable';
40
35
  this.canvas = null;
41
36
  this.gl = null;
42
37
  this.program = null;
@@ -87,6 +82,7 @@ let HelixAura = class HelixAura extends HelixElement {
87
82
  }
88
83
  this.program = null;
89
84
  this.canvas?.toggleAttribute('hidden', true);
85
+ this.fallBack('lost');
90
86
  };
91
87
  this.handleRestored = () => {
92
88
  if (!this.prepare()) {
@@ -121,9 +117,11 @@ let HelixAura = class HelixAura extends HelixElement {
121
117
  const rect = this.getBoundingClientRect();
122
118
  this.box = { ...this.box, left: rect.left, top: rect.top };
123
119
  };
120
+ new TokenColorController(this, () => {
121
+ this.readPalette();
122
+ this.paintOnce();
123
+ });
124
124
  }
125
- static { HelixAura_1 = this; }
126
- static { this.styles = styles; }
127
125
  static { this.CONTEXT = {
128
126
  alpha: true,
129
127
  antialias: false,
@@ -132,7 +130,8 @@ let HelixAura = class HelixAura extends HelixElement {
132
130
  stencil: false,
133
131
  }; }
134
132
  render() {
135
- return html `<canvas part="canvas" aria-hidden="true"></canvas>`;
133
+ return html `<canvas part="canvas" aria-hidden="true"></canvas>
134
+ <div part="content"><slot></slot></div>`;
136
135
  }
137
136
  firstUpdated(changed) {
138
137
  super.firstUpdated(changed);
@@ -150,6 +149,7 @@ let HelixAura = class HelixAura extends HelixElement {
150
149
  this.gl = null;
151
150
  }
152
151
  if (!this.program && !this.gl?.isContextLost() && !this.build()) {
152
+ this.fallBack(this.refused);
153
153
  return;
154
154
  }
155
155
  this.canvas?.addEventListener('webglcontextlost', this.handleLost);
@@ -182,8 +182,10 @@ let HelixAura = class HelixAura extends HelixElement {
182
182
  return false;
183
183
  }
184
184
  if (HelixAura_1.drawsInSoftware()) {
185
+ this.refused = 'software';
185
186
  return false;
186
187
  }
188
+ this.refused = 'unavailable';
187
189
  let gl = canvas.getContext('webgl2', HelixAura_1.CONTEXT);
188
190
  if (gl?.isContextLost()) {
189
191
  const fresh = document.createElement('canvas');
@@ -212,6 +214,8 @@ let HelixAura = class HelixAura extends HelixElement {
212
214
  return false;
213
215
  }
214
216
  this.canvas?.toggleAttribute('hidden', false);
217
+ this.fallback = undefined;
218
+ this.toggleState('fallback', false);
215
219
  gl.useProgram(this.program);
216
220
  for (const name of [
217
221
  'uBloom',
@@ -263,17 +267,19 @@ let HelixAura = class HelixAura extends HelixElement {
263
267
  window.removeEventListener('scroll', this.handleScroll, { capture: true });
264
268
  this.release = window.setTimeout(this.drop, 0);
265
269
  }
270
+ fallBack(reason) {
271
+ if (this.fallback !== undefined) {
272
+ return;
273
+ }
274
+ this.fallback = reason;
275
+ this.toggleState('fallback', true);
276
+ this.dispatchEvent(new HelixAuraFallbackEvent({ reason }));
277
+ }
266
278
  readPalette() {
267
- const ground = this.tokens.read('--helix-color-background', [0, 0, 0]);
268
- const light = ground[0] * 0.2126 + ground[1] * 0.7152 + ground[2] * 0.0722 > 0.5;
269
- this.palette = {
270
- glow: this.tokens.read('--helix-color-primary', [0.88, 0.88, 0.88]),
271
- ground,
272
- haze: this.tokens.read('--helix-color-primary-subtle', [0.16, 0.16, 0.16]),
273
- peak: light
274
- ? this.tokens.read('--helix-color-primary-active', [0.02, 0.02, 0.02])
275
- : this.tokens.read('--helix-color-foreground', [1, 1, 1]),
276
- };
279
+ const canvas = this.renderRoot.querySelector('canvas');
280
+ if (canvas) {
281
+ this.palette = paletteOf(getComputedStyle(canvas), readColor);
282
+ }
277
283
  }
278
284
  link(vertex, fragment) {
279
285
  const gl = this.gl;
@@ -105,6 +105,41 @@ background-color: var(--badge-background-color, var(--helix-color-surface-raised
105
105
  color: var(--badge-color, var(--helix-color-foreground));
106
106
  }
107
107
 
108
+ :host([placement="top-start"]) [part="indicator"],
109
+ :host([placement="bottom-start"]) [part="indicator"] {
110
+ inset-inline-end: auto;
111
+ inset-inline-start: var(--badge-offset, calc(var(--_badge-size) / 4));
112
+ }
113
+
114
+ :host([placement="bottom-end"]) [part="indicator"],
115
+ :host([placement="bottom-start"]) [part="indicator"] {
116
+ inset-block-end: var(--badge-offset, calc(var(--_badge-size) / 4));
117
+ inset-block-start: auto;
118
+ }
119
+
120
+ :host([placement="top-start"]) [part="indicator"] {
121
+ translate: -50% -50%;
122
+ }
123
+
124
+ :host([placement="bottom-end"]) [part="indicator"] {
125
+ translate: 50% 50%;
126
+ }
127
+
128
+ :host([placement="bottom-start"]) [part="indicator"] {
129
+ translate: -50% 50%;
130
+ }
131
+
132
+ :host([placement="inline"]) {
133
+ align-items: center;
134
+ gap: var(--badge-gap, var(--helix-space-2xs));
135
+ }
136
+
137
+ :host([placement="inline"]) [part="indicator"] {
138
+ box-shadow: none;
139
+ position: static;
140
+ translate: none;
141
+ }
142
+
108
143
  @media print {
109
144
  :host {
110
145
  box-shadow: none;
@@ -8,6 +8,12 @@ import type { CSSResultGroup } from 'lit';
8
8
  * where it overlaps the element it is pinned to, such as a dark badge on a dark
9
9
  * icon.
10
10
  *
11
+ * `placement` pins it to another corner, or puts it in the line with
12
+ * `inline`. **Inside a control, `inline` puts the count in the control's
13
+ * name**: `<button>Inbox <helix-badge placement="inline" value="8"
14
+ * label="8 unread"></helix-badge></button>` is the button "Inbox 8 unread",
15
+ * kept current by the badge with no label of yours to update.
16
+ *
11
17
  * @since 0.1.0
12
18
  * @status stable
13
19
  * @category markers
@@ -16,10 +22,20 @@ import type { CSSResultGroup } from 'lit';
16
22
  *
17
23
  * @cssproperty --badge-background-color - The fill of the indicator.
18
24
  * @cssproperty --badge-color - The color of the count, to pair with a fill set through `--badge-background-color`.
25
+ * @cssproperty --badge-gap - The space between the content and the count under `placement="inline"`.
19
26
  * @cssproperty --badge-offset - Pulls the mark in from the corner, along both axes.
20
27
  * @cssproperty --badge-ring-color - The color of the ring between the indicator and what is behind it.
21
28
  */
22
29
  export declare class HelixBadge extends HelixHeadlessBadge {
30
+ /**
31
+ * Where the mark sits: a corner, `top-start`, `bottom-end` or `bottom-start`,
32
+ * or `inline`, in the line after the content.
33
+ *
34
+ * Absent is the top end, the corner a count is looked for in. `inline` is
35
+ * for a badge inside a control, where its count is read as part of the
36
+ * control's name.
37
+ */
38
+ placement?: 'bottom-end' | 'bottom-start' | 'inline' | 'top-start';
23
39
  /**
24
40
  * What the mark means. The stylesheet picks the fill from it.
25
41
  *
@@ -11,6 +11,9 @@ import { styles } from './badge-root.css.js';
11
11
  let HelixBadge = class HelixBadge extends HelixHeadlessBadge {
12
12
  static { this.styles = styles; }
13
13
  };
14
+ __decorate([
15
+ property({ reflect: true })
16
+ ], HelixBadge.prototype, "placement", void 0);
14
17
  __decorate([
15
18
  property({ reflect: true })
16
19
  ], HelixBadge.prototype, "tone", void 0);
@@ -14,8 +14,8 @@ margin: var(--helix-space-none);
14
14
 
15
15
  slot:not([name]) {
16
16
 
17
- color: var(--helix-color-foreground-muted);
18
- font-family: var(--helix-font-display);
17
+ color: var(--blockquote-color, var(--helix-color-foreground-muted));
18
+ font-family: var(--blockquote-font-family, var(--helix-font-display));
19
19
  font-size: var(--blockquote-size, var(--helix-text-xl));
20
20
  font-weight: var(--helix-weight-medium);
21
21
  letter-spacing: var(--helix-tracking-tight);
@@ -27,10 +27,10 @@ margin: var(--helix-space-none);
27
27
  }
28
28
 
29
29
  [part="attribution"] {
30
- color: var(--helix-color-foreground-muted);
31
- font-size: var(--helix-text-sm);
30
+ color: var(--blockquote-attribution-color, var(--helix-color-foreground-muted));
31
+ font-size: var(--blockquote-attribution-size, var(--helix-text-sm));
32
32
 
33
- margin-block-start: var(--helix-space-sm);
33
+ margin-block-start: var(--blockquote-gap, var(--helix-space-sm));
34
34
  }
35
35
 
36
36
  [part="attribution"][data-empty] {
@@ -14,6 +14,11 @@ import type { CSSResultGroup } from 'lit';
14
14
  * @aliases Pullquote, Citation, Excerpt
15
15
  * @documentation https://fusion.dev/helix/components/blockquote
16
16
  *
17
+ * @cssproperty --blockquote-attribution-color - The color of the attribution.
18
+ * @cssproperty --blockquote-attribution-size - The font size of the attribution.
19
+ * @cssproperty --blockquote-color - The color of the quoted passage.
20
+ * @cssproperty --blockquote-font-family - The typeface of the quoted passage, the display face by default.
21
+ * @cssproperty --blockquote-gap - The space between the passage and its attribution.
17
22
  * @cssproperty --blockquote-size - The font size of the quoted passage.
18
23
  */
19
24
  export declare class HelixBlockquote extends HelixHeadlessBlockquote {
@@ -38,7 +38,7 @@ display: none;
38
38
 
39
39
  ::slotted(a) {
40
40
  background-color: transparent;
41
- border-radius: var(--helix-radii-sm);
41
+ border-radius: var(--breadcrumbs-radius, var(--helix-radii-sm));
42
42
  padding: var(--helix-space-2xs) var(--helix-space-xs);
43
43
  transition: background-color var(--helix-duration-fast) var(--helix-easing-standard);
44
44
  }
@@ -61,17 +61,17 @@ outline-offset: var(--helix-size-focus-offset);
61
61
  }
62
62
 
63
63
  :host {
64
- font-weight: var(--helix-weight-medium);
64
+ font-weight: var(--breadcrumbs-font-weight, var(--helix-weight-medium));
65
65
  }
66
66
 
67
67
  :host([current]) {
68
- color: var(--helix-color-foreground);
68
+ color: var(--breadcrumbs-current-color, var(--helix-color-foreground));
69
69
  }
70
70
 
71
71
  [part="link"] {
72
72
  align-items: center;
73
- border-radius: var(--helix-radii-sm);
74
- color: var(--helix-color-foreground-muted);
73
+ border-radius: var(--breadcrumbs-radius, var(--helix-radii-sm));
74
+ color: var(--breadcrumbs-link-color, var(--helix-color-foreground-muted));
75
75
  display: inline-flex;
76
76
  gap: var(--helix-space-xs);
77
77
  padding: var(--helix-space-2xs) var(--helix-space-xs);
@@ -95,11 +95,11 @@ background-color: var(
95
95
  --breadcrumbs-hover-color,
96
96
  color-mix(in oklab, var(--helix-color-foreground) 8%, transparent)
97
97
  );
98
- color: var(--helix-color-foreground);
98
+ color: var(--breadcrumbs-current-color, var(--helix-color-foreground));
99
99
  }
100
100
 
101
101
  :host([current]) [part="link"] {
102
- color: var(--helix-color-foreground);
102
+ color: var(--breadcrumbs-current-color, var(--helix-color-foreground));
103
103
  }
104
104
 
105
105
  :host([hidden]) {
@@ -25,7 +25,12 @@ import type { CSSResultGroup } from 'lit';
25
25
  *
26
26
  * @cssproperty --breadcrumbs-control-padding-inline - Inline padding of a control slotted into a crumb, matching the steps either side of it.
27
27
  * @cssproperty --breadcrumbs-control-size - How tall a control slotted into a crumb is.
28
+ * @cssproperty --breadcrumbs-current-color - Text color of the current page's crumb.
29
+ * @cssproperty --breadcrumbs-font-weight - Weight of every crumb's text.
28
30
  * @cssproperty --breadcrumbs-hover-color - Fill behind a step under the pointer.
31
+ * @cssproperty --breadcrumbs-link-color - Text color of a crumb that is not the current page. A link
32
+ * you slot inherits it unless your own styles set a color.
33
+ * @cssproperty --breadcrumbs-radius - Corner radius of the fill behind a step under the pointer.
29
34
  * @cssproperty --breadcrumbs-separator-color - Color of the chevron.
30
35
  */
31
36
  export declare class HelixBreadcrumb extends HelixHeadlessBreadcrumb {
@@ -7,7 +7,7 @@ display: block;
7
7
  align-items: center;
8
8
  display: flex;
9
9
  flex-wrap: wrap;
10
- font-size: var(--helix-text-sm);
10
+ font-size: var(--breadcrumbs-font-size, var(--helix-text-sm));
11
11
  gap: var(--breadcrumbs-gap, var(--helix-space-xs));
12
12
 
13
13
  list-style: none;
@@ -1,5 +1,6 @@
1
1
  import { HelixHeadlessBreadcrumbs } from '@fusion.dev/helix-headless/breadcrumbs';
2
2
  import type { CSSResultGroup } from 'lit';
3
+ import '../breadcrumb/breadcrumb.js';
3
4
  /**
4
5
  * @summary Shows the path to the current page.
5
6
  *
@@ -17,9 +18,11 @@ import type { CSSResultGroup } from 'lit';
17
18
  *
18
19
  * @csspart list - The ordered list.
19
20
  *
21
+ * @cssproperty --breadcrumbs-font-size - Size of the trail's text.
20
22
  * @cssproperty --breadcrumbs-gap - Space between items and separators.
21
23
  */
22
24
  export declare class HelixBreadcrumbs extends HelixHeadlessBreadcrumbs {
25
+ static tier: string;
23
26
  static styles: CSSResultGroup;
24
27
  }
25
28
  declare global {
@@ -7,7 +7,9 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
7
7
  import { customElement } from '@fusion.dev/helix-core';
8
8
  import { HelixHeadlessBreadcrumbs } from '@fusion.dev/helix-headless/breadcrumbs';
9
9
  import { styles } from './breadcrumbs-root.css.js';
10
+ import '../breadcrumb/breadcrumb.js';
10
11
  let HelixBreadcrumbs = class HelixBreadcrumbs extends HelixHeadlessBreadcrumbs {
12
+ static { this.tier = 'helix-'; }
11
13
  static { this.styles = styles; }
12
14
  };
13
15
  HelixBreadcrumbs = __decorate([
@@ -14,6 +14,8 @@ max-inline-size: 100%;
14
14
  --_button-on-tone: var(--helix-color-background);
15
15
  --_button-tone: var(--helix-color-foreground);
16
16
 
17
+ --_button-turn: 0.8s;
18
+
17
19
  --_button-tone-hover: color-mix(
18
20
  in oklab,
19
21
  var(--helix-color-foreground) 86%,
@@ -61,7 +63,7 @@ color-mix(in oklab, var(--_button-tone) 6%, transparent)
61
63
  );
62
64
 
63
65
  block-size: var(--button-size, var(--helix-size-control));
64
- border: var(--helix-border-thin) solid var(--_button-edge);
66
+ border: var(--helix-border-thin) solid var(--button-border-color, var(--_button-edge));
65
67
  box-sizing: border-box;
66
68
  color: var(--button-foreground-color, var(--_button-tone));
67
69
  cursor: pointer;
@@ -183,6 +185,41 @@ text-box: trim-both cap alphabetic;
183
185
  --icon-size: 1.15em;
184
186
  }
185
187
 
188
+ :host(:state(pending)) [part="button"] {
189
+ cursor: progress;
190
+ position: relative;
191
+ }
192
+
193
+ :host(:state(pending)) [part="button"] > slot {
194
+ visibility: hidden;
195
+ }
196
+
197
+ :host(:state(pending)) [part="button"]::after {
198
+ animation: helix-button-turn var(--_button-turn) linear infinite;
199
+ block-size: var(--button-spinner-size, 1.15em);
200
+ border: var(--helix-border-thick) solid color-mix(in oklab, currentColor 30%, transparent);
201
+ border-block-start-color: currentColor;
202
+ border-radius: var(--helix-radii-full);
203
+ box-sizing: border-box;
204
+ content: "";
205
+ inline-size: var(--button-spinner-size, 1.15em);
206
+ inset: 0;
207
+ margin: auto;
208
+ position: absolute;
209
+ }
210
+
211
+ @keyframes helix-button-turn {
212
+ to {
213
+ rotate: 1turn;
214
+ }
215
+ }
216
+
217
+ @media (prefers-reduced-motion: reduce) {
218
+ :host(:state(pending)) [part="button"]::after {
219
+ animation-duration: calc(var(--helix-duration-slow) * 12);
220
+ }
221
+ }
222
+
186
223
  @media print {
187
224
  :host {
188
225
  display: none;