@aceshooting/lyra-ui 1.2.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 (384) hide show
  1. package/README.md +98 -14
  2. package/custom-elements.json +30279 -12124
  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 +168 -0
  8. package/dist/components/app-rail/app-rail.js +419 -0
  9. package/dist/components/app-rail/app-rail.styles.d.ts +1 -0
  10. package/dist/components/app-rail/app-rail.styles.js +128 -0
  11. package/dist/components/attachment-chip/attachment-chip.d.ts +141 -0
  12. package/dist/components/attachment-chip/attachment-chip.js +356 -0
  13. package/dist/components/attachment-chip/attachment-chip.styles.d.ts +1 -0
  14. package/dist/components/attachment-chip/attachment-chip.styles.js +184 -0
  15. package/dist/components/attachment-trigger/attachment-trigger.d.ts +96 -0
  16. package/dist/components/attachment-trigger/attachment-trigger.js +270 -0
  17. package/dist/components/attachment-trigger/attachment-trigger.styles.d.ts +1 -0
  18. package/dist/components/attachment-trigger/attachment-trigger.styles.js +90 -0
  19. package/dist/components/chart/bar-chart.js +2 -18
  20. package/dist/components/chart/box-plot.d.ts +25 -1
  21. package/dist/components/chart/box-plot.js +147 -7
  22. package/dist/components/chart/box-plot.styles.js +13 -0
  23. package/dist/components/chart/bubble-chart.js +2 -18
  24. package/dist/components/chart/chart-loader.d.ts +44 -13
  25. package/dist/components/chart/chart-loader.js +65 -18
  26. package/dist/components/chart/chart.d.ts +55 -12
  27. package/dist/components/chart/chart.js +247 -49
  28. package/dist/components/chart/doughnut-chart.js +2 -18
  29. package/dist/components/chart/histogram-bin.d.ts +7 -1
  30. package/dist/components/chart/histogram-bin.js +32 -14
  31. package/dist/components/chart/histogram.js +8 -16
  32. package/dist/components/chart/line-chart.js +2 -18
  33. package/dist/components/chart/lite-chart.d.ts +134 -3
  34. package/dist/components/chart/lite-chart.js +382 -67
  35. package/dist/components/chart/lite-chart.styles.js +9 -0
  36. package/dist/components/chart/pie-chart.js +2 -18
  37. package/dist/components/chart/polar-area-chart.js +2 -18
  38. package/dist/components/chart/radar-chart.js +2 -18
  39. package/dist/components/chart/scatter-chart.js +2 -18
  40. package/dist/components/chat-composer/chat-composer.d.ts +133 -0
  41. package/dist/components/chat-composer/chat-composer.js +366 -0
  42. package/dist/components/chat-composer/chat-composer.styles.d.ts +1 -0
  43. package/dist/components/chat-composer/chat-composer.styles.js +145 -0
  44. package/dist/components/chat-message/chat-message.d.ts +141 -0
  45. package/dist/components/chat-message/chat-message.js +331 -0
  46. package/dist/components/chat-message/chat-message.styles.d.ts +1 -0
  47. package/dist/components/chat-message/chat-message.styles.js +203 -0
  48. package/dist/components/checkbox/checkbox.d.ts +117 -0
  49. package/dist/components/checkbox/checkbox.js +353 -0
  50. package/dist/components/checkbox/checkbox.styles.d.ts +1 -0
  51. package/dist/components/checkbox/checkbox.styles.js +77 -0
  52. package/dist/components/chip/chip-group.d.ts +56 -0
  53. package/dist/components/chip/chip-group.js +130 -0
  54. package/dist/components/chip/chip-group.styles.d.ts +1 -0
  55. package/dist/components/chip/chip-group.styles.js +57 -0
  56. package/dist/components/chip/chip.d.ts +64 -0
  57. package/dist/components/chip/chip.js +122 -0
  58. package/dist/components/chip/chip.styles.d.ts +1 -0
  59. package/dist/components/chip/chip.styles.js +115 -0
  60. package/dist/components/citation-badge/citation-badge.d.ts +113 -0
  61. package/dist/components/citation-badge/citation-badge.js +318 -0
  62. package/dist/components/citation-badge/citation-badge.styles.d.ts +1 -0
  63. package/dist/components/citation-badge/citation-badge.styles.js +96 -0
  64. package/dist/components/code-block/code-block.d.ts +127 -0
  65. package/dist/components/code-block/code-block.js +382 -0
  66. package/dist/components/code-block/code-block.styles.d.ts +1 -0
  67. package/dist/components/code-block/code-block.styles.js +187 -0
  68. package/dist/components/code-block/code-loader.d.ts +87 -0
  69. package/dist/components/code-block/code-loader.js +142 -0
  70. package/dist/components/combobox/combobox.d.ts +65 -6
  71. package/dist/components/combobox/combobox.js +258 -48
  72. package/dist/components/combobox/combobox.styles.js +3 -3
  73. package/dist/components/combobox/option.d.ts +5 -1
  74. package/dist/components/combobox/option.js +35 -0
  75. package/dist/components/context-meter/context-meter.d.ts +53 -0
  76. package/dist/components/context-meter/context-meter.js +159 -0
  77. package/dist/components/context-meter/context-meter.styles.d.ts +1 -0
  78. package/dist/components/context-meter/context-meter.styles.js +114 -0
  79. package/dist/components/conversation-item/conversation-item.d.ts +125 -0
  80. package/dist/components/conversation-item/conversation-item.js +331 -0
  81. package/dist/components/conversation-item/conversation-item.styles.d.ts +1 -0
  82. package/dist/components/conversation-item/conversation-item.styles.js +155 -0
  83. package/dist/components/date-picker/calendar-core.d.ts +24 -0
  84. package/dist/components/date-picker/calendar-core.js +51 -4
  85. package/dist/components/date-picker/date-input.d.ts +100 -9
  86. package/dist/components/date-picker/date-input.js +383 -66
  87. package/dist/components/date-picker/date-picker.d.ts +35 -4
  88. package/dist/components/date-picker/date-picker.js +171 -44
  89. package/dist/components/dialog/confirm.d.ts +40 -0
  90. package/dist/components/dialog/confirm.js +76 -0
  91. package/dist/components/dialog/dialog.d.ts +129 -0
  92. package/dist/components/dialog/dialog.js +288 -0
  93. package/dist/components/dialog/dialog.styles.d.ts +1 -0
  94. package/dist/components/dialog/dialog.styles.js +96 -0
  95. package/dist/components/dock-panel/dock-panel.d.ts +142 -0
  96. package/dist/components/dock-panel/dock-panel.js +359 -0
  97. package/dist/components/dock-panel/dock-panel.styles.d.ts +1 -0
  98. package/dist/components/dock-panel/dock-panel.styles.js +159 -0
  99. package/dist/components/document-preview/document-preview.d.ts +143 -0
  100. package/dist/components/document-preview/document-preview.js +388 -0
  101. package/dist/components/document-preview/document-preview.styles.d.ts +1 -0
  102. package/dist/components/document-preview/document-preview.styles.js +191 -0
  103. package/dist/components/empty/empty.d.ts +1 -2
  104. package/dist/components/empty/empty.js +18 -12
  105. package/dist/components/empty/empty.styles.js +0 -3
  106. package/dist/components/export-button/csv.js +1 -1
  107. package/dist/components/export-button/export-button.d.ts +12 -0
  108. package/dist/components/export-button/export-button.js +35 -5
  109. package/dist/components/export-button/export-button.styles.js +5 -1
  110. package/dist/components/file-input/accept.js +2 -0
  111. package/dist/components/file-input/file-input.d.ts +10 -1
  112. package/dist/components/file-input/file-input.js +36 -5
  113. package/dist/components/flag/flag.d.ts +29 -13
  114. package/dist/components/flag/flag.js +54 -14
  115. package/dist/components/flag/flag.styles.js +1 -1
  116. package/dist/components/flag/language-map.d.ts +4 -1
  117. package/dist/components/flag/language-map.js +6 -3
  118. package/dist/components/gauge/gauge.d.ts +10 -1
  119. package/dist/components/gauge/gauge.js +41 -13
  120. package/dist/components/generation-status/generation-status.d.ts +117 -0
  121. package/dist/components/generation-status/generation-status.js +327 -0
  122. package/dist/components/generation-status/generation-status.styles.d.ts +1 -0
  123. package/dist/components/generation-status/generation-status.styles.js +84 -0
  124. package/dist/components/graph/graph.d.ts +37 -3
  125. package/dist/components/graph/graph.js +132 -20
  126. package/dist/components/heatmap/calendar-grid.d.ts +19 -7
  127. package/dist/components/heatmap/calendar-grid.js +42 -18
  128. package/dist/components/heatmap/heatmap-scale.d.ts +11 -1
  129. package/dist/components/heatmap/heatmap-scale.js +14 -2
  130. package/dist/components/heatmap/heatmap.d.ts +227 -12
  131. package/dist/components/heatmap/heatmap.js +488 -93
  132. package/dist/components/json-viewer/json-viewer.d.ts +70 -0
  133. package/dist/components/json-viewer/json-viewer.js +361 -0
  134. package/dist/components/json-viewer/json-viewer.styles.d.ts +1 -0
  135. package/dist/components/json-viewer/json-viewer.styles.js +177 -0
  136. package/dist/components/kbd/kbd.d.ts +77 -0
  137. package/dist/components/kbd/kbd.js +231 -0
  138. package/dist/components/kbd/kbd.styles.d.ts +1 -0
  139. package/dist/components/kbd/kbd.styles.js +52 -0
  140. package/dist/components/live-region/live-region.d.ts +90 -0
  141. package/dist/components/live-region/live-region.js +189 -0
  142. package/dist/components/live-region/live-region.styles.d.ts +1 -0
  143. package/dist/components/live-region/live-region.styles.js +10 -0
  144. package/dist/components/map/map.d.ts +32 -7
  145. package/dist/components/map/map.js +133 -32
  146. package/dist/components/markdown/markdown-loader.d.ts +58 -0
  147. package/dist/components/markdown/markdown-loader.js +77 -0
  148. package/dist/components/markdown/markdown.d.ts +119 -0
  149. package/dist/components/markdown/markdown.js +389 -0
  150. package/dist/components/markdown/markdown.styles.d.ts +1 -0
  151. package/dist/components/markdown/markdown.styles.js +88 -0
  152. package/dist/components/media-card/media-card.d.ts +130 -0
  153. package/dist/components/media-card/media-card.js +273 -0
  154. package/dist/components/media-card/media-card.styles.d.ts +1 -0
  155. package/dist/components/media-card/media-card.styles.js +132 -0
  156. package/dist/components/mention-popover/mention-popover.d.ts +203 -0
  157. package/dist/components/mention-popover/mention-popover.js +493 -0
  158. package/dist/components/mention-popover/mention-popover.styles.d.ts +1 -0
  159. package/dist/components/mention-popover/mention-popover.styles.js +101 -0
  160. package/dist/components/menu/menu-item.d.ts +91 -0
  161. package/dist/components/menu/menu-item.js +206 -0
  162. package/dist/components/menu/menu-item.styles.d.ts +1 -0
  163. package/dist/components/menu/menu-item.styles.js +75 -0
  164. package/dist/components/menu/menu.d.ts +167 -0
  165. package/dist/components/menu/menu.js +461 -0
  166. package/dist/components/menu/menu.styles.d.ts +1 -0
  167. package/dist/components/menu/menu.styles.js +67 -0
  168. package/dist/components/model-select/model-select.d.ts +170 -0
  169. package/dist/components/model-select/model-select.js +588 -0
  170. package/dist/components/model-select/model-select.styles.d.ts +1 -0
  171. package/dist/components/model-select/model-select.styles.js +203 -0
  172. package/dist/components/model-settings-panel/model-settings-panel.d.ts +93 -0
  173. package/dist/components/model-settings-panel/model-settings-panel.js +209 -0
  174. package/dist/components/model-settings-panel/model-settings-panel.styles.d.ts +1 -0
  175. package/dist/components/model-settings-panel/model-settings-panel.styles.js +82 -0
  176. package/dist/components/playback/playback.d.ts +19 -3
  177. package/dist/components/playback/playback.js +109 -33
  178. package/dist/components/playback/playback.styles.js +6 -1
  179. package/dist/components/responsive-panel/responsive-panel.d.ts +163 -0
  180. package/dist/components/responsive-panel/responsive-panel.js +363 -0
  181. package/dist/components/responsive-panel/responsive-panel.styles.d.ts +1 -0
  182. package/dist/components/responsive-panel/responsive-panel.styles.js +103 -0
  183. package/dist/components/result-card/result-card.d.ts +50 -0
  184. package/dist/components/result-card/result-card.js +89 -0
  185. package/dist/components/result-card/result-card.styles.d.ts +1 -0
  186. package/dist/components/result-card/result-card.styles.js +49 -0
  187. package/dist/components/result-card/result-field.d.ts +36 -0
  188. package/dist/components/result-card/result-field.js +87 -0
  189. package/dist/components/result-card/result-field.styles.d.ts +1 -0
  190. package/dist/components/result-card/result-field.styles.js +32 -0
  191. package/dist/components/select/select.d.ts +84 -4
  192. package/dist/components/select/select.js +251 -36
  193. package/dist/components/skeleton/skeleton.d.ts +3 -0
  194. package/dist/components/skeleton/skeleton.js +7 -1
  195. package/dist/components/skeleton/skeleton.styles.js +5 -4
  196. package/dist/components/slider/slider.d.ts +141 -0
  197. package/dist/components/slider/slider.js +467 -0
  198. package/dist/components/slider/slider.styles.d.ts +1 -0
  199. package/dist/components/slider/slider.styles.js +87 -0
  200. package/dist/components/source-card/source-card.d.ts +104 -0
  201. package/dist/components/source-card/source-card.js +195 -0
  202. package/dist/components/source-card/source-card.styles.d.ts +1 -0
  203. package/dist/components/source-card/source-card.styles.js +69 -0
  204. package/dist/components/source-list/source-list.d.ts +63 -0
  205. package/dist/components/source-list/source-list.js +130 -0
  206. package/dist/components/source-list/source-list.styles.d.ts +1 -0
  207. package/dist/components/source-list/source-list.styles.js +59 -0
  208. package/dist/components/sparkline/sparkline.js +58 -20
  209. package/dist/components/split/split.d.ts +224 -5
  210. package/dist/components/split/split.js +617 -43
  211. package/dist/components/split/split.styles.js +47 -0
  212. package/dist/components/stat/stat.d.ts +15 -4
  213. package/dist/components/stat/stat.js +53 -12
  214. package/dist/components/stream-status/stream-status.d.ts +126 -0
  215. package/dist/components/stream-status/stream-status.js +292 -0
  216. package/dist/components/stream-status/stream-status.styles.d.ts +1 -0
  217. package/dist/components/stream-status/stream-status.styles.js +103 -0
  218. package/dist/components/streaming-text/streaming-text.d.ts +104 -0
  219. package/dist/components/streaming-text/streaming-text.js +224 -0
  220. package/dist/components/streaming-text/streaming-text.styles.d.ts +1 -0
  221. package/dist/components/streaming-text/streaming-text.styles.js +63 -0
  222. package/dist/components/switch/switch.d.ts +103 -0
  223. package/dist/components/switch/switch.js +250 -0
  224. package/dist/components/switch/switch.styles.d.ts +1 -0
  225. package/dist/components/switch/switch.styles.js +75 -0
  226. package/dist/components/table/table.d.ts +89 -5
  227. package/dist/components/table/table.js +243 -26
  228. package/dist/components/table/table.styles.js +6 -1
  229. package/dist/components/tabs/tabs.d.ts +74 -0
  230. package/dist/components/tabs/tabs.js +254 -0
  231. package/dist/components/tabs/tabs.styles.d.ts +1 -0
  232. package/dist/components/tabs/tabs.styles.js +74 -0
  233. package/dist/components/thinking-panel/thinking-panel.d.ts +123 -0
  234. package/dist/components/thinking-panel/thinking-panel.js +260 -0
  235. package/dist/components/thinking-panel/thinking-panel.styles.d.ts +1 -0
  236. package/dist/components/thinking-panel/thinking-panel.styles.js +123 -0
  237. package/dist/components/time-range/time-range.d.ts +59 -2
  238. package/dist/components/time-range/time-range.js +163 -67
  239. package/dist/components/toast/toast-item.d.ts +12 -2
  240. package/dist/components/toast/toast-item.js +106 -44
  241. package/dist/components/toast/toast-item.styles.js +59 -28
  242. package/dist/components/toast/toast.js +17 -5
  243. package/dist/components/toast/toaster.js +10 -1
  244. package/dist/components/tool-approval-dialog/tool-approval-dialog.d.ts +131 -0
  245. package/dist/components/tool-approval-dialog/tool-approval-dialog.js +329 -0
  246. package/dist/components/tool-approval-dialog/tool-approval-dialog.styles.d.ts +1 -0
  247. package/dist/components/tool-approval-dialog/tool-approval-dialog.styles.js +160 -0
  248. package/dist/components/tool-call-chip/tool-call-chip.d.ts +105 -0
  249. package/dist/components/tool-call-chip/tool-call-chip.js +349 -0
  250. package/dist/components/tool-call-chip/tool-call-chip.styles.d.ts +1 -0
  251. package/dist/components/tool-call-chip/tool-call-chip.styles.js +203 -0
  252. package/dist/components/tool-param-form/tool-param-form.d.ts +206 -0
  253. package/dist/components/tool-param-form/tool-param-form.js +610 -0
  254. package/dist/components/tool-param-form/tool-param-form.styles.d.ts +1 -0
  255. package/dist/components/tool-param-form/tool-param-form.styles.js +75 -0
  256. package/dist/components/tool-result-dialog/tool-result-dialog.d.ts +122 -0
  257. package/dist/components/tool-result-dialog/tool-result-dialog.js +358 -0
  258. package/dist/components/tool-result-dialog/tool-result-dialog.styles.d.ts +1 -0
  259. package/dist/components/tool-result-dialog/tool-result-dialog.styles.js +176 -0
  260. package/dist/components/tool-result-view/registry.d.ts +73 -0
  261. package/dist/components/tool-result-view/registry.js +89 -0
  262. package/dist/components/tool-result-view/tool-result-view.d.ts +58 -0
  263. package/dist/components/tool-result-view/tool-result-view.js +152 -0
  264. package/dist/components/tool-result-view/tool-result-view.styles.d.ts +1 -0
  265. package/dist/components/tool-result-view/tool-result-view.styles.js +13 -0
  266. package/dist/components/tool-select-dialog/tool-select-dialog.d.ts +151 -0
  267. package/dist/components/tool-select-dialog/tool-select-dialog.js +350 -0
  268. package/dist/components/tool-select-dialog/tool-select-dialog.styles.d.ts +1 -0
  269. package/dist/components/tool-select-dialog/tool-select-dialog.styles.js +191 -0
  270. package/dist/components/tree/tree-node.d.ts +15 -3
  271. package/dist/components/tree/tree-node.js +20 -7
  272. package/dist/components/tree/tree.d.ts +25 -10
  273. package/dist/components/tree/tree.js +39 -31
  274. package/dist/components/typing-indicator/typing-indicator.d.ts +70 -0
  275. package/dist/components/typing-indicator/typing-indicator.js +108 -0
  276. package/dist/components/typing-indicator/typing-indicator.styles.d.ts +1 -0
  277. package/dist/components/typing-indicator/typing-indicator.styles.js +132 -0
  278. package/dist/components/virtual-list/virtual-list.d.ts +210 -0
  279. package/dist/components/virtual-list/virtual-list.js +607 -0
  280. package/dist/components/virtual-list/virtual-list.styles.d.ts +1 -0
  281. package/dist/components/virtual-list/virtual-list.styles.js +56 -0
  282. package/dist/components/widget/widget.d.ts +5 -4
  283. package/dist/components/widget/widget.js +54 -120
  284. package/dist/components/widget/widget.styles.js +8 -2
  285. package/dist/components/word-cloud/word-cloud-layout.d.ts +7 -0
  286. package/dist/components/word-cloud/word-cloud-layout.js +29 -2
  287. package/dist/components/word-cloud/word-cloud.d.ts +28 -2
  288. package/dist/components/word-cloud/word-cloud.js +69 -19
  289. package/dist/components/word-cloud/word-cloud.styles.js +16 -3
  290. package/dist/internal/anchored-validity.d.ts +1 -0
  291. package/dist/internal/anchored-validity.js +86 -0
  292. package/dist/internal/announcer.d.ts +57 -0
  293. package/dist/internal/announcer.js +71 -0
  294. package/dist/internal/form-associated.d.ts +8 -0
  295. package/dist/internal/form-associated.js +98 -15
  296. package/dist/internal/group-by-recency.d.ts +50 -0
  297. package/dist/internal/group-by-recency.js +80 -0
  298. package/dist/internal/numbers.d.ts +12 -0
  299. package/dist/internal/numbers.js +26 -0
  300. package/dist/internal/overlay-manager.d.ts +51 -0
  301. package/dist/internal/overlay-manager.js +523 -0
  302. package/dist/internal/positioner.js +27 -3
  303. package/dist/internal/rtl.d.ts +23 -0
  304. package/dist/internal/rtl.js +28 -0
  305. package/dist/internal/safe-url.d.ts +12 -0
  306. package/dist/internal/safe-url.js +41 -0
  307. package/dist/internal/scroll-lock.d.ts +10 -5
  308. package/dist/internal/scroll-lock.js +30 -14
  309. package/dist/internal/tokens.styles.js +22 -10
  310. package/dist/lyra.d.ts +133 -31
  311. package/dist/lyra.js +96 -26
  312. package/llms-full.txt +4546 -183
  313. package/llms.txt +21 -5
  314. package/package.json +41 -6
  315. package/dist/components/chart/bar-chart.stories.d.ts +0 -5
  316. package/dist/components/chart/bar-chart.stories.js +0 -20
  317. package/dist/components/chart/box-plot.stories.d.ts +0 -5
  318. package/dist/components/chart/box-plot.stories.js +0 -29
  319. package/dist/components/chart/bubble-chart.stories.d.ts +0 -5
  320. package/dist/components/chart/bubble-chart.stories.js +0 -26
  321. package/dist/components/chart/chart.stories.d.ts +0 -32
  322. package/dist/components/chart/chart.stories.js +0 -141
  323. package/dist/components/chart/doughnut-chart.stories.d.ts +0 -5
  324. package/dist/components/chart/doughnut-chart.stories.js +0 -26
  325. package/dist/components/chart/histogram.stories.d.ts +0 -5
  326. package/dist/components/chart/histogram.stories.js +0 -17
  327. package/dist/components/chart/line-chart.stories.d.ts +0 -22
  328. package/dist/components/chart/line-chart.stories.js +0 -99
  329. package/dist/components/chart/lite-chart.stories.d.ts +0 -14
  330. package/dist/components/chart/lite-chart.stories.js +0 -114
  331. package/dist/components/chart/pie-chart.stories.d.ts +0 -5
  332. package/dist/components/chart/pie-chart.stories.js +0 -26
  333. package/dist/components/chart/polar-area-chart.stories.d.ts +0 -5
  334. package/dist/components/chart/polar-area-chart.stories.js +0 -20
  335. package/dist/components/chart/radar-chart.stories.d.ts +0 -5
  336. package/dist/components/chart/radar-chart.stories.js +0 -20
  337. package/dist/components/chart/scatter-chart.stories.d.ts +0 -5
  338. package/dist/components/chart/scatter-chart.stories.js +0 -31
  339. package/dist/components/combobox/combobox.stories.d.ts +0 -24
  340. package/dist/components/combobox/combobox.stories.js +0 -102
  341. package/dist/components/date-picker/date-input.stories.d.ts +0 -10
  342. package/dist/components/date-picker/date-input.stories.js +0 -48
  343. package/dist/components/date-picker/date-picker.stories.d.ts +0 -10
  344. package/dist/components/date-picker/date-picker.stories.js +0 -25
  345. package/dist/components/empty/empty.stories.d.ts +0 -7
  346. package/dist/components/empty/empty.stories.js +0 -34
  347. package/dist/components/export-button/export-button.stories.d.ts +0 -7
  348. package/dist/components/export-button/export-button.stories.js +0 -37
  349. package/dist/components/file-input/file-input.stories.d.ts +0 -7
  350. package/dist/components/file-input/file-input.stories.js +0 -19
  351. package/dist/components/flag/flag.stories.d.ts +0 -6
  352. package/dist/components/flag/flag.stories.js +0 -31
  353. package/dist/components/gauge/gauge.stories.d.ts +0 -8
  354. package/dist/components/gauge/gauge.stories.js +0 -19
  355. package/dist/components/graph/graph.stories.d.ts +0 -8
  356. package/dist/components/graph/graph.stories.js +0 -68
  357. package/dist/components/heatmap/heatmap.stories.d.ts +0 -27
  358. package/dist/components/heatmap/heatmap.stories.js +0 -179
  359. package/dist/components/map/map.stories.d.ts +0 -15
  360. package/dist/components/map/map.stories.js +0 -135
  361. package/dist/components/playback/playback.stories.d.ts +0 -7
  362. package/dist/components/playback/playback.stories.js +0 -16
  363. package/dist/components/select/select.stories.d.ts +0 -21
  364. package/dist/components/select/select.stories.js +0 -91
  365. package/dist/components/skeleton/skeleton.stories.d.ts +0 -5
  366. package/dist/components/skeleton/skeleton.stories.js +0 -16
  367. package/dist/components/sparkline/sparkline.stories.d.ts +0 -11
  368. package/dist/components/sparkline/sparkline.stories.js +0 -39
  369. package/dist/components/split/split.stories.d.ts +0 -7
  370. package/dist/components/split/split.stories.js +0 -36
  371. package/dist/components/stat/stat.stories.d.ts +0 -9
  372. package/dist/components/stat/stat.stories.js +0 -81
  373. package/dist/components/table/table.stories.d.ts +0 -12
  374. package/dist/components/table/table.stories.js +0 -67
  375. package/dist/components/time-range/time-range.stories.d.ts +0 -8
  376. package/dist/components/time-range/time-range.stories.js +0 -26
  377. package/dist/components/toast/toast.stories.d.ts +0 -8
  378. package/dist/components/toast/toast.stories.js +0 -72
  379. package/dist/components/tree/tree.stories.d.ts +0 -9
  380. package/dist/components/tree/tree.stories.js +0 -52
  381. package/dist/components/widget/widget.stories.d.ts +0 -9
  382. package/dist/components/widget/widget.stories.js +0 -74
  383. package/dist/components/word-cloud/word-cloud.stories.d.ts +0 -10
  384. package/dist/components/word-cloud/word-cloud.stories.js +0 -55
