@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.
Files changed (224) hide show
  1. package/README.md +87 -14
  2. package/custom-elements.json +11555 -5539
  3. package/dist/components/app-rail/app-rail-item.d.ts +30 -0
  4. package/dist/components/app-rail/app-rail-item.js +68 -0
  5. package/dist/components/app-rail/app-rail-item.styles.d.ts +1 -0
  6. package/dist/components/app-rail/app-rail-item.styles.js +65 -0
  7. package/dist/components/app-rail/app-rail.d.ts +21 -24
  8. package/dist/components/app-rail/app-rail.js +68 -132
  9. package/dist/components/app-rail/app-rail.styles.js +5 -2
  10. package/dist/components/attachment-chip/attachment-chip.d.ts +38 -11
  11. package/dist/components/attachment-chip/attachment-chip.js +73 -29
  12. package/dist/components/attachment-trigger/attachment-trigger.d.ts +13 -0
  13. package/dist/components/attachment-trigger/attachment-trigger.js +13 -1
  14. package/dist/components/attachment-trigger/attachment-trigger.styles.js +28 -6
  15. package/dist/components/chart/bar-chart.js +2 -18
  16. package/dist/components/chart/box-plot.d.ts +25 -1
  17. package/dist/components/chart/box-plot.js +136 -6
  18. package/dist/components/chart/box-plot.styles.js +13 -0
  19. package/dist/components/chart/bubble-chart.js +2 -18
  20. package/dist/components/chart/chart.d.ts +54 -10
  21. package/dist/components/chart/chart.js +182 -39
  22. package/dist/components/chart/doughnut-chart.js +2 -18
  23. package/dist/components/chart/histogram-bin.d.ts +5 -2
  24. package/dist/components/chart/histogram-bin.js +12 -4
  25. package/dist/components/chart/histogram.js +8 -16
  26. package/dist/components/chart/line-chart.js +2 -18
  27. package/dist/components/chart/lite-chart.d.ts +80 -3
  28. package/dist/components/chart/lite-chart.js +250 -53
  29. package/dist/components/chart/pie-chart.js +2 -18
  30. package/dist/components/chart/polar-area-chart.js +2 -18
  31. package/dist/components/chart/radar-chart.js +2 -18
  32. package/dist/components/chart/scatter-chart.js +2 -18
  33. package/dist/components/chat-composer/chat-composer.d.ts +42 -1
  34. package/dist/components/chat-composer/chat-composer.js +84 -3
  35. package/dist/components/chat-composer/chat-composer.styles.js +11 -1
  36. package/dist/components/chat-message/chat-message.d.ts +32 -4
  37. package/dist/components/chat-message/chat-message.js +57 -17
  38. package/dist/components/checkbox/checkbox.d.ts +66 -8
  39. package/dist/components/checkbox/checkbox.js +173 -50
  40. package/dist/components/checkbox/checkbox.styles.js +9 -2
  41. package/dist/components/chip/chip-group.js +8 -2
  42. package/dist/components/chip/chip.js +9 -2
  43. package/dist/components/citation-badge/citation-badge.js +21 -3
  44. package/dist/components/code-block/code-block.d.ts +38 -0
  45. package/dist/components/code-block/code-block.js +72 -7
  46. package/dist/components/code-block/code-loader.d.ts +44 -1
  47. package/dist/components/code-block/code-loader.js +63 -0
  48. package/dist/components/combobox/combobox.d.ts +46 -5
  49. package/dist/components/combobox/combobox.js +175 -35
  50. package/dist/components/combobox/combobox.styles.js +3 -3
  51. package/dist/components/context-meter/context-meter.js +17 -8
  52. package/dist/components/context-meter/context-meter.styles.js +0 -6
  53. package/dist/components/conversation-item/conversation-item.d.ts +13 -16
  54. package/dist/components/conversation-item/conversation-item.js +29 -20
  55. package/dist/components/date-picker/calendar-core.d.ts +24 -0
  56. package/dist/components/date-picker/calendar-core.js +51 -4
  57. package/dist/components/date-picker/date-input.d.ts +77 -10
  58. package/dist/components/date-picker/date-input.js +278 -73
  59. package/dist/components/date-picker/date-picker.d.ts +28 -4
  60. package/dist/components/date-picker/date-picker.js +95 -37
  61. package/dist/components/dialog/confirm.js +3 -6
  62. package/dist/components/dialog/dialog.d.ts +75 -31
  63. package/dist/components/dialog/dialog.js +147 -131
  64. package/dist/components/dialog/dialog.styles.js +46 -2
  65. package/dist/components/dock-panel/dock-panel.d.ts +8 -0
  66. package/dist/components/dock-panel/dock-panel.js +15 -1
  67. package/dist/components/dock-panel/dock-panel.styles.js +15 -1
  68. package/dist/components/document-preview/document-preview.d.ts +15 -7
  69. package/dist/components/document-preview/document-preview.js +29 -13
  70. package/dist/components/empty/empty.d.ts +1 -2
  71. package/dist/components/empty/empty.js +18 -12
  72. package/dist/components/empty/empty.styles.js +0 -3
  73. package/dist/components/export-button/export-button.d.ts +12 -0
  74. package/dist/components/export-button/export-button.js +33 -5
  75. package/dist/components/export-button/export-button.styles.js +5 -1
  76. package/dist/components/file-input/accept.js +2 -0
  77. package/dist/components/file-input/file-input.d.ts +10 -1
  78. package/dist/components/file-input/file-input.js +36 -5
  79. package/dist/components/flag/flag.d.ts +1 -1
  80. package/dist/components/flag/flag.js +15 -1
  81. package/dist/components/flag/flag.styles.js +1 -1
  82. package/dist/components/flag/language-map.d.ts +4 -1
  83. package/dist/components/flag/language-map.js +6 -3
  84. package/dist/components/gauge/gauge.d.ts +10 -1
  85. package/dist/components/gauge/gauge.js +28 -9
  86. package/dist/components/generation-status/generation-status.d.ts +13 -5
  87. package/dist/components/generation-status/generation-status.js +59 -5
  88. package/dist/components/graph/graph.d.ts +37 -3
  89. package/dist/components/graph/graph.js +132 -20
  90. package/dist/components/heatmap/calendar-grid.d.ts +15 -6
  91. package/dist/components/heatmap/calendar-grid.js +17 -6
  92. package/dist/components/heatmap/heatmap-scale.d.ts +5 -1
  93. package/dist/components/heatmap/heatmap-scale.js +8 -2
  94. package/dist/components/heatmap/heatmap.d.ts +166 -25
  95. package/dist/components/heatmap/heatmap.js +372 -89
  96. package/dist/components/json-viewer/json-viewer.d.ts +22 -5
  97. package/dist/components/json-viewer/json-viewer.js +115 -37
  98. package/dist/components/json-viewer/json-viewer.styles.js +2 -1
  99. package/dist/components/kbd/kbd.js +24 -7
  100. package/dist/components/live-region/live-region.d.ts +10 -1
  101. package/dist/components/live-region/live-region.js +42 -6
  102. package/dist/components/map/map.d.ts +24 -1
  103. package/dist/components/map/map.js +89 -24
  104. package/dist/components/markdown/markdown-loader.d.ts +24 -0
  105. package/dist/components/markdown/markdown-loader.js +35 -1
  106. package/dist/components/markdown/markdown.d.ts +46 -8
  107. package/dist/components/markdown/markdown.js +136 -31
  108. package/dist/components/markdown/markdown.styles.js +7 -1
  109. package/dist/components/media-card/media-card.d.ts +25 -17
  110. package/dist/components/media-card/media-card.js +43 -65
  111. package/dist/components/mention-popover/mention-popover.d.ts +4 -1
  112. package/dist/components/mention-popover/mention-popover.js +23 -5
  113. package/dist/components/menu/menu-item.d.ts +32 -3
  114. package/dist/components/menu/menu-item.js +94 -7
  115. package/dist/components/menu/menu-item.styles.js +8 -0
  116. package/dist/components/menu/menu.d.ts +25 -1
  117. package/dist/components/menu/menu.js +99 -3
  118. package/dist/components/menu/menu.styles.js +3 -2
  119. package/dist/components/model-select/model-select.d.ts +48 -3
  120. package/dist/components/model-select/model-select.js +120 -22
  121. package/dist/components/model-select/model-select.styles.js +17 -3
  122. package/dist/components/model-settings-panel/model-settings-panel.d.ts +25 -1
  123. package/dist/components/model-settings-panel/model-settings-panel.js +65 -1
  124. package/dist/components/playback/playback.d.ts +6 -2
  125. package/dist/components/playback/playback.js +72 -29
  126. package/dist/components/playback/playback.styles.js +6 -1
  127. package/dist/components/responsive-panel/responsive-panel.d.ts +29 -16
  128. package/dist/components/responsive-panel/responsive-panel.js +130 -132
  129. package/dist/components/responsive-panel/responsive-panel.styles.js +1 -1
  130. package/dist/components/result-card/result-card.d.ts +8 -2
  131. package/dist/components/result-card/result-card.js +9 -3
  132. package/dist/components/result-card/result-card.styles.js +0 -1
  133. package/dist/components/select/select.d.ts +59 -20
  134. package/dist/components/select/select.js +125 -43
  135. package/dist/components/skeleton/skeleton.d.ts +3 -0
  136. package/dist/components/skeleton/skeleton.js +7 -1
  137. package/dist/components/skeleton/skeleton.styles.js +5 -4
  138. package/dist/components/slider/slider.d.ts +57 -5
  139. package/dist/components/slider/slider.js +195 -80
  140. package/dist/components/source-card/source-card.d.ts +17 -5
  141. package/dist/components/source-card/source-card.js +55 -8
  142. package/dist/components/source-card/source-card.styles.js +1 -1
  143. package/dist/components/source-list/source-list.js +9 -1
  144. package/dist/components/sparkline/sparkline.js +34 -10
  145. package/dist/components/split/split.d.ts +141 -14
  146. package/dist/components/split/split.js +357 -52
  147. package/dist/components/split/split.styles.js +18 -1
  148. package/dist/components/stat/stat.d.ts +10 -4
  149. package/dist/components/stat/stat.js +46 -11
  150. package/dist/components/stream-status/stream-status.d.ts +27 -11
  151. package/dist/components/stream-status/stream-status.js +95 -13
  152. package/dist/components/streaming-text/streaming-text.d.ts +9 -3
  153. package/dist/components/streaming-text/streaming-text.js +25 -10
  154. package/dist/components/streaming-text/streaming-text.styles.js +3 -2
  155. package/dist/components/switch/switch.d.ts +52 -7
  156. package/dist/components/switch/switch.js +111 -40
  157. package/dist/components/switch/switch.styles.js +1 -1
  158. package/dist/components/table/table.d.ts +18 -3
  159. package/dist/components/table/table.js +88 -20
  160. package/dist/components/tabs/tabs.d.ts +23 -0
  161. package/dist/components/tabs/tabs.js +76 -12
  162. package/dist/components/tabs/tabs.styles.js +11 -0
  163. package/dist/components/thinking-panel/thinking-panel.d.ts +3 -1
  164. package/dist/components/thinking-panel/thinking-panel.js +34 -9
  165. package/dist/components/thinking-panel/thinking-panel.styles.js +6 -0
  166. package/dist/components/time-range/time-range.d.ts +59 -2
  167. package/dist/components/time-range/time-range.js +163 -67
  168. package/dist/components/toast/toast-item.d.ts +12 -3
  169. package/dist/components/toast/toast-item.js +90 -53
  170. package/dist/components/toast/toast-item.styles.js +59 -28
  171. package/dist/components/toast/toast.js +17 -5
  172. package/dist/components/toast/toaster.js +10 -1
  173. package/dist/components/tool-approval-dialog/tool-approval-dialog.d.ts +11 -10
  174. package/dist/components/tool-approval-dialog/tool-approval-dialog.js +50 -124
  175. package/dist/components/tool-approval-dialog/tool-approval-dialog.styles.js +1 -1
  176. package/dist/components/tool-call-chip/tool-call-chip.d.ts +18 -2
  177. package/dist/components/tool-call-chip/tool-call-chip.js +86 -25
  178. package/dist/components/tool-param-form/tool-param-form.d.ts +89 -28
  179. package/dist/components/tool-param-form/tool-param-form.js +350 -106
  180. package/dist/components/tool-result-dialog/tool-result-dialog.d.ts +27 -7
  181. package/dist/components/tool-result-dialog/tool-result-dialog.js +80 -115
  182. package/dist/components/tool-result-dialog/tool-result-dialog.styles.js +1 -1
  183. package/dist/components/tool-result-view/registry.d.ts +0 -8
  184. package/dist/components/tool-result-view/registry.js +7 -2
  185. package/dist/components/tool-result-view/tool-result-view.d.ts +6 -3
  186. package/dist/components/tool-result-view/tool-result-view.js +18 -4
  187. package/dist/components/tool-select-dialog/tool-select-dialog.d.ts +11 -11
  188. package/dist/components/tool-select-dialog/tool-select-dialog.js +44 -133
  189. package/dist/components/tool-select-dialog/tool-select-dialog.styles.js +13 -4
  190. package/dist/components/tree/tree-node.d.ts +4 -1
  191. package/dist/components/tree/tree-node.js +4 -1
  192. package/dist/components/tree/tree.d.ts +17 -8
  193. package/dist/components/tree/tree.js +21 -20
  194. package/dist/components/typing-indicator/typing-indicator.d.ts +12 -2
  195. package/dist/components/typing-indicator/typing-indicator.js +16 -4
  196. package/dist/components/typing-indicator/typing-indicator.styles.js +2 -2
  197. package/dist/components/virtual-list/virtual-list.d.ts +56 -19
  198. package/dist/components/virtual-list/virtual-list.js +184 -38
  199. package/dist/components/virtual-list/virtual-list.styles.js +12 -0
  200. package/dist/components/widget/widget.d.ts +5 -4
  201. package/dist/components/widget/widget.js +54 -120
  202. package/dist/components/widget/widget.styles.js +8 -2
  203. package/dist/components/word-cloud/word-cloud-layout.d.ts +7 -0
  204. package/dist/components/word-cloud/word-cloud-layout.js +20 -6
  205. package/dist/components/word-cloud/word-cloud.d.ts +22 -2
  206. package/dist/components/word-cloud/word-cloud.js +45 -6
  207. package/dist/components/word-cloud/word-cloud.styles.js +13 -1
  208. package/dist/internal/anchored-validity.d.ts +1 -0
  209. package/dist/internal/anchored-validity.js +86 -0
  210. package/dist/internal/form-associated.d.ts +7 -0
  211. package/dist/internal/form-associated.js +43 -4
  212. package/dist/internal/numbers.d.ts +12 -0
  213. package/dist/internal/numbers.js +26 -0
  214. package/dist/internal/overlay-manager.d.ts +51 -0
  215. package/dist/internal/overlay-manager.js +523 -0
  216. package/dist/internal/positioner.js +27 -3
  217. package/dist/internal/safe-url.d.ts +12 -0
  218. package/dist/internal/safe-url.js +41 -0
  219. package/dist/internal/tokens.styles.js +17 -11
  220. package/dist/lyra.d.ts +5 -2
  221. package/dist/lyra.js +3 -1
  222. package/llms-full.txt +970 -426
  223. package/llms.txt +5 -4
  224. 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
