@fusion.dev/helix-headless 0.31.0 → 0.33.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 +880 -177
- package/dist/area-chart/root/area-chart-root.d.ts +8 -0
- package/dist/area-chart/root/area-chart-root.js +1 -0
- package/dist/bar-chart/root/bar-chart-root.d.ts +8 -0
- package/dist/bar-chart/root/bar-chart-root.js +2 -1
- package/dist/breadcrumbs/breadcrumb/breadcrumb.js +1 -1
- package/dist/carousel/root/carousel-root.d.ts +12 -0
- package/dist/carousel/root/carousel-root.js +17 -11
- package/dist/chat/composer/chat-composer.d.ts +4 -0
- package/dist/chat/root/chat-root.d.ts +17 -0
- package/dist/chat/root/chat-root.js +12 -1
- package/dist/code-block/root/code-block-root.d.ts +8 -0
- package/dist/code-block/root/code-block-root.js +4 -1
- package/dist/color-picker/root/color-picker-root.js +2 -1
- package/dist/copy-button/root/copy-button-root.d.ts +8 -0
- package/dist/copy-button/root/copy-button-root.js +4 -1
- package/dist/data-table/root/data-table-root.d.ts +22 -3
- package/dist/data-table/root/data-table-root.js +25 -16
- package/dist/date-input/root/date-input-root.d.ts +34 -1
- package/dist/date-input/root/date-input-root.js +27 -1
- package/dist/date-picker/root/date-picker-root.js +6 -8
- package/dist/donut-chart/root/donut-chart-root.d.ts +21 -5
- package/dist/donut-chart/root/donut-chart-root.js +18 -6
- package/dist/drilldown/item/drilldown-item.d.ts +36 -1
- package/dist/drilldown/item/drilldown-item.js +30 -3
- package/dist/drilldown/root/drilldown-root.js +5 -4
- package/dist/heatmap/root/heatmap-root.d.ts +11 -2
- package/dist/icon/root/icon-root.d.ts +8 -0
- package/dist/icon/root/icon-root.js +5 -0
- package/dist/line-chart/root/line-chart-root.d.ts +9 -1
- package/dist/line-chart/root/line-chart-root.js +1 -0
- package/dist/menu/item/menu-item.js +1 -1
- package/dist/menu/root/menu-root.js +5 -4
- package/dist/object-inspector/root/object-inspector-root.d.ts +8 -0
- package/dist/object-inspector/root/object-inspector-root.js +20 -15
- package/dist/pagination/root/pagination-root.js +1 -1
- package/dist/pin-input/root/pin-input-root.d.ts +7 -1
- package/dist/pin-input/root/pin-input-root.js +5 -7
- package/dist/scatter-chart/root/scatter-chart-root.d.ts +20 -0
- package/dist/scatter-chart/root/scatter-chart-root.js +15 -9
- package/dist/scroll-area/root/scroll-area-root.js +3 -2
- package/dist/sparkline/root/sparkline-root.js +1 -0
- package/dist/splitter/root/splitter-root.d.ts +11 -0
- package/dist/splitter/root/splitter-root.js +16 -16
- package/dist/table/cell/table-cell.d.ts +2 -0
- package/dist/table/column/table-column.d.ts +50 -5
- package/dist/table/column/table-column.js +24 -5
- package/dist/table/root/table-root.d.ts +76 -11
- package/dist/table/root/table-root.js +90 -3
- package/dist/table/row/table-row.d.ts +14 -0
- package/dist/table/row/table-row.js +16 -0
- package/dist/toolbar/root/toolbar-root.js +6 -5
- package/dist/tooltip/root/tooltip-root.d.ts +20 -0
- package/dist/tooltip/root/tooltip-root.js +21 -3
- package/dist/tour/root/tour-root.js +1 -1
- package/dist/tour/stop/tour-stop.d.ts +15 -0
- package/dist/tour/stop/tour-stop.js +16 -2
- package/dist/tree/root/tree-root.js +4 -3
- package/dist/video/root/video-root.js +7 -0
- package/package.json +5 -5
- package/types/jsx.d.ts +1556 -582
- package/types/vue.d.ts +65 -22
|
@@ -75,9 +75,17 @@ declare const HelixHeadlessAreaChart_base: typeof HelixElement & (new (...args:
|
|
|
75
75
|
* @csspart tooltip - The bubble, forwarded from `Tooltip`.
|
|
76
76
|
* @csspart tooltip-anchor - The `Tooltip` element itself.
|
|
77
77
|
* @csspart tooltip-arrow - The bubble's point, forwarded from `Tooltip`.
|
|
78
|
+
* @csspart tooltip-arrow-bottom - The point while the bubble is below the reading, so on its top edge, beside `tooltip-arrow`.
|
|
79
|
+
* @csspart tooltip-arrow-left - The point while the bubble is left of the reading, so on its right edge, beside `tooltip-arrow`.
|
|
80
|
+
* @csspart tooltip-arrow-right - The point while the bubble is right of the reading, so on its left edge, beside `tooltip-arrow`.
|
|
81
|
+
* @csspart tooltip-arrow-top - The point while the bubble is above the reading, so on its bottom edge, beside `tooltip-arrow`.
|
|
82
|
+
* @csspart tooltip-bottom - The bubble while it is below the reading, beside `tooltip`.
|
|
78
83
|
* @csspart tooltip-cell - One column's name and value inside the tooltip.
|
|
79
84
|
* @csspart tooltip-label - The reading's own name inside the tooltip.
|
|
85
|
+
* @csspart tooltip-left - The bubble while it is left of the reading, beside `tooltip`.
|
|
80
86
|
* @csspart tooltip-name - A column's name inside the tooltip.
|
|
87
|
+
* @csspart tooltip-right - The bubble while it is right of the reading, beside `tooltip`.
|
|
88
|
+
* @csspart tooltip-top - The bubble while it is above the reading, beside `tooltip`.
|
|
81
89
|
* @csspart tooltip-value - A column's value inside the tooltip.
|
|
82
90
|
*/
|
|
83
91
|
export declare class HelixHeadlessAreaChart extends HelixHeadlessAreaChart_base {
|
|
@@ -84,6 +84,7 @@ let HelixHeadlessAreaChart = class HelixHeadlessAreaChart extends MixinChartSour
|
|
|
84
84
|
const order = stack.layers.map((_, depth) => depth).reverse();
|
|
85
85
|
return html `<div aria-hidden="true" id="helix-chart-plot" part="plot">
|
|
86
86
|
<svg part="svg"
|
|
87
|
+
data-mirror
|
|
87
88
|
preserveAspectRatio="none"
|
|
88
89
|
viewBox="0 0 ${WIDTH} ${HEIGHT}"
|
|
89
90
|
xmlns="http://www.w3.org/2000/svg"
|
|
@@ -52,9 +52,17 @@ declare const HelixHeadlessBarChart_base: typeof HelixElement & (new (...args: a
|
|
|
52
52
|
* @csspart tooltip - The bubble, forwarded from `Tooltip`.
|
|
53
53
|
* @csspart tooltip-anchor - The `Tooltip` element itself.
|
|
54
54
|
* @csspart tooltip-arrow - The bubble's point, forwarded from `Tooltip`.
|
|
55
|
+
* @csspart tooltip-arrow-bottom - The point while the bubble is below the reading, so on its top edge, beside `tooltip-arrow`.
|
|
56
|
+
* @csspart tooltip-arrow-left - The point while the bubble is left of the reading, so on its right edge, beside `tooltip-arrow`.
|
|
57
|
+
* @csspart tooltip-arrow-right - The point while the bubble is right of the reading, so on its left edge, beside `tooltip-arrow`.
|
|
58
|
+
* @csspart tooltip-arrow-top - The point while the bubble is above the reading, so on its bottom edge, beside `tooltip-arrow`.
|
|
59
|
+
* @csspart tooltip-bottom - The bubble while it is below the reading, beside `tooltip`.
|
|
55
60
|
* @csspart tooltip-cell - One column's name and value inside the tooltip.
|
|
56
61
|
* @csspart tooltip-label - The reading's own name inside the tooltip.
|
|
62
|
+
* @csspart tooltip-left - The bubble while it is left of the reading, beside `tooltip`.
|
|
57
63
|
* @csspart tooltip-name - A column's name inside the tooltip.
|
|
64
|
+
* @csspart tooltip-right - The bubble while it is right of the reading, beside `tooltip`.
|
|
65
|
+
* @csspart tooltip-top - The bubble while it is above the reading, beside `tooltip`.
|
|
58
66
|
* @csspart tooltip-value - A column's value inside the tooltip.
|
|
59
67
|
*
|
|
60
68
|
* @cssproperty --bar-chart-axis - The color of a single-series axis, taken from that series.
|
|
@@ -107,6 +107,7 @@ let HelixHeadlessBarChart = class HelixHeadlessBarChart extends MixinChartSource
|
|
|
107
107
|
part="plot"
|
|
108
108
|
>
|
|
109
109
|
<svg part="svg"
|
|
110
|
+
data-mirror
|
|
110
111
|
preserveAspectRatio="none"
|
|
111
112
|
viewBox="0 0 100 ${HEIGHT}"
|
|
112
113
|
xmlns="http://www.w3.org/2000/svg"
|
|
@@ -219,7 +220,7 @@ let HelixHeadlessBarChart = class HelixHeadlessBarChart extends MixinChartSource
|
|
|
219
220
|
const slot = 100 / this.readings;
|
|
220
221
|
const across = at * slot + slot / 2;
|
|
221
222
|
return drawTooltip(this.sourceRows, at, this.tag('tooltip'), {
|
|
222
|
-
placement: sideways ? 'right' : 'top',
|
|
223
|
+
placement: sideways ? (this.pointer.mirrored ? 'left' : 'right') : 'top',
|
|
223
224
|
x: sideways ? `${far}%` : `${across}%`,
|
|
224
225
|
y: sideways ? `${across}%` : `${far}%`,
|
|
225
226
|
});
|
|
@@ -23,7 +23,7 @@ let HelixHeadlessBreadcrumb = class HelixHeadlessBreadcrumb extends HelixElement
|
|
|
23
23
|
}
|
|
24
24
|
renderSeparator() {
|
|
25
25
|
return html `<slot name="separator"
|
|
26
|
-
><svg part="separator-mark" fill="currentColor" viewBox=${caretRight.viewBox}>
|
|
26
|
+
><svg part="separator-mark" data-mirror fill="currentColor" viewBox=${caretRight.viewBox}>
|
|
27
27
|
${unsafeSVG(caretRight.content)}
|
|
28
28
|
</svg></slot
|
|
29
29
|
>`;
|
|
@@ -191,6 +191,9 @@ export declare class HelixHeadlessCarousel extends HelixElement {
|
|
|
191
191
|
* changes the slide, because an indicator that could be focused without
|
|
192
192
|
* selecting would leave the highlight and the slide disagreeing with nothing
|
|
193
193
|
* on screen saying which is which.
|
|
194
|
+
*
|
|
195
|
+
* Along the line, so on a right-to-left page, where the first indicator is on
|
|
196
|
+
* the right, the left arrow is the one that moves on.
|
|
194
197
|
*/
|
|
195
198
|
private readonly handleIndicatorKeydown;
|
|
196
199
|
/** Moves to a slide, wrapping only where `loop` says to. */
|
|
@@ -224,6 +227,15 @@ export declare class HelixHeadlessCarousel extends HelixElement {
|
|
|
224
227
|
* to index 0 put its edge back on the clip edge. Measured on the insights
|
|
225
228
|
* carousel: `scrollLeft` resting at 4 against a 4px bleed, the first card
|
|
226
229
|
* shaved, and no scrolling done to cause it.
|
|
230
|
+
*
|
|
231
|
+
* **On a right-to-left track the leading edge is the right one**, and
|
|
232
|
+
* `scrollLeft` counts down from zero as the track moves on. Measured from the
|
|
233
|
+
* left, a carousel showing one slide at a time happened to come out right,
|
|
234
|
+
* each slide a whole track to the left of the one before it; one showing
|
|
235
|
+
* three put every one of the first few slides at a positive offset the
|
|
236
|
+
* scroller cannot reach, so it clamped to zero and the next arrow moved the
|
|
237
|
+
* dots and not the slides. Measured in Chromium on the several-across
|
|
238
|
+
* example: three presses of next, `index` at 2 and `scrollLeft` still at 0.
|
|
227
239
|
*/
|
|
228
240
|
private edgeOf;
|
|
229
241
|
private scrollToIndex;
|
|
@@ -4,7 +4,7 @@ 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, HelixSelectEvent, hostAria, requestChange, } from '@fusion.dev/helix-core';
|
|
7
|
+
import { customElement, HelixElement, HelixSelectEvent, hostAria, inlineStep, requestChange, } from '@fusion.dev/helix-core';
|
|
8
8
|
import { caretLeft, caretRight, play, stop } from '@fusion.dev/helix-icons';
|
|
9
9
|
import { html, nothing } from 'lit';
|
|
10
10
|
import { property, state } from 'lit/decorators.js';
|
|
@@ -21,7 +21,7 @@ let HelixHeadlessCarousel = class HelixHeadlessCarousel extends HelixElement {
|
|
|
21
21
|
this.loop = false;
|
|
22
22
|
this.rotating = false;
|
|
23
23
|
this.handleIndicatorKeydown = (event) => {
|
|
24
|
-
const step =
|
|
24
|
+
const step = inlineStep(this, event.key);
|
|
25
25
|
if (step === 0) {
|
|
26
26
|
return;
|
|
27
27
|
}
|
|
@@ -121,9 +121,13 @@ let HelixHeadlessCarousel = class HelixHeadlessCarousel extends HelixElement {
|
|
|
121
121
|
return Number.isNaN(read) ? 0 : read;
|
|
122
122
|
}
|
|
123
123
|
edgeOf(slide, track, bleed) {
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
124
|
+
if (this.orientation === 'vertical') {
|
|
125
|
+
return slide.offsetTop - track.offsetTop - bleed;
|
|
126
|
+
}
|
|
127
|
+
if (getComputedStyle(track).direction === 'rtl') {
|
|
128
|
+
return slide.offsetLeft + slide.offsetWidth - (track.offsetLeft + track.offsetWidth) + bleed;
|
|
129
|
+
}
|
|
130
|
+
return slide.offsetLeft - track.offsetLeft - bleed;
|
|
127
131
|
}
|
|
128
132
|
scrollToIndex() {
|
|
129
133
|
const slide = this.panes[this.index];
|
|
@@ -133,15 +137,17 @@ let HelixHeadlessCarousel = class HelixHeadlessCarousel extends HelixElement {
|
|
|
133
137
|
}
|
|
134
138
|
const vertical = this.orientation === 'vertical';
|
|
135
139
|
const target = this.edgeOf(slide, track, this.bleed(track));
|
|
140
|
+
const at = vertical ? { top: target } : { left: target };
|
|
136
141
|
if (Math.abs(target - (vertical ? track.scrollTop : track.scrollLeft)) < 1) {
|
|
142
|
+
if (this.settling) {
|
|
143
|
+
track.scrollTo({ behavior: 'instant', ...at });
|
|
144
|
+
this.settling = false;
|
|
145
|
+
}
|
|
137
146
|
return;
|
|
138
147
|
}
|
|
139
148
|
const still = globalThis.matchMedia?.('(prefers-reduced-motion: reduce)').matches ?? false;
|
|
140
149
|
this.settling = true;
|
|
141
|
-
track.scrollTo({
|
|
142
|
-
behavior: still ? 'instant' : 'smooth',
|
|
143
|
-
...(vertical ? { top: target } : { left: target }),
|
|
144
|
-
});
|
|
150
|
+
track.scrollTo({ behavior: still ? 'instant' : 'smooth', ...at });
|
|
145
151
|
}
|
|
146
152
|
stop() {
|
|
147
153
|
this.stopped = true;
|
|
@@ -262,7 +268,7 @@ let HelixHeadlessCarousel = class HelixHeadlessCarousel extends HelixElement {
|
|
|
262
268
|
aria-label="Previous slide"
|
|
263
269
|
@click=${() => this.goTo(this.index - 1)}
|
|
264
270
|
>
|
|
265
|
-
<svg part="previous-mark" fill="currentColor" viewBox=${caretLeft.viewBox} aria-hidden="true">
|
|
271
|
+
<svg part="previous-mark" data-mirror fill="currentColor" viewBox=${caretLeft.viewBox} aria-hidden="true">
|
|
266
272
|
${unsafeSVG(caretLeft.content)}
|
|
267
273
|
</svg>
|
|
268
274
|
</button>
|
|
@@ -272,7 +278,7 @@ let HelixHeadlessCarousel = class HelixHeadlessCarousel extends HelixElement {
|
|
|
272
278
|
aria-label="Next slide"
|
|
273
279
|
@click=${() => this.goTo(this.index + 1)}
|
|
274
280
|
>
|
|
275
|
-
<svg part="next-mark" fill="currentColor" viewBox=${caretRight.viewBox} aria-hidden="true">
|
|
281
|
+
<svg part="next-mark" data-mirror fill="currentColor" viewBox=${caretRight.viewBox} aria-hidden="true">
|
|
276
282
|
${unsafeSVG(caretRight.content)}
|
|
277
283
|
</svg>
|
|
278
284
|
</button>`}
|
|
@@ -110,6 +110,10 @@ export declare class HelixHeadlessChatComposer extends HelixElement {
|
|
|
110
110
|
* and the key are one affordance and should look like it. `send-label` is the
|
|
111
111
|
* accessible name rather than a visible one, so a screen reader still hears
|
|
112
112
|
* the word.
|
|
113
|
+
*
|
|
114
|
+
* **Not mirrored on a right-to-left page**, where every caret meaning next
|
|
115
|
+
* is. It pictures a key rather than a way to go, like the arrows `Kbd`
|
|
116
|
+
* draws, and a picture of a key is not turned round with the text.
|
|
113
117
|
*/
|
|
114
118
|
protected renderSend(): TemplateResult;
|
|
115
119
|
/**
|
|
@@ -59,6 +59,15 @@ declare const HelixHeadlessChat_base: (new (...args: any[]) => import("@fusion.d
|
|
|
59
59
|
* too long to hold as elements: it is drawn a window at a time, measured as it
|
|
60
60
|
* goes, and the log needs a block size of its own for that to mean anything.
|
|
61
61
|
*
|
|
62
|
+
* **A fed turn is styled through this element, not its own.** Its message is
|
|
63
|
+
* drawn in this shadow root, where `[author="me"]` cannot reach it, so every
|
|
64
|
+
* fed turn's parts are forwarded as `message-*`, and the ones that change with
|
|
65
|
+
* the turn a second time while it holds: `-mine` for a turn by `me`, and
|
|
66
|
+
* `message-meta-failed`, `message-content-sending` and
|
|
67
|
+
* `message-content-streaming` for its state. Every other author has the plain
|
|
68
|
+
* names only, so a conversation styling each participant apart passes its
|
|
69
|
+
* turns as children.
|
|
70
|
+
*
|
|
62
71
|
* @since 0.1.0
|
|
63
72
|
* @status experimental
|
|
64
73
|
* @category feedback
|
|
@@ -89,11 +98,19 @@ declare const HelixHeadlessChat_base: (new (...args: any[]) => import("@fusion.d
|
|
|
89
98
|
* @csspart message - A turn fed as data: the message drawn for it, forwarded whole.
|
|
90
99
|
* @csspart message-actions - The controls offered on a fed turn, beside its time.
|
|
91
100
|
* @csspart message-avatar - A fed turn's leading slot's box.
|
|
101
|
+
* @csspart message-avatar-mine - The leading slot's box on a fed turn by `me`.
|
|
92
102
|
* @csspart message-body - What a fed turn said, and the line under it.
|
|
103
|
+
* @csspart message-body-mine - What a fed turn by `me` said, and the line under it.
|
|
93
104
|
* @csspart message-content - A fed turn's text.
|
|
105
|
+
* @csspart message-content-mine - The text of a fed turn by `me`.
|
|
106
|
+
* @csspart message-content-sending - A fed turn's text while it is `sending`.
|
|
107
|
+
* @csspart message-content-streaming - A fed turn's text while it is `streaming`.
|
|
94
108
|
* @csspart message-indicator - A fed turn's default wait.
|
|
95
109
|
* @csspart message-mark - The status glyph beside a fed turn's failure.
|
|
96
110
|
* @csspart message-meta - The line under a fed turn: its time, its state, and its controls.
|
|
111
|
+
* @csspart message-meta-failed - The line under a fed turn that `failed`, which says so.
|
|
112
|
+
* @csspart message-meta-mine - The line under a fed turn by `me`.
|
|
113
|
+
* @csspart message-mine - A fed turn by `me`: the message drawn for it.
|
|
97
114
|
* @csspart message-retry - The control offered on a fed turn that failed.
|
|
98
115
|
* @csspart message-sources - What a fed turn was drawn from.
|
|
99
116
|
* @csspart message-state - What has happened to a fed turn, where that is worth saying.
|
|
@@ -13,6 +13,17 @@ import { repeat } from 'lit/directives/repeat.js';
|
|
|
13
13
|
import { html } from 'lit/static-html.js';
|
|
14
14
|
import { FAILED_LABEL } from '../message/chat-message.js';
|
|
15
15
|
const REGIONS = ['header', 'actions', 'resume', 'status', 'composer'];
|
|
16
|
+
const SECOND_NAMES = {
|
|
17
|
+
author: {
|
|
18
|
+
me: 'avatar: message-avatar-mine, body: message-body-mine, content: message-content-mine, message: message-mine, meta: message-meta-mine',
|
|
19
|
+
},
|
|
20
|
+
state: {
|
|
21
|
+
failed: 'meta: message-meta-failed',
|
|
22
|
+
sending: 'content: message-content-sending',
|
|
23
|
+
streaming: 'content: message-content-streaming',
|
|
24
|
+
},
|
|
25
|
+
};
|
|
26
|
+
const secondNames = (table, key) => key !== undefined && Object.hasOwn(table, key) ? `, ${table[key]}` : '';
|
|
16
27
|
const settled = (turn) => turn.state !== 'sending' && turn.state !== 'streaming';
|
|
17
28
|
const newsworthy = (turn) => turn.author !== 'me' || turn.state === 'failed';
|
|
18
29
|
const spoken = (message) => [...message.childNodes]
|
|
@@ -394,7 +405,7 @@ let HelixHeadlessChat = class HelixHeadlessChat extends MixinCollection(HelixEle
|
|
|
394
405
|
exportparts="actions: message-actions, avatar: message-avatar, body: message-body,
|
|
395
406
|
content: message-content, indicator: message-indicator, mark: message-mark, message,
|
|
396
407
|
meta: message-meta, retry: message-retry, sources: message-sources,
|
|
397
|
-
state: message-state, time: message-time"
|
|
408
|
+
state: message-state, time: message-time${secondNames(SECOND_NAMES.author, turn.author)}${secondNames(SECOND_NAMES.state, turn.state)}"
|
|
398
409
|
author=${turn.author ?? nothing}
|
|
399
410
|
at=${turn.at ?? nothing}
|
|
400
411
|
state=${turn.state ?? nothing}
|
|
@@ -58,6 +58,14 @@ import '../../copy-button/index.js';
|
|
|
58
58
|
* @csspart copy-mark - The clipboard glyph, and the confirmation that replaces it.
|
|
59
59
|
* @csspart copy-tooltip - The bubble, forwarded from the tooltip inside.
|
|
60
60
|
* @csspart copy-tooltip-arrow - The point, resting against the trigger.
|
|
61
|
+
* @csspart copy-tooltip-arrow-bottom - The point while the bubble is below the copy button, so on its top edge, beside `copy-tooltip-arrow`.
|
|
62
|
+
* @csspart copy-tooltip-arrow-left - The point while the bubble is left of the copy button, so on its right edge, beside `copy-tooltip-arrow`.
|
|
63
|
+
* @csspart copy-tooltip-arrow-right - The point while the bubble is right of the copy button, so on its left edge, beside `copy-tooltip-arrow`.
|
|
64
|
+
* @csspart copy-tooltip-arrow-top - The point while the bubble is above the copy button, so on its bottom edge, beside `copy-tooltip-arrow`.
|
|
65
|
+
* @csspart copy-tooltip-bottom - The bubble while it is below the copy button, beside `copy-tooltip`.
|
|
66
|
+
* @csspart copy-tooltip-left - The bubble while it is left of the copy button, beside `copy-tooltip`.
|
|
67
|
+
* @csspart copy-tooltip-right - The bubble while it is right of the copy button, beside `copy-tooltip`.
|
|
68
|
+
* @csspart copy-tooltip-top - The bubble while it is above the copy button, beside `copy-tooltip`.
|
|
61
69
|
* @csspart file - In a diff, one file's header and block.
|
|
62
70
|
* @csspart filler - In a split diff, the empty row opposite a line the other side does not have.
|
|
63
71
|
* @csspart frame - The code and the copy button beside it.
|
|
@@ -57,7 +57,10 @@ let HelixHeadlessCodeBlock = class HelixHeadlessCodeBlock extends HelixElement {
|
|
|
57
57
|
return html `<${this.tag('copy-button')}
|
|
58
58
|
part="copy"
|
|
59
59
|
exportparts="button: copy-button, mark: copy-mark, tooltip: copy-tooltip,
|
|
60
|
-
tooltip-arrow: copy-tooltip-arrow
|
|
60
|
+
tooltip-arrow: copy-tooltip-arrow, tooltip-arrow-bottom: copy-tooltip-arrow-bottom,
|
|
61
|
+
tooltip-arrow-left: copy-tooltip-arrow-left, tooltip-arrow-right: copy-tooltip-arrow-right,
|
|
62
|
+
tooltip-arrow-top: copy-tooltip-arrow-top, tooltip-bottom: copy-tooltip-bottom,
|
|
63
|
+
tooltip-left: copy-tooltip-left, tooltip-right: copy-tooltip-right, tooltip-top: copy-tooltip-top"
|
|
61
64
|
label="Copy code"
|
|
62
65
|
.value=${value}
|
|
63
66
|
></${this.tag('copy-button')}>`;
|
|
@@ -87,7 +87,8 @@ let HelixHeadlessColorPicker = class HelixHeadlessColorPicker extends MixinContr
|
|
|
87
87
|
if (box.width === 0 || box.height === 0) {
|
|
88
88
|
return;
|
|
89
89
|
}
|
|
90
|
-
const
|
|
90
|
+
const fromLeft = Math.min(1, Math.max(0, (event.clientX - box.left) / box.width));
|
|
91
|
+
const across = getComputedStyle(grid).direction === 'rtl' ? 1 - fromLeft : fromLeft;
|
|
91
92
|
const down = Math.min(1, Math.max(0, (event.clientY - box.top) / box.height));
|
|
92
93
|
this.move({ brightness: Math.round((1 - down) * 100), saturation: Math.round(across * 100) });
|
|
93
94
|
};
|
|
@@ -31,6 +31,14 @@ import '../../tooltip/index.js';
|
|
|
31
31
|
* @csspart mark - The clipboard glyph, and the confirmation that replaces it.
|
|
32
32
|
* @csspart tooltip - The bubble, forwarded from the tooltip inside.
|
|
33
33
|
* @csspart tooltip-arrow - The point, resting against the trigger.
|
|
34
|
+
* @csspart tooltip-arrow-bottom - The point while the bubble is below the button, so on its top edge, beside `tooltip-arrow`.
|
|
35
|
+
* @csspart tooltip-arrow-left - The point while the bubble is left of the button, so on its right edge, beside `tooltip-arrow`.
|
|
36
|
+
* @csspart tooltip-arrow-right - The point while the bubble is right of the button, so on its left edge, beside `tooltip-arrow`.
|
|
37
|
+
* @csspart tooltip-arrow-top - The point while the bubble is above the button, so on its bottom edge, beside `tooltip-arrow`.
|
|
38
|
+
* @csspart tooltip-bottom - The bubble while it is below the button, beside `tooltip`.
|
|
39
|
+
* @csspart tooltip-left - The bubble while it is left of the button, beside `tooltip`.
|
|
40
|
+
* @csspart tooltip-right - The bubble while it is right of the button, beside `tooltip`.
|
|
41
|
+
* @csspart tooltip-top - The bubble while it is above the button, beside `tooltip`.
|
|
34
42
|
*/
|
|
35
43
|
export declare class HelixHeadlessCopyButton extends HelixHeadlessIconButton {
|
|
36
44
|
/**
|
|
@@ -61,7 +61,10 @@ let HelixHeadlessCopyButton = HelixHeadlessCopyButton_1 = class HelixHeadlessCop
|
|
|
61
61
|
}
|
|
62
62
|
renderTooltip(control) {
|
|
63
63
|
return html `<${this.tag('tooltip')} content=${this.says} persist
|
|
64
|
-
exportparts="arrow: tooltip-arrow, tooltip
|
|
64
|
+
exportparts="arrow: tooltip-arrow, arrow-bottom: tooltip-arrow-bottom,
|
|
65
|
+
arrow-left: tooltip-arrow-left, arrow-right: tooltip-arrow-right,
|
|
66
|
+
arrow-top: tooltip-arrow-top, tooltip, tooltip-bottom, tooltip-left, tooltip-right,
|
|
67
|
+
tooltip-top">
|
|
65
68
|
${control}
|
|
66
69
|
</${this.tag('tooltip')}>`;
|
|
67
70
|
}
|
|
@@ -371,6 +371,16 @@ export declare class HelixHeadlessDataTable extends HelixHeadlessDataTable_base
|
|
|
371
371
|
* where it was written: it has nothing to be named by.
|
|
372
372
|
*/
|
|
373
373
|
get orderedColumns(): HelixHeadlessTableColumn[];
|
|
374
|
+
/**
|
|
375
|
+
* The columns drawn: the arranged ones less any that are hidden.
|
|
376
|
+
*
|
|
377
|
+
* **A hidden column takes no track and draws no cells.** Left in, its
|
|
378
|
+
* heading went and its track and its cell in every row stayed, so the header
|
|
379
|
+
* row came up a heading short, the first cell filled the gap, and every row
|
|
380
|
+
* after it began a column late. It keeps its place in `order` and in the
|
|
381
|
+
* sort, which are by field, so showing it again puts it back where it was.
|
|
382
|
+
*/
|
|
383
|
+
private get shownColumns();
|
|
374
384
|
/** The fields in the order on screen. */
|
|
375
385
|
private get fields();
|
|
376
386
|
/** The columns reduced to what the ordering needs. */
|
|
@@ -474,16 +484,25 @@ export declare class HelixHeadlessDataTable extends HelixHeadlessDataTable_base
|
|
|
474
484
|
private readonly toggleRow;
|
|
475
485
|
/** Selects every row, or clears them all where every one already was. */
|
|
476
486
|
private readonly toggleAll;
|
|
477
|
-
/**
|
|
487
|
+
/**
|
|
488
|
+
* Moves a column by some places among the ones that move and are drawn.
|
|
489
|
+
*
|
|
490
|
+
* Counted among the drawn ones, so a key moves the heading past one a reader
|
|
491
|
+
* can see: counted among all of them, a step past a hidden column changed the
|
|
492
|
+
* order and nothing on screen. A hidden column keeps its place among the rest.
|
|
493
|
+
*/
|
|
478
494
|
private moveColumn;
|
|
495
|
+
/** Every field in order, with one taken out and put back beside another. */
|
|
496
|
+
private placed;
|
|
479
497
|
/**
|
|
480
498
|
* The result as CSV: every row the filter lets through, in the order on
|
|
481
499
|
* screen, in the columns on screen, headed by their headings.
|
|
482
500
|
*
|
|
483
501
|
* **Values, not cells.** A cell may be a template, a badge or a link, so each
|
|
484
502
|
* column gives its field's value, which is what a spreadsheet wants anyway.
|
|
485
|
-
* A column with no field has no value and is left out
|
|
486
|
-
* is
|
|
503
|
+
* A column with no field has no value and is left out, and so is a hidden
|
|
504
|
+
* one, which is not on screen. In `server` mode this is the page it holds,
|
|
505
|
+
* which is all it can know.
|
|
487
506
|
*
|
|
488
507
|
* **A text value that a spreadsheet would run is quoted as text.** A cell
|
|
489
508
|
* opening with `=`, `+`, `-` or `@` is a formula to a spreadsheet, and a
|
|
@@ -5,7 +5,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
5
5
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
6
|
};
|
|
7
7
|
var HelixHeadlessDataTable_1;
|
|
8
|
-
import { customElement, HelixElement, HelixFilterEvent, HelixNavigateEvent, HelixReorderEvent, HelixSelectEvent, HelixSortEvent, hostAria, MixinCollection, requestChange, slotFilled, VirtualizeController, } from '@fusion.dev/helix-core';
|
|
8
|
+
import { customElement, HelixElement, HelixFilterEvent, HelixNavigateEvent, HelixReorderEvent, HelixSelectEvent, HelixSortEvent, hostAria, inlineStep, MixinCollection, requestChange, slotFilled, VirtualizeController, } from '@fusion.dev/helix-core';
|
|
9
9
|
import { nothing } from 'lit';
|
|
10
10
|
import { property, state } from 'lit/decorators.js';
|
|
11
11
|
import { repeat } from 'lit/directives/repeat.js';
|
|
@@ -99,8 +99,7 @@ let HelixHeadlessDataTable = class HelixHeadlessDataTable extends MixinCollectio
|
|
|
99
99
|
return;
|
|
100
100
|
}
|
|
101
101
|
const column = this.columnFrom(event);
|
|
102
|
-
const
|
|
103
|
-
const by = event.key === 'ArrowRight' ? forward : event.key === 'ArrowLeft' ? -forward : 0;
|
|
102
|
+
const by = inlineStep(this, event.key);
|
|
104
103
|
if (column && by !== 0) {
|
|
105
104
|
event.preventDefault();
|
|
106
105
|
this.moveColumn(column.field, by);
|
|
@@ -126,7 +125,7 @@ let HelixHeadlessDataTable = class HelixHeadlessDataTable extends MixinCollectio
|
|
|
126
125
|
return;
|
|
127
126
|
}
|
|
128
127
|
const rtl = getComputedStyle(this).direction === 'rtl';
|
|
129
|
-
const others = this.
|
|
128
|
+
const others = this.shownColumns.filter((column) => column.field !== '' && column.field !== dragging.field);
|
|
130
129
|
const place = others.filter((column) => {
|
|
131
130
|
const box = column.shadowRoot?.querySelector('[part="column"]')?.getBoundingClientRect();
|
|
132
131
|
if (!box) {
|
|
@@ -135,8 +134,11 @@ let HelixHeadlessDataTable = class HelixHeadlessDataTable extends MixinCollectio
|
|
|
135
134
|
const middle = box.left + box.width / 2;
|
|
136
135
|
return rtl ? event.clientX < middle : event.clientX > middle;
|
|
137
136
|
}).length;
|
|
138
|
-
const
|
|
139
|
-
|
|
137
|
+
const beside = others[place - 1] ?? others[0];
|
|
138
|
+
if (!beside) {
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
const next = this.placed(dragging.field, beside.field, place > 0);
|
|
140
142
|
if (next.join(' ') !== this.dragOrder.join(' ')) {
|
|
141
143
|
this.dragOrder = next;
|
|
142
144
|
}
|
|
@@ -272,6 +274,9 @@ let HelixHeadlessDataTable = class HelixHeadlessDataTable extends MixinCollectio
|
|
|
272
274
|
let next = 0;
|
|
273
275
|
return columns.map((column) => (column.field === '' ? column : (moving[next++] ?? column)));
|
|
274
276
|
}
|
|
277
|
+
get shownColumns() {
|
|
278
|
+
return this.orderedColumns.filter((column) => column.shown);
|
|
279
|
+
}
|
|
275
280
|
get fields() {
|
|
276
281
|
return this.orderedColumns.filter((column) => column.field !== '').map((column) => column.field);
|
|
277
282
|
}
|
|
@@ -281,7 +286,7 @@ let HelixHeadlessDataTable = class HelixHeadlessDataTable extends MixinCollectio
|
|
|
281
286
|
.map((column) => ({ field: column.field, order: (row) => column.order(row) }));
|
|
282
287
|
}
|
|
283
288
|
get template() {
|
|
284
|
-
const declared = this.
|
|
289
|
+
const declared = this.shownColumns;
|
|
285
290
|
if (declared.length === 0) {
|
|
286
291
|
return '';
|
|
287
292
|
}
|
|
@@ -408,17 +413,21 @@ let HelixHeadlessDataTable = class HelixHeadlessDataTable extends MixinCollectio
|
|
|
408
413
|
return rows.map((row, place) => this.keyOf(row, place));
|
|
409
414
|
}
|
|
410
415
|
moveColumn(field, by) {
|
|
411
|
-
const
|
|
412
|
-
const from =
|
|
413
|
-
const
|
|
414
|
-
if (from < 0 ||
|
|
416
|
+
const drawn = this.shownColumns.filter((column) => column.field !== '');
|
|
417
|
+
const from = drawn.findIndex((column) => column.field === field);
|
|
418
|
+
const past = drawn[from + by];
|
|
419
|
+
if (from < 0 || !past) {
|
|
415
420
|
return false;
|
|
416
421
|
}
|
|
417
|
-
|
|
418
|
-
|
|
422
|
+
return this.requestOrder(this.placed(field, past.field, by > 0));
|
|
423
|
+
}
|
|
424
|
+
placed(field, beside, after) {
|
|
425
|
+
const fields = this.fields.filter((one) => one !== field);
|
|
426
|
+
fields.splice(fields.indexOf(beside) + (after ? 1 : 0), 0, field);
|
|
427
|
+
return fields;
|
|
419
428
|
}
|
|
420
429
|
csv() {
|
|
421
|
-
const columns = this.
|
|
430
|
+
const columns = this.shownColumns.filter((column) => column.field !== '');
|
|
422
431
|
const rows = this.mode === 'server' ? this.rows : this.arrange().rows;
|
|
423
432
|
const quote = (value) => {
|
|
424
433
|
if (value === undefined || value === null) {
|
|
@@ -559,7 +568,7 @@ let HelixHeadlessDataTable = class HelixHeadlessDataTable extends MixinCollectio
|
|
|
559
568
|
></${checkbox}>`;
|
|
560
569
|
}
|
|
561
570
|
renderRows(rows) {
|
|
562
|
-
const columns = this.
|
|
571
|
+
const columns = this.shownColumns;
|
|
563
572
|
const field = this.rowKey;
|
|
564
573
|
const start = this.windowStart;
|
|
565
574
|
const chosen = this.selectable ? this.chosen : undefined;
|
|
@@ -611,7 +620,7 @@ let HelixHeadlessDataTable = class HelixHeadlessDataTable extends MixinCollectio
|
|
|
611
620
|
render() {
|
|
612
621
|
const { available, matched, rows } = this.view;
|
|
613
622
|
const template = this.template;
|
|
614
|
-
const columns = this.
|
|
623
|
+
const columns = this.shownColumns;
|
|
615
624
|
const pagination = this.tag('pagination');
|
|
616
625
|
return html `<div part="toolbar"><slot name="toolbar"></slot></div>
|
|
617
626
|
<div
|
|
@@ -145,9 +145,42 @@ export declare class HelixHeadlessDateInput extends HelixHeadlessDateInput_base
|
|
|
145
145
|
*
|
|
146
146
|
* Worth more than one mainly for a range, where picking a start in March and
|
|
147
147
|
* an end in April otherwise means paging between them and losing sight of the
|
|
148
|
-
* first. The panel is sized by its content, so this widens it
|
|
148
|
+
* first. The panel is sized by its content, so this widens it, and where the
|
|
149
|
+
* window has no room for that width it shows one month until there is.
|
|
149
150
|
*/
|
|
150
151
|
months: number;
|
|
152
|
+
/**
|
|
153
|
+
* How many months the panel is showing, where that is fewer than `months`.
|
|
154
|
+
*
|
|
155
|
+
* **One month rather than a squeezed two**, and decided here rather than in a
|
|
156
|
+
* stylesheet because what changes is markup. Two months measure 600 pixels
|
|
157
|
+
* across, measured 15 Sep 2026, and in a 390 window that ran past both
|
|
158
|
+
* edges. A rule could only clip them, which hides the next-month control with
|
|
159
|
+
* the month it sits on, or stack them, which makes a panel taller than most
|
|
160
|
+
* of a phone. The count is behavior, as a carousel's per-view is.
|
|
161
|
+
*/
|
|
162
|
+
private fitted;
|
|
163
|
+
/**
|
|
164
|
+
* How wide the panel was the last time it held every month, in pixels.
|
|
165
|
+
*
|
|
166
|
+
* Measured rather than estimated, because a month's width is its locale's:
|
|
167
|
+
* the weekday names set it. Remembered, so a panel showing one month knows
|
|
168
|
+
* what it would take to show them all, and the answer cannot flip back and
|
|
169
|
+
* forth between two measurements of different things.
|
|
170
|
+
*/
|
|
171
|
+
private wide;
|
|
172
|
+
/**
|
|
173
|
+
* Shows one month where the window has no room for them all, and all of them
|
|
174
|
+
* again once it does.
|
|
175
|
+
*
|
|
176
|
+
* Called after every placement, with the room the floating pass measured,
|
|
177
|
+
* which is the window less a margin on each side. The panel hangs in the top
|
|
178
|
+
* layer, so the window is its box, the argument Dialog makes for reading the
|
|
179
|
+
* viewport. The surface's own width is read, since it is sized by its content
|
|
180
|
+
* and never capped.
|
|
181
|
+
*/
|
|
182
|
+
protected placed(room: number | undefined): void;
|
|
183
|
+
protected willUpdate(changed: PropertyValues): void;
|
|
151
184
|
/**
|
|
152
185
|
* What the field says before a date is in it.
|
|
153
186
|
*/
|
|
@@ -33,6 +33,8 @@ let HelixHeadlessDateInput = class HelixHeadlessDateInput extends MixinPickerEdi
|
|
|
33
33
|
this.max = '';
|
|
34
34
|
this.min = '';
|
|
35
35
|
this.months = 1;
|
|
36
|
+
this.fitted = undefined;
|
|
37
|
+
this.wide = undefined;
|
|
36
38
|
this.placeholder = 'YYYY-MM-DD';
|
|
37
39
|
this.step = 1;
|
|
38
40
|
this.draft = '';
|
|
@@ -82,6 +84,27 @@ let HelixHeadlessDateInput = class HelixHeadlessDateInput extends MixinPickerEdi
|
|
|
82
84
|
};
|
|
83
85
|
this.triggerLabel = 'Choose a date';
|
|
84
86
|
}
|
|
87
|
+
placed(room) {
|
|
88
|
+
const all = Math.max(1, Math.floor(this.months) || 1);
|
|
89
|
+
const surface = this.partNamed('surface');
|
|
90
|
+
if (room === undefined || all === 1 || !surface) {
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
if (this.fitted === undefined) {
|
|
94
|
+
this.wide = surface.offsetWidth;
|
|
95
|
+
}
|
|
96
|
+
const next = this.wide === undefined || this.wide <= room ? undefined : 1;
|
|
97
|
+
if (next !== this.fitted) {
|
|
98
|
+
this.fitted = next;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
willUpdate(changed) {
|
|
102
|
+
super.willUpdate(changed);
|
|
103
|
+
if (changed.has('months') || changed.has('locale')) {
|
|
104
|
+
this.fitted = undefined;
|
|
105
|
+
this.wide = undefined;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
85
108
|
get picked() {
|
|
86
109
|
const held = dates(this.value);
|
|
87
110
|
return held.length > 0 && held.every(isIso) ? held.join(',') : '';
|
|
@@ -153,7 +176,7 @@ let HelixHeadlessDateInput = class HelixHeadlessDateInput extends MixinPickerEdi
|
|
|
153
176
|
week: picker-week, weekday: picker-weekday"
|
|
154
177
|
?invalid=${this.resolvedFeedback !== ''}
|
|
155
178
|
mode=${this.mode ?? nothing}
|
|
156
|
-
months=${this.months}
|
|
179
|
+
months=${this.fitted ?? this.months}
|
|
157
180
|
.value=${this.picked}
|
|
158
181
|
disable-dates=${this.disableDates || nothing}
|
|
159
182
|
disable-days=${this.disableDays || nothing}
|
|
@@ -274,6 +297,9 @@ __decorate([
|
|
|
274
297
|
__decorate([
|
|
275
298
|
property({ type: Number })
|
|
276
299
|
], HelixHeadlessDateInput.prototype, "months", void 0);
|
|
300
|
+
__decorate([
|
|
301
|
+
state()
|
|
302
|
+
], HelixHeadlessDateInput.prototype, "fitted", void 0);
|
|
277
303
|
__decorate([
|
|
278
304
|
property()
|
|
279
305
|
], HelixHeadlessDateInput.prototype, "placeholder", void 0);
|
|
@@ -4,7 +4,7 @@ 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 { valueAsDate as asDate, customElement, dateAsValue as fromDate, HelixFormElement, HelixNavigateEvent, hostAria, MixinControllerValue, requestChange, } from '@fusion.dev/helix-core';
|
|
7
|
+
import { valueAsDate as asDate, customElement, dateAsValue as fromDate, HelixFormElement, HelixNavigateEvent, hostAria, inlineStep, MixinControllerValue, requestChange, } from '@fusion.dev/helix-core';
|
|
8
8
|
import { caretLeft, caretRight } from '@fusion.dev/helix-icons';
|
|
9
9
|
import { html, nothing } from 'lit';
|
|
10
10
|
import { property, state } from 'lit/decorators.js';
|
|
@@ -75,14 +75,12 @@ let HelixHeadlessDatePicker = class HelixHeadlessDatePicker extends MixinControl
|
|
|
75
75
|
return;
|
|
76
76
|
}
|
|
77
77
|
const from = this.anchor;
|
|
78
|
+
const along = inlineStep(this, event.key);
|
|
78
79
|
if (event.key === 'Enter' || event.key === ' ') {
|
|
79
80
|
this.select(from);
|
|
80
81
|
}
|
|
81
|
-
else if (
|
|
82
|
-
this.moveTo(addDays(from,
|
|
83
|
-
}
|
|
84
|
-
else if (event.key === 'ArrowRight') {
|
|
85
|
-
this.moveTo(addDays(from, 1));
|
|
82
|
+
else if (along !== 0) {
|
|
83
|
+
this.moveTo(addDays(from, along));
|
|
86
84
|
}
|
|
87
85
|
else if (event.key === 'ArrowUp') {
|
|
88
86
|
this.moveTo(addDays(from, -7));
|
|
@@ -296,14 +294,14 @@ let HelixHeadlessDatePicker = class HelixHeadlessDatePicker extends MixinControl
|
|
|
296
294
|
}
|
|
297
295
|
renderPreviousMark() {
|
|
298
296
|
return html `<slot name="previous-icon">
|
|
299
|
-
<svg part="previous-mark" fill="currentColor" viewBox=${caretLeft.viewBox} aria-hidden="true">
|
|
297
|
+
<svg part="previous-mark" data-mirror fill="currentColor" viewBox=${caretLeft.viewBox} aria-hidden="true">
|
|
300
298
|
${unsafeSVG(caretLeft.content)}
|
|
301
299
|
</svg>
|
|
302
300
|
</slot>`;
|
|
303
301
|
}
|
|
304
302
|
renderNextMark() {
|
|
305
303
|
return html `<slot name="next-icon">
|
|
306
|
-
<svg part="next-mark" fill="currentColor" viewBox=${caretRight.viewBox} aria-hidden="true">
|
|
304
|
+
<svg part="next-mark" data-mirror fill="currentColor" viewBox=${caretRight.viewBox} aria-hidden="true">
|
|
307
305
|
${unsafeSVG(caretRight.content)}
|
|
308
306
|
</svg>
|
|
309
307
|
</slot>`;
|