@fusion.dev/helix-headless 0.198.0 → 0.199.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 (53) hide show
  1. package/api.json +1 -1
  2. package/custom-elements.json +8267 -2270
  3. package/dist/carousel/root/carousel-root.d.ts +14 -0
  4. package/dist/carousel/root/carousel-root.js +15 -1
  5. package/dist/element-events.generated.js +19 -0
  6. package/dist/graph/root/graph-root.d.ts +33 -0
  7. package/dist/graph/root/graph-root.js +57 -0
  8. package/dist/index.d.ts +4 -0
  9. package/dist/index.js +4 -0
  10. package/dist/map/raster/map-raster.d.ts +7 -3
  11. package/dist/map/raster/map-raster.js +5 -3
  12. package/dist/motion-toggle/index.d.ts +1 -0
  13. package/dist/motion-toggle/index.js +1 -0
  14. package/dist/motion-toggle/root/motion-toggle-root.d.ts +77 -0
  15. package/dist/motion-toggle/root/motion-toggle-root.js +56 -0
  16. package/dist/spatial-bar-chart/bars.d.ts +79 -0
  17. package/dist/spatial-bar-chart/bars.js +72 -0
  18. package/dist/spatial-bar-chart/index.d.ts +2 -0
  19. package/dist/spatial-bar-chart/index.js +2 -0
  20. package/dist/spatial-bar-chart/root/spatial-bar-chart-root.d.ts +245 -0
  21. package/dist/spatial-bar-chart/root/spatial-bar-chart-root.js +262 -0
  22. package/dist/spatial-ribbon-chart/index.d.ts +2 -0
  23. package/dist/spatial-ribbon-chart/index.js +2 -0
  24. package/dist/spatial-ribbon-chart/ribbons.d.ts +55 -0
  25. package/dist/spatial-ribbon-chart/ribbons.js +99 -0
  26. package/dist/spatial-ribbon-chart/root/spatial-ribbon-chart-root.d.ts +243 -0
  27. package/dist/spatial-ribbon-chart/root/spatial-ribbon-chart-root.js +259 -0
  28. package/dist/spatial-scatter-chart/field.d.ts +8 -0
  29. package/dist/spatial-scatter-chart/root/spatial-scatter-chart-root.d.ts +14 -0
  30. package/dist/spatial-scatter-chart/root/spatial-scatter-chart-root.js +20 -6
  31. package/dist/spatial-scatter-chart/view.d.ts +14 -1
  32. package/dist/spatial-scatter-chart/view.js +29 -9
  33. package/dist/spatial-surface-chart/grid.d.ts +22 -0
  34. package/dist/spatial-surface-chart/grid.js +67 -1
  35. package/dist/spatial-surface-chart/index.d.ts +1 -1
  36. package/dist/spatial-surface-chart/index.js +1 -1
  37. package/dist/spatial-surface-chart/root/spatial-surface-chart-root.d.ts +20 -0
  38. package/dist/spatial-surface-chart/root/spatial-surface-chart-root.js +38 -5
  39. package/dist/spatial-treemap/blocks.d.ts +106 -0
  40. package/dist/spatial-treemap/blocks.js +215 -0
  41. package/dist/spatial-treemap/index.d.ts +2 -0
  42. package/dist/spatial-treemap/index.js +2 -0
  43. package/dist/spatial-treemap/root/spatial-treemap-root.d.ts +236 -0
  44. package/dist/spatial-treemap/root/spatial-treemap-root.js +249 -0
  45. package/dist/video/root/video-root.d.ts +14 -0
  46. package/dist/video/root/video-root.js +30 -2
  47. package/examples.json +1 -1
  48. package/lint.json +1 -1
  49. package/package.json +5 -5
  50. package/types/jsx.d.ts +3037 -99
  51. package/types/svelte.d.ts +4 -0
  52. package/types/vue.d.ts +519 -3
  53. package/types/words.d.ts +149 -0