- this.lastSignature = '';
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 !== 'Enter' && 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.emitPoint(datasetIndex, index);
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 groupW = slot * (1 - BAR_GROUP_GAP);
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 + plotH - ((barValHi - lo) / span) * plotH;
323
- const y2 = plotY + plotH - ((barValLo - lo) / span) * plotH;
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
- bars.push(svg `
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=${Math.max(0, barW)}
331
- height=${Math.max(0, y2 - y1)}
485
+ width=${w}
486
+ height=${h}
332
487
  fill=${color}
333
- tabindex="0"
488
+ tabindex=${activeMarkIndex === markIndex ? '0' : '-1'}
334
489
  role="button"
335
- aria-label=${`${s.label}, ${label}: ${v}`}
490
+ aria-label=${ariaLabel}
336
491
  @click=${() => this.emitPoint(di, i)}
337
- @keydown=${(e) => this.onPointKeyDown(e, di, i)}
338
- ><title>${s.label} ${label}: ${v}</title></rect>
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="0"
535
+ tabindex=${activeMarkIndex === markIndex ? '0' : '-1'}
374
536
  role="button"
375
- aria-label=${`${s.label}, ${label}: ${v}`}
537
+ aria-label=${ariaLabel}
376
538
  @click=${() => this.emitPoint(di, i)}
377
- @keydown=${(e) => this.onPointKeyDown(e, di, i)}
378
- ><title>${s.label} ${label}: ${v}</title></circle>
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
- if (!this.visible && this.lastResult)
386
- return this.lastResult;
387
- const signature = this.computeSignature();
388
- if (signature === this.lastSignature && this.lastResult)
389
- return this.lastResult;
390
- this.lastSignature = signature;
391
- const result = this.renderChart();
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
- // `type` is locked read-only rather than a settable class field with just a
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
- // `type` is locked read-only rather than a settable class field with just a
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
- // `type` is locked read-only rather than a settable class field with just a
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
- // `type` is locked read-only rather than a settable class field with just a
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
  }