@@ -8,9 +8,25 @@ import { html, nothing } from 'lit';
8
8
  import { property, query, state } from 'lit/decorators.js';
9
9
  import { LyraElement } from '../../internal/lyra-element.js';
10
10
  import { defineElement } from '../../internal/prefix.js';
11
- import { loadChartJs } from './chart-loader.js';
11
+ import { nextId, srOnly } from '../../internal/a11y.js';
12
+ import { loadChartJs, loadChartJsWithZoom } from './chart-loader.js';
12
13
  import { styles } from './chart.styles.js';
13
14
  import '../skeleton/skeleton.js';
15
+ const CHART_TYPES = new Set([
16
+ 'line',
17
+ 'bar',
18
+ 'scatter',
19
+ 'pie',
20
+ 'doughnut',
21
+ 'radar',
22
+ 'polarArea',
23
+ 'bubble',
24
+ ]);
25
+ function normalizeChartType(value) {
26
+ return typeof value === 'string' && CHART_TYPES.has(value)
27
+ ? value
28
+ : 'line';
29
+ }
14
30
  /**
15
31
  * Recursively merges `override` onto `base`, matching JSON-merge semantics:
16
32
  * plain objects are merged key-by-key at every depth; arrays, functions, and
@@ -39,15 +55,21 @@ const FALLBACK_TICK_COLOR = '#6b7280';
39
55
  const FALLBACK_LEGEND_COLOR = '#1a1a1a';
40
56
  const FALLBACK_TOOLTIP_BG = '#fff';
41
57
  const FALLBACK_TOOLTIP_TEXT = '#1a1a1a';
42
- function deepMerge(base, override) {
58
+ function deepMerge(base, override, seen = new WeakMap()) {
59
+ if (typeof override === 'object' && override !== null) {
60
+ const previous = seen.get(override);
61
+ if (previous !== undefined)
62
+ return previous;
63
+ }
43
64
  if (!isPlainObject(base) || !isPlainObject(override)) {
44
65
  return (override === undefined ? base : override);
45
66
  }
46
67
  const result = { ...base };
68
+ seen.set(override, result);
47
69
  for (const key of Object.keys(override)) {
48
70
  if (UNSAFE_KEYS.has(key))
49
71
  continue;
50
- result[key] = deepMerge(base[key], override[key]);
72
+ result[key] = deepMerge(base[key], override[key], seen);
51
73
  }
52
74
  return result;
53
75
  }
@@ -76,7 +98,12 @@ function deepMerge(base, override) {
76
98
  * intersect-only — see `handlePointClick()`) a data point/segment.
77
99
  * `detail: { datasetIndex: number, index: number, label: string |
78
100
  * undefined, value: unknown }`.
79
- * @csspart base, canvas, reset-zoom-button
101
+ * @csspart base - The chart wrapper.
102
+ * @csspart canvas - The Chart.js canvas.
103
+ * @csspart reset-zoom-button - The reset-zoom control when zoom is active.
104
+ * @csspart description - The accessible chart summary.
105
+ * @csspart data-table - The optional generated or slotted data table.
106
+ * @slot data-table - An optional consumer-provided accessible table alternative.
80
107
  */