@@ -0,0 +1,249 @@
1
+ import { __decorate } from "tslib";
2
+ import { AriaForwardController, CHART_PLOT, customElement, drawTooltip, formatWords, HelixElement, HelixPlotChangeEvent, HelixPlotTurnEvent, HelixReadingChangeEvent, HelixReadingPressEvent, isRtl, MixinChartSource, MixinChartStatus, spokenReading, words, } from '@fusion.dev/helix-core';
3
+ import { html, nothing, svg, } from 'lit';
4
+ import { property, state } from 'lit/decorators.js';
5
+ import '../../tooltip/index.js';
6
+ import { boundsOf, boxView, DragTurn, drawBox, SPATIAL_VIEW, turned, } from '../../spatial-scatter-chart/view.js';
7
+ import { blocksDrawn, paintOrder, treemapOf, } from '../blocks.js';
8
+ const TURNS = {
9
+ ArrowDown: { across: 0, up: -1 },
10
+ ArrowLeft: { across: -1, up: 0 },
11
+ ArrowRight: { across: 1, up: 0 },
12
+ ArrowUp: { across: 0, up: 1 },
13
+ };
14
+ const SERIES = 24;
15
+ let HelixHeadlessSpatialTreemap = class HelixHeadlessSpatialTreemap extends MixinChartStatus(MixinChartSource(HelixElement)) {
16
+ constructor() {
17
+ super(...arguments);
18
+ this.groupBy = '';
19
+ this.noBox = false;
20
+ this.plotLabel = '3D treemap';
21
+ this.summaryLabel = '{count, plural, one {# item} other {# items}} in {groups, plural, one {# group} other {# groups}}, sized from {low} to {high}.';
22
+ this.rendered = false;
23
+ this.camera = SPATIAL_VIEW;
24
+ this.drag = new DragTurn((next) => {
25
+ this.camera = next(this.camera);
26
+ }, () => this.requestUpdate());
27
+ this.told = -1;
28
+ this.aria = new AriaForwardController(this, {
29
+ target: () => this.partNamed('plot'),
30
+ });
31
+ this.onPlotKeydown = (event) => {
32
+ const turn = TURNS[event.key];
33
+ if (!event.shiftKey || !turn || event.altKey || event.ctrlKey || event.metaKey) {
34
+ return;
35
+ }
36
+ event.preventDefault();
37
+ event.stopPropagation();
38
+ this.camera = turned(this.camera, turn.across, turn.up);
39
+ this.dispatchEvent(new HelixPlotTurnEvent(turn));
40
+ };
41
+ this.onDrawingMove = (event) => {
42
+ if (this.drag.move(event)) {
43
+ return;
44
+ }
45
+ if (event.pointerType === 'touch') {
46
+ return;
47
+ }
48
+ this.requestActive(this.blockAt(event), event.pointerType === 'pen' ? 'pen' : 'mouse');
49
+ };
50
+ this.onDrawingDown = (event) => {
51
+ this.drag.down(event);
52
+ };
53
+ this.onDrawingCancel = (event) => {
54
+ this.drag.up(event);
55
+ };
56
+ this.onDrawingLeave = (event) => {
57
+ if (event.pointerType !== 'touch') {
58
+ this.requestActive(-1, 'mouse');
59
+ }
60
+ };
61
+ this.onDrawingTap = (event) => {
62
+ if (this.drag.up(event)) {
63
+ return;
64
+ }
65
+ if (event.pointerType === 'touch') {
66
+ this.requestActive(this.blockAt(event), 'touch');
67
+ }
68
+ };
69
+ }
70
+ static { this.words = 'helix-spatial-treemap'; }
71
+ get field() {
72
+ const rows = this.sourceRows;
73
+ const columns = this.plottedColumns;
74
+ if (this.memo?.rows !== rows ||
75
+ this.memo.columns !== columns ||
76
+ this.memo.groupBy !== this.groupBy) {
77
+ this.memo = {
78
+ columns,
79
+ field: treemapOf(rows, columns, this.groupBy),
80
+ groupBy: this.groupBy,
81
+ rows,
82
+ };
83
+ }
84
+ return this.memo.field;
85
+ }
86
+ get active() {
87
+ return this.pointer.at;
88
+ }
89
+ get readings() {
90
+ return this.field.blocks.length;
91
+ }
92
+ rendererDrawn(on = true) {
93
+ this.rendered = on;
94
+ this.toggleState('drawn', on);
95
+ }
96
+ requestActive(index, kind = 'mouse') {
97
+ if (kind === 'touch') {
98
+ this.pointer.tapTo(index);
99
+ }
100
+ else if (index >= 0 || !this.pointer.keyed) {
101
+ this.pointer.set(index);
102
+ }
103
+ }
104
+ placeReading(at) {
105
+ this.place = at;
106
+ }
107
+ connectedCallback() {
108
+ super.connectedCallback();
109
+ this.pointer.axis = 'none';
110
+ this.pointer.onReading = (heard, detail) => {
111
+ const block = this.field.blocks[detail.index];
112
+ const told = { ...detail, index: block?.row ?? -1, label: block?.label ?? '' };
113
+ this.dispatchEvent(heard === 'press' ? new HelixReadingPressEvent(told) : new HelixReadingChangeEvent(told));
114
+ };
115
+ }
116
+ updated(changed) {
117
+ super.updated(changed);
118
+ const field = this.field;
119
+ if (field !== this.last) {
120
+ this.last = field;
121
+ this.dispatchEvent(new HelixPlotChangeEvent({ kind: 'data' }));
122
+ }
123
+ if (this.pointer.at !== this.told) {
124
+ this.told = this.pointer.at;
125
+ this.dispatchEvent(new HelixPlotChangeEvent({ kind: 'focus' }));
126
+ }
127
+ if (changed.has('place')) {
128
+ ;
129
+ this.renderRoot.querySelector('[for="helix-chart-mark"]')?.reposition?.();
130
+ }
131
+ }
132
+ blockAt(event) {
133
+ const block = event.composedPath()[0]?.closest?.('[data-index]');
134
+ const index = Number(block?.getAttribute('data-index') ?? -1);
135
+ return Number.isInteger(index) ? index : -1;
136
+ }
137
+ render() {
138
+ const field = this.field;
139
+ const readable = field.blocks.length > 0;
140
+ const at = this.pointer.at;
141
+ return html `<div
142
+ aria-describedby=${readable ? 'helix-chart-summary' : nothing}
143
+ aria-label=${this.named || this.plotLabel}
144
+ id=${CHART_PLOT}
145
+ part="plot"
146
+ role=${readable ? 'application' : 'img'}
147
+ tabindex=${readable ? '0' : nothing}
148
+ @keydown=${this.onPlotKeydown}
149
+ >
150
+ <slot></slot>
151
+ ${readable ? this.renderFallback(field, at) : nothing}
152
+ ${readable ? this.renderLive(field, at) : nothing}
153
+ ${this.renderTooltip(field.blocks[at]?.row)}
154
+ </div>
155
+ ${readable ? this.renderSummary(field) : this.renderStatus()}${this.renderTable()}`;
156
+ }
157
+ renderFallback(field, at) {
158
+ const view = boxView(field.axes, this.camera, [], this.noBox);
159
+ const blocks = blocksDrawn(field, view.projection);
160
+ const active = blocks[at];
161
+ const bounds = this.drag.frame(this.noBox
162
+ ? boundsOf(blocks.flatMap((block) => block.corners), 0.1)
163
+ : view.bounds, view.on([0, 0, 0]));
164
+ return html `<div aria-hidden="true" dir="ltr" ?hidden=${this.rendered} part="fallback">
165
+ <svg
166
+ part="drawing"
167
+ preserveAspectRatio="xMidYMid meet"
168
+ viewBox="${bounds.x} ${bounds.y} ${bounds.width} ${bounds.height}"
169
+ xmlns="http://www.w3.org/2000/svg"
170
+ @click=${this.drag.click}
171
+ @pointercancel=${this.onDrawingCancel}
172
+ @pointerdown=${this.onDrawingDown}
173
+ @pointerleave=${this.onDrawingLeave}
174
+ @pointermove=${this.onDrawingMove}
175
+ @pointerup=${this.onDrawingTap}
176
+ >${this.noBox ? nothing : drawBox(view)}${paintOrder(view.projection, blocks).map((block) => svg `${this.renderBlock(field, block, at)}${block === active ? svg `<path d=${active.drawn.outline} part="ring"></path>` : nothing}`)}${active
177
+ ? svg `<foreignObject height="0.001" overflow="visible" width="0.001" x=${active.drawn.peak.x} y=${active.drawn.peak.y}>${this.renderOwnTooltip(field.blocks[at]?.row)}</foreignObject>`
178
+ : nothing}</svg>
179
+ </div>`;
180
+ }
181
+ renderBlock(field, block, at) {
182
+ const group = field.blocks[block.index]?.groupIndex ?? 0;
183
+ const short = (value) => Math.round(value * 1000) / 1000;
184
+ return svg `<g data-index=${block.index} part="block${block.index === at ? ' block-active' : ''}" style="--chart-series: var(--chart-series-${(group % SERIES) + 1})">${block.drawn.faces.map((face) => svg `<path d=${face.d} part="face" style="--spatial-treemap-shade: ${short(face.darken)}"></path>`)}</g>`;
185
+ }
186
+ renderLive(field, at) {
187
+ const row = this.sourceRows[field.blocks[at]?.row ?? -1];
188
+ const said = this.pointer.keyed && row
189
+ ? spokenReading(row, this.pointer.column, (cell) => this.pointer.shows(cell), this.pointer.position)
190
+ : '';
191
+ return html `<span aria-live="polite" part="live" role="status">${said}</span>`;
192
+ }
193
+ renderOwnTooltip(row) {
194
+ if (this.rendered || row === undefined || !this.sourceRows[row]) {
195
+ return nothing;
196
+ }
197
+ return drawTooltip(this.sourceRows, row, this.tag('tooltip'), { dir: isRtl(this) ? 'rtl' : 'ltr', fixed: true, placement: 'top', x: '0%', y: '0%' }, () => undefined);
198
+ }
199
+ renderTooltip(row) {
200
+ const place = this.place;
201
+ if (!this.rendered || !place || row === undefined || !this.sourceRows[row]) {
202
+ return nothing;
203
+ }
204
+ return drawTooltip(this.sourceRows, row, this.tag('tooltip'), {
205
+ dir: isRtl(this) ? 'rtl' : 'ltr',
206
+ fixed: true,
207
+ placement: 'top',
208
+ x: `${place.x * 100}%`,
209
+ y: `${place.y * 100}%`,
210
+ }, () => undefined);
211
+ }
212
+ renderSummary(field) {
213
+ const sizes = field.blocks.map((block) => block.size);
214
+ const said = formatWords(this, 'summaryLabel', {
215
+ count: field.blocks.length,
216
+ groups: field.groups.length,
217
+ high: Math.max(...sizes),
218
+ low: Math.min(...sizes),
219
+ });
220
+ return html `<p id="helix-chart-summary" part="summary">${said}</p>`;
221
+ }
222
+ };
223
+ __decorate([
224
+ property({ attribute: 'group-by' })
225
+ ], HelixHeadlessSpatialTreemap.prototype, "groupBy", void 0);
226
+ __decorate([
227
+ property({ attribute: 'no-box', reflect: true, type: Boolean })
228
+ ], HelixHeadlessSpatialTreemap.prototype, "noBox", void 0);
229
+ __decorate([
230
+ words,
231
+ property({ attribute: 'plot-label' })
232
+ ], HelixHeadlessSpatialTreemap.prototype, "plotLabel", void 0);
233
+ __decorate([
234
+ words,
235
+ property({ attribute: 'summary-label' })
236
+ ], HelixHeadlessSpatialTreemap.prototype, "summaryLabel", void 0);
237
+ __decorate([
238
+ state()
239
+ ], HelixHeadlessSpatialTreemap.prototype, "rendered", void 0);
240
+ __decorate([
241
+ state()
242
+ ], HelixHeadlessSpatialTreemap.prototype, "camera", void 0);
243
+ __decorate([
244
+ state()
245
+ ], HelixHeadlessSpatialTreemap.prototype, "place", void 0);
246
+ HelixHeadlessSpatialTreemap = __decorate([
247
+ customElement('helix-headless-spatial-treemap')
248
+ ], HelixHeadlessSpatialTreemap);
249
+ export { HelixHeadlessSpatialTreemap };
@@ -196,6 +196,12 @@ export declare class HelixHeadlessVideo extends HelixElement {
196
196
  * permitted is the browser's policy, and what follows a refused autoplay is a
197
197
  * paused player showing its start control, which is the correct thing to be
198
198
  * looking at.
199
+ *
200
+ * **Not where the reader asked for less motion**, or while the page has
201
+ * paused its motion, through `pauseMotion` or `Motion Toggle`: the player
202
+ * waits on its start control. A page that pauses its motion pauses a video
203
+ * that started itself, and one that lets it run again plays it again. A
204
+ * video the reader started is theirs, and neither touches it.
199
205
  */
200
206
  autoplay: boolean;
201
207
  /**
@@ -842,6 +848,14 @@ export declare class HelixHeadlessVideo extends HelixElement {
842
848
  * render that draws them.
843
849
  */
844
850
  protected willUpdate(changed: PropertyValues): void;
851
+ /** What stops hearing the page's pause. */
852
+ private unpaused;
853
+ /** Whether the page's pause stopped a video that started itself, which letting motion run starts again. */
854
+ private heldByPage;
855
+ connectedCallback(): void;
856
+ disconnectedCallback(): void;
857
+ /** The page paused its motion, or let it run again, which a video that started itself follows. */
858
+ private readonly handlePageMotion;
845
859
  protected firstUpdated(changed: PropertyValues): void;
846
860
  /**
847
861
  * Mirrors playback onto the host as `data-playing`.
@@ -1,5 +1,5 @@
1
1
  import { __decorate } from "tslib";
2
- import { activeCue, adoptTrack, auditName, CueController, captionsAmong, captionTracks, copiesOf, customElement, drawIcon, FullscreenController, formatWords, HelixElement, HelixNextEvent, HelixPreviousEvent, IdleController, MediaSessionController, onUnlessFalse, RemotePlaybackController, reportRuntime, SKIP_SECONDS, sameCopies, showCaption, words, writtenList, writtenNumbers, } from '@fusion.dev/helix-core';
2
+ import { activeCue, adoptTrack, auditName, CueController, captionsAmong, captionTracks, copiesOf, customElement, drawIcon, FullscreenController, formatWords, HelixElement, HelixNextEvent, HelixPreviousEvent, IdleController, MediaSessionController, motionPaused, onMotionChange, onUnlessFalse, RemotePlaybackController, reducedMotion, reportRuntime, SKIP_SECONDS, sameCopies, showCaption, words, writtenList, writtenNumbers, } from '@fusion.dev/helix-core';
3
3
  import { airplay, arrowClockwise, arrowCounterClockwise, closedCaptioning, cornersIn, cornersOut, dotsThreeVertical, download, gauge, pause, pictureInPicture, play, skipBack, skipForward, speakerHigh, speakerX, } from '@fusion.dev/helix-icons';
4
4
  import { nothing } from 'lit';
5
5
  import { property, state } from 'lit/decorators.js';
@@ -216,6 +216,21 @@ let HelixHeadlessVideo = class HelixHeadlessVideo extends HelixElement {
216
216
  };
217
217
  this.said = '';
218
218
  this.captions = [];
219
+ this.heldByPage = false;
220
+ this.handlePageMotion = (paused) => {
221
+ const video = this.video;
222
+ if (!video || !this.autoplay) {
223
+ return;
224
+ }
225
+ if (paused && !video.paused) {
226
+ this.heldByPage = true;
227
+ video.pause();
228
+ }
229
+ else if (!paused && this.heldByPage) {
230
+ this.heldByPage = false;
231
+ void this.play();
232
+ }
233
+ };
219
234
  }
220
235
  static { this.words = 'helix-video'; }
221
236
  get conditions() {
@@ -456,9 +471,22 @@ let HelixHeadlessVideo = class HelixHeadlessVideo extends HelixElement {
456
471
  this.captionCount = this.captions.length;
457
472
  }
458
473
  }
474
+ connectedCallback() {
475
+ super.connectedCallback();
476
+ this.unpaused ??= onMotionChange(this.handlePageMotion);
477
+ }
478
+ disconnectedCallback() {
479
+ super.disconnectedCallback();
480
+ this.unpaused?.();
481
+ this.unpaused = undefined;
482
+ }
459
483
  firstUpdated(changed) {
460
484
  super.firstUpdated?.(changed);
461
485
  this.finishHydration();
486
+ if (this.autoplay && (reducedMotion() || motionPaused())) {
487
+ this.heldByPage = motionPaused();
488
+ this.video?.pause();
489
+ }
462
490
  auditName(this, () => null, 'video', () => this.label !== '');
463
491
  const video = this.video;
464
492
  if (video) {
@@ -867,7 +895,7 @@ let HelixHeadlessVideo = class HelixHeadlessVideo extends HelixElement {
867
895
  poster=${this.poster || nothing}
868
896
  preload=${this.preload}
869
897
  crossorigin=${this.crossOrigin ?? nothing}
870
- ?autoplay=${this.autoplay}
898
+ ?autoplay=${this.autoplay && !reducedMotion() && !motionPaused()}
871
899
  ?controls=${this.controls}
872
900
  ?disablepictureinpicture=${this.disablePictureInPicture}
873
901
  ?disableremoteplayback=${this.disableRemotePlayback}