@fusion.dev/helix-headless 0.184.0 → 0.186.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.
- package/custom-elements.json +3796 -1105
- package/dist/accordion/item/accordion-item.js +1 -1
- package/dist/button-group/root/button-group-root.js +1 -1
- package/dist/canvas/root/canvas-root.js +1 -1
- package/dist/data-table/root/data-table-root.d.ts +25 -6
- package/dist/data-table/root/data-table-root.js +21 -9
- package/dist/dialog/root/dialog-root.js +1 -1
- package/dist/drawer/root/drawer-root.js +1 -1
- package/dist/drilldown/item/drilldown-item.js +1 -1
- package/dist/element-events.generated.js +7 -0
- package/dist/graph/root/graph-root.d.ts +6 -4
- package/dist/graph/root/graph-root.js +3 -3
- package/dist/heatmap/root/heatmap-root.d.ts +15 -15
- package/dist/icon/all/index.js +0 -3
- package/dist/icon/root/icon-root.d.ts +11 -18
- package/dist/icon/root/icon-root.js +4 -16
- package/dist/icon/set.js +2 -16
- package/dist/index.d.ts +2 -1
- package/dist/index.js +2 -1
- package/dist/isometric-heatmap/index.d.ts +1 -0
- package/dist/isometric-heatmap/index.js +1 -0
- package/dist/isometric-heatmap/projection.d.ts +70 -0
- package/dist/isometric-heatmap/projection.js +49 -0
- package/dist/isometric-heatmap/root/isometric-heatmap-root.d.ts +118 -0
- package/dist/isometric-heatmap/root/isometric-heatmap-root.js +127 -0
- package/dist/lightbox/root/lightbox-root.js +1 -1
- package/dist/list/root/list-root.js +1 -1
- package/dist/map/root/map-root.js +1 -1
- package/dist/menu/item/menu-item.js +1 -1
- package/dist/outline/root/outline-root.js +2 -2
- package/dist/popover/root/popover-root.js +1 -1
- package/dist/table/root/table-root.d.ts +4 -6
- package/dist/table/root/table-root.js +3 -29
- package/dist/table/tracks.d.ts +20 -0
- package/dist/table/tracks.js +28 -0
- package/dist/tabs/root/tabs-root.js +4 -5
- package/dist/tabs/tab/tab.js +2 -3
- package/dist/time-picker/root/time-picker-root.js +1 -1
- package/dist/toggle/root/toggle-root.js +1 -1
- package/dist/tour/root/tour-root.js +1 -1
- package/dist/tree/root/tree-root.js +1 -1
- package/dist/video/root/video-root.js +1 -1
- package/lint.json +1 -1
- package/package.json +6 -6
- package/types/jsx.d.ts +1340 -74
- package/types/svelte.d.ts +1 -0
- package/types/vue.d.ts +279 -13
- package/types/words.d.ts +69 -0
|
@@ -83,7 +83,7 @@ let HelixHeadlessAccordionItem = class HelixHeadlessAccordionItem extends MixinC
|
|
|
83
83
|
}
|
|
84
84
|
firstUpdated(changed) {
|
|
85
85
|
super.firstUpdated(changed);
|
|
86
|
-
auditName(this, () => this.renderRoot.querySelector(`#${TRIGGER_ID}`), '
|
|
86
|
+
auditName(this, () => this.renderRoot.querySelector(`#${TRIGGER_ID}`), 'accordion-item');
|
|
87
87
|
}
|
|
88
88
|
get accordion() {
|
|
89
89
|
return closestInstance(this, HelixHeadlessAccordion);
|
|
@@ -206,7 +206,7 @@ let HelixHeadlessButtonGroup = class HelixHeadlessButtonGroup extends HelixEleme
|
|
|
206
206
|
}
|
|
207
207
|
firstUpdated(changed) {
|
|
208
208
|
super.firstUpdated(changed);
|
|
209
|
-
auditName(this, () => null, '
|
|
209
|
+
auditName(this, () => null, 'button-group', () => this.label !== '');
|
|
210
210
|
}
|
|
211
211
|
updated(changed) {
|
|
212
212
|
super.updated(changed);
|
|
@@ -1951,7 +1951,7 @@ let HelixHeadlessCanvas = class HelixHeadlessCanvas extends MixinViewport(HelixE
|
|
|
1951
1951
|
firstUpdated(changed) {
|
|
1952
1952
|
super.firstUpdated(changed);
|
|
1953
1953
|
this.finishHydration();
|
|
1954
|
-
auditName(this, () => null, '
|
|
1954
|
+
auditName(this, () => null, 'canvas', () => this.label !== '');
|
|
1955
1955
|
if (this.waiting) {
|
|
1956
1956
|
this.measured = this.box;
|
|
1957
1957
|
this.view = this.waiting;
|
|
@@ -125,11 +125,12 @@ declare const HelixHeadlessDataTable_base: (new (...args: any[]) => import("@fus
|
|
|
125
125
|
* `csv()` returns the result as text: every row that passes the filter, in the
|
|
126
126
|
* order and the columns on screen. Saving the file is up to you.
|
|
127
127
|
*
|
|
128
|
-
*
|
|
129
|
-
*
|
|
130
|
-
*
|
|
131
|
-
*
|
|
132
|
-
*
|
|
128
|
+
* Size a column with its own `width`, or every column at once with `columns`,
|
|
129
|
+
* a track list dealt out one track to a column in the order they are written,
|
|
130
|
+
* as `Table` deals it. A column's `width` wins in its place. **A table that
|
|
131
|
+
* serves its first page takes its widths from `columns`**: a server and a
|
|
132
|
+
* stylesheet can read the table's own attributes and not its columns', so the
|
|
133
|
+
* served rows are laid out at the widths the table draws.
|
|
133
134
|
*
|
|
134
135
|
* **The columns are an import of their own.** A column is the Table family's
|
|
135
136
|
* `TableColumn`, which the data table does not register, so a page that writes
|
|
@@ -275,6 +276,18 @@ export declare class HelixHeadlessDataTable extends HelixHeadlessDataTable_base
|
|
|
275
276
|
* it. No default, so a table that sets none writes nothing onto its host.
|
|
276
277
|
*/
|
|
277
278
|
childField?: string;
|
|
279
|
+
/**
|
|
280
|
+
* The column tracks, as a grid track list such as `2fr 1fr max-content`,
|
|
281
|
+
* dealt out one track to a column in the order the columns are written. A
|
|
282
|
+
* column's own `width` wins in its place, and a column it does not reach
|
|
283
|
+
* takes the track a column with no `width` takes.
|
|
284
|
+
*
|
|
285
|
+
* **The one track list a server can send.** A server rendering this element
|
|
286
|
+
* has no columns to read a `width` from, and neither has a stylesheet laying
|
|
287
|
+
* out the rows a page served before the table upgrades, so a table sized here
|
|
288
|
+
* lays those rows out at the widths it draws.
|
|
289
|
+
*/
|
|
290
|
+
columns: string;
|
|
278
291
|
/**
|
|
279
292
|
* The keys of the rows open at the start, separated by commas. Used until
|
|
280
293
|
* `expanded` is set.
|
|
@@ -786,7 +799,13 @@ export declare class HelixHeadlessDataTable extends HelixHeadlessDataTable_base
|
|
|
786
799
|
private get shownFields();
|
|
787
800
|
/** The columns reduced to what the ordering needs. */
|
|
788
801
|
private get axes();
|
|
789
|
-
/**
|
|
802
|
+
/**
|
|
803
|
+
* The track list: each column's `width`, or its track in `columns`, or the
|
|
804
|
+
* track a column with neither takes.
|
|
805
|
+
*
|
|
806
|
+
* A render that knows no columns, on a server or hydrating what one sent,
|
|
807
|
+
* has `columns` alone, and sends it as it is.
|
|
808
|
+
*/
|
|
790
809
|
private get template();
|
|
791
810
|
/**
|
|
792
811
|
* How many rows this draws before it is worth saying something, and why 2,000.
|
|
@@ -8,6 +8,7 @@ import { repeat } from 'lit/directives/repeat.js';
|
|
|
8
8
|
import { unsafeSVG } from 'lit/directives/unsafe-svg.js';
|
|
9
9
|
import { html } from 'lit/static-html.js';
|
|
10
10
|
import { edgeOf } from '../../table/edge.js';
|
|
11
|
+
import { tracksOf } from '../../table/tracks.js';
|
|
11
12
|
import '../../checkbox/index.js';
|
|
12
13
|
import '../../pagination/index.js';
|
|
13
14
|
import { toggledOpen } from '../keys.js';
|
|
@@ -28,6 +29,7 @@ let HelixHeadlessDataTable = class HelixHeadlessDataTable extends MixinCollectio
|
|
|
28
29
|
this.statusSlots = true;
|
|
29
30
|
this.ascendingLabel = 'ascending';
|
|
30
31
|
this.canceledLabel = 'Canceled';
|
|
32
|
+
this.columns = '';
|
|
31
33
|
this.defaultExpanded = '';
|
|
32
34
|
this.defaultFilter = '';
|
|
33
35
|
this.defaultOrder = '';
|
|
@@ -573,11 +575,16 @@ let HelixHeadlessDataTable = class HelixHeadlessDataTable extends MixinCollectio
|
|
|
573
575
|
}
|
|
574
576
|
get template() {
|
|
575
577
|
const declared = this.shownColumns;
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
578
|
+
const written = this.tableColumns;
|
|
579
|
+
const listed = tracksOf(this.columns, written.length);
|
|
580
|
+
const tracks = written.length === 0
|
|
581
|
+
? this.columns
|
|
582
|
+
: declared
|
|
583
|
+
.map((column) => column.width ? column.track : listed[written.indexOf(column)] || column.track)
|
|
584
|
+
.join(' ');
|
|
585
|
+
return tracks
|
|
586
|
+
? [...Array.from({ length: this.lead }, () => 'max-content'), tracks].join(' ')
|
|
587
|
+
: '';
|
|
581
588
|
}
|
|
582
589
|
static { this.COMFORTABLE = 2_000; }
|
|
583
590
|
warnIfCrowded(drawn) {
|
|
@@ -1217,6 +1224,10 @@ let HelixHeadlessDataTable = class HelixHeadlessDataTable extends MixinCollectio
|
|
|
1217
1224
|
const pagination = this.tag('pagination');
|
|
1218
1225
|
const counted = this.mode === 'server' ? Math.max(this.total, available) : matched;
|
|
1219
1226
|
const countKnown = counted > 0 || (this.sourceKnown && !serving);
|
|
1227
|
+
const held = serving &&
|
|
1228
|
+
this.paginated &&
|
|
1229
|
+
!countKnown &&
|
|
1230
|
+
(!this.sourceKnown || this.servedRows.length >= this.pageSize);
|
|
1220
1231
|
this.counts = {
|
|
1221
1232
|
columns: columns.length ? columns.length + this.lead : undefined,
|
|
1222
1233
|
rows: countKnown ? counted + 1 + (this.moreDrawn ? 1 : 0) : undefined,
|
|
@@ -1231,9 +1242,7 @@ let HelixHeadlessDataTable = class HelixHeadlessDataTable extends MixinCollectio
|
|
|
1231
1242
|
@scroll=${this.handleScroll}
|
|
1232
1243
|
>
|
|
1233
1244
|
<div part="head" role="row" aria-rowindex="1">
|
|
1234
|
-
${this.rowGrips && this.
|
|
1235
|
-
? this.renderGripHead(headStop && this.currentColumn === 0)
|
|
1236
|
-
: nothing}${this.selectable && this.sourceKnown
|
|
1245
|
+
${this.rowGrips ? this.renderGripHead(headStop && this.currentColumn === 0) : nothing}${this.selectable
|
|
1237
1246
|
? this.renderSelectAll(headStop && this.currentColumn === this.selectAt)
|
|
1238
1247
|
: nothing}${this.assignsByName && !this.hydrating
|
|
1239
1248
|
? this.orderedColumns.map((_, index) => html `<slot name=${`column-${index + 1}`} @slotchange=${this.handleSlotChange}></slot>`)
|
|
@@ -1247,7 +1256,7 @@ let HelixHeadlessDataTable = class HelixHeadlessDataTable extends MixinCollectio
|
|
|
1247
1256
|
${this.renderMore(page)}${this.errorText === '' ? this.renderStatus(filled, 'gridcell') : this.renderError()}
|
|
1248
1257
|
</div>
|
|
1249
1258
|
${this.errorText === '' ? this.renderLive(filled) : html `<span part="live" role="status">${this.errorText}</span>`}
|
|
1250
|
-
<div part="footer">
|
|
1259
|
+
<div part="footer" ?data-held=${held}>
|
|
1251
1260
|
<slot name="footer"></slot>
|
|
1252
1261
|
${this.paginated
|
|
1253
1262
|
? html `<${pagination}
|
|
@@ -1557,6 +1566,9 @@ __decorate([
|
|
|
1557
1566
|
__decorate([
|
|
1558
1567
|
property({ attribute: 'child-field', reflect: true })
|
|
1559
1568
|
], HelixHeadlessDataTable.prototype, "childField", void 0);
|
|
1569
|
+
__decorate([
|
|
1570
|
+
property()
|
|
1571
|
+
], HelixHeadlessDataTable.prototype, "columns", void 0);
|
|
1560
1572
|
__decorate([
|
|
1561
1573
|
property({ attribute: 'default-expanded' })
|
|
1562
1574
|
], HelixHeadlessDataTable.prototype, "defaultExpanded", void 0);
|
|
@@ -144,7 +144,7 @@ let HelixHeadlessDialog = class HelixHeadlessDialog extends MixinControllerOpen(
|
|
|
144
144
|
return;
|
|
145
145
|
}
|
|
146
146
|
if (this.open && !dialog.open) {
|
|
147
|
-
auditName(this, () => null, '
|
|
147
|
+
auditName(this, () => null, 'dialog', () => this.label !== '' ||
|
|
148
148
|
this.namedByHeader ||
|
|
149
149
|
headingsIn(this.renderRoot
|
|
150
150
|
.querySelector('slot[name="header"]')
|
|
@@ -242,7 +242,7 @@ let HelixHeadlessDrawer = class HelixHeadlessDrawer extends MixinControllerOpen(
|
|
|
242
242
|
return;
|
|
243
243
|
}
|
|
244
244
|
if (this.open && !panel.open) {
|
|
245
|
-
auditName(this, () => null, '
|
|
245
|
+
auditName(this, () => null, 'dialog', () => this.label !== '' ||
|
|
246
246
|
this.namedByHeader ||
|
|
247
247
|
headingsIn(this.renderRoot
|
|
248
248
|
.querySelector('slot[name="header"]')
|
|
@@ -58,7 +58,7 @@ let HelixHeadlessDrilldownItem = class HelixHeadlessDrilldownItem extends HelixE
|
|
|
58
58
|
updated(changed) {
|
|
59
59
|
super.updated(changed);
|
|
60
60
|
if (this.partNamed('item')) {
|
|
61
|
-
auditName(this, () => this.partNamed('item'), '
|
|
61
|
+
auditName(this, () => this.partNamed('item'), 'row');
|
|
62
62
|
}
|
|
63
63
|
}
|
|
64
64
|
firstUpdated(changed) {
|
|
@@ -148,6 +148,13 @@ registerElementEvents({
|
|
|
148
148
|
'helix-headless-icon-button': ['helix-press'],
|
|
149
149
|
'helix-headless-image': ['error', 'load'],
|
|
150
150
|
'helix-headless-input': ['change', 'helix-before-change', 'helix-clear', 'input'],
|
|
151
|
+
'helix-headless-isometric-heatmap': [
|
|
152
|
+
'change',
|
|
153
|
+
'helix-before-change',
|
|
154
|
+
'helix-reading-change',
|
|
155
|
+
'helix-reading-press',
|
|
156
|
+
'helix-resize',
|
|
157
|
+
],
|
|
151
158
|
'helix-headless-kbd': ['helix-shortcut'],
|
|
152
159
|
'helix-headless-legend': ['change', 'helix-before-change'],
|
|
153
160
|
'helix-headless-lightbox': [
|
|
@@ -6,10 +6,12 @@ declare const HelixHeadlessGraph_base: (new (...args: any[]) => import("@fusion.
|
|
|
6
6
|
* @summary A frame around a graph of notes drawn by another library, and the list that makes it readable.
|
|
7
7
|
*
|
|
8
8
|
* @description
|
|
9
|
-
*
|
|
10
|
-
* WebGL, which a renderer such as Sigma.js does
|
|
11
|
-
*
|
|
12
|
-
*
|
|
9
|
+
* The frame draws no graph itself. A force layout of thousands of notes is
|
|
10
|
+
* physics and WebGL, which a renderer such as Sigma.js does, and an
|
|
11
|
+
* architecture diagram is drawn by `isometricDriver` from
|
|
12
|
+
* `@fusion.dev/helix-graph/isometric`. Put the drawing's box in the frame, and
|
|
13
|
+
* `connectGraph` from `@fusion.dev/helix-graph` draws `nodes` and `links` in
|
|
14
|
+
* it and keeps it in step with the frame.
|
|
13
15
|
*
|
|
14
16
|
* What the frame adds is what a drawing of a graph cannot do: a list of every
|
|
15
17
|
* note beside it, which is the graph for a screen reader and a quick way to
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { __decorate } from "tslib";
|
|
2
|
-
import { auditName, customElement, focusItemOf, formatWords, HelixElement, HelixGraphFilterEvent, HelixGraphLayoutEvent, HelixGraphPanEvent, HelixGraphPartChangeEvent, HelixGraphReadyEvent, HelixGraphSignalEvent, HelixGraphZoomEvent, isRtl, KeyboardNavigationController, MixinControllerActive, MixinViewport, SCROLLER_RULE,
|
|
2
|
+
import { auditName, customElement, focusItemOf, formatWords, HelixElement, HelixGraphFilterEvent, HelixGraphLayoutEvent, HelixGraphPanEvent, HelixGraphPartChangeEvent, HelixGraphReadyEvent, HelixGraphSignalEvent, HelixGraphZoomEvent, isRtl, KeyboardNavigationController, MixinControllerActive, MixinViewport, SCROLLER_RULE, scrollRoom, scrollWithin, Typeahead, typeaheadBy, VIRTUAL_RULE, VirtualizeController, words, wordsLocale, } from '@fusion.dev/helix-core';
|
|
3
3
|
import { list, magnifyingGlass } from '@fusion.dev/helix-icons';
|
|
4
4
|
import { html, nothing } from 'lit';
|
|
5
5
|
import { property, state } from 'lit/decorators.js';
|
|
@@ -213,7 +213,7 @@ let HelixHeadlessGraph = class HelixHeadlessGraph extends MixinViewport(MixinCon
|
|
|
213
213
|
}
|
|
214
214
|
firstUpdated(changed) {
|
|
215
215
|
super.firstUpdated(changed);
|
|
216
|
-
auditName(this, () => null, '
|
|
216
|
+
auditName(this, () => null, 'graph', () => this.label !== '');
|
|
217
217
|
}
|
|
218
218
|
willUpdate(changed) {
|
|
219
219
|
super.willUpdate(changed);
|
|
@@ -384,7 +384,7 @@ let HelixHeadlessGraph = class HelixHeadlessGraph extends MixinViewport(MixinCon
|
|
|
384
384
|
if (this.cursor >= first && this.cursor < last) {
|
|
385
385
|
const row = this.renderRoot.querySelector?.(`[data-index="${this.cursor}"]`);
|
|
386
386
|
if (row) {
|
|
387
|
-
|
|
387
|
+
scrollWithin(row, list);
|
|
388
388
|
}
|
|
389
389
|
return;
|
|
390
390
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AriaForwardController, HelixElement } from '@fusion.dev/helix-core';
|
|
1
|
+
import { AriaForwardController, HelixElement, StatusController } from '@fusion.dev/helix-core';
|
|
2
2
|
import { nothing, type PropertyValues, type TemplateResult } from 'lit';
|
|
3
3
|
import '../../tooltip/index.js';
|
|
4
4
|
import { type Reading } from './buckets.js';
|
|
@@ -309,7 +309,7 @@ export declare class HelixHeadlessHeatmap extends HelixHeadlessHeatmap_base {
|
|
|
309
309
|
* difference is a whole strip: unmeasured has to show everything, since a
|
|
310
310
|
* first paint that shows one cell and then expands is a flicker on every load.
|
|
311
311
|
*/
|
|
312
|
-
|
|
312
|
+
protected width: number | undefined;
|
|
313
313
|
/**
|
|
314
314
|
* The cell and gap the strip is drawing, in pixels, once it has been read.
|
|
315
315
|
*
|
|
@@ -353,13 +353,13 @@ export declare class HelixHeadlessHeatmap extends HelixHeadlessHeatmap_base {
|
|
|
353
353
|
/** The `value` the last rectangle wrote. */
|
|
354
354
|
private shaped;
|
|
355
355
|
/** The region a change of selection is said in, rendered from the first change. */
|
|
356
|
-
|
|
356
|
+
protected readonly status: StatusController;
|
|
357
357
|
/**
|
|
358
358
|
* The name each drawn cell stands for in `value`: the date its row's header
|
|
359
359
|
* carries in a `<time datetime>`, or the header's words where it carries
|
|
360
360
|
* none.
|
|
361
361
|
*/
|
|
362
|
-
|
|
362
|
+
protected keysOf(cells: readonly Reading[]): string[];
|
|
363
363
|
/**
|
|
364
364
|
* Moves `value` to `next`, asking first: `helix-before-change` carries it,
|
|
365
365
|
* a listener that refuses keeps the selection, and `change` follows, with
|
|
@@ -375,7 +375,7 @@ export declare class HelixHeadlessHeatmap extends HelixHeadlessHeatmap_base {
|
|
|
375
375
|
*/
|
|
376
376
|
private stretch;
|
|
377
377
|
/** Notes where the keys rest before the pointer controller moves them. */
|
|
378
|
-
|
|
378
|
+
protected readonly onStripKeydown: () => void;
|
|
379
379
|
/**
|
|
380
380
|
* Space and Enter select the cell the keys rest on, and Shift with a key
|
|
381
381
|
* that moved them takes in the range from the anchor. After the pointer
|
|
@@ -386,7 +386,7 @@ export declare class HelixHeadlessHeatmap extends HelixHeadlessHeatmap_base {
|
|
|
386
386
|
* A press on a cell selects it, under `selection-mode`, and Shift takes the
|
|
387
387
|
* rectangle to it under `selection-shape="rectangle"`.
|
|
388
388
|
*/
|
|
389
|
-
|
|
389
|
+
protected readonly onClick: (event: MouseEvent) => void;
|
|
390
390
|
/**
|
|
391
391
|
* Every row in the table, oldest first, as the table is written, with its
|
|
392
392
|
* reading where the row has one.
|
|
@@ -400,7 +400,7 @@ export declare class HelixHeadlessHeatmap extends HelixHeadlessHeatmap_base {
|
|
|
400
400
|
* cell along, while the tooltip still counted rows and named the day beside
|
|
401
401
|
* the one under the pointer.
|
|
402
402
|
*/
|
|
403
|
-
|
|
403
|
+
protected get points(): Reading[];
|
|
404
404
|
/**
|
|
405
405
|
* `rows` as a usable count, which is not always what the attribute says.
|
|
406
406
|
*
|
|
@@ -408,7 +408,7 @@ export declare class HelixHeadlessHeatmap extends HelixHeadlessHeatmap_base {
|
|
|
408
408
|
* need it, and a `rows="0"` or a `rows="2.5"` that reached one of them and not
|
|
409
409
|
* the other would draw a strip whose columns and whose capacity disagreed.
|
|
410
410
|
*/
|
|
411
|
-
|
|
411
|
+
protected get rowCount(): number;
|
|
412
412
|
/**
|
|
413
413
|
* The cell width the arithmetic should plan around, in pixels.
|
|
414
414
|
*
|
|
@@ -416,11 +416,11 @@ export declare class HelixHeadlessHeatmap extends HelixHeadlessHeatmap_base {
|
|
|
416
416
|
* it is for; otherwise what the strip draws, and the declared default only
|
|
417
417
|
* until the first measurement lands.
|
|
418
418
|
*/
|
|
419
|
-
|
|
419
|
+
protected get cellPx(): number;
|
|
420
420
|
/** The gap the arithmetic should plan around, on the same terms as `cellPx`. */
|
|
421
|
-
|
|
421
|
+
protected get gapPx(): number;
|
|
422
422
|
/** How many cells the container has room for, as a whole number of columns. */
|
|
423
|
-
|
|
423
|
+
protected get room(): number;
|
|
424
424
|
/**
|
|
425
425
|
* Reads back the cell and the gap the strip resolved.
|
|
426
426
|
*
|
|
@@ -443,7 +443,7 @@ export declare class HelixHeadlessHeatmap extends HelixHeadlessHeatmap_base {
|
|
|
443
443
|
* The tail rather than the head: a status strip that drops the newest days to
|
|
444
444
|
* keep the oldest is answering a question nobody asked.
|
|
445
445
|
*/
|
|
446
|
-
|
|
446
|
+
protected get drawn(): Reading[];
|
|
447
447
|
/** How many of the oldest rows a narrow strip leaves undrawn. */
|
|
448
448
|
private get dropped();
|
|
449
449
|
/**
|
|
@@ -533,9 +533,9 @@ export declare class HelixHeadlessHeatmap extends HelixHeadlessHeatmap_base {
|
|
|
533
533
|
* bubbles, so one handler covers however many cells there are, and unlike
|
|
534
534
|
* `mouseover` it is delivered for a pen.
|
|
535
535
|
*/
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
536
|
+
protected readonly onPointerOver: (event: PointerEvent) => void;
|
|
537
|
+
protected readonly onPointerUp: (event: PointerEvent) => void;
|
|
538
|
+
protected readonly onPointerLeave: () => void;
|
|
539
539
|
}
|
|
540
540
|
declare global {
|
|
541
541
|
interface HTMLElementTagNameMap {
|
package/dist/icon/all/index.js
CHANGED
|
@@ -18,14 +18,11 @@ import { nothing, type PropertyValues, type TemplateResult } from 'lit';
|
|
|
18
18
|
* a dark background. Shapes that set their own `fill` or `stroke` are
|
|
19
19
|
* unaffected.
|
|
20
20
|
*
|
|
21
|
-
* **A name is looked up in a registry.** The family's entry registers
|
|
22
|
-
* set
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
* `@fusion.dev/helix-headless/icon/root`, registers none: a page that imports
|
|
27
|
-
* it and calls `registerIcons` with the glyphs it names ships those and no
|
|
28
|
-
* others. `registerIconLibrary` resolves names under a prefix of your own,
|
|
21
|
+
* **A name is looked up in a registry.** The family's entry registers the
|
|
22
|
+
* whole set, so any name in it draws, and `icon/all` registers the same set.
|
|
23
|
+
* The element's own entry, `@fusion.dev/helix-headless/icon/root`, registers
|
|
24
|
+
* none: a page that imports it and calls `registerIcons` with the glyphs it
|
|
25
|
+
* names ships those and no others. `registerIconLibrary` resolves names under a prefix of your own,
|
|
29
26
|
* such as `lucide:camera`, at once or later, and the element fires `load` when
|
|
30
27
|
* a glyph that came later is drawn. A glyph registered after the element
|
|
31
28
|
* rendered is drawn then.
|
|
@@ -98,10 +95,12 @@ export declare class HelixHeadlessIcon extends HelixElement {
|
|
|
98
95
|
* The name of the icon in the Helix set.
|
|
99
96
|
*
|
|
100
97
|
* **A lookup, and the reason both this and `icon` exist.** A name is a string,
|
|
101
|
-
* so it is what markup can carry, and resolving one means an index
|
|
102
|
-
* bundler can shake
|
|
103
|
-
*
|
|
104
|
-
*
|
|
98
|
+
* so it is what markup can carry, and resolving one means an index of the
|
|
99
|
+
* whole set that no bundler can shake: 15 kB for a consumer who renders one
|
|
100
|
+
* mark. An attribute is the only thing an HTML author can write, and that is
|
|
101
|
+
* worth the index; a consumer who would rather not pay it imports the
|
|
102
|
+
* element from `icon/root` and registers the glyphs it names, or hands over
|
|
103
|
+
* the value instead.
|
|
105
104
|
*
|
|
106
105
|
* A name written `prefix:name` asks the library registered under that
|
|
107
106
|
* prefix.
|
|
@@ -152,12 +151,6 @@ export declare class HelixHeadlessIcon extends HelixElement {
|
|
|
152
151
|
protected updated(changed: PropertyValues): void;
|
|
153
152
|
/** Hands the drawn `<svg>` to the mutator of the library `name` asks, where it has one. */
|
|
154
153
|
private mutate;
|
|
155
|
-
/**
|
|
156
|
-
* Asks the button or link a decorative icon sits in whether it has a name.
|
|
157
|
-
* Its content is this icon alone where it has none, and the audit says so
|
|
158
|
-
* once, in a development build only. A Helix button reports its own name.
|
|
159
|
-
*/
|
|
160
|
-
private auditControl;
|
|
161
154
|
/** The name a report is waiting on the page to settle for, so it is asked once. */
|
|
162
155
|
private pending;
|
|
163
156
|
/**
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { __decorate } from "tslib";
|
|
2
|
-
import {
|
|
2
|
+
import { auditIconControl, customElement, HelixElement, hostAria, MIRROR_RULE, reportRuntime, } from '@fusion.dev/helix-core';
|
|
3
3
|
import { html, nothing } from 'lit';
|
|
4
4
|
import { property } from 'lit/decorators.js';
|
|
5
5
|
import { unsafeSVG } from 'lit/directives/unsafe-svg.js';
|
|
@@ -81,7 +81,7 @@ let HelixHeadlessIcon = class HelixHeadlessIcon extends HelixElement {
|
|
|
81
81
|
super.updated(changed);
|
|
82
82
|
if (this.drawn !== undefined) {
|
|
83
83
|
this.mutate();
|
|
84
|
-
this.
|
|
84
|
+
auditIconControl(this, this.label);
|
|
85
85
|
}
|
|
86
86
|
const asked = this.asked;
|
|
87
87
|
if (this.arrived === asked && this.drawn !== undefined) {
|
|
@@ -105,16 +105,6 @@ let HelixHeadlessIcon = class HelixHeadlessIcon extends HelixElement {
|
|
|
105
105
|
mutator(svg);
|
|
106
106
|
}
|
|
107
107
|
}
|
|
108
|
-
auditControl() {
|
|
109
|
-
if (this.label !== '' || this.hasAttribute('aria-label')) {
|
|
110
|
-
return;
|
|
111
|
-
}
|
|
112
|
-
const control = this.closest('a[href], button, summary, [role="button"], [role="link"]');
|
|
113
|
-
if (control) {
|
|
114
|
-
auditName(control, () => null, `Its only content is <${this.localName}>, which is decorative: give the icon a \`label\`, or the control an \`aria-label\`.`, () => (control.textContent ?? '').trim() !== '' ||
|
|
115
|
-
control.querySelector('[alt]:not([alt=""]), [aria-label]:not([aria-label=""])') !== null);
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
108
|
reportMissing() {
|
|
119
109
|
const asked = this.pending;
|
|
120
110
|
this.pending = '';
|
|
@@ -127,10 +117,8 @@ let HelixHeadlessIcon = class HelixHeadlessIcon extends HelixElement {
|
|
|
127
117
|
kind: 'unknown-icon',
|
|
128
118
|
message: this.src === ''
|
|
129
119
|
? `<${this.localName} name="${asked}"> names no registered icon, so it draws ` +
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
: '@fusion.dev/helix'}/icon/all', which registers every one. Otherwise check the name, or register ` +
|
|
133
|
-
'the glyph with `registerIcons`.'
|
|
120
|
+
'nothing. Check the name, register the glyph with `registerIcons`, or import it ' +
|
|
121
|
+
'and pass it as `icon`.'
|
|
134
122
|
: `<${this.localName} src="${asked}"> could not be fetched as an SVG file, so it ` +
|
|
135
123
|
'draws nothing. Check the URL, and that the file is an `<svg>`.',
|
|
136
124
|
tag: this.localName,
|
package/dist/icon/set.js
CHANGED
|
@@ -1,17 +1,3 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { icons } from '@fusion.dev/helix-icons';
|
|
2
2
|
import { registerIcons } from './registry.js';
|
|
3
|
-
registerIcons(
|
|
4
|
-
arrowLeft,
|
|
5
|
-
arrowRight,
|
|
6
|
-
caretDown,
|
|
7
|
-
caretLeft,
|
|
8
|
-
caretRight,
|
|
9
|
-
caretUp,
|
|
10
|
-
check,
|
|
11
|
-
info,
|
|
12
|
-
magnifyingGlass,
|
|
13
|
-
minus,
|
|
14
|
-
plus,
|
|
15
|
-
warning,
|
|
16
|
-
x,
|
|
17
|
-
]);
|
|
3
|
+
registerIcons(icons);
|
package/dist/index.d.ts
CHANGED
|
@@ -50,10 +50,11 @@ export * from './filter-input/menu/index.js';
|
|
|
50
50
|
export * from './format-date/index.js';
|
|
51
51
|
export * from './graph/index.js';
|
|
52
52
|
export * from './heatmap/index.js';
|
|
53
|
-
export * from './icon/
|
|
53
|
+
export * from './icon/index.js';
|
|
54
54
|
export * from './icon-button/index.js';
|
|
55
55
|
export * from './image/index.js';
|
|
56
56
|
export * from './input/index.js';
|
|
57
|
+
export * from './isometric-heatmap/index.js';
|
|
57
58
|
export * from './kbd/index.js';
|
|
58
59
|
export * from './legend/index.js';
|
|
59
60
|
export * from './lightbox/index.js';
|
package/dist/index.js
CHANGED
|
@@ -41,10 +41,11 @@ export * from './filter-input/menu/index.js';
|
|
|
41
41
|
export * from './format-date/index.js';
|
|
42
42
|
export * from './graph/index.js';
|
|
43
43
|
export * from './heatmap/index.js';
|
|
44
|
-
export * from './icon/
|
|
44
|
+
export * from './icon/index.js';
|
|
45
45
|
export * from './icon-button/index.js';
|
|
46
46
|
export * from './image/index.js';
|
|
47
47
|
export * from './input/index.js';
|
|
48
|
+
export * from './isometric-heatmap/index.js';
|
|
48
49
|
export * from './kbd/index.js';
|
|
49
50
|
export * from './legend/index.js';
|
|
50
51
|
export * from './lightbox/index.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { HelixHeadlessIsometricHeatmap } from './root/isometric-heatmap-root.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { HelixHeadlessIsometricHeatmap } from './root/isometric-heatmap-root.js';
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Where each reading of an isometric heatmap stands, as SVG path data.
|
|
3
|
+
*
|
|
4
|
+
* Kept apart from the element because it is arithmetic a picture hides: a face
|
|
5
|
+
* drawn in the wrong order is covered by the prism it should cover, and a
|
|
6
|
+
* height off by one reading's share still looks like a relief.
|
|
7
|
+
*
|
|
8
|
+
* **The units are cells.** A step along a column or a row is one cell, and a
|
|
9
|
+
* prism's height is in the same unit, so the drawing scales as a whole through
|
|
10
|
+
* the `viewBox` and a server can write it with no width to measure.
|
|
11
|
+
*/
|
|
12
|
+
/** How far across the page one step along either axis goes: the cosine of 30 degrees. */
|
|
13
|
+
export declare const ACROSS: number;
|
|
14
|
+
/** A point on the page, in cells. */
|
|
15
|
+
export interface Point {
|
|
16
|
+
x: number;
|
|
17
|
+
y: number;
|
|
18
|
+
}
|
|
19
|
+
/** One reading drawn as a prism: three visible faces, as path data. */
|
|
20
|
+
export interface Prism {
|
|
21
|
+
/** The reading's place among those drawn. */
|
|
22
|
+
index: number;
|
|
23
|
+
/** The face toward the next row, drawn at the lower left. */
|
|
24
|
+
left: string;
|
|
25
|
+
/** The middle of the top face, which is where the tooltip points. */
|
|
26
|
+
peak: Point;
|
|
27
|
+
/** The face toward the next column, drawn at the lower right. */
|
|
28
|
+
right: string;
|
|
29
|
+
/** The face the reading's tone is painted on. */
|
|
30
|
+
top: string;
|
|
31
|
+
}
|
|
32
|
+
/** Every prism, and the box they fit in. */
|
|
33
|
+
export interface Relief {
|
|
34
|
+
/** The box every face fits in, in cells: its left, top, width, and height. */
|
|
35
|
+
box: {
|
|
36
|
+
height: number;
|
|
37
|
+
width: number;
|
|
38
|
+
x: number;
|
|
39
|
+
y: number;
|
|
40
|
+
};
|
|
41
|
+
/** In the order they are painted, which is the order of the readings. */
|
|
42
|
+
prisms: Prism[];
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Each reading's height, from zero, as a share of the highest reading times
|
|
46
|
+
* `tallest`.
|
|
47
|
+
*
|
|
48
|
+
* **From zero, because the height is the value.** A height measured from the
|
|
49
|
+
* lowest reading would make a day of 9 against a day of 10 look like nothing
|
|
50
|
+
* against something. A blank reading, a zero, and a negative one stand at zero,
|
|
51
|
+
* a prism having nothing below the floor to show.
|
|
52
|
+
*/
|
|
53
|
+
export declare const heightsOf: (values: readonly (number | undefined)[], highest: number, tallest: number) => number[];
|
|
54
|
+
/** The highest positive reading, or zero where there is none. */
|
|
55
|
+
export declare const highestOf: (values: readonly (number | undefined)[]) => number;
|
|
56
|
+
/**
|
|
57
|
+
* Every reading as a prism, filling down each column of `rows` and then
|
|
58
|
+
* across, as the flat heatmap does.
|
|
59
|
+
*
|
|
60
|
+
* **Columns run down to the right and rows down to the left, so the order of
|
|
61
|
+
* the readings is the order to paint them in.** A prism can only cover the
|
|
62
|
+
* neighbors behind it, which are the one before it in its column and the one in
|
|
63
|
+
* the same row of the column before, and both come earlier in the table. With
|
|
64
|
+
* the axes the other way round, the newest column would stand at the back and
|
|
65
|
+
* every tall reading in front of it would hide it.
|
|
66
|
+
*
|
|
67
|
+
* `footprint` is how much of its cell a prism covers along each edge, so `1`
|
|
68
|
+
* leaves no gap between neighbors.
|
|
69
|
+
*/
|
|
70
|
+
export declare const reliefOf: (heights: readonly number[], rows: number, footprint: number) => Relief;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
export const ACROSS = Math.sqrt(3) / 2;
|
|
2
|
+
export const heightsOf = (values, highest, tallest) => values.map((value) => highest > 0 && value !== undefined && value > 0
|
|
3
|
+
? (Math.min(value, highest) / highest) * tallest
|
|
4
|
+
: 0);
|
|
5
|
+
export const highestOf = (values) => values.reduce((high, value) => (value !== undefined && value > high ? value : high), 0);
|
|
6
|
+
const short = (value) => String(Math.round(value * 1000) / 1000 || 0);
|
|
7
|
+
const at = (column, row, height) => ({
|
|
8
|
+
x: (column - row) * ACROSS,
|
|
9
|
+
y: (column + row) / 2 - height,
|
|
10
|
+
});
|
|
11
|
+
const path = (points) => `M${points.map((point) => `${short(point.x)} ${short(point.y)}`).join('L')}Z`;
|
|
12
|
+
export const reliefOf = (heights, rows, footprint) => {
|
|
13
|
+
const count = Math.max(1, Math.floor(rows) || 1);
|
|
14
|
+
const inset = (1 - Math.min(1, Math.max(0, footprint))) / 2;
|
|
15
|
+
let left = Number.POSITIVE_INFINITY;
|
|
16
|
+
let right = Number.NEGATIVE_INFINITY;
|
|
17
|
+
let top = Number.POSITIVE_INFINITY;
|
|
18
|
+
let bottom = Number.NEGATIVE_INFINITY;
|
|
19
|
+
const prisms = heights.map((height, index) => {
|
|
20
|
+
const column = Math.floor(index / count);
|
|
21
|
+
const row = index % count;
|
|
22
|
+
const near = column + inset;
|
|
23
|
+
const far = column + 1 - inset;
|
|
24
|
+
const start = row + inset;
|
|
25
|
+
const end = row + 1 - inset;
|
|
26
|
+
const back = at(near, start, height);
|
|
27
|
+
const across = at(far, start, height);
|
|
28
|
+
const front = at(far, end, height);
|
|
29
|
+
const down = at(near, end, height);
|
|
30
|
+
const acrossFloor = at(far, start, 0);
|
|
31
|
+
const frontFloor = at(far, end, 0);
|
|
32
|
+
const downFloor = at(near, end, 0);
|
|
33
|
+
left = Math.min(left, down.x);
|
|
34
|
+
right = Math.max(right, across.x);
|
|
35
|
+
top = Math.min(top, back.y);
|
|
36
|
+
bottom = Math.max(bottom, frontFloor.y);
|
|
37
|
+
return {
|
|
38
|
+
index,
|
|
39
|
+
left: path([down, front, frontFloor, downFloor]),
|
|
40
|
+
peak: at(column + 0.5, row + 0.5, height),
|
|
41
|
+
right: path([front, across, acrossFloor, frontFloor]),
|
|
42
|
+
top: path([back, across, front, down]),
|
|
43
|
+
};
|
|
44
|
+
});
|
|
45
|
+
if (prisms.length === 0) {
|
|
46
|
+
return { box: { height: 0, width: 0, x: 0, y: 0 }, prisms };
|
|
47
|
+
}
|
|
48
|
+
return { box: { height: bottom - top, width: right - left, x: left, y: top }, prisms };
|
|
49
|
+
};
|