81
108
  export class LyraChart extends LyraElement {
82
109
  constructor() {
@@ -92,6 +119,12 @@ export class LyraChart extends LyraElement {
92
119
  this.yLabel = '';
93
120
  this.y2Label = '';
94
121
  this.beginAtZero = true;
122
+ /** Accessible name applied to the canvas. Falls back to the dataset labels. */
123
+ this.accessibleLabel = '';
124
+ /** Accessible description for the canvas. When unset, a concise data/trend summary is generated. */
125
+ this.accessibleDescription = '';
126
+ /** Makes the generated data table visible; it remains screen-reader available when false. */
127
+ this.showDataTable = false;
95
128
  /** Sets `options.indexAxis = 'y'`, Chart.js's own mechanism for horizontal bars (also applies to line/area types). */
96
129
  this.horizontal = false;
97
130
  /** Stacks the `x`/`y`(/`y2`) scale entries `buildScales()` returns; only meaningful for `bar` and `line` types. */
@@ -100,18 +133,21 @@ export class LyraChart extends LyraElement {
100
133
  this.loading = true;
101
134
  this.zoomed = false;
102
135
  this.visible = true;
103
- this.lastSignature = '';
104
136
  // `chartjs-plugin-zoom`'s own `resetZoom()` synchronously re-invokes the
105
137
  // `onZoomComplete` callback below as part of its reset, which would emit a
106
138
  // stale `{zoomed: true}` right before `resetZoom()` emits the real
107
139
  // `{zoomed: false}`. Set while this component's own `resetZoom()` is
108
140
  // driving the plugin so that re-entrant callback is ignored.
109
141
  this.suppressZoomComplete = false;
142
+ this.descriptionId = nextId('chart-description');
110
143
  }
111
- static { this.styles = [LyraElement.styles, styles]; }
144
+ static { this.styles = [LyraElement.styles, styles, srOnly]; }
112
145
  connectedCallback() {
113
146
  super.connectedCallback();
114
- void loadChartJs().then((mod) => {
147
+ const load = this.zoom ? loadChartJsWithZoom() : loadChartJs();
148
+ void load.then((mod) => {
149
+ if (!this.isConnected)
150
+ return;
115
151
  this.loading = false;
116
152
  if (!mod)
117
153
  return;
@@ -134,7 +170,41 @@ export class LyraChart extends LyraElement {
134
170
  this.chart = undefined;
135
171
  this.intersectionObserver?.disconnect();
136
172
  }
173
+ /**
174
+ * Resets a stale `zoomed` flag before the render pass that's about to call
175
+ * `draw()`: a `type` (or `config.type` override) change that lands on a
176
+ * *different* effective Chart.js type makes `draw()` destroy the old
177
+ * `Chart` instance and construct a brand-new one, which was never zoomed —
178
+ * without this, `render()`'s reset-zoom-button stays visible for an
179
+ * instance that has no zoom/pan state left to reset. Computed here (before
180
+ * render), not in `updated()`/`draw()`, because setting `zoomed` — a
181
+ * reactive `@state` property — from `updated()` would schedule a second,
182
+ * redundant update pass; `willUpdate()` runs before this cycle's render is
183
+ * considered complete, so the same set just folds into the render already
184
+ * in progress. Same rationale as `toast-item.ts`'s `willUpdate()`-vs-
185
+ * `updated()` split.
186
+ */
187
+ willUpdate() {
188
+ if (!this.zoomed)
189
+ return;
190
+ if (this.effectiveType() !== this.builtType) {
191
+ this.zoomed = false;
192
+ }
193
+ }
137
194
  updated(changed) {
195
+ // Disconnected between the property change that scheduled this update
196
+ // and Lit's (microtask-deferred) processing of it — e.g. a property
197
+ // changes and the element is removed in the same synchronous tick, so
198
+ // `disconnectedCallback()` (which already destroyed `this.chart`) runs
199
+ // *before* this method does. Nothing below should run in that case:
200
+ // this method's own unconditional `draw()` call further down would
201
+ // otherwise construct a brand-new `Chart` bound to the now-detached
202
+ // canvas — `draw()`'s own guard (`!chartJsModule || !canvasEl`) doesn't
203
+ // catch this, since both persist on a disconnected-but-intact element.
204
+ // If the component is reconnected later, `connectedCallback()` re-kicks
205
+ // its own load/draw sequence, so nothing is lost by bailing out here.
206
+ if (!this.isConnected)
207
+ return;
138
208
  if (this.loading)
139
209
  this.setAttribute('aria-busy', 'true');
140
210
  else
@@ -154,15 +224,43 @@ export class LyraChart extends LyraElement {
154
224
  // other property having changed in the meantime.
155
225
  if (this.loading)
156
226
  return;
157
- const onlyZoomChanged = changed.size === 1 && changed.has('zoomed');
158
- if (onlyZoomChanged)
227
+ // `zoom` can also turn on after connect (it was false at
228
+ // `connectedCallback()` time, so only the core `loadChartJs()` load was
229
+ // kicked off) — load the zoom plugin on demand now and redraw once it's
230
+ // registered. Mirrors the same `isConnected` guard `connectedCallback()`
231
+ // uses: this method already bailed out above if *already* disconnected,
232
+ // but the element can *also* disconnect during the gap while this
233
+ // dynamic import is in flight — without this guard, `draw()` would
234
+ // construct a new, leaked `Chart` bound to the now-detached canvas once
235
+ // the import resolves.
236
+ if (changed.has('zoom') && this.zoom) {
237
+ void loadChartJsWithZoom().then(() => {
238
+ if (!this.isConnected)
239
+ return;
240
+ this.draw();
241
+ });
242
+ }
243
+ const contentChanged = [
244
+ 'type',
245
+ 'labels',
246
+ 'datasets',
247
+ 'legend',
248
+ 'area',
249
+ 'height',
250
+ 'xLabel',
251
+ 'yLabel',
252
+ 'y2Label',
253
+ 'beginAtZero',
254
+ 'horizontal',
255
+ 'stacked',
256
+ 'config',
257
+ 'zoom',
258
+ 'loading',
259
+ ].some((name) => changed.has(name));
260
+ if (!contentChanged)
159
261
  return;
160
262
  if (!this.visible)
161
263
  return; // becoming visible again triggers its own draw() via the observer above
162
- const signature = this.computeSignature();
163
- if (signature === this.lastSignature)
164
- return;
165
- this.lastSignature = signature;
166
264
  this.draw();
167
265
  }
168
266
  seriesToDataset(s) {
@@ -170,7 +268,20 @@ export class LyraChart extends LyraElement {
170
268
  return {
171
269
  label: s.label,
172
270
  data: s.points ?? s.data ?? [],
173
- type: s.type ?? this.type,
271
+ // Leave unset rather than defaulting to `this.type`: Chart.js already
272
+ // falls back to the chart-level (effective) type for any dataset that
273
+ // doesn't set its own `type`, and forcing `this.type` here unconditionally
274
+ // used to be harmless (it normally matched the effective type anyway) —
275
+ // but it actively breaks a `config.type` override to a different chart
276
+ // family (e.g. attribute `type="line"` + `config.type: 'radar'`): every
277
+ // dataset would carry an explicit `type: 'line'` under a chart whose
278
+ // scales are built for `radar` (a single radial `r` scale, no `x`/`y`),
279
+ // which Chart.js can't reconcile — it hangs the page trying to lay out
280
+ // a cartesian-scale controller against a radial-only scale set. Only
281
+ // `s.type` (an explicit per-series mixed-type override, e.g. a line
282
+ // series over a bar chart of the *same* effective family) is passed
283
+ // through.
284
+ type: s.type,
174
285
  fill: s.fill ?? this.area,
175
286
  borderWidth: s.width ?? 2,
176
287
  borderDash: s.dash ? [4, 4] : undefined,
@@ -179,7 +290,6 @@ export class LyraChart extends LyraElement {
179
290
  pointBackgroundColor: s.pointColors,
180
291
  pointRadius: s.pointRadius,
181
292
  yAxisID: s.axis === 'y2' ? 'y2' : 'y',
182
- tooltip: s.noTooltip ? { enabled: false } : undefined,
183
293
  };
184
294
  }
185
295
  /**
@@ -200,29 +310,6 @@ export class LyraChart extends LyraElement {
200
310
  tooltipText: cs.getPropertyValue('--lyra-chart-tooltip-text').trim() || FALLBACK_TOOLTIP_TEXT,
201
311
  };
202
312
  }
203
- /**
204
- * A content-affecting-properties fingerprint used by `updated()` to skip a
205
- * redundant `draw()` when neither visibility nor any of these properties
206
- * actually changed since the last draw (e.g. an unrelated property/state
207
- * update, or `requestUpdate()` with nothing changed). Mirrors
208
- * `lite-chart.ts`'s `computeSignature()`.
209
- */
210
- computeSignature() {
211
- return JSON.stringify([
212
- this.type,
213
- this.labels,
214
- this.datasets,
215
- this.legend,
216
- this.area,
217
- this.xLabel,
218
- this.yLabel,
219
- this.y2Label,
220
- this.beginAtZero,
221
- this.horizontal,
222
- this.stacked,
223
- this.config,
224
- ]);
225
- }
226
313
  /**
227
314
  * Builds `options.scales` for the effective chart type: no scale at all for
228
315
  * pie/doughnut (a proportional-area chart has no axis), the single radial
@@ -235,10 +322,10 @@ export class LyraChart extends LyraElement {
235
322
  * scale's `ticks.color`/`grid.color`/axis `title.color` so grid lines and
236
323
  * labels retheme instead of sitting at Chart.js's own hardcoded defaults.
237
324
  */
238
- buildScales(theme) {
239
- if (this.type === 'pie' || this.type === 'doughnut')
325
+ buildScales(effectiveType, theme) {
326
+ if (effectiveType === 'pie' || effectiveType === 'doughnut')
240
327
  return {};
241
- if (this.type === 'radar' || this.type === 'polarArea') {
328
+ if (effectiveType === 'radar' || effectiveType === 'polarArea') {
242
329
  return {
243
330
  r: {
244
331
  beginAtZero: this.beginAtZero,
@@ -253,10 +340,10 @@ export class LyraChart extends LyraElement {
253
340
  // `stacked` only applies to bar/line-family charts sharing a categorical
254
341
  // axis, per the design spec — scatter/bubble's linear x scale and the
255
342
  // radial r scale above are out of scope.
256
- const stacked = this.stacked && (this.type === 'bar' || this.type === 'line');
343
+ const stacked = this.stacked && (effectiveType === 'bar' || effectiveType === 'line');
257
344
  return {
258
345
  x: {
259
- type: this.type === 'scatter' || this.type === 'bubble' ? 'linear' : 'category',
346
+ type: effectiveType === 'scatter' || effectiveType === 'bubble' ? 'linear' : 'category',
260
347
  title: { display: !!this.xLabel, text: this.xLabel, color: theme.tick },
261
348
  ticks: { color: theme.tick },
262
349
  grid: { color: theme.grid },
@@ -308,10 +395,27 @@ export class LyraChart extends LyraElement {
308
395
  const value = chart.data.datasets[datasetIndex]?.data?.[index] ?? null;
309
396
  this.emit('lyra-point-click', { datasetIndex, index, label, value });
310
397
  }
398
+ /**
399
+ * `config.type` (if set) overrides the attribute `type` post-merge — this
400
+ * is the one place that resolution logic lives, shared by `buildConfig()`
401
+ * (which needs it to build scales/interaction for the right type) and
402
+ * `willUpdate()` (which needs it to detect a type change against the last
403
+ * *actually built* type, `this.builtType`, before the render pass that
404
+ * would rebuild the `Chart` instance).
405
+ */
406
+ effectiveType() {
407
+ return (this.config?.type ?? normalizeChartType(this.type));
408
+ }
311
409
  buildConfig() {
312
410
  const theme = this.themeColors();
411
+ // Resolve the effective type up front: `config.type` (if set) overrides
412
+ // the attribute `type` post-merge, so scales/interaction must be built
413
+ // for *that* type, not `this.type` — otherwise a config.type override
414
+ // (e.g. line -> radar) ships with the wrong axis shape (categorical x/y
415
+ // instead of a radial r scale).
416
+ const effectiveType = this.effectiveType();
313
417
  const generated = {
314
- type: this.type,
418
+ type: effectiveType,
315
419
  data: {
316
420
  labels: this.labels,
317
421
  datasets: this.datasets.map((s) => this.seriesToDataset(s)),
@@ -329,7 +433,7 @@ export class LyraChart extends LyraElement {
329
433
  // canvas-internal animation loop, so `prefersReducedMotion()` is
330
434
  // checked here instead and fed into `options.animation`.
331
435
  animation: prefersReducedMotion() ? false : undefined,
332
- interaction: { intersect: false, mode: this.type === 'scatter' ? 'nearest' : 'index' },
436
+ interaction: { intersect: false, mode: effectiveType === 'scatter' ? 'nearest' : 'index' },
333
437
  onClick: (event, _elements, chart) => this.handlePointClick(event, chart),
334
438
  plugins: {
335
439
  legend: { display: this.legend, labels: { color: theme.legend } },
@@ -337,6 +441,10 @@ export class LyraChart extends LyraElement {
337
441
  backgroundColor: theme.tooltipBg,
338
442
  titleColor: theme.tooltipText,
339
443
  bodyColor: theme.tooltipText,
444
+ // Chart.js's tooltip plugin has no per-dataset `tooltip.enabled`
445
+ // — `Series.noTooltip` is implemented here instead, via the one
446
+ // mechanism the core tooltip plugin actually reads.
447
+ filter: (item) => !this.datasets[item.datasetIndex]?.noTooltip,
340
448
  },
341
449
  zoom: this.zoom
342
450
  ? {
@@ -357,7 +465,7 @@ export class LyraChart extends LyraElement {
357
465
  }
358
466
  : undefined,
359
467
  },
360
- scales: this.buildScales(theme),
468
+ scales: this.buildScales(effectiveType, theme),
361
469
  },
362
470
  };
363
471
  if (!this.config)
@@ -408,6 +516,56 @@ export class LyraChart extends LyraElement {
408
516
  refreshTheme() {
409
517
  this.draw();
410
518
  }
519
+ seriesValues(series) {
520
+ if (series.points)
521
+ return series.points.map((point) => point.y).filter((value) => Number.isFinite(value));
522
+ return (series.data ?? []).filter((value) => value != null && Number.isFinite(value));
523
+ }
524
+ chartDescription() {
525
+ if (this.accessibleDescription)
526
+ return this.accessibleDescription;
527
+ const summaries = this.datasets.map((series) => {
528
+ const values = this.seriesValues(series);
529
+ if (!values.length)
530
+ return `${series.label}: no data`;
531
+ const first = values[0];
532
+ const last = values[values.length - 1];
533
+ const trend = last > first ? 'increasing' : last < first ? 'decreasing' : 'flat';
534
+ let min = values[0];
535
+ let max = values[0];
536
+ for (const value of values) {
537
+ min = Math.min(min, value);
538
+ max = Math.max(max, value);
539
+ }
540
+ return `${series.label}: ${values.length} values, range ${min} to ${max}, ${trend} trend`;
541
+ });
542
+ return `${this.effectiveType()} chart${summaries.length ? `. ${summaries.join('. ')}` : ' with no data'}.`;
543
+ }
544
+ renderDataTable() {
545
+ const rowCount = Math.max(this.labels.length, ...this.datasets.map((series) => (series.points ? series.points.length : series.data?.length ?? 0)), 0);
546
+ return html `
547
+ <table class=${this.showDataTable ? nothing : 'sr-only'}>
548
+ <caption>${this.accessibleLabel || 'Chart data'}</caption>
549
+ <thead>
550
+ <tr>
551
+ <th scope="col">Category</th>
552
+ ${this.datasets.map((series) => html `<th scope="col">${series.label}</th>`)}
553
+ </tr>
554
+ </thead>
555
+ <tbody>
556
+ ${Array.from({ length: rowCount }, (_, index) => html `
557
+ <tr>
558
+ <th scope="row">${this.labels[index] ?? `Point ${index + 1}`}</th>
559
+ ${this.datasets.map((series) => {
560
+ const value = series.points ? series.points[index]?.y : series.data?.[index];
561
+ return html `<td>${value == null || !Number.isFinite(value) ? 'No data' : value}</td>`;
562
+ })}
563
+ </tr>
564
+ `)}
565
+ </tbody>
566
+ </table>
567
+ `;
568
+ }
411
569
  render() {
412
570
  if (this.loading) {
413
571
  return html `
@@ -416,10 +574,16 @@ export class LyraChart extends LyraElement {
416
574
  </div>
417
575
  `;
418
576
  }
419
- const label = this.datasets.map((d) => d.label).join(', ') || 'Chart';
577
+ const label = this.accessibleLabel || this.datasets.map((d) => d.label).join(', ') || 'Chart';
578
+ const description = this.chartDescription();
420
579
  return html `
421
580
  <div part="base">
422
- <canvas part="canvas" role="img" aria-label=${label}></canvas>
581
+ <canvas part="canvas" role="img" aria-label=${label} aria-describedby=${this.descriptionId}></canvas>
582
+ <p part="description" id=${this.descriptionId} class="sr-only">${description}</p>
583
+ <div part="data-table">
584
+ <slot name="data-table"></slot>
585
+ ${this.renderDataTable()}
586
+ </div>
423
587
  ${this.zoom && this.zoomed
424
588
  ? html `<button part="reset-zoom-button" type="button" @click=${() => this.resetZoom()}>
425
589
  Reset zoom
@@ -430,7 +594,7 @@ export class LyraChart extends LyraElement {
430
594
  }
431
595
  }
432
596
  __decorate([
433
- property()
597
+ property({ converter: { fromAttribute: (value) => normalizeChartType(value) } })
434
598
  ], LyraChart.prototype, "type", void 0);
435
599
  __decorate([
436
600
  property({ attribute: false })
@@ -462,6 +626,15 @@ __decorate([
462
626
  __decorate([
463
627
  property({ type: Boolean, attribute: 'begin-at-zero' })
464
628
  ], LyraChart.prototype, "beginAtZero", void 0);
629
+ __decorate([
630
+ property({ attribute: 'accessible-label' })
631
+ ], LyraChart.prototype, "accessibleLabel", void 0);
632
+ __decorate([
633
+ property({ attribute: 'accessible-description' })
634
+ ], LyraChart.prototype, "accessibleDescription", void 0);
635
+ __decorate([
636
+ property({ type: Boolean, attribute: 'show-data-table' })
637
+ ], LyraChart.prototype, "showDataTable", void 0);
465
638
  __decorate([
466
639
  property({ type: Boolean })
467
640
  ], LyraChart.prototype, "horizontal", void 0);
@@ -484,3 +657,28 @@ __decorate([
484
657
  query('canvas')
485
658
  ], LyraChart.prototype, "canvasEl", void 0);
486
659
  defineElement('chart', LyraChart);
660
+ /**
661
+ * Installs a read-only `type` accessor pair on a `LyraChart` subclass's
662
+ * prototype, locking it to `value` — assigning `.type` afterwards (attribute
663
+ * or property) is silently ignored. `LyraChart` declares `type` as a plain
664
+ * (decorator-managed) class field, and TypeScript forbids a subclass from
665
+ * re-declaring a base field as a getter/setter pair via ordinary class
666
+ * syntax (TS2611), so the accessor pair is installed directly on the
667
+ * prototype instead, which is runtime-equivalent (same shadowing semantics
668
+ * as a class-syntax override) without tripping that check. Shared by every
669
+ * `lyra-*-chart` subclass (bar/line/pie/doughnut/scatter/bubble/radar/
670
+ * polarArea) plus `lyra-histogram`, replacing what used to be an identical
671
+ * ~16-line `Object.defineProperty` block copy-pasted into each file.
672
+ */
673
+ export function lockChartType(ctor, value) {
674
+ Object.defineProperty(ctor.prototype, 'type', {
675
+ configurable: true,
676
+ enumerable: true,
677
+ get() {
678
+ return value;
679
+ },
680
+ set(_v) {
681
+ /* locked to `value`; direct writes are ignored */
682
+ },
683
+ });
684
+ }
@@ -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-doughnut-chart>` — `<lyra-chart>` with `type` locked to `"doughnut"`.
@@ -7,21 +7,5 @@ import { defineElement } from '../../internal/prefix.js';
7
7
  */
8
8
  export class LyraDoughnutChart 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(LyraDoughnutChart.prototype, 'type', {
18
- configurable: true,
19
- enumerable: true,
20
- get() {
21
- return 'doughnut';
22
- },
23
- set(_v) {
24
- /* locked to 'doughnut'; direct writes are ignored */
25
- },
26
- });
10
+ lockChartType(LyraDoughnutChart, 'doughnut');
27
11
  defineElement('doughnut-chart', LyraDoughnutChart);
@@ -2,5 +2,11 @@ export interface HistogramBucket {
2
2
  label: string;
3
3
  count: number;
4
4
  }
5
- /** Splits `values` into `binCount` equal-width buckets and counts membership. */
5
+ export declare const MAX_HISTOGRAM_BINS = 1000;
6
+ /** Converts an untyped bucket count to a bounded, non-negative integer. */
7
+ export declare function normalizeHistogramBinCount(binCount: unknown): number;
8
+ /** Splits `values` into `binCount` equal-width buckets and counts membership.
9
+ * Non-finite `binCount` (or <= 0) yields no buckets; a fractional `binCount`
10
+ * is floored and an excessive count is capped; non-finite samples in
11
+ * `values` are dropped rather than corrupting bucket-index math. */
6
12
  export declare function binValues(values: number[], binCount: number): HistogramBucket[];
@@ -1,29 +1,47 @@
1
- /** Splits `values` into `binCount` equal-width buckets and counts membership. */
1
+ export const MAX_HISTOGRAM_BINS = 1_000;
2
+ /** Converts an untyped bucket count to a bounded, non-negative integer. */
3
+ export function normalizeHistogramBinCount(binCount) {
4
+ const numeric = typeof binCount === 'number' ? binCount : Number(binCount);
5
+ if (!Number.isFinite(numeric))
6
+ return 0;
7
+ return Math.min(MAX_HISTOGRAM_BINS, Math.max(0, Math.floor(numeric)));
8
+ }
9
+ /** Splits `values` into `binCount` equal-width buckets and counts membership.
10
+ * Non-finite `binCount` (or <= 0) yields no buckets; a fractional `binCount`
11
+ * is floored and an excessive count is capped; non-finite samples in
12
+ * `values` are dropped rather than corrupting bucket-index math. */
2
13
  export function binValues(values, binCount) {
3
- if (values.length === 0 || binCount <= 0)
14
+ const finite = values.filter((v) => Number.isFinite(v));
15
+ if (finite.length === 0)
16
+ return [];
17
+ const bins = normalizeHistogramBinCount(binCount);
18
+ if (bins <= 0)
4
19
  return [];
5
- // Spreading `values` as call arguments (`Math.min(...values)`) throws
6
- // `RangeError: Maximum call stack size exceeded` once `values` is large
7
- // enough to overflow the engine's argument-list limit — reduce manually
8
- // instead so an arbitrarily large sample never crashes.
9
- let lo = values[0];
10
- let hi = values[0];
11
- for (const v of values) {
20
+ let lo = finite[0];
21
+ let hi = finite[0];
22
+ for (const v of finite) {
12
23
  if (v < lo)
13
24
  lo = v;
14
25
  if (v > hi)
15
26
  hi = v;
16
27
  }
28
+ // Constant data (lo === hi) previously fell into the `v === hi` branch
29
+ // below, which places every value in the *last* bucket alone — misleading,
30
+ // since every other bucket reads 0 and the label implies a spread that
31
+ // isn't real. Spread it into the *first* bucket instead so a single-value
32
+ // dataset reads as "N items, one bucket populated" starting from the data's
33
+ // own value, not its synthetic +1 upper edge.
34
+ const constant = hi === lo;
17
35
  const span = hi - lo || 1;
18
- const width = span / binCount;
19
- const buckets = Array.from({ length: binCount }, (_, i) => {
36
+ const width = span / bins;
37
+ const buckets = Array.from({ length: bins }, (_, i) => {
20
38
  const bLo = lo + i * width;
21
39
  const bHi = lo + (i + 1) * width;
22
40
  return { label: `${bLo.toFixed(1)}–${bHi.toFixed(1)}`, count: 0 };
23
41
  });
24
- for (const v of values) {
25
- const index = v === hi ? binCount - 1 : Math.floor((v - lo) / width);
26
- buckets[Math.min(binCount - 1, Math.max(0, index))].count++;
42
+ for (const v of finite) {
43
+ const index = constant ? 0 : v === hi ? bins - 1 : Math.floor((v - lo) / width);
44
+ buckets[Math.min(bins - 1, Math.max(0, index))].count++;
27
45
  }
28
46
  return buckets;
29
47
  }
@@ -5,10 +5,10 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
5
5
  return c > 3 && r && Object.defineProperty(target, key, r), r;
6
6
  };
7
7
  import { property } from 'lit/decorators.js';
8
- import { LyraChart } from './chart.js';
8
+ import { LyraChart, lockChartType } from './chart.js';
9
9
  import { LyraElement } from '../../internal/lyra-element.js';
10
10
  import { defineElement } from '../../internal/prefix.js';
11
- import { binValues } from './histogram-bin.js';
11
+ import { binValues, normalizeHistogramBinCount, } from './histogram-bin.js';
12
12
  import { styles } from './histogram.styles.js';
13
13
  /**
14
14
  * `<lyra-histogram>` — bins `values` into `bins` equal-width buckets and
@@ -32,7 +32,7 @@ export class LyraHistogram extends LyraChart {
32
32
  static { this.styles = [LyraElement.styles, styles]; }
33
33
  }
34
34
  __decorate([
35
- property({ type: Number })
35
+ property({ converter: { fromAttribute: (value) => normalizeHistogramBinCount(value) } })
36
36
  ], LyraHistogram.prototype, "bins", void 0);
37
37
  __decorate([
38
38
  property({ attribute: false })
@@ -48,12 +48,13 @@ __decorate([
48
48
  // change doesn't re-run the O(n) bucketing loop from scratch on every access.
49
49
  const bucketCache = new WeakMap();
50
50
  export function binnedBuckets(el) {
51
+ const bins = normalizeHistogramBinCount(el.bins);
51
52
  const cached = bucketCache.get(el);
52
- if (cached && cached.values === el.values && cached.bins === el.bins) {
53
+ if (cached && cached.values === el.values && cached.bins === bins) {
53
54
  return cached.buckets;
54
55
  }
55
- const buckets = binValues(el.values, el.bins);
56
- bucketCache.set(el, { values: el.values, bins: el.bins, buckets });
56
+ const buckets = binValues(el.values, bins);
57
+ bucketCache.set(el, { values: el.values, bins, buckets });
57
58
  return buckets;
58
59
  }
59
60
  // `labels`/`datasets` are computed from `values`/`bins` rather than settable
@@ -87,14 +88,5 @@ Object.defineProperty(LyraHistogram.prototype, 'datasets', {
87
88
  // just a default value, not an enforced lock, so without this a `type="line"`
88
89
  // attribute (or `el.type = 'line'`) would silently turn a histogram into a
89
90
  // line chart of its own bucket counts.
90
- Object.defineProperty(LyraHistogram.prototype, 'type', {
91
- configurable: true,
92
- enumerable: true,
93
- get() {
94
- return 'bar';
95
- },
96
- set(_v) {
97
- /* locked to 'bar'; direct writes are ignored */
98
- },
99
- });
91
+ lockChartType(LyraHistogram, 'bar');
100
92
  defineElement('histogram', LyraHistogram);
@@ -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-line-chart>` — `<lyra-chart>` with `type` locked to `"line"`.
@@ -7,21 +7,5 @@ import { defineElement } from '../../internal/prefix.js';
7
7
  */
8
8
  export class LyraLineChart 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(LyraLineChart.prototype, 'type', {
18
- configurable: true,
19
- enumerable: true,
20
- get() {
21
- return 'line';
22
- },
23
- set(_v) {
24
- /* locked to 'line'; direct writes are ignored */
25
- },
26
- });
10
+ lockChartType(LyraLineChart, 'line');
27
11
  defineElement('line-chart', LyraLineChart);