@aceshooting/lyra-ui 1.1.0 → 2.0.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 (335) hide show
  1. package/README.md +12 -1
  2. package/custom-elements.json +21460 -8489
  3. package/dist/components/app-rail/app-rail.d.ts +171 -0
  4. package/dist/components/app-rail/app-rail.js +483 -0
  5. package/dist/components/app-rail/app-rail.styles.d.ts +1 -0
  6. package/dist/components/app-rail/app-rail.styles.js +125 -0
  7. package/dist/components/attachment-chip/attachment-chip.d.ts +114 -0
  8. package/dist/components/attachment-chip/attachment-chip.js +312 -0
  9. package/dist/components/attachment-chip/attachment-chip.styles.d.ts +1 -0
  10. package/dist/components/attachment-chip/attachment-chip.styles.js +184 -0
  11. package/dist/components/attachment-trigger/attachment-trigger.d.ts +83 -0
  12. package/dist/components/attachment-trigger/attachment-trigger.js +258 -0
  13. package/dist/components/attachment-trigger/attachment-trigger.styles.d.ts +1 -0
  14. package/dist/components/attachment-trigger/attachment-trigger.styles.js +68 -0
  15. package/dist/components/chart/box-plot.js +11 -1
  16. package/dist/components/chart/chart-loader.d.ts +44 -13
  17. package/dist/components/chart/chart-loader.js +65 -18
  18. package/dist/components/chart/chart.d.ts +12 -2
  19. package/dist/components/chart/chart.js +121 -14
  20. package/dist/components/chart/histogram-bin.d.ts +4 -1
  21. package/dist/components/chart/histogram-bin.js +24 -14
  22. package/dist/components/chart/lite-chart.d.ts +63 -0
  23. package/dist/components/chart/lite-chart.js +181 -23
  24. package/dist/components/chart/lite-chart.styles.js +9 -0
  25. package/dist/components/chat-composer/chat-composer.d.ts +92 -0
  26. package/dist/components/chat-composer/chat-composer.js +285 -0
  27. package/dist/components/chat-composer/chat-composer.styles.d.ts +1 -0
  28. package/dist/components/chat-composer/chat-composer.styles.js +135 -0
  29. package/dist/components/chat-message/chat-message.d.ts +113 -0
  30. package/dist/components/chat-message/chat-message.js +291 -0
  31. package/dist/components/chat-message/chat-message.styles.d.ts +1 -0
  32. package/dist/components/chat-message/chat-message.styles.js +203 -0
  33. package/dist/components/checkbox/checkbox.d.ts +59 -0
  34. package/dist/components/checkbox/checkbox.js +230 -0
  35. package/dist/components/checkbox/checkbox.styles.d.ts +1 -0
  36. package/dist/components/checkbox/checkbox.styles.js +70 -0
  37. package/dist/components/chip/chip-group.d.ts +56 -0
  38. package/dist/components/chip/chip-group.js +124 -0
  39. package/dist/components/chip/chip-group.styles.d.ts +1 -0
  40. package/dist/components/chip/chip-group.styles.js +57 -0
  41. package/dist/components/chip/chip.d.ts +64 -0
  42. package/dist/components/chip/chip.js +115 -0
  43. package/dist/components/chip/chip.styles.d.ts +1 -0
  44. package/dist/components/chip/chip.styles.js +115 -0
  45. package/dist/components/citation-badge/citation-badge.d.ts +113 -0
  46. package/dist/components/citation-badge/citation-badge.js +300 -0
  47. package/dist/components/citation-badge/citation-badge.styles.d.ts +1 -0
  48. package/dist/components/citation-badge/citation-badge.styles.js +96 -0
  49. package/dist/components/code-block/code-block.d.ts +89 -0
  50. package/dist/components/code-block/code-block.js +317 -0
  51. package/dist/components/code-block/code-block.styles.d.ts +1 -0
  52. package/dist/components/code-block/code-block.styles.js +187 -0
  53. package/dist/components/code-block/code-loader.d.ts +44 -0
  54. package/dist/components/code-block/code-loader.js +79 -0
  55. package/dist/components/combobox/combobox.d.ts +19 -1
  56. package/dist/components/combobox/combobox.js +84 -14
  57. package/dist/components/combobox/option.d.ts +5 -1
  58. package/dist/components/combobox/option.js +35 -0
  59. package/dist/components/context-meter/context-meter.d.ts +53 -0
  60. package/dist/components/context-meter/context-meter.js +150 -0
  61. package/dist/components/context-meter/context-meter.styles.d.ts +1 -0
  62. package/dist/components/context-meter/context-meter.styles.js +120 -0
  63. package/dist/components/conversation-item/conversation-item.d.ts +128 -0
  64. package/dist/components/conversation-item/conversation-item.js +322 -0
  65. package/dist/components/conversation-item/conversation-item.styles.d.ts +1 -0
  66. package/dist/components/conversation-item/conversation-item.styles.js +155 -0
  67. package/dist/components/date-picker/date-input.d.ts +24 -0
  68. package/dist/components/date-picker/date-input.js +134 -22
  69. package/dist/components/date-picker/date-picker.d.ts +7 -0
  70. package/dist/components/date-picker/date-picker.js +85 -16
  71. package/dist/components/dialog/confirm.d.ts +40 -0
  72. package/dist/components/dialog/confirm.js +79 -0
  73. package/dist/components/dialog/dialog.d.ts +85 -0
  74. package/dist/components/dialog/dialog.js +272 -0
  75. package/dist/components/dialog/dialog.styles.d.ts +1 -0
  76. package/dist/components/dialog/dialog.styles.js +52 -0
  77. package/dist/components/dock-panel/dock-panel.d.ts +134 -0
  78. package/dist/components/dock-panel/dock-panel.js +345 -0
  79. package/dist/components/dock-panel/dock-panel.styles.d.ts +1 -0
  80. package/dist/components/dock-panel/dock-panel.styles.js +145 -0
  81. package/dist/components/document-preview/document-preview.d.ts +135 -0
  82. package/dist/components/document-preview/document-preview.js +372 -0
  83. package/dist/components/document-preview/document-preview.styles.d.ts +1 -0
  84. package/dist/components/document-preview/document-preview.styles.js +191 -0
  85. package/dist/components/export-button/csv.js +1 -1
  86. package/dist/components/export-button/export-button.js +2 -0
  87. package/dist/components/flag/flag.d.ts +42 -5
  88. package/dist/components/flag/flag.js +70 -3
  89. package/dist/components/gauge/gauge.js +19 -10
  90. package/dist/components/generation-status/generation-status.d.ts +109 -0
  91. package/dist/components/generation-status/generation-status.js +273 -0
  92. package/dist/components/generation-status/generation-status.styles.d.ts +1 -0
  93. package/dist/components/generation-status/generation-status.styles.js +84 -0
  94. package/dist/components/heatmap/calendar-grid.d.ts +4 -1
  95. package/dist/components/heatmap/calendar-grid.js +25 -12
  96. package/dist/components/heatmap/heatmap-scale.d.ts +6 -0
  97. package/dist/components/heatmap/heatmap-scale.js +7 -1
  98. package/dist/components/heatmap/heatmap.d.ts +89 -3
  99. package/dist/components/heatmap/heatmap.js +158 -29
  100. package/dist/components/json-viewer/json-viewer.d.ts +53 -0
  101. package/dist/components/json-viewer/json-viewer.js +283 -0
  102. package/dist/components/json-viewer/json-viewer.styles.d.ts +1 -0
  103. package/dist/components/json-viewer/json-viewer.styles.js +176 -0
  104. package/dist/components/kbd/kbd.d.ts +77 -0
  105. package/dist/components/kbd/kbd.js +214 -0
  106. package/dist/components/kbd/kbd.styles.d.ts +1 -0
  107. package/dist/components/kbd/kbd.styles.js +52 -0
  108. package/dist/components/live-region/live-region.d.ts +81 -0
  109. package/dist/components/live-region/live-region.js +153 -0
  110. package/dist/components/live-region/live-region.styles.d.ts +1 -0
  111. package/dist/components/live-region/live-region.styles.js +10 -0
  112. package/dist/components/map/map.d.ts +8 -6
  113. package/dist/components/map/map.js +44 -8
  114. package/dist/components/markdown/markdown-loader.d.ts +34 -0
  115. package/dist/components/markdown/markdown-loader.js +43 -0
  116. package/dist/components/markdown/markdown.d.ts +81 -0
  117. package/dist/components/markdown/markdown.js +284 -0
  118. package/dist/components/markdown/markdown.styles.d.ts +1 -0
  119. package/dist/components/markdown/markdown.styles.js +82 -0
  120. package/dist/components/media-card/media-card.d.ts +122 -0
  121. package/dist/components/media-card/media-card.js +295 -0
  122. package/dist/components/media-card/media-card.styles.d.ts +1 -0
  123. package/dist/components/media-card/media-card.styles.js +132 -0
  124. package/dist/components/mention-popover/mention-popover.d.ts +200 -0
  125. package/dist/components/mention-popover/mention-popover.js +475 -0
  126. package/dist/components/mention-popover/mention-popover.styles.d.ts +1 -0
  127. package/dist/components/mention-popover/mention-popover.styles.js +101 -0
  128. package/dist/components/menu/menu-item.d.ts +62 -0
  129. package/dist/components/menu/menu-item.js +119 -0
  130. package/dist/components/menu/menu-item.styles.d.ts +1 -0
  131. package/dist/components/menu/menu-item.styles.js +67 -0
  132. package/dist/components/menu/menu.d.ts +143 -0
  133. package/dist/components/menu/menu.js +365 -0
  134. package/dist/components/menu/menu.styles.d.ts +1 -0
  135. package/dist/components/menu/menu.styles.js +66 -0
  136. package/dist/components/model-select/model-select.d.ts +125 -0
  137. package/dist/components/model-select/model-select.js +490 -0
  138. package/dist/components/model-select/model-select.styles.d.ts +1 -0
  139. package/dist/components/model-select/model-select.styles.js +189 -0
  140. package/dist/components/model-settings-panel/model-settings-panel.d.ts +69 -0
  141. package/dist/components/model-settings-panel/model-settings-panel.js +145 -0
  142. package/dist/components/model-settings-panel/model-settings-panel.styles.d.ts +1 -0
  143. package/dist/components/model-settings-panel/model-settings-panel.styles.js +82 -0
  144. package/dist/components/playback/playback.d.ts +13 -1
  145. package/dist/components/playback/playback.js +47 -14
  146. package/dist/components/responsive-panel/responsive-panel.d.ts +150 -0
  147. package/dist/components/responsive-panel/responsive-panel.js +365 -0
  148. package/dist/components/responsive-panel/responsive-panel.styles.d.ts +1 -0
  149. package/dist/components/responsive-panel/responsive-panel.styles.js +103 -0
  150. package/dist/components/result-card/result-card.d.ts +44 -0
  151. package/dist/components/result-card/result-card.js +83 -0
  152. package/dist/components/result-card/result-card.styles.d.ts +1 -0
  153. package/dist/components/result-card/result-card.styles.js +50 -0
  154. package/dist/components/result-card/result-field.d.ts +36 -0
  155. package/dist/components/result-card/result-field.js +87 -0
  156. package/dist/components/result-card/result-field.styles.d.ts +1 -0
  157. package/dist/components/result-card/result-field.styles.js +32 -0
  158. package/dist/components/select/select.d.ts +45 -1
  159. package/dist/components/select/select.js +114 -17
  160. package/dist/components/select/select.styles.js +26 -2
  161. package/dist/components/slider/slider.d.ts +89 -0
  162. package/dist/components/slider/slider.js +352 -0
  163. package/dist/components/slider/slider.styles.d.ts +1 -0
  164. package/dist/components/slider/slider.styles.js +87 -0
  165. package/dist/components/source-card/source-card.d.ts +92 -0
  166. package/dist/components/source-card/source-card.js +148 -0
  167. package/dist/components/source-card/source-card.styles.d.ts +1 -0
  168. package/dist/components/source-card/source-card.styles.js +69 -0
  169. package/dist/components/source-list/source-list.d.ts +63 -0
  170. package/dist/components/source-list/source-list.js +122 -0
  171. package/dist/components/source-list/source-list.styles.d.ts +1 -0
  172. package/dist/components/source-list/source-list.styles.js +59 -0
  173. package/dist/components/sparkline/sparkline.js +27 -13
  174. package/dist/components/split/split.d.ts +93 -1
  175. package/dist/components/split/split.js +284 -15
  176. package/dist/components/split/split.styles.js +30 -0
  177. package/dist/components/stat/stat.d.ts +22 -1
  178. package/dist/components/stat/stat.js +49 -3
  179. package/dist/components/stat/stat.styles.js +20 -0
  180. package/dist/components/stream-status/stream-status.d.ts +110 -0
  181. package/dist/components/stream-status/stream-status.js +210 -0
  182. package/dist/components/stream-status/stream-status.styles.d.ts +1 -0
  183. package/dist/components/stream-status/stream-status.styles.js +103 -0
  184. package/dist/components/streaming-text/streaming-text.d.ts +98 -0
  185. package/dist/components/streaming-text/streaming-text.js +209 -0
  186. package/dist/components/streaming-text/streaming-text.styles.d.ts +1 -0
  187. package/dist/components/streaming-text/streaming-text.styles.js +62 -0
  188. package/dist/components/switch/switch.d.ts +58 -0
  189. package/dist/components/switch/switch.js +179 -0
  190. package/dist/components/switch/switch.styles.d.ts +1 -0
  191. package/dist/components/switch/switch.styles.js +75 -0
  192. package/dist/components/table/table.d.ts +73 -4
  193. package/dist/components/table/table.js +169 -20
  194. package/dist/components/table/table.styles.js +6 -1
  195. package/dist/components/tabs/tabs.d.ts +51 -0
  196. package/dist/components/tabs/tabs.js +190 -0
  197. package/dist/components/tabs/tabs.styles.d.ts +1 -0
  198. package/dist/components/tabs/tabs.styles.js +63 -0
  199. package/dist/components/thinking-panel/thinking-panel.d.ts +121 -0
  200. package/dist/components/thinking-panel/thinking-panel.js +235 -0
  201. package/dist/components/thinking-panel/thinking-panel.styles.d.ts +1 -0
  202. package/dist/components/thinking-panel/thinking-panel.styles.js +117 -0
  203. package/dist/components/toast/toast-item.d.ts +1 -0
  204. package/dist/components/toast/toast-item.js +31 -6
  205. package/dist/components/tool-approval-dialog/tool-approval-dialog.d.ts +130 -0
  206. package/dist/components/tool-approval-dialog/tool-approval-dialog.js +403 -0
  207. package/dist/components/tool-approval-dialog/tool-approval-dialog.styles.d.ts +1 -0
  208. package/dist/components/tool-approval-dialog/tool-approval-dialog.styles.js +160 -0
  209. package/dist/components/tool-call-chip/tool-call-chip.d.ts +89 -0
  210. package/dist/components/tool-call-chip/tool-call-chip.js +288 -0
  211. package/dist/components/tool-call-chip/tool-call-chip.styles.d.ts +1 -0
  212. package/dist/components/tool-call-chip/tool-call-chip.styles.js +203 -0
  213. package/dist/components/tool-param-form/tool-param-form.d.ts +145 -0
  214. package/dist/components/tool-param-form/tool-param-form.js +366 -0
  215. package/dist/components/tool-param-form/tool-param-form.styles.d.ts +1 -0
  216. package/dist/components/tool-param-form/tool-param-form.styles.js +75 -0
  217. package/dist/components/tool-result-dialog/tool-result-dialog.d.ts +102 -0
  218. package/dist/components/tool-result-dialog/tool-result-dialog.js +393 -0
  219. package/dist/components/tool-result-dialog/tool-result-dialog.styles.d.ts +1 -0
  220. package/dist/components/tool-result-dialog/tool-result-dialog.styles.js +176 -0
  221. package/dist/components/tool-result-view/registry.d.ts +81 -0
  222. package/dist/components/tool-result-view/registry.js +84 -0
  223. package/dist/components/tool-result-view/tool-result-view.d.ts +55 -0
  224. package/dist/components/tool-result-view/tool-result-view.js +138 -0
  225. package/dist/components/tool-result-view/tool-result-view.styles.d.ts +1 -0
  226. package/dist/components/tool-result-view/tool-result-view.styles.js +13 -0
  227. package/dist/components/tool-select-dialog/tool-select-dialog.d.ts +151 -0
  228. package/dist/components/tool-select-dialog/tool-select-dialog.js +439 -0
  229. package/dist/components/tool-select-dialog/tool-select-dialog.styles.d.ts +1 -0
  230. package/dist/components/tool-select-dialog/tool-select-dialog.styles.js +182 -0
  231. package/dist/components/tree/tree-node.d.ts +11 -2
  232. package/dist/components/tree/tree-node.js +16 -6
  233. package/dist/components/tree/tree.d.ts +8 -2
  234. package/dist/components/tree/tree.js +18 -11
  235. package/dist/components/typing-indicator/typing-indicator.d.ts +60 -0
  236. package/dist/components/typing-indicator/typing-indicator.js +96 -0
  237. package/dist/components/typing-indicator/typing-indicator.styles.d.ts +1 -0
  238. package/dist/components/typing-indicator/typing-indicator.styles.js +132 -0
  239. package/dist/components/virtual-list/virtual-list.d.ts +173 -0
  240. package/dist/components/virtual-list/virtual-list.js +461 -0
  241. package/dist/components/virtual-list/virtual-list.styles.d.ts +1 -0
  242. package/dist/components/virtual-list/virtual-list.styles.js +44 -0
  243. package/dist/components/widget/widget.d.ts +10 -0
  244. package/dist/components/widget/widget.js +24 -1
  245. package/dist/components/widget/widget.styles.js +9 -2
  246. package/dist/components/word-cloud/word-cloud-layout.js +14 -1
  247. package/dist/components/word-cloud/word-cloud.d.ts +6 -0
  248. package/dist/components/word-cloud/word-cloud.js +25 -14
  249. package/dist/components/word-cloud/word-cloud.styles.js +4 -2
  250. package/dist/internal/announcer.d.ts +57 -0
  251. package/dist/internal/announcer.js +71 -0
  252. package/dist/internal/form-associated.d.ts +1 -0
  253. package/dist/internal/form-associated.js +55 -11
  254. package/dist/internal/group-by-recency.d.ts +50 -0
  255. package/dist/internal/group-by-recency.js +80 -0
  256. package/dist/internal/rtl.d.ts +23 -0
  257. package/dist/internal/rtl.js +28 -0
  258. package/dist/internal/scroll-lock.d.ts +10 -5
  259. package/dist/internal/scroll-lock.js +30 -14
  260. package/dist/internal/tokens.styles.js +6 -0
  261. package/dist/lyra.d.ts +130 -31
  262. package/dist/lyra.js +94 -26
  263. package/llms-full.txt +3921 -32
  264. package/llms.txt +16 -1
  265. package/package.json +23 -5
  266. package/dist/components/chart/bar-chart.stories.d.ts +0 -5
  267. package/dist/components/chart/bar-chart.stories.js +0 -20
  268. package/dist/components/chart/box-plot.stories.d.ts +0 -5
  269. package/dist/components/chart/box-plot.stories.js +0 -29
  270. package/dist/components/chart/bubble-chart.stories.d.ts +0 -5
  271. package/dist/components/chart/bubble-chart.stories.js +0 -26
  272. package/dist/components/chart/chart.stories.d.ts +0 -32
  273. package/dist/components/chart/chart.stories.js +0 -141
  274. package/dist/components/chart/doughnut-chart.stories.d.ts +0 -5
  275. package/dist/components/chart/doughnut-chart.stories.js +0 -26
  276. package/dist/components/chart/histogram.stories.d.ts +0 -5
  277. package/dist/components/chart/histogram.stories.js +0 -17
  278. package/dist/components/chart/line-chart.stories.d.ts +0 -22
  279. package/dist/components/chart/line-chart.stories.js +0 -99
  280. package/dist/components/chart/lite-chart.stories.d.ts +0 -12
  281. package/dist/components/chart/lite-chart.stories.js +0 -98
  282. package/dist/components/chart/pie-chart.stories.d.ts +0 -5
  283. package/dist/components/chart/pie-chart.stories.js +0 -26
  284. package/dist/components/chart/polar-area-chart.stories.d.ts +0 -5
  285. package/dist/components/chart/polar-area-chart.stories.js +0 -20
  286. package/dist/components/chart/radar-chart.stories.d.ts +0 -5
  287. package/dist/components/chart/radar-chart.stories.js +0 -20
  288. package/dist/components/chart/scatter-chart.stories.d.ts +0 -5
  289. package/dist/components/chart/scatter-chart.stories.js +0 -31
  290. package/dist/components/combobox/combobox.stories.d.ts +0 -24
  291. package/dist/components/combobox/combobox.stories.js +0 -102
  292. package/dist/components/date-picker/date-input.stories.d.ts +0 -10
  293. package/dist/components/date-picker/date-input.stories.js +0 -48
  294. package/dist/components/date-picker/date-picker.stories.d.ts +0 -10
  295. package/dist/components/date-picker/date-picker.stories.js +0 -25
  296. package/dist/components/empty/empty.stories.d.ts +0 -7
  297. package/dist/components/empty/empty.stories.js +0 -34
  298. package/dist/components/export-button/export-button.stories.d.ts +0 -7
  299. package/dist/components/export-button/export-button.stories.js +0 -37
  300. package/dist/components/file-input/file-input.stories.d.ts +0 -7
  301. package/dist/components/file-input/file-input.stories.js +0 -19
  302. package/dist/components/flag/flag.stories.d.ts +0 -5
  303. package/dist/components/flag/flag.stories.js +0 -17
  304. package/dist/components/gauge/gauge.stories.d.ts +0 -8
  305. package/dist/components/gauge/gauge.stories.js +0 -19
  306. package/dist/components/graph/graph.stories.d.ts +0 -8
  307. package/dist/components/graph/graph.stories.js +0 -68
  308. package/dist/components/heatmap/heatmap.stories.d.ts +0 -22
  309. package/dist/components/heatmap/heatmap.stories.js +0 -154
  310. package/dist/components/map/map.stories.d.ts +0 -15
  311. package/dist/components/map/map.stories.js +0 -135
  312. package/dist/components/playback/playback.stories.d.ts +0 -7
  313. package/dist/components/playback/playback.stories.js +0 -16
  314. package/dist/components/select/select.stories.d.ts +0 -19
  315. package/dist/components/select/select.stories.js +0 -75
  316. package/dist/components/skeleton/skeleton.stories.d.ts +0 -5
  317. package/dist/components/skeleton/skeleton.stories.js +0 -16
  318. package/dist/components/sparkline/sparkline.stories.d.ts +0 -11
  319. package/dist/components/sparkline/sparkline.stories.js +0 -39
  320. package/dist/components/split/split.stories.d.ts +0 -7
  321. package/dist/components/split/split.stories.js +0 -36
  322. package/dist/components/stat/stat.stories.d.ts +0 -8
  323. package/dist/components/stat/stat.stories.js +0 -64
  324. package/dist/components/table/table.stories.d.ts +0 -12
  325. package/dist/components/table/table.stories.js +0 -67
  326. package/dist/components/time-range/time-range.stories.d.ts +0 -8
  327. package/dist/components/time-range/time-range.stories.js +0 -26
  328. package/dist/components/toast/toast.stories.d.ts +0 -8
  329. package/dist/components/toast/toast.stories.js +0 -72
  330. package/dist/components/tree/tree.stories.d.ts +0 -9
  331. package/dist/components/tree/tree.stories.js +0 -52
  332. package/dist/components/widget/widget.stories.d.ts +0 -7
  333. package/dist/components/widget/widget.stories.js +0 -41
  334. package/dist/components/word-cloud/word-cloud.stories.d.ts +0 -10
  335. package/dist/components/word-cloud/word-cloud.stories.js +0 -55
