@fusion.dev/helix 0.142.0 → 0.143.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 (83) hide show
  1. package/README.md +9 -5
  2. package/custom-elements.json +19275 -1410
  3. package/dist/accordion/item/accordion-item.css.js +6 -1
  4. package/dist/accordion/item/accordion-item.d.ts +1 -0
  5. package/dist/announcement/root/announcement-root.d.ts +3 -3
  6. package/dist/app-header/root/app-header-root.d.ts +1 -3
  7. package/dist/aura/shader.d.ts +5 -1
  8. package/dist/aura/shader.js +88 -613
  9. package/dist/avatar/root/avatar-root.d.ts +3 -3
  10. package/dist/badge/root/badge-root.css.js +3 -2
  11. package/dist/badge/root/badge-root.d.ts +1 -0
  12. package/dist/bar-chart/root/bar-chart-root.css.js +10 -0
  13. package/dist/blockquote/root/blockquote-root.css.js +4 -0
  14. package/dist/card/root/card-root.css.js +1 -0
  15. package/dist/carousel/root/carousel-root.js +2 -1
  16. package/dist/checkbox/root/checkbox-root.css.js +3 -3
  17. package/dist/color-picker/root/color-picker-root.d.ts +0 -1
  18. package/dist/color-picker/root/color-picker-root.js +0 -1
  19. package/dist/combobox/root/combobox-root.css.js +5 -4
  20. package/dist/data-table/root/data-table-root.css.js +7 -0
  21. package/dist/date-picker/root/date-picker-root.css.js +15 -3
  22. package/dist/donut-chart/root/donut-chart-root.css.js +10 -0
  23. package/dist/drawer/root/drawer-root.css.js +25 -4
  24. package/dist/element-events.generated.js +41 -10
  25. package/dist/file-input/root/file-input-root.d.ts +0 -1
  26. package/dist/file-input/root/file-input-root.js +0 -1
  27. package/dist/filter-input/root/filter-input-root.d.ts +0 -1
  28. package/dist/filter-input/root/filter-input-root.js +0 -1
  29. package/dist/grid/root/grid-root.d.ts +15 -11
  30. package/dist/grid/root/grid-root.js +49 -15
  31. package/dist/icon-button/root/icon-button-root.css.js +43 -16
  32. package/dist/icon-button/root/icon-button-root.d.ts +4 -1
  33. package/dist/image/root/image-root.css.js +1 -1
  34. package/dist/input/root/input-root.d.ts +0 -1
  35. package/dist/input/root/input-root.js +0 -1
  36. package/dist/line-chart/root/line-chart-root.css.js +10 -0
  37. package/dist/list/item/list-item.css.js +7 -1
  38. package/dist/loader/root/loader-root.d.ts +7 -4
  39. package/dist/menu/item/menu-item.css.js +1 -1
  40. package/dist/menu/root/menu-root.d.ts +0 -3
  41. package/dist/meter/root/meter-root.css.js +4 -4
  42. package/dist/number-input/root/number-input-root.d.ts +3 -0
  43. package/dist/orb/root/orb-root.d.ts +11 -2
  44. package/dist/orb/root/orb-root.js +5 -1
  45. package/dist/qr-code/root/qr-code-root.css.js +2 -1
  46. package/dist/qr-code/root/qr-code-root.d.ts +2 -2
  47. package/dist/rating/root/rating-root.d.ts +3 -0
  48. package/dist/sandbox/index.d.ts +2 -2
  49. package/dist/sandbox/root/sandbox-root.d.ts +20 -1
  50. package/dist/sandbox/root/sandbox-root.js +27 -10
  51. package/dist/sandbox/source/sandbox-source.d.ts +6 -1
  52. package/dist/sandbox/source/sandbox-source.js +13 -3
  53. package/dist/sandbox/terminal/sandbox-terminal.d.ts +3 -1
  54. package/dist/sandbox/terminal/sandbox-terminal.js +3 -1
  55. package/dist/skeleton/root/skeleton-root.css.js +4 -0
  56. package/dist/skeleton/root/skeleton-root.d.ts +4 -1
  57. package/dist/table/column/table-column.css.js +5 -0
  58. package/dist/tabs/panel/tab-panel.css.js +1 -1
  59. package/dist/tabs/panel/tab-panel.d.ts +2 -0
  60. package/dist/tabs/root/tabs-root.css.js +13 -7
  61. package/dist/tabs/root/tabs-root.d.ts +5 -0
  62. package/dist/tabs/tab/tab.css.js +4 -4
  63. package/dist/tabs/tab/tab.d.ts +5 -0
  64. package/dist/tag/root/tag-root.d.ts +2 -3
  65. package/dist/text/root/text-root.css.js +58 -1
  66. package/dist/text/root/text-root.d.ts +11 -2
  67. package/dist/text/root/text-root.js +19 -1
  68. package/dist/time-input/root/time-input-root.d.ts +0 -1
  69. package/dist/time-input/root/time-input-root.js +0 -1
  70. package/dist/toast/root/toast-root.css.js +31 -7
  71. package/dist/toast/root/toast-root.d.ts +6 -9
  72. package/dist/toggle/group/toggle-group.d.ts +3 -0
  73. package/dist/tour/stop/tour-stop.css.js +5 -0
  74. package/dist/trend/root/trend-root.d.ts +0 -1
  75. package/dist/trend/root/trend-root.js +0 -1
  76. package/dist/video/root/video-root.d.ts +0 -1
  77. package/dist/video/root/video-root.js +0 -1
  78. package/dist/video-playlist/menu/video-playlist-menu.d.ts +0 -1
  79. package/dist/video-playlist/menu/video-playlist-menu.js +0 -1
  80. package/lint.json +1 -1
  81. package/package.json +6 -6
  82. package/types/jsx.d.ts +4973 -1964
  83. package/types/vue.d.ts +998 -212
