@aceshooting/lyra-ui 2.0.0 → 2.1.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/README.md +87 -14
- package/custom-elements.json +11555 -5539
- package/dist/components/app-rail/app-rail-item.d.ts +30 -0
- package/dist/components/app-rail/app-rail-item.js +68 -0
- package/dist/components/app-rail/app-rail-item.styles.d.ts +1 -0
- package/dist/components/app-rail/app-rail-item.styles.js +65 -0
- package/dist/components/app-rail/app-rail.d.ts +21 -24
- package/dist/components/app-rail/app-rail.js +68 -132
- package/dist/components/app-rail/app-rail.styles.js +5 -2
- package/dist/components/attachment-chip/attachment-chip.d.ts +38 -11
- package/dist/components/attachment-chip/attachment-chip.js +73 -29
- package/dist/components/attachment-trigger/attachment-trigger.d.ts +13 -0
- package/dist/components/attachment-trigger/attachment-trigger.js +13 -1
- package/dist/components/attachment-trigger/attachment-trigger.styles.js +28 -6
- package/dist/components/chart/bar-chart.js +2 -18
- package/dist/components/chart/box-plot.d.ts +25 -1
- package/dist/components/chart/box-plot.js +136 -6
- package/dist/components/chart/box-plot.styles.js +13 -0
- package/dist/components/chart/bubble-chart.js +2 -18
- package/dist/components/chart/chart.d.ts +54 -10
- package/dist/components/chart/chart.js +182 -39
- package/dist/components/chart/doughnut-chart.js +2 -18
- package/dist/components/chart/histogram-bin.d.ts +5 -2
- package/dist/components/chart/histogram-bin.js +12 -4
- package/dist/components/chart/histogram.js +8 -16
- package/dist/components/chart/line-chart.js +2 -18
- package/dist/components/chart/lite-chart.d.ts +80 -3
- package/dist/components/chart/lite-chart.js +250 -53
- package/dist/components/chart/pie-chart.js +2 -18
- package/dist/components/chart/polar-area-chart.js +2 -18
- package/dist/components/chart/radar-chart.js +2 -18
- package/dist/components/chart/scatter-chart.js +2 -18
- package/dist/components/chat-composer/chat-composer.d.ts +42 -1
- package/dist/components/chat-composer/chat-composer.js +84 -3
- package/dist/components/chat-composer/chat-composer.styles.js +11 -1
- package/dist/components/chat-message/chat-message.d.ts +32 -4
- package/dist/components/chat-message/chat-message.js +57 -17
- package/dist/components/checkbox/checkbox.d.ts +66 -8
- package/dist/components/checkbox/checkbox.js +173 -50
- package/dist/components/checkbox/checkbox.styles.js +9 -2
- package/dist/components/chip/chip-group.js +8 -2
- package/dist/components/chip/chip.js +9 -2
- package/dist/components/citation-badge/citation-badge.js +21 -3
- package/dist/components/code-block/code-block.d.ts +38 -0
- package/dist/components/code-block/code-block.js +72 -7
- package/dist/components/code-block/code-loader.d.ts +44 -1
- package/dist/components/code-block/code-loader.js +63 -0
- package/dist/components/combobox/combobox.d.ts +46 -5
- package/dist/components/combobox/combobox.js +175 -35
- package/dist/components/combobox/combobox.styles.js +3 -3
- package/dist/components/context-meter/context-meter.js +17 -8
- package/dist/components/context-meter/context-meter.styles.js +0 -6
- package/dist/components/conversation-item/conversation-item.d.ts +13 -16
- package/dist/components/conversation-item/conversation-item.js +29 -20
- package/dist/components/date-picker/calendar-core.d.ts +24 -0
- package/dist/components/date-picker/calendar-core.js +51 -4
- package/dist/components/date-picker/date-input.d.ts +77 -10
- package/dist/components/date-picker/date-input.js +278 -73
- package/dist/components/date-picker/date-picker.d.ts +28 -4
- package/dist/components/date-picker/date-picker.js +95 -37
- package/dist/components/dialog/confirm.js +3 -6
- package/dist/components/dialog/dialog.d.ts +75 -31
- package/dist/components/dialog/dialog.js +147 -131
- package/dist/components/dialog/dialog.styles.js +46 -2
- package/dist/components/dock-panel/dock-panel.d.ts +8 -0
- package/dist/components/dock-panel/dock-panel.js +15 -1
- package/dist/components/dock-panel/dock-panel.styles.js +15 -1
- package/dist/components/document-preview/document-preview.d.ts +15 -7
- package/dist/components/document-preview/document-preview.js +29 -13
- package/dist/components/empty/empty.d.ts +1 -2
- package/dist/components/empty/empty.js +18 -12
- package/dist/components/empty/empty.styles.js +0 -3
- package/dist/components/export-button/export-button.d.ts +12 -0
- package/dist/components/export-button/export-button.js +33 -5
- package/dist/components/export-button/export-button.styles.js +5 -1
- package/dist/components/file-input/accept.js +2 -0
- package/dist/components/file-input/file-input.d.ts +10 -1
- package/dist/components/file-input/file-input.js +36 -5
- package/dist/components/flag/flag.d.ts +1 -1
- package/dist/components/flag/flag.js +15 -1
- package/dist/components/flag/flag.styles.js +1 -1
- package/dist/components/flag/language-map.d.ts +4 -1
- package/dist/components/flag/language-map.js +6 -3
- package/dist/components/gauge/gauge.d.ts +10 -1
- package/dist/components/gauge/gauge.js +28 -9
- package/dist/components/generation-status/generation-status.d.ts +13 -5
- package/dist/components/generation-status/generation-status.js +59 -5
- package/dist/components/graph/graph.d.ts +37 -3
- package/dist/components/graph/graph.js +132 -20
- package/dist/components/heatmap/calendar-grid.d.ts +15 -6
- package/dist/components/heatmap/calendar-grid.js +17 -6
- package/dist/components/heatmap/heatmap-scale.d.ts +5 -1
- package/dist/components/heatmap/heatmap-scale.js +8 -2
- package/dist/components/heatmap/heatmap.d.ts +166 -25
- package/dist/components/heatmap/heatmap.js +372 -89
- package/dist/components/json-viewer/json-viewer.d.ts +22 -5
- package/dist/components/json-viewer/json-viewer.js +115 -37
- package/dist/components/json-viewer/json-viewer.styles.js +2 -1
- package/dist/components/kbd/kbd.js +24 -7
- package/dist/components/live-region/live-region.d.ts +10 -1
- package/dist/components/live-region/live-region.js +42 -6
- package/dist/components/map/map.d.ts +24 -1
- package/dist/components/map/map.js +89 -24
- package/dist/components/markdown/markdown-loader.d.ts +24 -0
- package/dist/components/markdown/markdown-loader.js +35 -1
- package/dist/components/markdown/markdown.d.ts +46 -8
- package/dist/components/markdown/markdown.js +136 -31
- package/dist/components/markdown/markdown.styles.js +7 -1
- package/dist/components/media-card/media-card.d.ts +25 -17
- package/dist/components/media-card/media-card.js +43 -65
- package/dist/components/mention-popover/mention-popover.d.ts +4 -1
- package/dist/components/mention-popover/mention-popover.js +23 -5
- package/dist/components/menu/menu-item.d.ts +32 -3
- package/dist/components/menu/menu-item.js +94 -7
- package/dist/components/menu/menu-item.styles.js +8 -0
- package/dist/components/menu/menu.d.ts +25 -1
- package/dist/components/menu/menu.js +99 -3
- package/dist/components/menu/menu.styles.js +3 -2
- package/dist/components/model-select/model-select.d.ts +48 -3
- package/dist/components/model-select/model-select.js +120 -22
- package/dist/components/model-select/model-select.styles.js +17 -3
- package/dist/components/model-settings-panel/model-settings-panel.d.ts +25 -1
- package/dist/components/model-settings-panel/model-settings-panel.js +65 -1
- package/dist/components/playback/playback.d.ts +6 -2
- package/dist/components/playback/playback.js +72 -29
- package/dist/components/playback/playback.styles.js +6 -1
- package/dist/components/responsive-panel/responsive-panel.d.ts +29 -16
- package/dist/components/responsive-panel/responsive-panel.js +130 -132
- package/dist/components/responsive-panel/responsive-panel.styles.js +1 -1
- package/dist/components/result-card/result-card.d.ts +8 -2
- package/dist/components/result-card/result-card.js +9 -3
- package/dist/components/result-card/result-card.styles.js +0 -1
- package/dist/components/select/select.d.ts +59 -20
- package/dist/components/select/select.js +125 -43
- package/dist/components/skeleton/skeleton.d.ts +3 -0
- package/dist/components/skeleton/skeleton.js +7 -1
- package/dist/components/skeleton/skeleton.styles.js +5 -4
- package/dist/components/slider/slider.d.ts +57 -5
- package/dist/components/slider/slider.js +195 -80
- package/dist/components/source-card/source-card.d.ts +17 -5
- package/dist/components/source-card/source-card.js +55 -8
- package/dist/components/source-card/source-card.styles.js +1 -1
- package/dist/components/source-list/source-list.js +9 -1
- package/dist/components/sparkline/sparkline.js +34 -10
- package/dist/components/split/split.d.ts +141 -14
- package/dist/components/split/split.js +357 -52
- package/dist/components/split/split.styles.js +18 -1
- package/dist/components/stat/stat.d.ts +10 -4
- package/dist/components/stat/stat.js +46 -11
- package/dist/components/stream-status/stream-status.d.ts +27 -11
- package/dist/components/stream-status/stream-status.js +95 -13
- package/dist/components/streaming-text/streaming-text.d.ts +9 -3
- package/dist/components/streaming-text/streaming-text.js +25 -10
- package/dist/components/streaming-text/streaming-text.styles.js +3 -2
- package/dist/components/switch/switch.d.ts +52 -7
- package/dist/components/switch/switch.js +111 -40
- package/dist/components/switch/switch.styles.js +1 -1
- package/dist/components/table/table.d.ts +18 -3
- package/dist/components/table/table.js +88 -20
- package/dist/components/tabs/tabs.d.ts +23 -0
- package/dist/components/tabs/tabs.js +76 -12
- package/dist/components/tabs/tabs.styles.js +11 -0
- package/dist/components/thinking-panel/thinking-panel.d.ts +3 -1
- package/dist/components/thinking-panel/thinking-panel.js +34 -9
- package/dist/components/thinking-panel/thinking-panel.styles.js +6 -0
- package/dist/components/time-range/time-range.d.ts +59 -2
- package/dist/components/time-range/time-range.js +163 -67
- package/dist/components/toast/toast-item.d.ts +12 -3
- package/dist/components/toast/toast-item.js +90 -53
- package/dist/components/toast/toast-item.styles.js +59 -28
- package/dist/components/toast/toast.js +17 -5
- package/dist/components/toast/toaster.js +10 -1
- package/dist/components/tool-approval-dialog/tool-approval-dialog.d.ts +11 -10
- package/dist/components/tool-approval-dialog/tool-approval-dialog.js +50 -124
- package/dist/components/tool-approval-dialog/tool-approval-dialog.styles.js +1 -1
- package/dist/components/tool-call-chip/tool-call-chip.d.ts +18 -2
- package/dist/components/tool-call-chip/tool-call-chip.js +86 -25
- package/dist/components/tool-param-form/tool-param-form.d.ts +89 -28
- package/dist/components/tool-param-form/tool-param-form.js +350 -106
- package/dist/components/tool-result-dialog/tool-result-dialog.d.ts +27 -7
- package/dist/components/tool-result-dialog/tool-result-dialog.js +80 -115
- package/dist/components/tool-result-dialog/tool-result-dialog.styles.js +1 -1
- package/dist/components/tool-result-view/registry.d.ts +0 -8
- package/dist/components/tool-result-view/registry.js +7 -2
- package/dist/components/tool-result-view/tool-result-view.d.ts +6 -3
- package/dist/components/tool-result-view/tool-result-view.js +18 -4
- package/dist/components/tool-select-dialog/tool-select-dialog.d.ts +11 -11
- package/dist/components/tool-select-dialog/tool-select-dialog.js +44 -133
- package/dist/components/tool-select-dialog/tool-select-dialog.styles.js +13 -4
- package/dist/components/tree/tree-node.d.ts +4 -1
- package/dist/components/tree/tree-node.js +4 -1
- package/dist/components/tree/tree.d.ts +17 -8
- package/dist/components/tree/tree.js +21 -20
- package/dist/components/typing-indicator/typing-indicator.d.ts +12 -2
- package/dist/components/typing-indicator/typing-indicator.js +16 -4
- package/dist/components/typing-indicator/typing-indicator.styles.js +2 -2
- package/dist/components/virtual-list/virtual-list.d.ts +56 -19
- package/dist/components/virtual-list/virtual-list.js +184 -38
- package/dist/components/virtual-list/virtual-list.styles.js +12 -0
- package/dist/components/widget/widget.d.ts +5 -4
- package/dist/components/widget/widget.js +54 -120
- package/dist/components/widget/widget.styles.js +8 -2
- package/dist/components/word-cloud/word-cloud-layout.d.ts +7 -0
- package/dist/components/word-cloud/word-cloud-layout.js +20 -6
- package/dist/components/word-cloud/word-cloud.d.ts +22 -2
- package/dist/components/word-cloud/word-cloud.js +45 -6
- package/dist/components/word-cloud/word-cloud.styles.js +13 -1
- package/dist/internal/anchored-validity.d.ts +1 -0
- package/dist/internal/anchored-validity.js +86 -0
- package/dist/internal/form-associated.d.ts +7 -0
- package/dist/internal/form-associated.js +43 -4
- package/dist/internal/numbers.d.ts +12 -0
- package/dist/internal/numbers.js +26 -0
- package/dist/internal/overlay-manager.d.ts +51 -0
- package/dist/internal/overlay-manager.js +523 -0
- package/dist/internal/positioner.js +27 -3
- package/dist/internal/safe-url.d.ts +12 -0
- package/dist/internal/safe-url.js +41 -0
- package/dist/internal/tokens.styles.js +17 -11
- package/dist/lyra.d.ts +5 -2
- package/dist/lyra.js +3 -1
- package/llms-full.txt +970 -426
- package/llms.txt +5 -4
- package/package.json +19 -2
|
@@ -8,6 +8,7 @@ import { html, svg, nothing } from 'lit';
|
|
|
8
8
|
import { property, state, query } from 'lit/decorators.js';
|
|
9
9
|
import { LyraElement } from '../../internal/lyra-element.js';
|
|
10
10
|
import { defineElement } from '../../internal/prefix.js';
|
|
11
|
+
import { srOnly } from '../../internal/a11y.js';
|
|
11
12
|
import { styles } from './lite-chart.styles.js';
|
|
12
13
|
// Colorblind-considered categorical palette, used round-robin when a Series
|
|
13
14
|
// doesn't set its own `color` — same role as Chart.js's default dataset
|
|
@@ -30,6 +31,7 @@ const AXIS_TITLE_SPACE = 14;
|
|
|
30
31
|
const TICK_COUNT = 4;
|
|
31
32
|
const BAR_GROUP_GAP = 0.2; // fraction of a category slot left as gap between categories
|
|
32
33
|
const BAR_GAP = 0.08; // fraction of a category slot left as gap between grouped bars
|
|
34
|
+
const BAR_CORNER_RADIUS = 4; // px, used only when roundedBars is true
|
|
33
35
|
/**
|
|
34
36
|
* Picks a "nice" (1/2/5 × 10^n) step size for an axis spanning `span` over
|
|
35
37
|
* roughly `count` ticks — the standard Heckbert nice-numbers approach, so
|
|
@@ -86,6 +88,22 @@ function niceDomain(dataLo, dataHi, beginAtZero, count) {
|
|
|
86
88
|
* calendar columns — overriding the internal slot math for both bars and
|
|
87
89
|
* their labels. All three are additive and no-ops when left unset.
|
|
88
90
|
*
|
|
91
|
+
* Seven further additive, opt-in properties: `pointText` overrides the
|
|
92
|
+
* per-bar/per-point `<title>`/`aria-label` tooltip text (mirrors
|
|
93
|
+
* `lyra-heatmap`'s `cellText` hook), falling back to the built-in raw-value
|
|
94
|
+
* template when unset; `roundedBars` draws bars as a rounded-top path
|
|
95
|
+
* instead of a square-cornered rect; `skipZero` omits a bar entirely (not
|
|
96
|
+
* just zero-height) for an exactly-`0` value; `padLeft`/`barGapRatio`
|
|
97
|
+
* override the internal `PAD_LEFT`/`BAR_GROUP_GAP` layout constants; `scale`
|
|
98
|
+
* (`type="bar"` only) switches the bar-height mapping from the default
|
|
99
|
+
* linear `niceDomain` fraction to a `Math.sqrt(value / domainMax)`
|
|
100
|
+
* compression (mirroring `lyra-heatmap`'s matrix-mode `sqrt` scale) so a
|
|
101
|
+
* skewed dataset's smaller bars don't get washed out by one dominant value
|
|
102
|
+
* — gridlines/tick labels stay on the linear domain regardless, only the bar
|
|
103
|
+
* marks' own height changes, and `type="line"` ignores `scale` entirely; and
|
|
104
|
+
* `hideAxis` suppresses `renderGrid()`'s gridlines/tick labels altogether
|
|
105
|
+
* (x-axis category labels, rendered separately, are unaffected).
|
|
106
|
+
*
|
|
89
107
|
* @customElement lyra-lite-chart
|
|
90
108
|
* @event lyra-point-click - Fired when a bar/point is activated (click, or
|
|
91
109
|
* Enter/Space while focused). `detail: { datasetIndex: number, index:
|
|
@@ -101,6 +119,8 @@ function niceDomain(dataLo, dataHi, beginAtZero, count) {
|
|
|
101
119
|
* @csspart legend - The legend row, when `legend` is set.
|
|
102
120
|
* @csspart legend-item - Each legend entry.
|
|
103
121
|
* @csspart legend-swatch - Each legend entry's color swatch.
|
|
122
|
+
* @csspart live-region - The current mark announcement for keyboard users.
|
|
123
|
+
* @csspart data-list - A visually hidden list of all plotted data points.
|
|
104
124
|
*/
|
|
105
125
|
export class LyraLiteChart extends LyraElement {
|
|
106
126
|
constructor() {
|
|
@@ -124,12 +144,31 @@ export class LyraLiteChart extends LyraElement {
|
|
|
124
144
|
/** Fixed per-category bar width in px, used only when `layout="scroll"`. Ignored (as before this
|
|
125
145
|
* property existed) in `layout="fit"`, the default. */
|
|
126
146
|
this.barWidth = 32;
|
|
147
|
+
/** `type="bar"` only: draws each bar as a rounded-top-corner shape instead of the default
|
|
148
|
+
* square-cornered rect. Default `false` renders exactly today's plain `<rect>`. */
|
|
149
|
+
this.roundedBars = false;
|
|
150
|
+
/** `type="bar"` only: omits a bar entirely (no mark, no `tabindex`, no tooltip) for a value that
|
|
151
|
+
* is exactly `0` — `null`/non-finite values are always skipped regardless of this flag. Default
|
|
152
|
+
* `false` preserves today's behavior of a zero-height but focusable/titled bar. */
|
|
153
|
+
this.skipZero = false;
|
|
154
|
+
/** `type="bar"` only (no effect on `type="line"`): `'linear'` (default) maps a bar's value to
|
|
155
|
+
* height via the standard `niceDomain`-based fraction, unchanged from before this property
|
|
156
|
+
* existed. `'sqrt'` instead maps via `Math.sqrt(value / domainMax)` (mirroring `lyra-heatmap`'s
|
|
157
|
+
* matrix-mode `sqrt` scale), boosting smaller values relative to one dominant value so a skewed
|
|
158
|
+
* dataset's smaller bars don't get washed out. Gridlines/tick labels stay on the linear domain
|
|
159
|
+
* either way — only the bar marks' own height mapping changes. */
|
|
160
|
+
this.scale = 'linear';
|
|
161
|
+
/** Suppresses `renderGrid()` entirely — no gridlines, no y-axis tick labels. x-axis category
|
|
162
|
+
* labels (rendered separately) are unaffected. Default `false` preserves today's behavior. */
|
|
163
|
+
this.hideAxis = false;
|
|
127
164
|
this.plotWidth = 0;
|
|
128
165
|
this.plotHeight = 0;
|
|
129
166
|
this.visible = true;
|
|
130
|
-
|
|
167
|
+
/** One roving tab stop across all bar/point marks. */
|
|
168
|
+
this.activeMarkIndex = 0;
|
|
169
|
+
this.liveText = '';
|
|
131
170
|
}
|
|
132
|
-
static { this.styles = [LyraElement.styles, styles]; }
|
|
171
|
+
static { this.styles = [LyraElement.styles, styles, srOnly]; }
|
|
133
172
|
connectedCallback() {
|
|
134
173
|
super.connectedCallback();
|
|
135
174
|
this.resizeObserver = new ResizeObserver((entries) => {
|
|
@@ -188,6 +227,102 @@ export class LyraLiteChart extends LyraElement {
|
|
|
188
227
|
colorFor(index, series) {
|
|
189
228
|
return series.color ?? DEFAULT_PALETTE[index % DEFAULT_PALETTE.length];
|
|
190
229
|
}
|
|
230
|
+
/** Dispatches to the host-provided `pointText` formatter when set, otherwise `undefined` (the
|
|
231
|
+
* caller falls back to its own built-in template) — mirrors `lyra-heatmap`'s `resolveCellText()`. */
|
|
232
|
+
resolvePointText(label, value, datasetIndex) {
|
|
233
|
+
return this.pointText?.(label, value, datasetIndex);
|
|
234
|
+
}
|
|
235
|
+
/** The ordered set of visible marks used by both keyboard navigation and
|
|
236
|
+
* the screen-reader data alternative. */
|
|
237
|
+
interactiveMarks() {
|
|
238
|
+
const marks = [];
|
|
239
|
+
if (this.type === 'bar') {
|
|
240
|
+
for (let index = 0; index < this.labels.length; index++) {
|
|
241
|
+
for (let datasetIndex = 0; datasetIndex < this.datasets.length; datasetIndex++) {
|
|
242
|
+
const value = this.datasets[datasetIndex]?.data[index];
|
|
243
|
+
if (value == null || !Number.isFinite(value) || (this.skipZero && value === 0))
|
|
244
|
+
continue;
|
|
245
|
+
marks.push({ datasetIndex, index, label: this.labels[index] ?? '', value });
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
else {
|
|
250
|
+
this.datasets.forEach((series, datasetIndex) => {
|
|
251
|
+
series.data.forEach((value, index) => {
|
|
252
|
+
if (value == null || !Number.isFinite(value))
|
|
253
|
+
return;
|
|
254
|
+
marks.push({ datasetIndex, index, label: this.labels[index] ?? '', value });
|
|
255
|
+
});
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
return marks;
|
|
259
|
+
}
|
|
260
|
+
markIndexMap() {
|
|
261
|
+
return new Map(this.interactiveMarks().map((mark, index) => [`${mark.datasetIndex}:${mark.index}`, index]));
|
|
262
|
+
}
|
|
263
|
+
normalizedMarkIndex(marks = this.interactiveMarks()) {
|
|
264
|
+
return marks.length ? Math.min(Math.max(this.activeMarkIndex, 0), marks.length - 1) : -1;
|
|
265
|
+
}
|
|
266
|
+
markAnnouncement(index, marks = this.interactiveMarks()) {
|
|
267
|
+
const mark = marks[index];
|
|
268
|
+
if (!mark)
|
|
269
|
+
return '';
|
|
270
|
+
const series = this.datasets[mark.datasetIndex]?.label ?? 'Series';
|
|
271
|
+
const custom = this.resolvePointText(mark.label, mark.value, mark.datasetIndex);
|
|
272
|
+
return `${custom ?? `${series}, ${mark.label}: ${mark.value}`} (${index + 1} of ${marks.length})`;
|
|
273
|
+
}
|
|
274
|
+
onMarkFocus(index) {
|
|
275
|
+
const marks = this.interactiveMarks();
|
|
276
|
+
if (!marks[index])
|
|
277
|
+
return;
|
|
278
|
+
this.activeMarkIndex = index;
|
|
279
|
+
this.liveText = this.markAnnouncement(index, marks);
|
|
280
|
+
}
|
|
281
|
+
focusMark(index) {
|
|
282
|
+
const marks = this.interactiveMarks();
|
|
283
|
+
if (!marks[index])
|
|
284
|
+
return;
|
|
285
|
+
this.activeMarkIndex = index;
|
|
286
|
+
this.liveText = this.markAnnouncement(index, marks);
|
|
287
|
+
void this.updateComplete.then(() => {
|
|
288
|
+
const markEls = Array.from(this.renderRoot.querySelectorAll('[part="bar"], [part="point"]'));
|
|
289
|
+
markEls[index]?.focus();
|
|
290
|
+
});
|
|
291
|
+
}
|
|
292
|
+
/**
|
|
293
|
+
* A value-to-y-pixel mapping for a bar's top/bottom edge. `'linear'` (the
|
|
294
|
+
* default) is the standard `niceDomain`-fraction formula, unchanged from
|
|
295
|
+
* before `scale` existed. `'sqrt'` instead compresses via
|
|
296
|
+
* `Math.sqrt(value / domainMax)` (mirroring `lyra-heatmap`'s matrix-mode
|
|
297
|
+
* `sqrt` branch), clamping `value` to `[0, hi]` first since a negative
|
|
298
|
+
* input has no real square root — bar charts using `scale="sqrt"` are
|
|
299
|
+
* expected to carry non-negative data, same assumption as the heatmap
|
|
300
|
+
* precedent this mirrors.
|
|
301
|
+
*/
|
|
302
|
+
barValueToY(value, plotY, plotH, lo, hi) {
|
|
303
|
+
if (this.scale === 'sqrt') {
|
|
304
|
+
const domainMax = hi > 0 ? hi : 1;
|
|
305
|
+
const frac = Math.sqrt(Math.min(domainMax, Math.max(0, value)) / domainMax);
|
|
306
|
+
return plotY + plotH - frac * plotH;
|
|
307
|
+
}
|
|
308
|
+
const span = hi - lo || 1;
|
|
309
|
+
return plotY + plotH - ((value - lo) / span) * plotH;
|
|
310
|
+
}
|
|
311
|
+
/**
|
|
312
|
+
* A rounded-top-corners `<path>` `d` string for a bar occupying
|
|
313
|
+
* `[x, y, x+w, y+h]` — an SVG `<rect>` can only express a uniform radius
|
|
314
|
+
* on all four corners, so `roundedBars` switches the mark to a path
|
|
315
|
+
* instead of adding `rx`/`ry` to keep the bottom edge square against the
|
|
316
|
+
* baseline. `r` is clamped so it never exceeds half the bar's width or its
|
|
317
|
+
* full height (a thin/short bar degrades to a plain rectangle path rather
|
|
318
|
+
* than self-intersecting).
|
|
319
|
+
*/
|
|
320
|
+
roundedBarPath(x, y, w, h) {
|
|
321
|
+
const r = Math.max(0, Math.min(BAR_CORNER_RADIUS, w / 2, h));
|
|
322
|
+
if (r <= 0)
|
|
323
|
+
return `M${x},${y} h${w} v${h} h${-w} Z`;
|
|
324
|
+
return `M${x},${y + r} Q${x},${y} ${x + r},${y} H${x + w - r} Q${x + w},${y} ${x + w},${y + r} V${y + h} H${x} Z`;
|
|
325
|
+
}
|
|
191
326
|
domain() {
|
|
192
327
|
let lo = Infinity;
|
|
193
328
|
let hi = -Infinity;
|
|
@@ -226,38 +361,34 @@ export class LyraLiteChart extends LyraElement {
|
|
|
226
361
|
}
|
|
227
362
|
return niceDomain(lo, hi, this.beginAtZero, TICK_COUNT);
|
|
228
363
|
}
|
|
229
|
-
computeSignature() {
|
|
230
|
-
return JSON.stringify([
|
|
231
|
-
this.type,
|
|
232
|
-
this.labels,
|
|
233
|
-
this.datasets,
|
|
234
|
-
this.legend,
|
|
235
|
-
this.xLabel,
|
|
236
|
-
this.yLabel,
|
|
237
|
-
this.beginAtZero,
|
|
238
|
-
this.stacked,
|
|
239
|
-
this.plotWidth,
|
|
240
|
-
this.plotHeight,
|
|
241
|
-
this.layout,
|
|
242
|
-
this.barWidth,
|
|
243
|
-
this.maxLabels,
|
|
244
|
-
// `tickFormat`/`barX` are functions -- JSON.stringify() silently drops
|
|
245
|
-
// function-valued entries, so (matching tickFormat's existing,
|
|
246
|
-
// pre-this-change exclusion) they can't be included here anyway; a
|
|
247
|
-
// consumer swapping one in/out post-mount should also change some
|
|
248
|
-
// other signature input, same pre-existing caveat as tickFormat.
|
|
249
|
-
]);
|
|
250
|
-
}
|
|
251
364
|
emitPoint(datasetIndex, index) {
|
|
252
365
|
const label = this.labels[index];
|
|
253
366
|
const value = this.datasets[datasetIndex]?.data[index] ?? null;
|
|
254
367
|
this.emit('lyra-point-click', { datasetIndex, index, label, value });
|
|
255
368
|
}
|
|
256
|
-
onPointKeyDown(e, datasetIndex, index) {
|
|
257
|
-
if (e.key
|
|
369
|
+
onPointKeyDown(e, datasetIndex, index, markIndex) {
|
|
370
|
+
if (e.key === 'Enter' || e.key === ' ') {
|
|
371
|
+
e.preventDefault();
|
|
372
|
+
this.onMarkFocus(markIndex);
|
|
373
|
+
this.emitPoint(datasetIndex, index);
|
|
374
|
+
return;
|
|
375
|
+
}
|
|
376
|
+
const marks = this.interactiveMarks();
|
|
377
|
+
if (!marks.length)
|
|
378
|
+
return;
|
|
379
|
+
let next = markIndex;
|
|
380
|
+
if (e.key === 'ArrowRight' || e.key === 'ArrowDown')
|
|
381
|
+
next = Math.min(marks.length - 1, markIndex + 1);
|
|
382
|
+
else if (e.key === 'ArrowLeft' || e.key === 'ArrowUp')
|
|
383
|
+
next = Math.max(0, markIndex - 1);
|
|
384
|
+
else if (e.key === 'Home')
|
|
385
|
+
next = 0;
|
|
386
|
+
else if (e.key === 'End')
|
|
387
|
+
next = marks.length - 1;
|
|
388
|
+
else
|
|
258
389
|
return;
|
|
259
390
|
e.preventDefault();
|
|
260
|
-
this.
|
|
391
|
+
this.focusMark(next);
|
|
261
392
|
}
|
|
262
393
|
renderGrid(plotX, plotY, plotW, plotH, ticks, lo, hi) {
|
|
263
394
|
const span = hi - lo || 1;
|
|
@@ -277,11 +408,13 @@ export class LyraLiteChart extends LyraElement {
|
|
|
277
408
|
* x-position calc so the two can never drift apart from each other.
|
|
278
409
|
*/
|
|
279
410
|
renderBars(plotX, plotY, plotH, slot, lo, hi) {
|
|
280
|
-
const span = hi - lo || 1;
|
|
281
411
|
const n = this.labels.length;
|
|
282
412
|
const groupCount = this.stacked ? 1 : Math.max(1, this.datasets.length);
|
|
283
|
-
const
|
|
413
|
+
const groupGap = this.barGapRatio ?? BAR_GROUP_GAP;
|
|
414
|
+
const groupW = slot * (1 - groupGap);
|
|
284
415
|
const barW = (groupW - BAR_GAP * slot * (groupCount - 1)) / groupCount;
|
|
416
|
+
const markIndexes = this.markIndexMap();
|
|
417
|
+
const activeMarkIndex = this.normalizedMarkIndex();
|
|
285
418
|
const bars = [];
|
|
286
419
|
for (let i = 0; i < n; i++) {
|
|
287
420
|
// `this.barX`, when set, overrides just the category's own x-origin
|
|
@@ -296,6 +429,8 @@ export class LyraLiteChart extends LyraElement {
|
|
|
296
429
|
const v = s.data[i];
|
|
297
430
|
if (v == null || !Number.isFinite(v))
|
|
298
431
|
return;
|
|
432
|
+
if (this.skipZero && v === 0)
|
|
433
|
+
return;
|
|
299
434
|
const color = this.colorFor(di, s);
|
|
300
435
|
let rectX;
|
|
301
436
|
let barValLo;
|
|
@@ -319,23 +454,44 @@ export class LyraLiteChart extends LyraElement {
|
|
|
319
454
|
barValLo = Math.min(zeroClamped, v);
|
|
320
455
|
barValHi = Math.max(zeroClamped, v);
|
|
321
456
|
}
|
|
322
|
-
const y1 = plotY
|
|
323
|
-
const y2 = plotY
|
|
457
|
+
const y1 = this.barValueToY(barValHi, plotY, plotH, lo, hi);
|
|
458
|
+
const y2 = this.barValueToY(barValLo, plotY, plotH, lo, hi);
|
|
324
459
|
const label = this.labels[i];
|
|
325
|
-
|
|
460
|
+
const custom = this.resolvePointText(label, v, di);
|
|
461
|
+
const ariaLabel = custom ?? `${s.label}, ${label}: ${v}`;
|
|
462
|
+
const titleText = custom ?? `${s.label} — ${label}: ${v}`;
|
|
463
|
+
const w = Math.max(0, barW);
|
|
464
|
+
const h = Math.max(0, y2 - y1);
|
|
465
|
+
const markIndex = markIndexes.get(`${di}:${i}`);
|
|
466
|
+
bars.push(this.roundedBars
|
|
467
|
+
? svg `
|
|
468
|
+
<path
|
|
469
|
+
part="bar"
|
|
470
|
+
d=${this.roundedBarPath(rectX, y1, w, h)}
|
|
471
|
+
fill=${color}
|
|
472
|
+
tabindex=${activeMarkIndex === markIndex ? '0' : '-1'}
|
|
473
|
+
role="button"
|
|
474
|
+
aria-label=${ariaLabel}
|
|
475
|
+
@click=${() => this.emitPoint(di, i)}
|
|
476
|
+
@focus=${() => this.onMarkFocus(markIndex)}
|
|
477
|
+
@keydown=${(e) => this.onPointKeyDown(e, di, i, markIndex)}
|
|
478
|
+
><title>${titleText}</title></path>
|
|
479
|
+
`
|
|
480
|
+
: svg `
|
|
326
481
|
<rect
|
|
327
482
|
part="bar"
|
|
328
483
|
x=${rectX}
|
|
329
484
|
y=${y1}
|
|
330
|
-
width=${
|
|
331
|
-
height=${
|
|
485
|
+
width=${w}
|
|
486
|
+
height=${h}
|
|
332
487
|
fill=${color}
|
|
333
|
-
tabindex
|
|
488
|
+
tabindex=${activeMarkIndex === markIndex ? '0' : '-1'}
|
|
334
489
|
role="button"
|
|
335
|
-
aria-label=${
|
|
490
|
+
aria-label=${ariaLabel}
|
|
336
491
|
@click=${() => this.emitPoint(di, i)}
|
|
337
|
-
@
|
|
338
|
-
|
|
492
|
+
@focus=${() => this.onMarkFocus(markIndex)}
|
|
493
|
+
@keydown=${(e) => this.onPointKeyDown(e, di, i, markIndex)}
|
|
494
|
+
><title>${titleText}</title></rect>
|
|
339
495
|
`);
|
|
340
496
|
});
|
|
341
497
|
}
|
|
@@ -346,6 +502,8 @@ export class LyraLiteChart extends LyraElement {
|
|
|
346
502
|
const n = this.labels.length;
|
|
347
503
|
const xFor = (i) => plotX + (n > 1 ? (i / (n - 1)) * plotW : plotW / 2);
|
|
348
504
|
const yFor = (v) => plotY + plotH - ((v - lo) / span) * plotH;
|
|
505
|
+
const markIndexes = this.markIndexMap();
|
|
506
|
+
const activeMarkIndex = this.normalizedMarkIndex();
|
|
349
507
|
return this.datasets.map((s, di) => {
|
|
350
508
|
const color = this.colorFor(di, s);
|
|
351
509
|
let d = '';
|
|
@@ -363,6 +521,10 @@ export class LyraLiteChart extends LyraElement {
|
|
|
363
521
|
if (v == null || !Number.isFinite(v))
|
|
364
522
|
return nothing;
|
|
365
523
|
const label = this.labels[i];
|
|
524
|
+
const custom = this.resolvePointText(label, v, di);
|
|
525
|
+
const ariaLabel = custom ?? `${s.label}, ${label}: ${v}`;
|
|
526
|
+
const titleText = custom ?? `${s.label} — ${label}: ${v}`;
|
|
527
|
+
const markIndex = markIndexes.get(`${di}:${i}`);
|
|
366
528
|
return svg `
|
|
367
529
|
<circle
|
|
368
530
|
part="point"
|
|
@@ -370,27 +532,26 @@ export class LyraLiteChart extends LyraElement {
|
|
|
370
532
|
cy=${yFor(v)}
|
|
371
533
|
r="4"
|
|
372
534
|
fill=${color}
|
|
373
|
-
tabindex
|
|
535
|
+
tabindex=${activeMarkIndex === markIndex ? '0' : '-1'}
|
|
374
536
|
role="button"
|
|
375
|
-
aria-label=${
|
|
537
|
+
aria-label=${ariaLabel}
|
|
376
538
|
@click=${() => this.emitPoint(di, i)}
|
|
377
|
-
@
|
|
378
|
-
|
|
539
|
+
@focus=${() => this.onMarkFocus(markIndex)}
|
|
540
|
+
@keydown=${(e) => this.onPointKeyDown(e, di, i, markIndex)}
|
|
541
|
+
><title>${titleText}</title></circle>
|
|
379
542
|
`;
|
|
380
543
|
});
|
|
381
544
|
return svg `<path part="line" d=${d.trim()} stroke=${color}></path>${dots}`;
|
|
382
545
|
});
|
|
383
546
|
}
|
|
384
547
|
render() {
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
this.lastResult = result;
|
|
393
|
-
return result;
|
|
548
|
+
// Lit already tracks every reactive input, including function-valued
|
|
549
|
+
// properties such as `tickFormat` and `barX`. Returning a cached
|
|
550
|
+
// TemplateResult here would make callback replacement invisible and
|
|
551
|
+
// serializing arbitrary data would throw for circular objects/BigInt.
|
|
552
|
+
// Rendering this small SVG template is cheaper and more correct than a
|
|
553
|
+
// lossy content fingerprint.
|
|
554
|
+
return this.renderChart();
|
|
394
555
|
}
|
|
395
556
|
/**
|
|
396
557
|
* Step size for `maxLabels` decimation: 1 (show every label, today's
|
|
@@ -408,7 +569,7 @@ export class LyraLiteChart extends LyraElement {
|
|
|
408
569
|
renderChart() {
|
|
409
570
|
const n = this.labels.length;
|
|
410
571
|
const h = this.plotHeight || 200;
|
|
411
|
-
const padLeft = PAD_LEFT + (this.yLabel ? AXIS_TITLE_SPACE : 0);
|
|
572
|
+
const padLeft = (this.padLeft ?? PAD_LEFT) + (this.yLabel ? AXIS_TITLE_SPACE : 0);
|
|
412
573
|
const padBottom = PAD_BOTTOM + (this.xLabel ? AXIS_TITLE_SPACE : 0);
|
|
413
574
|
const plotX = padLeft;
|
|
414
575
|
const plotY = PAD_TOP;
|
|
@@ -434,7 +595,7 @@ export class LyraLiteChart extends LyraElement {
|
|
|
434
595
|
slot = n > 0 ? plotW / n : 0;
|
|
435
596
|
}
|
|
436
597
|
const { lo, hi, ticks } = this.domain();
|
|
437
|
-
const grid = this.renderGrid(plotX, plotY, plotW, plotH, ticks, lo, hi);
|
|
598
|
+
const grid = this.hideAxis ? [] : this.renderGrid(plotX, plotY, plotW, plotH, ticks, lo, hi);
|
|
438
599
|
const marks = this.type === 'bar'
|
|
439
600
|
? this.renderBars(plotX, plotY, plotH, slot, lo, hi)
|
|
440
601
|
: this.renderLines(plotX, plotY, plotW, plotH, lo, hi);
|
|
@@ -448,6 +609,8 @@ export class LyraLiteChart extends LyraElement {
|
|
|
448
609
|
return svg `<text part="axis-label" x=${x} y=${plotY + plotH + 14} text-anchor="middle">${label}</text>`;
|
|
449
610
|
});
|
|
450
611
|
const chartLabel = this.datasets.map((d) => d.label).join(', ') || 'Chart';
|
|
612
|
+
const marksForA11y = this.interactiveMarks();
|
|
613
|
+
const activeMark = this.normalizedMarkIndex(marksForA11y);
|
|
451
614
|
return html `
|
|
452
615
|
<div part="base">
|
|
453
616
|
<svg
|
|
@@ -455,6 +618,7 @@ export class LyraLiteChart extends LyraElement {
|
|
|
455
618
|
style=${this.layout === 'scroll' ? `inline-size: ${w}px` : nothing}
|
|
456
619
|
role="group"
|
|
457
620
|
aria-label=${chartLabel}
|
|
621
|
+
tabindex=${marksForA11y.length ? '-1' : '0'}
|
|
458
622
|
>
|
|
459
623
|
${grid}
|
|
460
624
|
${categoryLabels}
|
|
@@ -466,6 +630,12 @@ export class LyraLiteChart extends LyraElement {
|
|
|
466
630
|
? svg `<text part="axis-title" x=${plotX + plotW / 2} y=${plotY + plotH + padBottom - 2} text-anchor="middle">${this.xLabel}</text>`
|
|
467
631
|
: nothing}
|
|
468
632
|
</svg>
|
|
633
|
+
<div part="live-region" class="sr-only" role="status" aria-live="polite" aria-atomic="true">
|
|
634
|
+
${activeMark >= 0 ? this.liveText || this.markAnnouncement(activeMark, marksForA11y) : ''}
|
|
635
|
+
</div>
|
|
636
|
+
<ul part="data-list" class="sr-only" aria-label="Chart data">
|
|
637
|
+
${marksForA11y.map((mark, index) => html `<li>${this.markAnnouncement(index, marksForA11y)}</li>`)}
|
|
638
|
+
</ul>
|
|
469
639
|
${this.legend
|
|
470
640
|
? html `<div part="legend">
|
|
471
641
|
${this.datasets.map((s, i) => html `
|
|
@@ -522,6 +692,27 @@ __decorate([
|
|
|
522
692
|
__decorate([
|
|
523
693
|
property({ attribute: false })
|
|
524
694
|
], LyraLiteChart.prototype, "barX", void 0);
|
|
695
|
+
__decorate([
|
|
696
|
+
property({ attribute: false })
|
|
697
|
+
], LyraLiteChart.prototype, "pointText", void 0);
|
|
698
|
+
__decorate([
|
|
699
|
+
property({ type: Boolean, attribute: 'rounded-bars' })
|
|
700
|
+
], LyraLiteChart.prototype, "roundedBars", void 0);
|
|
701
|
+
__decorate([
|
|
702
|
+
property({ type: Boolean, attribute: 'skip-zero' })
|
|
703
|
+
], LyraLiteChart.prototype, "skipZero", void 0);
|
|
704
|
+
__decorate([
|
|
705
|
+
property({ type: Number, attribute: 'pad-left' })
|
|
706
|
+
], LyraLiteChart.prototype, "padLeft", void 0);
|
|
707
|
+
__decorate([
|
|
708
|
+
property({ type: Number, attribute: 'bar-gap-ratio' })
|
|
709
|
+
], LyraLiteChart.prototype, "barGapRatio", void 0);
|
|
710
|
+
__decorate([
|
|
711
|
+
property()
|
|
712
|
+
], LyraLiteChart.prototype, "scale", void 0);
|
|
713
|
+
__decorate([
|
|
714
|
+
property({ type: Boolean, attribute: 'hide-axis' })
|
|
715
|
+
], LyraLiteChart.prototype, "hideAxis", void 0);
|
|
525
716
|
__decorate([
|
|
526
717
|
state()
|
|
527
718
|
], LyraLiteChart.prototype, "plotWidth", void 0);
|
|
@@ -531,6 +722,12 @@ __decorate([
|
|
|
531
722
|
__decorate([
|
|
532
723
|
state()
|
|
533
724
|
], LyraLiteChart.prototype, "visible", void 0);
|
|
725
|
+
__decorate([
|
|
726
|
+
state()
|
|
727
|
+
], LyraLiteChart.prototype, "activeMarkIndex", void 0);
|
|
728
|
+
__decorate([
|
|
729
|
+
state()
|
|
730
|
+
], LyraLiteChart.prototype, "liveText", void 0);
|
|
534
731
|
__decorate([
|
|
535
732
|
query('svg')
|
|
536
733
|
], LyraLiteChart.prototype, "svgEl", void 0);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { LyraChart } from './chart.js';
|
|
1
|
+
import { LyraChart, lockChartType } from './chart.js';
|
|
2
2
|
import { defineElement } from '../../internal/prefix.js';
|
|
3
3
|
/**
|
|
4
4
|
* `<lyra-pie-chart>` — `<lyra-chart>` with `type` locked to `"pie"`. Single-series:
|
|
@@ -8,21 +8,5 @@ import { defineElement } from '../../internal/prefix.js';
|
|
|
8
8
|
*/
|
|
9
9
|
export class LyraPieChart extends LyraChart {
|
|
10
10
|
}
|
|
11
|
-
|
|
12
|
-
// default value — `LyraChart` declares it as a plain (decorator-managed)
|
|
13
|
-
// class field, and TypeScript forbids a subclass from re-declaring a base
|
|
14
|
-
// field as a getter/setter pair via ordinary class syntax (TS2611) — so the
|
|
15
|
-
// accessor pair is installed directly on the prototype instead, which is
|
|
16
|
-
// runtime-equivalent (same shadowing semantics as a class-syntax override)
|
|
17
|
-
// without tripping that check.
|
|
18
|
-
Object.defineProperty(LyraPieChart.prototype, 'type', {
|
|
19
|
-
configurable: true,
|
|
20
|
-
enumerable: true,
|
|
21
|
-
get() {
|
|
22
|
-
return 'pie';
|
|
23
|
-
},
|
|
24
|
-
set(_v) {
|
|
25
|
-
/* locked to 'pie'; direct writes are ignored */
|
|
26
|
-
},
|
|
27
|
-
});
|
|
11
|
+
lockChartType(LyraPieChart, 'pie');
|
|
28
12
|
defineElement('pie-chart', LyraPieChart);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { LyraChart } from './chart.js';
|
|
1
|
+
import { LyraChart, lockChartType } from './chart.js';
|
|
2
2
|
import { defineElement } from '../../internal/prefix.js';
|
|
3
3
|
/**
|
|
4
4
|
* `<lyra-polar-area-chart>` — `<lyra-chart>` with `type` locked to `"polarArea"`.
|
|
@@ -7,21 +7,5 @@ import { defineElement } from '../../internal/prefix.js';
|
|
|
7
7
|
*/
|
|
8
8
|
export class LyraPolarAreaChart extends LyraChart {
|
|
9
9
|
}
|
|
10
|
-
|
|
11
|
-
// default value — `LyraChart` declares it as a plain (decorator-managed)
|
|
12
|
-
// class field, and TypeScript forbids a subclass from re-declaring a base
|
|
13
|
-
// field as a getter/setter pair via ordinary class syntax (TS2611) — so the
|
|
14
|
-
// accessor pair is installed directly on the prototype instead, which is
|
|
15
|
-
// runtime-equivalent (same shadowing semantics as a class-syntax override)
|
|
16
|
-
// without tripping that check.
|
|
17
|
-
Object.defineProperty(LyraPolarAreaChart.prototype, 'type', {
|
|
18
|
-
configurable: true,
|
|
19
|
-
enumerable: true,
|
|
20
|
-
get() {
|
|
21
|
-
return 'polarArea';
|
|
22
|
-
},
|
|
23
|
-
set(_v) {
|
|
24
|
-
/* locked to 'polarArea'; direct writes are ignored */
|
|
25
|
-
},
|
|
26
|
-
});
|
|
10
|
+
lockChartType(LyraPolarAreaChart, 'polarArea');
|
|
27
11
|
defineElement('polar-area-chart', LyraPolarAreaChart);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { LyraChart } from './chart.js';
|
|
1
|
+
import { LyraChart, lockChartType } from './chart.js';
|
|
2
2
|
import { defineElement } from '../../internal/prefix.js';
|
|
3
3
|
/**
|
|
4
4
|
* `<lyra-radar-chart>` — `<lyra-chart>` with `type` locked to `"radar"`.
|
|
@@ -7,21 +7,5 @@ import { defineElement } from '../../internal/prefix.js';
|
|
|
7
7
|
*/
|
|
8
8
|
export class LyraRadarChart extends LyraChart {
|
|
9
9
|
}
|
|
10
|
-
|
|
11
|
-
// default value — `LyraChart` declares it as a plain (decorator-managed)
|
|
12
|
-
// class field, and TypeScript forbids a subclass from re-declaring a base
|
|
13
|
-
// field as a getter/setter pair via ordinary class syntax (TS2611) — so the
|
|
14
|
-
// accessor pair is installed directly on the prototype instead, which is
|
|
15
|
-
// runtime-equivalent (same shadowing semantics as a class-syntax override)
|
|
16
|
-
// without tripping that check.
|
|
17
|
-
Object.defineProperty(LyraRadarChart.prototype, 'type', {
|
|
18
|
-
configurable: true,
|
|
19
|
-
enumerable: true,
|
|
20
|
-
get() {
|
|
21
|
-
return 'radar';
|
|
22
|
-
},
|
|
23
|
-
set(_v) {
|
|
24
|
-
/* locked to 'radar'; direct writes are ignored */
|
|
25
|
-
},
|
|
26
|
-
});
|
|
10
|
+
lockChartType(LyraRadarChart, 'radar');
|
|
27
11
|
defineElement('radar-chart', LyraRadarChart);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { LyraChart } from './chart.js';
|
|
1
|
+
import { LyraChart, lockChartType } from './chart.js';
|
|
2
2
|
import { defineElement } from '../../internal/prefix.js';
|
|
3
3
|
/**
|
|
4
4
|
* `<lyra-scatter-chart>` — `<lyra-chart>` with `type` locked to `"scatter"`. Feed
|
|
@@ -8,21 +8,5 @@ import { defineElement } from '../../internal/prefix.js';
|
|
|
8
8
|
*/
|
|
9
9
|
export class LyraScatterChart extends LyraChart {
|
|
10
10
|
}
|
|
11
|
-
|
|
12
|
-
// default value — `LyraChart` declares it as a plain (decorator-managed)
|
|
13
|
-
// class field, and TypeScript forbids a subclass from re-declaring a base
|
|
14
|
-
// field as a getter/setter pair via ordinary class syntax (TS2611) — so the
|
|
15
|
-
// accessor pair is installed directly on the prototype instead, which is
|
|
16
|
-
// runtime-equivalent (same shadowing semantics as a class-syntax override)
|
|
17
|
-
// without tripping that check.
|
|
18
|
-
Object.defineProperty(LyraScatterChart.prototype, 'type', {
|
|
19
|
-
configurable: true,
|
|
20
|
-
enumerable: true,
|
|
21
|
-
get() {
|
|
22
|
-
return 'scatter';
|
|
23
|
-
},
|
|
24
|
-
set(_v) {
|
|
25
|
-
/* locked to 'scatter'; direct writes are ignored */
|
|
26
|
-
},
|
|
27
|
-
});
|
|
11
|
+
lockChartType(LyraScatterChart, 'scatter');
|
|
28
12
|
defineElement('scatter-chart', LyraScatterChart);
|
|
@@ -14,7 +14,12 @@ declare const LyraChatComposer_base: typeof LyraElement & (new (...args: any[])
|
|
|
14
14
|
* border at runtime (`resizeTextarea()`) rather than assuming a fixed
|
|
15
15
|
* px-per-row constant, so it stays correct under a consumer's own font-size/
|
|
16
16
|
* line-height overrides. It grows between `min-rows` and `max-rows`, then
|
|
17
|
-
* switches to internal scrolling.
|
|
17
|
+
* switches to internal scrolling. A `ResizeObserver` on the textarea itself
|
|
18
|
+
* re-runs the same fit whenever its *width* changes (a responsive
|
|
19
|
+
* breakpoint, a sidebar toggling, a window resize, an orientation change)
|
|
20
|
+
* even though `value`/`min-rows`/`max-rows` never did -- a narrower box
|
|
21
|
+
* wraps the same text across more lines, so the previously-fitted height
|
|
22
|
+
* would otherwise go stale and clip content with no scrollbar to reveal it.
|
|
18
23
|
*
|
|
19
24
|
* Enter-to-send (only active while `submit-on-enter` is true, the default):
|
|
20
25
|
* plain Enter submits and is prevented from inserting a newline; Shift+Enter
|
|
@@ -60,10 +65,16 @@ export declare class LyraChatComposer extends LyraChatComposer_base {
|
|
|
60
65
|
private hasLeadingSlot;
|
|
61
66
|
private hasChipsSlot;
|
|
62
67
|
private hasTrailingSlot;
|
|
68
|
+
private touched;
|
|
63
69
|
private textareaEl?;
|
|
70
|
+
private textareaResizeObserver?;
|
|
71
|
+
private textareaResizeRaf?;
|
|
72
|
+
constructor();
|
|
64
73
|
protected willUpdate(): void;
|
|
65
74
|
protected firstUpdated(changed: PropertyValues): void;
|
|
75
|
+
disconnectedCallback(): void;
|
|
66
76
|
protected updated(changed: PropertyValues): void;
|
|
77
|
+
formResetCallback(): void;
|
|
67
78
|
private hasSlotted;
|
|
68
79
|
/**
|
|
69
80
|
* Grows/shrinks the textarea between `min-rows` and `max-rows`, reading
|
|
@@ -74,6 +85,35 @@ export declare class LyraChatComposer extends LyraChatComposer_base {
|
|
|
74
85
|
* scrolling (`overflow-y: auto`).
|
|
75
86
|
*/
|
|
76
87
|
private resizeTextarea;
|
|
88
|
+
/**
|
|
89
|
+
* Re-fits the textarea whenever its own box *width* changes, independent
|
|
90
|
+
* of any `value`/`min-rows`/`max-rows` update -- `updated()` above only
|
|
91
|
+
* reacts to those, so a pure layout change (a responsive breakpoint, a
|
|
92
|
+
* sidebar collapsing/expanding, a window resize, an orientation change)
|
|
93
|
+
* would otherwise leave the height pinned at whatever it last was, even
|
|
94
|
+
* though the same text now wraps across a different number of lines.
|
|
95
|
+
* Mirrors split.ts's `collapseResizeObserver`/virtual-list.ts's
|
|
96
|
+
* `containerResizeObserver`/lite-chart.ts's `resizeObserver`.
|
|
97
|
+
*
|
|
98
|
+
* Only reacts to an actual inline-size change rather than calling
|
|
99
|
+
* `resizeTextarea()` unconditionally on every callback: `resizeTextarea()`
|
|
100
|
+
* itself sets `ta.style.height`, a *block*-size change on the very element
|
|
101
|
+
* being observed, which would otherwise re-trigger this same observer
|
|
102
|
+
* every tick. Diffing against the last-seen width (same technique as
|
|
103
|
+
* split.ts keying its collapse state off `contentBoxSize[0].inlineSize`)
|
|
104
|
+
* keeps a same-width, height-only callback from doing anything.
|
|
105
|
+
*
|
|
106
|
+
* The actual recompute is deferred one animation frame rather than run
|
|
107
|
+
* synchronously inside the callback: `ResizeObserver`'s spec re-delivers,
|
|
108
|
+
* within the same notification pass, to any observed element resized by
|
|
109
|
+
* its own callback -- mutating `ta.style.height` synchronously here would
|
|
110
|
+
* do exactly that to the very box just observed, and the browser reports
|
|
111
|
+
* it as "ResizeObserver loop completed with undelivered notifications"
|
|
112
|
+
* (a real, user-visible console error, not just noise). Deferring the
|
|
113
|
+
* mutation to the next frame -- outside that notification pass -- avoids
|
|
114
|
+
* ever resizing the observed element from inside its own callback.
|
|
115
|
+
*/
|
|
116
|
+
private armTextareaResizeObserver;
|
|
77
117
|
private onTextareaInput;
|
|
78
118
|
private onTextareaKeyDown;
|
|
79
119
|
private onActionClick;
|
|
@@ -81,6 +121,7 @@ export declare class LyraChatComposer extends LyraChatComposer_base {
|
|
|
81
121
|
private onLeadingSlotChange;
|
|
82
122
|
private onChipsSlotChange;
|
|
83
123
|
private onTrailingSlotChange;
|
|
124
|
+
private onTextareaBlur;
|
|
84
125
|
private renderActionButton;
|
|
85
126
|
render(): TemplateResult;
|
|
86
127
|
}
|