@@ -0,0 +1,184 @@
1
+ import { css } from 'lit';
2
+ export const styles = css `
3
+ :host {
4
+ display: inline-flex;
5
+ max-inline-size: 100%;
6
+ /* Per-status accent -- one custom property swapped by the :host([status])
7
+ rules below rather than repeating background/border per part per
8
+ status. Mirrors lyra-tool-call-chip's identical
9
+ --lyra-tool-call-chip-accent/-bg/-border trio, so a chip's tone
10
+ vocabulary reads the same everywhere in the library. Defaults to the
11
+ 'pending' tone so an unset/unknown status still reads as neutral
12
+ instead of unstyled. */
13
+ --lyra-attachment-chip-accent: var(--lyra-color-text-quiet);
14
+ --lyra-attachment-chip-bg: var(--lyra-color-surface);
15
+ --lyra-attachment-chip-border: var(--lyra-color-border);
16
+ }
17
+
18
+ :host([status='uploading']) {
19
+ --lyra-attachment-chip-accent: var(--lyra-color-brand);
20
+ --lyra-attachment-chip-bg: var(--lyra-color-brand-quiet);
21
+ --lyra-attachment-chip-border: transparent;
22
+ }
23
+ :host([status='error']) {
24
+ --lyra-attachment-chip-accent: var(--lyra-color-danger);
25
+ --lyra-attachment-chip-bg: var(--lyra-color-danger-quiet);
26
+ --lyra-attachment-chip-border: transparent;
27
+ }
28
+ /* Optional neutral-positive tint for a finished upload -- subtler than
29
+ 'uploading'/'error' since there's nothing left for the user to act on. */
30
+ :host([status='done']) {
31
+ --lyra-attachment-chip-accent: var(--lyra-color-success);
32
+ --lyra-attachment-chip-bg: var(--lyra-color-success-quiet);
33
+ --lyra-attachment-chip-border: transparent;
34
+ }
35
+
36
+ [part='base'] {
37
+ display: flex;
38
+ align-items: center;
39
+ gap: var(--lyra-space-s);
40
+ max-inline-size: 100%;
41
+ box-sizing: border-box;
42
+ padding: var(--lyra-space-xs) var(--lyra-space-s);
43
+ border: 1px solid var(--lyra-attachment-chip-border);
44
+ border-radius: var(--lyra-radius);
45
+ background: var(--lyra-attachment-chip-bg);
46
+ color: var(--lyra-color-text);
47
+ font-size: 0.8125rem;
48
+ line-height: 1.3;
49
+ transition:
50
+ background-color var(--lyra-transition-fast),
51
+ border-color var(--lyra-transition-fast);
52
+ }
53
+
54
+ [part='thumbnail'] {
55
+ display: inline-flex;
56
+ flex: 0 0 auto;
57
+ align-items: center;
58
+ justify-content: center;
59
+ /* Reuses the shared icon-button box size as a ready-made "small square
60
+ glyph/image slot" token rather than inventing a new one-off dimension. */
61
+ inline-size: var(--lyra-icon-button-size);
62
+ block-size: var(--lyra-icon-button-size);
63
+ overflow: hidden;
64
+ border-radius: calc(var(--lyra-radius) * 0.6);
65
+ background: var(--lyra-color-surface);
66
+ color: var(--lyra-attachment-chip-accent);
67
+ }
68
+ [part='thumbnail'] img {
69
+ inline-size: 100%;
70
+ block-size: 100%;
71
+ object-fit: cover;
72
+ display: block;
73
+ }
74
+ [part='thumbnail'] svg {
75
+ display: block;
76
+ }
77
+
78
+ [part='meta'] {
79
+ display: flex;
80
+ flex-direction: column;
81
+ flex: 1 1 auto;
82
+ min-inline-size: 0;
83
+ gap: 0.125rem;
84
+ }
85
+ [part='name'] {
86
+ overflow: hidden;
87
+ text-overflow: ellipsis;
88
+ white-space: nowrap;
89
+ font-weight: 600;
90
+ color: var(--lyra-color-text);
91
+ }
92
+ [part='size'] {
93
+ /* Full-strength text, not --lyra-color-text-quiet -- this sits on top of
94
+ the per-status *-quiet tint backgrounds above (e.g. danger-quiet), and
95
+ text-quiet's gray fails WCAG AA contrast against several of those
96
+ tints even though it comfortably passes against the plain surface
97
+ background used by the resting state. Same fix, same rationale, as
98
+ lyra-tool-call-chip's identical [part='duration']/[part='category']. */
99
+ color: var(--lyra-color-text);
100
+ font-variant-numeric: tabular-nums;
101
+ }
102
+ [part='status-text'] {
103
+ color: var(--lyra-attachment-chip-accent);
104
+ font-weight: 600;
105
+ }
106
+
107
+ [part='progress'] {
108
+ flex: 0 0 auto;
109
+ inline-size: 3.5rem;
110
+ block-size: var(--lyra-space-xs);
111
+ border-radius: 999px;
112
+ background: var(--lyra-color-border);
113
+ overflow: hidden;
114
+ }
115
+ [part='progress-fill'] {
116
+ block-size: 100%;
117
+ border-radius: inherit;
118
+ background: var(--lyra-attachment-chip-accent);
119
+ transition: inline-size var(--lyra-transition-base);
120
+ }
121
+
122
+ [part='spinner'] {
123
+ flex: 0 0 auto;
124
+ display: inline-block;
125
+ inline-size: 1rem;
126
+ block-size: 1rem;
127
+ border-radius: 50%;
128
+ border: 2px solid var(--lyra-color-border);
129
+ border-block-start-color: var(--lyra-attachment-chip-accent);
130
+ animation: lyra-attachment-chip-spin 0.8s linear infinite;
131
+ }
132
+
133
+ [part='retry-button'],
134
+ [part='remove-button'] {
135
+ flex: 0 0 auto;
136
+ display: inline-flex;
137
+ align-items: center;
138
+ justify-content: center;
139
+ min-inline-size: min(var(--lyra-icon-button-size), 1.75rem);
140
+ min-block-size: min(var(--lyra-icon-button-size), 1.75rem);
141
+ padding: 0;
142
+ border: none;
143
+ border-radius: calc(var(--lyra-radius) * 0.6);
144
+ background: transparent;
145
+ color: var(--lyra-color-text-quiet);
146
+ font: inherit;
147
+ cursor: pointer;
148
+ -webkit-tap-highlight-color: transparent;
149
+ transition: background-color var(--lyra-transition-fast);
150
+ }
151
+ [part='retry-button'] {
152
+ color: var(--lyra-color-danger);
153
+ }
154
+ [part='retry-button']:hover,
155
+ [part='remove-button']:hover {
156
+ background: color-mix(in srgb, var(--lyra-color-text) 8%, transparent);
157
+ }
158
+ [part='retry-button']:focus-visible,
159
+ [part='remove-button']:focus-visible {
160
+ outline: var(--lyra-focus-ring-width) solid var(--lyra-focus-ring-color);
161
+ outline-offset: var(--lyra-focus-ring-offset);
162
+ }
163
+ [part='retry-button'] svg,
164
+ [part='remove-button'] svg {
165
+ display: block;
166
+ }
167
+
168
+ @keyframes lyra-attachment-chip-spin {
169
+ to {
170
+ transform: rotate(360deg);
171
+ }
172
+ }
173
+ @media (prefers-reduced-motion: reduce) {
174
+ [part='base'] {
175
+ transition: none !important;
176
+ }
177
+ [part='progress-fill'] {
178
+ transition: none !important;
179
+ }
180
+ [part='spinner'] {
181
+ animation: none !important;
182
+ }
183
+ }
184
+ `;
@@ -0,0 +1,83 @@
1
+ import { type TemplateResult } from 'lit';
2
+ import { LyraElement } from '../../internal/lyra-element.js';
3
+ import '../menu/menu.js';
4
+ import '../menu/menu-item.js';
5
+ export type AttachmentCapability = 'files' | 'image' | 'camera';
6
+ /** The two capabilities that resolve to a real file selection (as opposed
7
+ * to `camera`, which never touches a file input -- see the class doc). */
8
+ export type FileBackedCapability = Exclude<AttachmentCapability, 'camera'>;
9
+ export interface AttachmentPickDetail {
10
+ capability: FileBackedCapability;
11
+ files: FileList;
12
+ }
13
+ /**
14
+ * `<lyra-attachment-trigger>` — a compact attach affordance designed for a
15
+ * chat composer's leading slot (see `<lyra-chat-composer>`'s own `leading`
16
+ * slot, which this drops straight into, though this component has no code
17
+ * dependency on it). Its shape adapts to how many attachment `capabilities`
18
+ * are configured:
19
+ * - Exactly one capability: a single plain icon button ([part='trigger']).
20
+ * Activating it performs that capability's action directly.
21
+ * - More than one: a small anchored menu ([part='menu'], composed from
22
+ * `<lyra-menu>`/`<lyra-menu-item>`) listing each capability as a row.
23
+ *
24
+ * Two of the three capabilities (`files`, `image`) are file-picker-backed:
25
+ * activating them opens a hidden native `<input type="file">` via a
26
+ * synthetic `.click()`, and the resulting selection is re-emitted as
27
+ * `lyra-pick`. `accept` is shared across both — `image` defaults it to
28
+ * `'image/*'` unless the `accept` prop overrides it, `files` always uses
29
+ * `accept` as-is (empty means "any file type", matching a bare native
30
+ * `<input type="file">` with no `accept` attribute).
31
+ *
32
+ * **`camera` is scope-limited by design.** This component does not
33
+ * implement any camera capture UI itself — no `getUserMedia`, no
34
+ * `<input capture>` — because that's entirely a host/browser concern with
35
+ * no single right answer (a desktop web app, a mobile PWA, and a native
36
+ * wrapper all want different things here). Activating the `camera`
37
+ * capability only fires `lyra-camera-request`; the host owns everything
38
+ * from that point on (opening its own capture UI, then presumably handing
39
+ * the resulting `File` back to something like `<lyra-attachment-chip>`).
40
+ *
41
+ * @customElement lyra-attachment-trigger
42
+ * @event lyra-pick - A file-backed capability's hidden file input produced a
43
+ * real selection. `detail: { capability: 'files' | 'image', files }` — a
44
+ * real `FileList` (not a plain array), matching the native input's own
45
+ * `.files` shape, but an independent snapshot rather than that same live
46
+ * object — see `onInputChange`'s own doc for why a live reference would be
47
+ * unsafe to hand out here.
48
+ * @event lyra-camera-request - The `camera` capability was activated. No
49
+ * detail payload — see the class doc's scope note; the host implements the
50
+ * actual capture flow.
51
+ * @csspart trigger - The single-capability icon button. Only rendered when `capabilities.length === 1`.
52
+ * @csspart menu - The `<lyra-menu>` wrapper. Only rendered when `capabilities.length > 1`.
53
+ */
54
+ export declare class LyraAttachmentTrigger extends LyraElement {
55
+ static styles: import("lit").CSSResultGroup[];
56
+ /** Which attachment capabilities to offer, in display order. A single
57
+ * entry renders a plain button; more than one renders a menu. */
58
+ capabilities: AttachmentCapability[];
59
+ /** Native-file-input-style accept string (e.g. `'image/*'` or
60
+ * `'.pdf,.docx'`), forwarded to the hidden file input for the
61
+ * `files`/`image` capabilities — see the class doc for how each uses it. */
62
+ accept: string;
63
+ /** Forwarded to the hidden file input's own `multiple` attribute. */
64
+ multiple: boolean;
65
+ disabled: boolean;
66
+ private inputEl?;
67
+ private pendingCapability;
68
+ private get hasFileCapability();
69
+ private effectiveAccept;
70
+ private activateCapability;
71
+ private onTriggerClick;
72
+ private onMenuSelect;
73
+ private onInputChange;
74
+ private renderHiddenInput;
75
+ private renderSingleTrigger;
76
+ private renderMenu;
77
+ render(): TemplateResult;
78
+ }
79
+ declare global {
80
+ interface HTMLElementTagNameMap {
81
+ 'lyra-attachment-trigger': LyraAttachmentTrigger;
82
+ }
83
+ }
@@ -0,0 +1,258 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ import { html, nothing, svg } from 'lit';
8
+ import { property, query } from 'lit/decorators.js';
9
+ import { LyraElement } from '../../internal/lyra-element.js';
10
+ import { defineElement } from '../../internal/prefix.js';
11
+ import { styles } from './attachment-trigger.styles.js';
12
+ import '../menu/menu.js';
13
+ import '../menu/menu-item.js';
14
+ // Mirrors the shared icon set's viewBox/stroke conventions
15
+ // (internal/icons.ts's chevronIcon()/closeIcon()/etc.) without adding these
16
+ // one-off glyphs to that module -- it's off limits here -- so they still
17
+ // read as part of the same visual language as the rest of the library's
18
+ // inline icons. Same approach as lyra-attachment-chip's local fileGlyph()/
19
+ // retryIcon() and lyra-checkbox's local checkmarkGlyph().
20
+ const ICON_VIEW_BOX = '0 0 24 24';
21
+ const ICON_STROKE_WIDTH = '1.75';
22
+ function icon(paths) {
23
+ return svg `
24
+ <svg
25
+ width="1em"
26
+ height="1em"
27
+ viewBox=${ICON_VIEW_BOX}
28
+ fill="none"
29
+ stroke="currentColor"
30
+ stroke-width=${ICON_STROKE_WIDTH}
31
+ stroke-linecap="round"
32
+ stroke-linejoin="round"
33
+ aria-hidden="true"
34
+ focusable="false"
35
+ >${paths}</svg>
36
+ `;
37
+ }
38
+ /** A paperclip glyph -- the generic "attach" affordance, used for the
39
+ * `files` capability and as the multi-capability menu's own trigger icon
40
+ * (the one glyph a user recognizes regardless of which capabilities the
41
+ * menu underneath actually offers). */
42
+ function paperclipIcon() {
43
+ return icon(svg `
44
+ <path d="M21.44 11.05 12.25 20.24a5.5 5.5 0 0 1-7.78-7.78l9.19-9.19a3.5 3.5 0 0 1 4.95 4.95l-9.2 9.19a1.5 1.5 0 0 1-2.12-2.12l8.49-8.48"></path>
45
+ `);
46
+ }
47
+ /** A picture-frame glyph for the `image` capability. */
48
+ function imageIcon() {
49
+ return icon(svg `
50
+ <rect x="3" y="3" width="18" height="18" rx="2"></rect>
51
+ <circle cx="8.5" cy="8.5" r="1.5"></circle>
52
+ <polyline points="21 15 16 10 5 21"></polyline>
53
+ `);
54
+ }
55
+ /** A camera-body glyph for the `camera` capability. */
56
+ function cameraIcon() {
57
+ return icon(svg `
58
+ <path d="M23 19a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h4l2-3h6l2 3h4a2 2 0 0 1 2 2Z"></path>
59
+ <circle cx="12" cy="13" r="4"></circle>
60
+ `);
61
+ }
62
+ const CAPABILITY_META = {
63
+ files: { icon: paperclipIcon, triggerLabel: 'Attach files', menuLabel: 'Upload files' },
64
+ image: { icon: imageIcon, triggerLabel: 'Attach an image', menuLabel: 'Upload a photo' },
65
+ camera: { icon: cameraIcon, triggerLabel: 'Use camera', menuLabel: 'Take a photo' },
66
+ };
67
+ /**
68
+ * `<lyra-attachment-trigger>` — a compact attach affordance designed for a
69
+ * chat composer's leading slot (see `<lyra-chat-composer>`'s own `leading`
70
+ * slot, which this drops straight into, though this component has no code
71
+ * dependency on it). Its shape adapts to how many attachment `capabilities`
72
+ * are configured:
73
+ * - Exactly one capability: a single plain icon button ([part='trigger']).
74
+ * Activating it performs that capability's action directly.
75
+ * - More than one: a small anchored menu ([part='menu'], composed from
76
+ * `<lyra-menu>`/`<lyra-menu-item>`) listing each capability as a row.
77
+ *
78
+ * Two of the three capabilities (`files`, `image`) are file-picker-backed:
79
+ * activating them opens a hidden native `<input type="file">` via a
80
+ * synthetic `.click()`, and the resulting selection is re-emitted as
81
+ * `lyra-pick`. `accept` is shared across both — `image` defaults it to
82
+ * `'image/*'` unless the `accept` prop overrides it, `files` always uses
83
+ * `accept` as-is (empty means "any file type", matching a bare native
84
+ * `<input type="file">` with no `accept` attribute).
85
+ *
86
+ * **`camera` is scope-limited by design.** This component does not
87
+ * implement any camera capture UI itself — no `getUserMedia`, no
88
+ * `<input capture>` — because that's entirely a host/browser concern with
89
+ * no single right answer (a desktop web app, a mobile PWA, and a native
90
+ * wrapper all want different things here). Activating the `camera`
91
+ * capability only fires `lyra-camera-request`; the host owns everything
92
+ * from that point on (opening its own capture UI, then presumably handing
93
+ * the resulting `File` back to something like `<lyra-attachment-chip>`).
94
+ *
95
+ * @customElement lyra-attachment-trigger
96
+ * @event lyra-pick - A file-backed capability's hidden file input produced a
97
+ * real selection. `detail: { capability: 'files' | 'image', files }` — a
98
+ * real `FileList` (not a plain array), matching the native input's own
99
+ * `.files` shape, but an independent snapshot rather than that same live
100
+ * object — see `onInputChange`'s own doc for why a live reference would be
101
+ * unsafe to hand out here.
102
+ * @event lyra-camera-request - The `camera` capability was activated. No
103
+ * detail payload — see the class doc's scope note; the host implements the
104
+ * actual capture flow.
105
+ * @csspart trigger - The single-capability icon button. Only rendered when `capabilities.length === 1`.
106
+ * @csspart menu - The `<lyra-menu>` wrapper. Only rendered when `capabilities.length > 1`.
107
+ */
108
+ export class LyraAttachmentTrigger extends LyraElement {
109
+ constructor() {
110
+ super(...arguments);
111
+ /** Which attachment capabilities to offer, in display order. A single
112
+ * entry renders a plain button; more than one renders a menu. */
113
+ this.capabilities = ['files'];
114
+ /** Native-file-input-style accept string (e.g. `'image/*'` or
115
+ * `'.pdf,.docx'`), forwarded to the hidden file input for the
116
+ * `files`/`image` capabilities — see the class doc for how each uses it. */
117
+ this.accept = '';
118
+ /** Forwarded to the hidden file input's own `multiple` attribute. */
119
+ this.multiple = true;
120
+ this.disabled = false;
121
+ // Which file-backed capability the hidden input's next 'change' event
122
+ // belongs to -- set synchronously right before the synthetic .click(), so
123
+ // one shared <input> can serve both 'files' and 'image' (each wanting a
124
+ // different `accept`) without needing two separate hidden inputs.
125
+ this.pendingCapability = 'files';
126
+ this.onTriggerClick = () => {
127
+ this.activateCapability(this.capabilities[0]);
128
+ };
129
+ this.onMenuSelect = (e) => {
130
+ this.activateCapability(e.detail.value);
131
+ };
132
+ this.onInputChange = (e) => {
133
+ const input = e.target;
134
+ const selected = input.files;
135
+ if (selected && selected.length > 0) {
136
+ // `input.files` is a *live* view of the input's own current
137
+ // selection, not a frozen snapshot -- clearing `.value` below (so
138
+ // re-picking the exact same file still fires another 'change' next
139
+ // time) mutates this very object back to empty in place. A listener
140
+ // that reads `detail.files` synchronously (a plain `addEventListener`
141
+ // callback) would never notice, but anything that reads it even one
142
+ // microtask later (an `async` handler, a queued upload) would see an
143
+ // empty list. Rehoming the selected files into a fresh `DataTransfer`
144
+ // produces an independent `FileList` — still the real `FileList` type
145
+ // the `lyra-pick` contract promises, just no longer tied to this
146
+ // input's own live state.
147
+ const snapshot = new DataTransfer();
148
+ for (const file of selected)
149
+ snapshot.items.add(file);
150
+ this.emit('lyra-pick', {
151
+ capability: this.pendingCapability,
152
+ files: snapshot.files,
153
+ });
154
+ }
155
+ // Clearing `.value` (not just leaving the stale selection in place)
156
+ // means re-picking the exact same file still fires another 'change'
157
+ // event next time, matching <lyra-file-input>'s identical reset.
158
+ input.value = '';
159
+ };
160
+ }
161
+ static { this.styles = [LyraElement.styles, styles]; }
162
+ get hasFileCapability() {
163
+ return this.capabilities.includes('files') || this.capabilities.includes('image');
164
+ }
165
+ effectiveAccept(capability) {
166
+ return capability === 'image' ? this.accept || 'image/*' : this.accept;
167
+ }
168
+ activateCapability(capability) {
169
+ if (this.disabled)
170
+ return;
171
+ if (capability === 'camera') {
172
+ this.emit('lyra-camera-request');
173
+ return;
174
+ }
175
+ this.pendingCapability = capability;
176
+ const input = this.inputEl;
177
+ if (!input)
178
+ return;
179
+ input.accept = this.effectiveAccept(capability);
180
+ input.click();
181
+ }
182
+ renderHiddenInput() {
183
+ return html `
184
+ <input
185
+ type="file"
186
+ tabindex="-1"
187
+ aria-hidden="true"
188
+ ?multiple=${this.multiple}
189
+ ?disabled=${this.disabled}
190
+ @change=${this.onInputChange}
191
+ />
192
+ `;
193
+ }
194
+ renderSingleTrigger(capability) {
195
+ const meta = CAPABILITY_META[capability];
196
+ return html `
197
+ <button
198
+ part="trigger"
199
+ class="trigger-button"
200
+ type="button"
201
+ aria-label=${meta.triggerLabel}
202
+ ?disabled=${this.disabled}
203
+ @click=${this.onTriggerClick}
204
+ >
205
+ ${meta.icon()}
206
+ </button>
207
+ `;
208
+ }
209
+ renderMenu() {
210
+ return html `
211
+ <lyra-menu part="menu" label="Add attachment" @lyra-menu-select=${this.onMenuSelect}>
212
+ <button
213
+ slot="trigger"
214
+ class="trigger-button"
215
+ type="button"
216
+ aria-label="Add attachment"
217
+ ?disabled=${this.disabled}
218
+ >
219
+ ${paperclipIcon()}
220
+ </button>
221
+ ${this.capabilities.map((capability) => {
222
+ const meta = CAPABILITY_META[capability];
223
+ return html `
224
+ <lyra-menu-item value=${capability}>
225
+ <span slot="icon">${meta.icon()}</span>
226
+ ${meta.menuLabel}
227
+ </lyra-menu-item>
228
+ `;
229
+ })}
230
+ </lyra-menu>
231
+ `;
232
+ }
233
+ render() {
234
+ const single = this.capabilities.length === 1;
235
+ const multi = this.capabilities.length > 1;
236
+ return html `
237
+ ${single ? this.renderSingleTrigger(this.capabilities[0]) : nothing}
238
+ ${multi ? this.renderMenu() : nothing}
239
+ ${this.hasFileCapability ? this.renderHiddenInput() : nothing}
240
+ `;
241
+ }
242
+ }
243
+ __decorate([
244
+ property({ attribute: false })
245
+ ], LyraAttachmentTrigger.prototype, "capabilities", void 0);
246
+ __decorate([
247
+ property()
248
+ ], LyraAttachmentTrigger.prototype, "accept", void 0);
249
+ __decorate([
250
+ property({ type: Boolean, reflect: true })
251
+ ], LyraAttachmentTrigger.prototype, "multiple", void 0);
252
+ __decorate([
253
+ property({ type: Boolean, reflect: true })
254
+ ], LyraAttachmentTrigger.prototype, "disabled", void 0);
255
+ __decorate([
256
+ query('input[type="file"]')
257
+ ], LyraAttachmentTrigger.prototype, "inputEl", void 0);
258
+ defineElement('attachment-trigger', LyraAttachmentTrigger);
@@ -0,0 +1 @@
1
+ export declare const styles: import("lit").CSSResult;
@@ -0,0 +1,68 @@
1
+ import { css } from 'lit';
2
+ export const styles = css `
3
+ /* Fully transparent to layout, matching lyra-menu's own :host — the
4
+ visible/clickable surface is entirely the rendered button (or, in the
5
+ multi-capability case, lyra-menu's own display:contents trigger wrapper
6
+ around that same button), so this host never contributes a stray box a
7
+ composer's leading slot would otherwise have to fight with margin/
8
+ inline-block quirks to line up against the textarea. */
9
+ :host {
10
+ display: contents;
11
+ }
12
+
13
+ /* Shared visual treatment for both the single-capability button
14
+ ([part='trigger']) and the multi-capability button slotted into
15
+ lyra-menu's own trigger slot -- the latter can't itself carry
16
+ part='trigger' (that name is reserved for the single-capability case,
17
+ so a consumer's ::part(trigger) selector unambiguously targets exactly
18
+ one button), so both buttons share this plain class instead of
19
+ duplicating the same declaration block twice. */
20
+ .trigger-button {
21
+ display: inline-flex;
22
+ flex: 0 0 auto;
23
+ align-items: center;
24
+ justify-content: center;
25
+ box-sizing: border-box;
26
+ /* Compact per the class doc -- capped well below the library's general
27
+ --lyra-icon-button-size (meant for a standalone icon-only button) so
28
+ this sits comfortably inside a composer's leading slot alongside a
29
+ textarea, matching lyra-combobox's clear-button / lyra-select's
30
+ toggle sizing convention. */
31
+ min-inline-size: min(var(--lyra-icon-button-size), 1.75rem);
32
+ min-block-size: min(var(--lyra-icon-button-size), 1.75rem);
33
+ padding: 0;
34
+ border: none;
35
+ border-radius: calc(var(--lyra-radius) * 0.6);
36
+ background: transparent;
37
+ color: var(--lyra-color-text-quiet);
38
+ font: inherit;
39
+ font-size: 1.125rem;
40
+ line-height: 1;
41
+ cursor: pointer;
42
+ -webkit-tap-highlight-color: transparent;
43
+ transition:
44
+ background-color var(--lyra-transition-fast),
45
+ color var(--lyra-transition-fast);
46
+ }
47
+ .trigger-button:hover:not(:disabled) {
48
+ background: color-mix(in srgb, var(--lyra-color-text) 8%, transparent);
49
+ color: var(--lyra-color-text);
50
+ }
51
+ .trigger-button:focus-visible {
52
+ outline: var(--lyra-focus-ring-width) solid var(--lyra-focus-ring-color);
53
+ outline-offset: var(--lyra-focus-ring-offset);
54
+ }
55
+ .trigger-button:disabled {
56
+ cursor: not-allowed;
57
+ opacity: var(--lyra-opacity-disabled);
58
+ }
59
+ .trigger-button svg {
60
+ display: block;
61
+ }
62
+
63
+ @media (prefers-reduced-motion: reduce) {
64
+ .trigger-button {
65
+ transition: none !important;
66
+ }
67
+ }
68
+ `;
@@ -70,11 +70,21 @@ export class LyraBoxPlot extends LyraElement {
70
70
  // case, so this must gate on its resolved value — mirroring the correct,
71
71
  // established pattern in `LyraChart.connectedCallback()` — instead of
72
72
  // unconditionally re-awaiting the already-cached `loadChartJs()` promise.
73
+ //
74
+ // Also guards against a disconnect while either lazy peer import is still
75
+ // in flight: `this.isConnected` is re-checked after each `await` gap, so a
76
+ // `<lyra-box-plot>` removed before the load settles never constructs a
77
+ // `Chart` bound to a (possibly detached) canvas.
73
78
  async onBoxPlotPluginLoaded(boxMod) {
79
+ if (!this.isConnected)
80
+ return;
74
81
  this.loading = false;
75
82
  if (!boxMod)
76
83
  return;
77
- this.chartJsModule = (await loadChartJs()) ?? undefined;
84
+ const chartMod = await loadChartJs();
85
+ if (!this.isConnected)
86
+ return;
87
+ this.chartJsModule = chartMod ?? undefined;
78
88
  this.draw();
79
89
  }
80
90
  disconnectedCallback() {