@fusion.dev/helix 0.217.0 → 0.219.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 (102) hide show
  1. package/api.json +1 -1
  2. package/custom-elements.json +1 -1
  3. package/dist/breadcrumbs/breadcrumb/breadcrumb.css.js +1 -1
  4. package/dist/canvas/root/canvas-root.d.ts +1 -0
  5. package/dist/canvas/root/canvas-root.js +1 -0
  6. package/dist/chat/composer/chat-composer.css.js +1 -1
  7. package/dist/chat/composer/chat-composer.d.ts +102 -5
  8. package/dist/chat/composer/chat-composer.js +134 -0
  9. package/dist/chat/message/chat-message.css.js +1 -1
  10. package/dist/chat/message/chat-message.d.ts +1 -0
  11. package/dist/checkbox/root/checkbox-root.css.js +1 -1
  12. package/dist/color-input/root/color-input-root.d.ts +1 -3
  13. package/dist/combobox/root/combobox-root.d.ts +1 -2
  14. package/dist/command/root/command-root.css.js +1 -1
  15. package/dist/command/root/command-root.d.ts +16 -1
  16. package/dist/command/root/command-root.js +16 -0
  17. package/dist/date-input/root/date-input-root.d.ts +1 -2
  18. package/dist/device-screen/root/device-screen-root.d.ts +1 -0
  19. package/dist/device-screen/root/device-screen-root.js +1 -0
  20. package/dist/dialog/root/dialog-root.css.js +1 -1
  21. package/dist/dialog/root/dialog-root.d.ts +14 -2
  22. package/dist/dialog/root/dialog-root.js +3 -0
  23. package/dist/drawer/root/drawer-root.css.js +1 -1
  24. package/dist/drawer/root/drawer-root.d.ts +1 -2
  25. package/dist/element-events.generated.js +1 -0
  26. package/dist/graph/root/graph-root.d.ts +1 -0
  27. package/dist/graph/root/graph-root.js +1 -0
  28. package/dist/index.d.ts +1 -0
  29. package/dist/index.js +1 -0
  30. package/dist/kbd/root/kbd-root.css.js +1 -1
  31. package/dist/log/group/log-group.css.js +1 -1
  32. package/dist/log/line/log-line.css.js +1 -1
  33. package/dist/log/root/log-root.css.js +1 -1
  34. package/dist/log/root/log-root.d.ts +5 -1
  35. package/dist/map/root/map-root.css.js +1 -1
  36. package/dist/map/root/map-root.d.ts +1 -0
  37. package/dist/map/root/map-root.js +1 -0
  38. package/dist/megamenu/root/megamenu-root.css.js +1 -1
  39. package/dist/megamenu/root/megamenu-root.d.ts +2 -2
  40. package/dist/menu/item/menu-item.css.js +1 -1
  41. package/dist/menu/root/menu-root.css.js +1 -1
  42. package/dist/menu/root/menu-root.d.ts +19 -1
  43. package/dist/menu/root/menu-root.js +4 -0
  44. package/dist/menu/section/menu-section.css.js +1 -1
  45. package/dist/meter/index.d.ts +1 -0
  46. package/dist/meter/index.js +1 -0
  47. package/dist/meter/root/meter-root.css.js +1 -1
  48. package/dist/meter/segment/meter-segment.css.d.ts +1 -0
  49. package/dist/meter/segment/meter-segment.css.js +2 -0
  50. package/dist/meter/segment/meter-segment.d.ts +39 -0
  51. package/dist/meter/segment/meter-segment.js +11 -0
  52. package/dist/popover/root/popover-root.css.js +1 -1
  53. package/dist/popover/root/popover-root.d.ts +20 -2
  54. package/dist/popover/root/popover-root.js +3 -0
  55. package/dist/radio/root/radio-root.css.js +1 -1
  56. package/dist/scroll-area/root/scroll-area-root.css.js +1 -1
  57. package/dist/scroll-area/root/scroll-area-root.d.ts +14 -2
  58. package/dist/scroll-area/root/scroll-area-root.js +29 -0
  59. package/dist/select/root/select-root.d.ts +1 -2
  60. package/dist/shared/floating/entrance.css.js +1 -1
  61. package/dist/skip-link/root/skip-link-root.d.ts +1 -2
  62. package/dist/spatial-bar-chart/root/spatial-bar-chart-root.css.js +1 -1
  63. package/dist/spatial-bar-chart/root/spatial-bar-chart-root.d.ts +9 -1
  64. package/dist/strands/renderer.d.ts +2 -0
  65. package/dist/strands/renderer.js +1 -0
  66. package/dist/strands/root/strands-root.css.js +1 -1
  67. package/dist/strands/root/strands-root.d.ts +14 -0
  68. package/dist/strands/root/strands-root.js +5 -0
  69. package/dist/strands/shader.d.ts +7 -1
  70. package/dist/strands/shader.js +11 -3
  71. package/dist/switch/root/switch-root.css.js +1 -1
  72. package/dist/tabs/root/tabs-root.css.js +1 -1
  73. package/dist/tabs/root/tabs-root.d.ts +36 -0
  74. package/dist/tabs/root/tabs-root.js +7 -0
  75. package/dist/tabs/tab/tab.css.js +1 -1
  76. package/dist/tabs/tab/tab.d.ts +2 -0
  77. package/dist/terminal/root/terminal-root.d.ts +1 -0
  78. package/dist/terminal/root/terminal-root.js +1 -0
  79. package/dist/time-input/root/time-input-root.d.ts +1 -2
  80. package/dist/toast/item/toast-item.d.ts +1 -2
  81. package/dist/tooltip/root/tooltip-root.css.js +1 -1
  82. package/dist/tour/root/tour-root.css.js +1 -1
  83. package/dist/tour/stop/tour-stop.d.ts +1 -2
  84. package/dist/tree/item/tree-item.css.js +1 -1
  85. package/dist/tree/root/tree-root.css.js +1 -1
  86. package/dist/tree/root/tree-root.d.ts +5 -1
  87. package/dist/voice-level/draw.d.ts +108 -0
  88. package/dist/voice-level/draw.js +53 -0
  89. package/dist/voice-level/index.d.ts +2 -0
  90. package/dist/voice-level/index.js +1 -0
  91. package/dist/voice-level/root/voice-level-root.css.d.ts +1 -0
  92. package/dist/voice-level/root/voice-level-root.css.js +2 -0
  93. package/dist/voice-level/root/voice-level-root.d.ts +186 -0
  94. package/dist/voice-level/root/voice-level-root.js +324 -0
  95. package/examples.json +1 -1
  96. package/lint.json +1 -1
  97. package/package.json +6 -6
  98. package/skills/helix/SKILL.md +2 -2
  99. package/types/jsx.d.ts +2145 -89
  100. package/types/svelte.d.ts +2 -0
  101. package/types/vue.d.ts +515 -26
  102. package/types/words.d.ts +15 -0