@@ -4,9 +4,9 @@ import type { CSSResultGroup } from 'lit';
4
4
  * @summary A person or entity, shown as an image or as their initials.
5
5
  *
6
6
  * @description
7
- * The font size of the initials is set in `em` against the avatar's own
8
- * dimension, so the initials scale with every size, including a size you set
9
- * through `--avatar-size`.
7
+ * The font size of the initials is a share of the avatar's own size, so the
8
+ * initials scale with every size, including a size you set through
9
+ * `--avatar-size`.
10
10
  *
11
11
  * @since 0.1.0
12
12
  * @status stable
@@ -20,7 +20,8 @@ block-size: var(--_badge-size);
20
20
  border-radius: var(--helix-radii-full);
21
21
 
22
22
  box-shadow: 0 0 0 var(--helix-border-thick) var(--badge-ring-color, var(--helix-color-background));
23
- color: var(--_badge-on);
23
+
24
+ color: var(--badge-color, var(--_badge-on));
24
25
  display: inline-flex;
25
26
  font-size: var(--_badge-text);
26
27
  font-weight: var(--helix-weight-semibold);
@@ -101,7 +102,7 @@ background-color: var(--badge-background-color, var(--helix-color-danger-surface
101
102
 
102
103
  :host([tone="neutral"]) [part="indicator"] {
103
104
  background-color: var(--badge-background-color, var(--helix-color-surface-raised));
104
- color: var(--helix-color-foreground);
105
+ color: var(--badge-color, var(--helix-color-foreground));
105
106
  }
106
107
 
107
108
  @media print {
@@ -15,6 +15,7 @@ import type { CSSResultGroup } from 'lit';
15
15
  * @documentation https://fusion.dev/helix/components/badge
16
16
  *
17
17
  * @cssproperty --badge-background-color - The fill of the indicator.
18
+ * @cssproperty --badge-color - The color of the count, to pair with a fill set through `--badge-background-color`.
18
19
  * @cssproperty --badge-offset - Pulls the mark in from the corner, along both axes.
19
20
  * @cssproperty --badge-ring-color - The color of the ring between the indicator and what is behind it.
20
21
  */
@@ -289,4 +289,14 @@ stop-opacity: calc(0.35 * var(--helix-material-opacity));
289
289
  :host {
290
290
  print-color-adjust: exact;
291
291
  }
292
+ }
293
+
294
+ [part="summary"] {
295
+ block-size: 1px;
296
+ clip-path: inset(50%);
297
+ inline-size: 1px;
298
+ margin: var(--helix-space-none);
299
+ overflow: hidden;
300
+ position: absolute;
301
+ white-space: nowrap;
292
302
  }`);
@@ -3,6 +3,10 @@ export const styles = createSheet(`:host {
3
3
  display: block;
4
4
  }
5
5
 
6
+ [part="figure"] {
7
+ margin: var(--helix-space-none);
8
+ }
9
+
6
10
  [part="blockquote"] {
7
11
  display: block;
8
12
  margin: var(--helix-space-none);
@@ -39,6 +39,7 @@ border-color: transparent;
39
39
  }
40
40
 
41
41
  :host([separation="plain"]) {
42
+ --card-shadow: none;
42
43
  background-color: transparent;
43
44
  border-color: transparent;
44
45
  }
@@ -7,9 +7,10 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
7
7
  import { customElement } from '@fusion.dev/helix-core';
8
8
  import { HelixHeadlessCarousel } from '@fusion.dev/helix-headless/carousel';
9
9
  import { property } from 'lit/decorators.js';
10
+ import { styles as liveStyles } from '../../shared/live/live.css.js';
10
11
  import { styles } from './carousel-root.css.js';
11
12
  let HelixCarousel = class HelixCarousel extends HelixHeadlessCarousel {
12
- static { this.styles = styles; }
13
+ static { this.styles = [liveStyles, styles]; }
13
14
  };
14
15
  __decorate([
15
16
  property({ attribute: 'controls-align', reflect: true })
@@ -54,7 +54,7 @@ border-color: var(--checkbox-border-color, var(--helix-color-foreground-muted));
54
54
  }
55
55
 
56
56
  :host(:state(checked)) [part="control"],
57
- :host([indeterminate]) [part="control"] {
57
+ :host(:state(indeterminate)) [part="control"] {
58
58
  border-color: var(
59
59
  --checkbox-border-color,
60
60
  var(--checkbox-checked-color, var(--helix-color-foreground))
@@ -78,7 +78,7 @@ transition: scale var(--helix-duration-fast) var(--helix-easing-emphasized);
78
78
  }
79
79
 
80
80
  :host(:state(checked)) [part~="mark"],
81
- :host([indeterminate]) [part~="mark"] {
81
+ :host(:state(indeterminate)) [part~="mark"] {
82
82
  scale: 1;
83
83
  }
84
84
 
@@ -97,7 +97,7 @@ border-color: var(--helix-color-danger);
97
97
  }
98
98
 
99
99
  :host(:state(invalid):state(checked)) [part="control"],
100
- :host(:state(invalid)[indeterminate]) [part="control"] {
100
+ :host(:state(invalid):state(indeterminate)) [part="control"] {
101
101
  border-color: var(--helix-color-danger);
102
102
  }
103
103
 
@@ -2,7 +2,6 @@ import { HelixHeadlessColorPicker } from '@fusion.dev/helix-headless/color-picke
2
2
  import type { CSSResultGroup } from 'lit';
3
3
  import '../../button/index.js';
4
4
  import '../../button-group/index.js';
5
- import '../../icon/index.js';
6
5
  import '../../slider/index.js';
7
6
  /**
8
7
  * @summary A color picker made of a square and two ramps.
@@ -8,7 +8,6 @@ import { customElement } from '@fusion.dev/helix-core';
8
8
  import { HelixHeadlessColorPicker } from '@fusion.dev/helix-headless/color-picker';
9
9
  import '../../button/index.js';
10
10
  import '../../button-group/index.js';
11
- import '../../icon/index.js';
12
11
  import '../../slider/index.js';
13
12
  import { styles as glyphStyles } from '../../shared/glyph/glyph.css.js';
14
13
  import { styles } from './color-picker-root.css.js';
@@ -97,7 +97,7 @@ padding: var(--helix-space-none);
97
97
  position: absolute;
98
98
  }
99
99
 
100
- [part="create"] {
100
+ [part~="create"] {
101
101
  all: unset;
102
102
 
103
103
  border-block-start: var(--helix-border-thin) solid var(--helix-color-border);
@@ -114,14 +114,15 @@ text-align: start;
114
114
  transition: background-color var(--helix-duration-fast) var(--helix-easing-standard);
115
115
  }
116
116
 
117
- [part="create"]:hover {
117
+ [part~="create"]:hover,
118
+ [part~="create-active"] {
118
119
  background-color: light-dark(
119
120
  color-mix(in oklab, var(--helix-color-foreground) 8%, transparent),
120
121
  color-mix(in oklab, var(--helix-color-foreground) 12%, transparent)
121
122
  );
122
123
  }
123
124
 
124
- [part="create"]:focus-visible {
125
+ [part~="create"]:focus-visible {
125
126
  outline: var(--helix-size-focus-ring) solid var(--helix-color-focus-ring);
126
127
  outline-offset: calc(var(--helix-size-focus-offset) * -1);
127
128
  }
@@ -138,7 +139,7 @@ display: block;
138
139
  transition: none;
139
140
  }
140
141
 
141
- [part="create"] {
142
+ [part~="create"] {
142
143
  transition: none;
143
144
  }
144
145
  }
@@ -86,6 +86,13 @@ border-block-end-color: transparent;
86
86
  cursor: pointer;
87
87
  }
88
88
 
89
+ [part~="cell"]:focus-visible,
90
+ [part~="select"]:focus-visible,
91
+ [part="select-all"]:focus-visible {
92
+ outline: var(--helix-size-focus-ring) solid var(--helix-color-focus-ring);
93
+ outline-offset: calc(var(--helix-size-focus-offset) * -1);
94
+ }
95
+
89
96
  [part~="select"],
90
97
  [part="select-all"] {
91
98
  align-items: center;
@@ -56,12 +56,24 @@ inline-size: var(--_calendar-day);
56
56
  justify-content: center;
57
57
  }
58
58
 
59
- [part="previous"]:hover,
60
- [part="next"]:hover {
59
+ [part="previous"]:hover:not(:disabled),
60
+ [part="next"]:hover:not(:disabled) {
61
61
  background-color: var(--helix-color-surface-sunken);
62
62
  color: var(--helix-color-foreground);
63
63
  }
64
64
 
65
+ [part="previous"]:focus-visible,
66
+ [part="next"]:focus-visible {
67
+ outline: var(--helix-size-focus-ring) solid var(--helix-color-focus-ring);
68
+ outline-offset: var(--helix-size-focus-offset);
69
+ }
70
+
71
+ [part="previous"]:disabled,
72
+ [part="next"]:disabled {
73
+ cursor: default;
74
+ opacity: 0.4;
75
+ }
76
+
65
77
  [part="previous"] svg,
66
78
  [part="next"] svg,
67
79
  ::slotted([slot="previous-icon"]),
@@ -167,7 +179,7 @@ color: var(--helix-color-foreground-inverse);
167
179
  cursor: default;
168
180
  }
169
181
 
170
- [part~="cell"][aria-disabled] [part~="day"] {
182
+ [part~="day-disabled"] {
171
183
  color: var(--helix-color-foreground-subtle);
172
184
  opacity: 0.4;
173
185
  }
@@ -175,4 +175,14 @@ stroke-opacity: calc(0.62 * var(--helix-material-opacity));
175
175
 
176
176
  :host([material="frosted"]) [part~="segment"] {
177
177
  stroke-opacity: calc(0.88 * var(--helix-material-opacity));
178
+ }
179
+
180
+ [part="summary"] {
181
+ block-size: 1px;
182
+ clip-path: inset(50%);
183
+ inline-size: 1px;
184
+ margin: var(--helix-space-none);
185
+ overflow: hidden;
186
+ position: absolute;
187
+ white-space: nowrap;
178
188
  }`);
@@ -55,6 +55,8 @@ flex-direction: column;
55
55
  outline: none;
56
56
  position: fixed;
57
57
 
58
+ transform: var(--_drawer-away);
59
+
58
60
  transition:
59
61
  transform var(--helix-duration-normal) var(--helix-easing-decelerate),
60
62
  display var(--helix-duration-normal) allow-discrete,
@@ -62,6 +64,10 @@ overlay var(--helix-duration-normal) allow-discrete;
62
64
  z-index: var(--helix-layer-overlay);
63
65
  }
64
66
 
67
+ [part="panel"]:not([open]) {
68
+ display: none;
69
+ }
70
+
65
71
  :host([material="glass"]) [part="panel"] {
66
72
  backdrop-filter: var(--drawer-backdrop, var(--helix-material-backdrop));
67
73
  background-color: var(
@@ -84,7 +90,7 @@ block-size: 100%;
84
90
  inline-size: min(var(--_drawer-size), 100%);
85
91
  inset-block: 0;
86
92
  inset-inline-end: 0;
87
- transform: translateX(100%);
93
+ --_drawer-away: translateX(100%);
88
94
  }
89
95
 
90
96
  :host([placement="start"]) [part="panel"] {
@@ -94,7 +100,7 @@ block-size: 100%;
94
100
  inline-size: min(var(--_drawer-size), 100%);
95
101
  inset-block: 0;
96
102
  inset-inline-start: 0;
97
- transform: translateX(-100%);
103
+ --_drawer-away: translateX(-100%);
98
104
  }
99
105
 
100
106
  :host([placement="bottom"]) [part="panel"] {
@@ -103,7 +109,7 @@ border-end-end-radius: var(--helix-radii-none);
103
109
  block-size: min(var(--_drawer-size), 100%);
104
110
  inset-block-end: 0;
105
111
  inset-inline: 0;
106
- transform: translateY(100%);
112
+ --_drawer-away: translateY(100%);
107
113
  }
108
114
 
109
115
  :host([placement="top"]) [part="panel"] {
@@ -112,7 +118,16 @@ border-start-end-radius: var(--helix-radii-none);
112
118
  block-size: min(var(--_drawer-size), 100%);
113
119
  inset-block-start: 0;
114
120
  inset-inline: 0;
115
- transform: translateY(-100%);
121
+ --_drawer-away: translateY(-100%);
122
+ }
123
+
124
+ :host(:dir(rtl):not([placement])) [part="panel"],
125
+ :host(:dir(rtl)[placement="end"]) [part="panel"] {
126
+ --_drawer-away: translateX(-100%);
127
+ }
128
+
129
+ :host(:dir(rtl)[placement="start"]) [part="panel"] {
130
+ --_drawer-away: translateX(100%);
116
131
  }
117
132
 
118
133
  :host(:state(open)) [part="panel"] {
@@ -122,6 +137,12 @@ box-shadow: var(--drawer-shadow, var(--helix-shadow-floating));
122
137
  transform: translate(0, 0);
123
138
  }
124
139
 
140
+ @starting-style {
141
+ :host(:state(open)) [part="panel"][open] {
142
+ transform: var(--_drawer-away);
143
+ }
144
+ }
145
+
125
146
  [part="header"] {
126
147
  flex: 0 0 auto;
127
148
  }
@@ -19,9 +19,9 @@ registerElementEvents({
19
19
  'helix-remove',
20
20
  'helix-select',
21
21
  ],
22
- 'helix-carousel': ['helix-select'],
23
- 'helix-chat': ['helix-before-pin', 'helix-history', 'helix-send'],
24
- 'helix-chat-composer': ['helix-send'],
22
+ 'helix-carousel': ['helix-activate', 'helix-select'],
23
+ 'helix-chat': ['helix-before-pin', 'helix-history', 'helix-pin', 'helix-send'],
24
+ 'helix-chat-composer': ['helix-send', 'input'],
25
25
  'helix-chat-message': ['helix-send'],
26
26
  'helix-checkbox': ['change', 'helix-before-toggle', 'input'],
27
27
  'helix-checkbox-group': ['change', 'helix-before-change', 'input'],
@@ -51,14 +51,25 @@ registerElementEvents({
51
51
  'input',
52
52
  'toggle',
53
53
  ],
54
- 'helix-command': ['helix-before-close', 'helix-before-open', 'helix-select', 'toggle'],
54
+ 'helix-command': [
55
+ 'helix-before-close',
56
+ 'helix-before-open',
57
+ 'helix-filter',
58
+ 'helix-select',
59
+ 'toggle',
60
+ ],
55
61
  'helix-copy-button': ['helix-copy'],
56
62
  'helix-data-table': [
63
+ 'helix-activate',
57
64
  'helix-filter',
65
+ 'helix-filtered',
58
66
  'helix-navigate',
59
67
  'helix-reorder',
68
+ 'helix-reordered',
60
69
  'helix-select',
70
+ 'helix-selected',
61
71
  'helix-sort',
72
+ 'helix-sorted',
62
73
  ],
63
74
  'helix-date-input': [
64
75
  'change',
@@ -99,6 +110,7 @@ registerElementEvents({
99
110
  'helix-graph-zoom',
100
111
  ],
101
112
  'helix-heatmap': ['helix-resize'],
113
+ 'helix-icon': ['error'],
102
114
  'helix-image': ['error', 'load'],
103
115
  'helix-input': ['change', 'helix-before-change', 'input'],
104
116
  'helix-kbd': ['helix-shortcut'],
@@ -112,7 +124,10 @@ registerElementEvents({
112
124
  ],
113
125
  'helix-listbox': ['change', 'helix-before-change', 'helix-filter', 'input'],
114
126
  'helix-map': [
127
+ 'change',
115
128
  'helix-activate',
129
+ 'helix-before-change',
130
+ 'helix-before-toggle',
116
131
  'helix-map-cluster',
117
132
  'helix-map-pan',
118
133
  'helix-map-part-change',
@@ -133,18 +148,19 @@ registerElementEvents({
133
148
  'helix-map-terrain': ['helix-map-part-change'],
134
149
  'helix-megamenu': ['helix-before-close', 'helix-before-open', 'toggle'],
135
150
  'helix-menu': ['helix-before-close', 'helix-before-open', 'helix-select', 'toggle'],
136
- 'helix-menu-item': ['helix-select'],
151
+ 'helix-menu-item': ['helix-before-toggle', 'helix-select'],
137
152
  'helix-notification': ['helix-dismiss', 'helix-read'],
138
- 'helix-notification-group': ['helix-before-close', 'helix-before-open'],
153
+ 'helix-notification-group': ['helix-before-close', 'helix-before-open', 'toggle'],
139
154
  'helix-notifications': ['helix-dismiss', 'helix-read'],
140
155
  'helix-number-input': ['change', 'helix-before-change', 'input'],
141
156
  'helix-object-inspector': ['helix-copy'],
142
157
  'helix-option': ['helix-select'],
143
158
  'helix-outline': ['helix-activate'],
144
- 'helix-pagination': ['helix-navigate'],
145
- 'helix-pagination-size': ['helix-before-change'],
159
+ 'helix-pagination': ['helix-activate', 'helix-navigate'],
160
+ 'helix-pagination-size': ['change', 'helix-before-change', 'input'],
146
161
  'helix-pin-input': ['change', 'helix-before-change', 'helix-complete', 'input'],
147
162
  'helix-popover': ['helix-before-close', 'helix-before-open', 'toggle'],
163
+ 'helix-qr-code': ['error'],
148
164
  'helix-radio': ['helix-select'],
149
165
  'helix-radio-group': ['change', 'helix-before-change', 'helix-select', 'input'],
150
166
  'helix-rating': ['change', 'helix-before-change', 'input'],
@@ -163,17 +179,24 @@ registerElementEvents({
163
179
  'helix-before-change',
164
180
  'helix-before-close',
165
181
  'helix-before-open',
182
+ 'helix-filter',
166
183
  'input',
167
184
  'toggle',
168
185
  ],
169
186
  'helix-slider': ['change', 'helix-before-change', 'input'],
170
187
  'helix-speed-dial': ['helix-before-close', 'helix-before-open', 'helix-select', 'toggle'],
171
188
  'helix-speed-dial-item': ['helix-select'],
172
- 'helix-splitter': ['helix-before-collapse', 'helix-before-resize'],
189
+ 'helix-splitter': [
190
+ 'helix-before-collapse',
191
+ 'helix-before-resize',
192
+ 'helix-collapse',
193
+ 'helix-resized',
194
+ ],
173
195
  'helix-step': ['helix-select'],
174
196
  'helix-steps': ['helix-activate', 'helix-before-activate', 'helix-select'],
175
197
  'helix-switch': ['change', 'helix-before-toggle', 'input'],
176
198
  'helix-tab': ['helix-select'],
199
+ 'helix-table': ['helix-sort'],
177
200
  'helix-table-column': ['helix-before-resize'],
178
201
  'helix-tabs': ['helix-activate', 'helix-before-activate', 'helix-select'],
179
202
  'helix-tag': ['helix-dismiss'],
@@ -192,7 +215,15 @@ registerElementEvents({
192
215
  'helix-toggle': ['helix-select'],
193
216
  'helix-toggle-group': ['change', 'helix-before-change', 'helix-select', 'input'],
194
217
  'helix-tooltip': ['helix-before-close', 'helix-before-open', 'toggle'],
195
- 'helix-tour': ['helix-before-activate', 'helix-before-close', 'helix-complete', 'helix-tour-ask'],
218
+ 'helix-tour': [
219
+ 'helix-activate',
220
+ 'helix-before-activate',
221
+ 'helix-before-close',
222
+ 'helix-before-open',
223
+ 'helix-complete',
224
+ 'helix-tour-ask',
225
+ 'toggle',
226
+ ],
196
227
  'helix-tour-stop': ['helix-tour-ask'],
197
228
  'helix-tree': ['helix-activate', 'helix-before-activate', 'helix-select'],
198
229
  'helix-tree-item': ['helix-before-close', 'helix-before-open', 'helix-select', 'toggle'],
@@ -1,6 +1,5 @@
1
1
  import { HelixHeadlessFileInput } from '@fusion.dev/helix-headless/file-input';
2
2
  import type { CSSResultGroup } from 'lit';
3
- import '../../icon/index.js';
4
3
  import '../../tag/index.js';
5
4
  /**
6
5
  * @summary A field for choosing files from a picker or by dropping them on it.
@@ -6,7 +6,6 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
6
6
  };
7
7
  import { customElement } from '@fusion.dev/helix-core';
8
8
  import { HelixHeadlessFileInput } from '@fusion.dev/helix-headless/file-input';
9
- import '../../icon/index.js';
10
9
  import '../../tag/index.js';
11
10
  import { styles as fieldStyles } from '../../shared/field/field.css.js';
12
11
  import { styles as fieldFrameStyles } from '../../shared/field/field-frame.css.js';
@@ -1,6 +1,5 @@
1
1
  import { HelixHeadlessFilterInput } from '@fusion.dev/helix-headless/filter-input';
2
2
  import type { CSSResultGroup } from 'lit';
3
- import '../../icon/index.js';
4
3
  import '../../option/index.js';
5
4
  /**
6
5
  * @summary A text field for filters, with the active filters shown in it as tokens.
@@ -6,7 +6,6 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
6
6
  };
7
7
  import { customElement } from '@fusion.dev/helix-core';
8
8
  import { HelixHeadlessFilterInput } from '@fusion.dev/helix-headless/filter-input';
9
- import '../../icon/index.js';
10
9
  import '../../option/index.js';
11
10
  import { styles as fieldStyles } from '../../shared/field/field.css.js';
12
11
  import { styles as fieldFrameStyles } from '../../shared/field/field-frame.css.js';
@@ -42,6 +42,9 @@ export declare class HelixGrid extends HelixElement {
42
42
  alignItems?: 'start' | 'center' | 'end' | 'stretch';
43
43
  /**
44
44
  * A fixed number of equal columns.
45
+ *
46
+ * Two to six are plain CSS. Any other count is written into the shadow
47
+ * root's rule, which the server renders too.
45
48
  */
46
49
  columns?: number;
47
50
  /**
@@ -51,12 +54,17 @@ export declare class HelixGrid extends HelixElement {
51
54
  /**
52
55
  * The minimum column width. The grid fits as many columns as the width allows.
53
56
  *
57
+ * A length, such as `12rem`, or `calc()`, `clamp()`, `min()`, `max()` and
58
+ * `var()` over lengths. Anything else is refused with a warning, and the grid
59
+ * lays out by `columns`.
60
+ *
54
61
  * Takes precedence over `columns`: a grid that both fixes a count and reflows
55
62
  * is two intentions in one element.
56
63
  */
57
64
  min: string;
58
65
  /**
59
- * Writes the track list into the shadow root's own stylesheet.
66
+ * The rule the shadow root's own `<style>` holds: the reset, and the track
67
+ * list `min` or an unlisted `columns` asks for.
60
68
  *
61
69
  * Into a `<style>` rather than onto `this.style`, and the difference is
62
70
  * hydration. An inline style on the host is an attribute the element gives
@@ -64,10 +72,11 @@ export declare class HelixGrid extends HelixElement {
64
72
  * it and hydration reports a mismatch it will not patch up. The shadow root
65
73
  * is not part of the tree React hydrates, so a rule written there is free.
66
74
  *
67
- * The element is filled imperatively because Lit refuses expressions inside
68
- * `<style>`: it is an invalid binding location and throws while rendering
69
- * rather than at build time. Hence a static, empty element in the template
70
- * and its `textContent` set here.
75
+ * **Static text, so the server renders it.** Lit refuses an expression inside
76
+ * `<style>`, and a rule filled in after upgrade left a server-rendered `min`
77
+ * grid in one column until then. `unsafeStatic` joins the text into the
78
+ * template itself, so it is safe only because `min` passed `lengthOf` and a
79
+ * count is an integer.
71
80
  *
72
81
  * It sets a custom property rather than the track list itself. A shadow
73
82
  * root's adopted stylesheets cascade *after* its own `<style>` elements, and
@@ -75,13 +84,8 @@ export declare class HelixGrid extends HelixElement {
75
84
  * one in the stylesheet and every `min` grid came out a single column. The
76
85
  * stylesheet only ever reads `--_grid-template`, so there is nothing to
77
86
  * lose against.
78
- *
79
- * The consequence is that a server-rendered grid falls back to the
80
- * stylesheet's single column until it upgrades. That is why `columns` is also
81
- * expressed as plain CSS below: the fixed-count case, which can be enumerated,
82
- * needs no JavaScript at all, and only `min` depends on this.
83
87
  */
84
- private applyTemplate;
88
+ private templateRule;
85
89
  protected updated(changed: PropertyValues): void;
86
90
  protected render(): TemplateResult;
87
91
  static styles: CSSResultGroup;
@@ -4,36 +4,70 @@ 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 } from '@fusion.dev/helix-core';
8
- import { html } from 'lit';
7
+ import { customElement, HelixElement, reportRuntime } from '@fusion.dev/helix-core';
9
8
  import { property } from 'lit/decorators.js';
9
+ import { html, unsafeStatic } from 'lit/static-html.js';
10
10
  import { styles } from './grid-root.css.js';
11
11
  const UNINHERITED = '--grid-columns: initial; --_grid-template: initial;';
12
+ const NUMBER = /^-?(?:\d+\.?\d*|\.\d+)(?:px|r?em|r?ex|r?ch|r?lh|r?ic|r?cap|%|[sdl]?v(?:w|h|i|b|min|max)|cq(?:w|h|i|b|min|max)|cm|mm|in|pt|pc|q)?$/i;
13
+ const TOKEN = /\s+|(?:calc|clamp|min|max)\(|var\(--[\w-]+|-?(?:\d+\.?\d*|\.\d+)[a-z%]*|[(),+*/-]/giy;
14
+ const lengthOf = (value) => {
15
+ const min = value?.trim() ?? '';
16
+ if (min === '' || min.includes('/*')) {
17
+ return undefined;
18
+ }
19
+ if (!min.includes('(')) {
20
+ return NUMBER.test(min) && /[a-z%]$/i.test(min) ? min : undefined;
21
+ }
22
+ let depth = 0;
23
+ TOKEN.lastIndex = 0;
24
+ while (TOKEN.lastIndex < min.length) {
25
+ const at = TOKEN.lastIndex;
26
+ const token = TOKEN.exec(min)?.[0];
27
+ if (token === undefined || TOKEN.lastIndex === at) {
28
+ return undefined;
29
+ }
30
+ if (/\d/.test(token) && /^-?[\d.]/.test(token) && !NUMBER.test(token)) {
31
+ return undefined;
32
+ }
33
+ depth += token.endsWith('(') || token.startsWith('var(') ? 1 : token === ')' ? -1 : 0;
34
+ if (depth < 0) {
35
+ return undefined;
36
+ }
37
+ }
38
+ return depth === 0 ? min : undefined;
39
+ };
12
40
  let HelixGrid = class HelixGrid extends HelixElement {
13
41
  constructor() {
14
42
  super(...arguments);
15
43
  this.min = '';
16
44
  }
17
- applyTemplate() {
18
- const sheet = this.renderRoot.querySelector('#template');
19
- if (!sheet) {
20
- return;
45
+ templateRule() {
46
+ const min = lengthOf(this.min);
47
+ if (min !== undefined) {
48
+ return `:host { ${UNINHERITED} --_grid-template: repeat(auto-fit, minmax(min(${min}, 100%), 1fr)); }`;
21
49
  }
22
- const length = /^-?(?:\d+\.?\d*|\.\d+)(?:px|r?em|%|v[hw]|ch|ex|cm|mm|in|pt|pc|q)$/i;
23
- const min = this.min?.trim() ?? '';
24
- sheet.textContent =
25
- min !== '' && length.test(min)
26
- ? `:host { ${UNINHERITED} --_grid-template: repeat(auto-fit, minmax(min(${min}, 100%), 1fr)); }`
27
- : `:host { ${UNINHERITED} }`;
50
+ const count = Number(this.columns);
51
+ if (Number.isInteger(count) && count > 6) {
52
+ return `:host { ${UNINHERITED} --_grid-template: repeat(${count}, minmax(0, 1fr)); }`;
53
+ }
54
+ return `:host { ${UNINHERITED} }`;
28
55
  }
29
56
  updated(changed) {
30
57
  super.updated(changed);
31
- if (changed.has('min')) {
32
- this.applyTemplate();
58
+ const min = this.min?.trim() ?? '';
59
+ if (changed.has('min') && min !== '' && lengthOf(min) === undefined) {
60
+ reportRuntime({
61
+ kind: 'refused-length',
62
+ message: `<helix-grid min="${min}"> is not a length the grid can write, so it lays out by ` +
63
+ '`columns`. Write a length such as `12rem`, or `calc()`, `clamp()`, `min()`, `max()` ' +
64
+ 'or `var()` over lengths.',
65
+ tag: this.localName,
66
+ });
33
67
  }
34
68
  }
35
69
  render() {
36
- return html `<style id="template">:host { --grid-columns: initial; --_grid-template: initial; }</style>
70
+ return html `<style id="template">${unsafeStatic(this.templateRule())}</style>
37
71
  <slot></slot>`;
38
72
  }
39
73
  static { this.styles = styles; }