@@ -0,0 +1,324 @@
1
+ import { __decorate } from "tslib";
2
+ import { customElement, HelixElement, hostAria, numberConverter, PaintGateController, readColorAlpha, words, writtenNumbers, } from '@fusion.dev/helix-core';
3
+ import { html } from 'lit';
4
+ import { property } from 'lit/decorators.js';
5
+ import { bandFor, barCount, centered, ease, envelope, QUIET_STOP, SILENT, STILL_TIME, stillLength, unit, WAVE_LINES, waveAt, } from '../draw.js';
6
+ import { styles } from './voice-level-root.css.js';
7
+ const GRAY = 'rgba(128,128,128,1)';
8
+ const FAINT = 0.45;
9
+ const TRACK = 0.18;
10
+ const WAVE_STEP = 2;
11
+ const ink = (value, alpha = 1) => {
12
+ const read = readColorAlpha(value);
13
+ return read ? `rgba(${read[0]},${read[1]},${read[2]},${read[3] * alpha})` : GRAY;
14
+ };
15
+ let HelixVoiceLevel = class HelixVoiceLevel extends HelixElement {
16
+ constructor() {
17
+ super(...arguments);
18
+ this.bands = '';
19
+ this.fallbackLabel = 'Voice level';
20
+ this.label = '';
21
+ this.level = 0;
22
+ this.still = false;
23
+ this.context = null;
24
+ this.lost = false;
25
+ this.width = 0;
26
+ this.height = 0;
27
+ this.shown = [];
28
+ this.swing = 0;
29
+ this.time = 0;
30
+ this.quiet = 0;
31
+ this.resting = false;
32
+ this.gate = new PaintGateController(this, {
33
+ canRun: () => !!this.context && !this.lost && !this.resting && !this.still,
34
+ onFrame: (delta) => {
35
+ this.step(delta);
36
+ this.paint();
37
+ if (this.quiet >= QUIET_STOP) {
38
+ this.resting = true;
39
+ this.gate.stop();
40
+ }
41
+ },
42
+ onMotion: () => {
43
+ this.paint();
44
+ },
45
+ onResize: () => {
46
+ this.measure();
47
+ this.paint();
48
+ },
49
+ });
50
+ this.handleRestyle = () => {
51
+ if (!this.gate.running) {
52
+ this.paint();
53
+ }
54
+ };
55
+ this.handleLost = () => {
56
+ this.lost = true;
57
+ this.gate.stop();
58
+ this.canvas?.toggleAttribute('hidden', true);
59
+ };
60
+ this.handleRestored = () => {
61
+ this.lost = false;
62
+ this.canvas?.toggleAttribute('hidden', false);
63
+ this.width = 0;
64
+ this.height = 0;
65
+ this.measure();
66
+ this.paint();
67
+ this.gate.play();
68
+ };
69
+ }
70
+ static { this.words = 'helix-voice-level'; }
71
+ static { this.styles = styles; }
72
+ willUpdate(changed) {
73
+ super.willUpdate(changed);
74
+ hostAria(this.internals, { label: this.label || this.fallbackLabel, role: 'img' });
75
+ if (changed.has('level') ||
76
+ changed.has('bands') ||
77
+ changed.has('still') ||
78
+ changed.has('variant')) {
79
+ this.wake();
80
+ }
81
+ }
82
+ render() {
83
+ return html `<canvas part="canvas" aria-hidden="true"></canvas>`;
84
+ }
85
+ firstUpdated(changed) {
86
+ super.firstUpdated(changed);
87
+ this.start();
88
+ }
89
+ connectedCallback() {
90
+ super.connectedCallback();
91
+ if (this.hasUpdated) {
92
+ this.start();
93
+ }
94
+ }
95
+ disconnectedCallback() {
96
+ super.disconnectedCallback();
97
+ this.width = 0;
98
+ this.height = 0;
99
+ this.canvas?.removeEventListener('contextlost', this.handleLost);
100
+ this.canvas?.removeEventListener('contextrestored', this.handleRestored);
101
+ this.canvas?.removeEventListener('transitionend', this.handleRestyle);
102
+ }
103
+ get readings() {
104
+ return writtenNumbers(this.bands).map(unit);
105
+ }
106
+ get sounding() {
107
+ return unit(this.level) > SILENT || this.readings.some((band) => band > SILENT);
108
+ }
109
+ wake() {
110
+ if (!this.context) {
111
+ return;
112
+ }
113
+ if (this.still) {
114
+ this.gate.stop();
115
+ this.paint();
116
+ return;
117
+ }
118
+ if (this.gate.reduced) {
119
+ this.paint();
120
+ return;
121
+ }
122
+ if (this.sounding) {
123
+ this.resting = false;
124
+ this.quiet = 0;
125
+ this.gate.play();
126
+ }
127
+ else if (!this.gate.running) {
128
+ this.paint();
129
+ }
130
+ }
131
+ start() {
132
+ if (!this.isConnected) {
133
+ return;
134
+ }
135
+ const canvas = this.renderRoot.querySelector('canvas');
136
+ if (!canvas) {
137
+ return;
138
+ }
139
+ this.canvas = canvas;
140
+ this.context ??= canvas.getContext('2d');
141
+ if (!this.context) {
142
+ return;
143
+ }
144
+ canvas.addEventListener('contextlost', this.handleLost);
145
+ canvas.addEventListener('contextrestored', this.handleRestored);
146
+ canvas.addEventListener('transitionend', this.handleRestyle);
147
+ if (this.lost && !this.context.isContextLost()) {
148
+ this.lost = false;
149
+ canvas.toggleAttribute('hidden', false);
150
+ }
151
+ this.gate.watch();
152
+ this.measure();
153
+ this.paint();
154
+ this.resting = !this.sounding;
155
+ this.gate.play();
156
+ }
157
+ measure() {
158
+ const canvas = this.canvas;
159
+ if (!canvas) {
160
+ return false;
161
+ }
162
+ const box = this.getBoundingClientRect();
163
+ const width = Math.round(box.width);
164
+ const height = Math.round(box.height);
165
+ if (width <= 0 || height <= 0 || (width === this.width && height === this.height)) {
166
+ return false;
167
+ }
168
+ this.width = width;
169
+ this.height = height;
170
+ const dpr = Math.min(2, window.devicePixelRatio || 1);
171
+ canvas.width = Math.round(width * dpr);
172
+ canvas.height = Math.round(height * dpr);
173
+ this.context?.setTransform(dpr, 0, 0, dpr, 0, 0);
174
+ return true;
175
+ }
176
+ step(delta) {
177
+ const count = this.bars;
178
+ const readings = this.readings;
179
+ if (this.shown.length !== count) {
180
+ this.shown = Array.from({ length: count }, (_, at) => this.shown[at] ?? 0);
181
+ }
182
+ let top = 0;
183
+ for (let at = 0; at < count; at++) {
184
+ const target = bandFor(readings, this.level, at, count) * envelope(at, count);
185
+ const next = ease(this.shown[at] ?? 0, target, delta);
186
+ this.shown[at] = next;
187
+ top = Math.max(top, next, target);
188
+ }
189
+ const level = unit(this.level);
190
+ this.swing = ease(this.swing, level, delta);
191
+ this.time += delta;
192
+ top = Math.max(top, this.swing, level);
193
+ this.quiet = top > SILENT ? 0 : this.quiet + delta;
194
+ }
195
+ settle() {
196
+ const count = this.bars;
197
+ const readings = this.readings;
198
+ this.shown = Array.from({ length: count }, (_, at) => bandFor(readings, this.level, at, count) * envelope(at, count));
199
+ this.swing = unit(this.level);
200
+ this.time = STILL_TIME;
201
+ }
202
+ get bars() {
203
+ return this.canvas ? barCount(getComputedStyle(this.canvas).animationIterationCount) : 0;
204
+ }
205
+ paint() {
206
+ const ctx = this.context;
207
+ const canvas = this.canvas;
208
+ if (!ctx || !canvas || this.width <= 0 || this.height <= 0) {
209
+ return;
210
+ }
211
+ const painted = getComputedStyle(canvas);
212
+ const main = ink(painted.color);
213
+ ctx.clearRect(0, 0, this.width, this.height);
214
+ if (this.still) {
215
+ this.settle();
216
+ }
217
+ if (this.gate.reduced && !this.still) {
218
+ this.paintStill(ctx, main, ink(painted.color, TRACK));
219
+ }
220
+ else if (this.variant === 'waves') {
221
+ this.paintWaves(ctx, main, painted, this.still ? STILL_TIME : this.time);
222
+ }
223
+ else {
224
+ this.paintSpectrum(ctx, main, ink(painted.textDecorationColor));
225
+ }
226
+ }
227
+ paintSpectrum(ctx, main, edge) {
228
+ const count = this.bars;
229
+ if (this.shown.length !== count) {
230
+ this.step(0);
231
+ }
232
+ const slot = this.width / count;
233
+ const thickness = Math.min(4, Math.max(1.5, slot * 0.5));
234
+ const middle = this.height / 2;
235
+ const center = new Path2D();
236
+ const ends = new Path2D();
237
+ for (let at = 0; at < count; at++) {
238
+ const tall = thickness + (this.shown[at] ?? 0) * (this.height - thickness);
239
+ const path = centered(at, count) ? center : ends;
240
+ rounded(path, slot * (at + 0.5) - thickness / 2, middle - tall / 2, thickness, tall);
241
+ }
242
+ ctx.fillStyle = edge;
243
+ ctx.fill(ends);
244
+ ctx.fillStyle = main;
245
+ ctx.fill(center);
246
+ }
247
+ paintWaves(ctx, main, painted, time) {
248
+ const middle = this.height / 2;
249
+ const colors = {
250
+ accent: ink(painted.columnRuleColor),
251
+ faint: ink(painted.color, FAINT),
252
+ main,
253
+ };
254
+ ctx.lineCap = 'round';
255
+ ctx.lineJoin = 'round';
256
+ for (const line of WAVE_LINES) {
257
+ const reach = Math.max(0, middle - line.width) * this.swing;
258
+ ctx.beginPath();
259
+ for (let x = 0; x <= this.width; x += WAVE_STEP) {
260
+ const y = middle - reach * waveAt(line, x / this.width, time);
261
+ if (x === 0) {
262
+ ctx.moveTo(x, y);
263
+ }
264
+ else {
265
+ ctx.lineTo(x, y);
266
+ }
267
+ }
268
+ ctx.lineTo(this.width, middle);
269
+ ctx.lineWidth = line.width;
270
+ ctx.strokeStyle = colors[line.ink];
271
+ ctx.stroke();
272
+ }
273
+ }
274
+ paintStill(ctx, main, faint) {
275
+ const thickness = this.variant === 'waves'
276
+ ? 2
277
+ : Math.min(4, Math.max(1.5, (this.width / (this.bars || 1)) * 0.5));
278
+ const readings = this.readings;
279
+ const level = this.level > 0 || readings.length === 0
280
+ ? this.level
281
+ : Math.max(...readings.map((band, at) => band * envelope(at, readings.length)));
282
+ const length = stillLength(level, this.width, thickness);
283
+ const top = (this.height - thickness) / 2;
284
+ const track = new Path2D();
285
+ rounded(track, 0, top, this.width, thickness);
286
+ ctx.fillStyle = faint;
287
+ ctx.fill(track);
288
+ const path = new Path2D();
289
+ rounded(path, (this.width - length) / 2, top, length, thickness);
290
+ ctx.fillStyle = main;
291
+ ctx.fill(path);
292
+ }
293
+ };
294
+ __decorate([
295
+ property()
296
+ ], HelixVoiceLevel.prototype, "bands", void 0);
297
+ __decorate([
298
+ words,
299
+ property({ attribute: 'fallback-label' })
300
+ ], HelixVoiceLevel.prototype, "fallbackLabel", void 0);
301
+ __decorate([
302
+ property()
303
+ ], HelixVoiceLevel.prototype, "label", void 0);
304
+ __decorate([
305
+ property({ converter: numberConverter('level', 0) })
306
+ ], HelixVoiceLevel.prototype, "level", void 0);
307
+ __decorate([
308
+ property({ type: Boolean })
309
+ ], HelixVoiceLevel.prototype, "still", void 0);
310
+ __decorate([
311
+ property({ reflect: true })
312
+ ], HelixVoiceLevel.prototype, "variant", void 0);
313
+ HelixVoiceLevel = __decorate([
314
+ customElement('helix-voice-level')
315
+ ], HelixVoiceLevel);
316
+ export { HelixVoiceLevel };
317
+ const rounded = (path, x, y, width, height) => {
318
+ if (typeof path.roundRect === 'function') {
319
+ path.roundRect(x, y, width, height, Math.min(width, height) / 2);
320
+ }
321
+ else {
322
+ path.rect(x, y, width, height);
323
+ }
324
+ };