@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,372 @@
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, state } from 'lit/decorators.js';
9
+ import { LyraElement } from '../../internal/lyra-element.js';
10
+ import { defineElement } from '../../internal/prefix.js';
11
+ import { srOnly } from '../../internal/a11y.js';
12
+ import { styles } from './document-preview.styles.js';
13
+ const IDLE_TEXT_FETCH = { kind: 'idle' };
14
+ function classifyFormat(mimeType) {
15
+ const mt = mimeType.trim().toLowerCase();
16
+ if (mt.startsWith('text/') || mt === 'application/json')
17
+ return 'text';
18
+ if (mt.startsWith('image/'))
19
+ return 'image';
20
+ return 'generic';
21
+ }
22
+ // Mirrors the shared icon set's viewBox/stroke conventions
23
+ // (internal/icons.ts's chevronIcon()/closeIcon()/etc.) without adding
24
+ // document/download glyphs to that module -- it's off limits here -- so
25
+ // these one-off icons still read as part of the same visual language as the
26
+ // rest of the library's inline icons.
27
+ const ICON_VIEW_BOX = '0 0 24 24';
28
+ const ICON_STROKE_WIDTH = '1.75';
29
+ /** A generic "document" glyph for the can't-preview-this fallback. Same
30
+ * shape as `<lyra-attachment-chip>`'s local `fileGlyph()` -- duplicated
31
+ * rather than imported (these are two independently consumable components)
32
+ * but kept visually identical so an unpreviewable-file affordance reads the
33
+ * same wherever it shows up in the library. */
34
+ function fileGlyph() {
35
+ return svg `
36
+ <svg
37
+ width="1em"
38
+ height="1em"
39
+ viewBox=${ICON_VIEW_BOX}
40
+ fill="none"
41
+ stroke="currentColor"
42
+ stroke-width=${ICON_STROKE_WIDTH}
43
+ stroke-linecap="round"
44
+ stroke-linejoin="round"
45
+ aria-hidden="true"
46
+ focusable="false"
47
+ ><path d="M6 2h8l6 6v12a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2Z"></path><polyline points="14 2 14 8 20 8"></polyline></svg>
48
+ `;
49
+ }
50
+ /** A downward arrow into a tray -- the conventional "download" glyph. */
51
+ function downloadIcon() {
52
+ return icon(svg `
53
+ <path d="M12 3v12"></path>
54
+ <polyline points="7 11 12 16 17 11"></polyline>
55
+ <path d="M4 18v2a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-2"></path>
56
+ `);
57
+ }
58
+ function icon(paths) {
59
+ return svg `
60
+ <svg
61
+ width="1em"
62
+ height="1em"
63
+ viewBox=${ICON_VIEW_BOX}
64
+ fill="none"
65
+ stroke="currentColor"
66
+ stroke-width=${ICON_STROKE_WIDTH}
67
+ stroke-linecap="round"
68
+ stroke-linejoin="round"
69
+ aria-hidden="true"
70
+ focusable="false"
71
+ >${paths}</svg>
72
+ `;
73
+ }
74
+ /**
75
+ * `<lyra-document-preview>` — a format-dispatching viewer for one document/
76
+ * attachment, plus the visual state machine for an async server-side
77
+ * conversion a host app runs in front of it.
78
+ *
79
+ * Format dispatch is intentionally minimal (see this family's scope
80
+ * guidance): only `text/*`/`application/json` (plain, scrollable `<pre>` —
81
+ * no syntax highlighting; compose `<lyra-code-block>` yourself via the
82
+ * `unsupported` slot for that) and `image/*` (a contained `<img>`) render
83
+ * inline. Everything else — PDF, office documents, video, audio, or any
84
+ * unrecognized MIME type — falls back to a generic "can't preview this"
85
+ * state: a file glyph, a short message, and (when `src` is set) a native
86
+ * `<a download>` link. This is a deliberate ceiling, not a gap: this
87
+ * component ships a dispatch *shell*, not a format registry. The
88
+ * `unsupported` slot is the escape hatch for every format left out of the
89
+ * built-in three — plug in a PDF.js viewer, an office-doc renderer, a
90
+ * `<lyra-code-block>`, or anything else keyed off `mime-type` yourself.
91
+ *
92
+ * `status="converting"` is a second, independent axis from format dispatch.
93
+ * This component does not know your backend's conversion API shape and
94
+ * therefore owns none of the actual polling/fetch — a host that's converting
95
+ * a non-natively-previewable format server-side (e.g. .docx → .pdf) polls
96
+ * its own backend and updates `status`/`progress`/`src` here as that
97
+ * proceeds. This component only *visualizes* that state: an indeterminate
98
+ * spinner, or a determinate one once `progress` is supplied. Once the host
99
+ * flips `status` to `"ready"` (typically alongside a new `src`/`mime-type`
100
+ * pointing at the converted artifact), normal format dispatch resumes.
101
+ *
102
+ * The one piece of async work this component *does* own is fetching a
103
+ * `text/*`/`application/json` `src` itself (there's no other way to get a
104
+ * `<pre>`'s text content from a URL) — gated behind the same generation-
105
+ * counter guard `<lyra-tool-result-view>`'s `resolve()` uses, so a `src`
106
+ * reassigned mid-fetch can't have a stale response clobber a newer one. A
107
+ * failure here (network error, non-2xx response) renders inline via
108
+ * `[part="error"]` and fires `lyra-render-error`, independently of the
109
+ * host-owned `status` prop — mirrors `<lyra-markdown>`'s identical stance
110
+ * that a *rendering* failure and a host's own state machine are different
111
+ * concerns.
112
+ *
113
+ * Accessibility: the `"converting"` state (no numeric `progress`) is a
114
+ * `role="status"` region wrapping a visually-hidden "Converting document…"
115
+ * string. This is a *plain* static region, not routed through
116
+ * `<lyra-live-region>`/`Announcer` — like `<lyra-typing-indicator>`'s
117
+ * identical judgement call (see that component's class doc), this only ever
118
+ * has one thing to announce (entering the state), not a rapidly-repeating
119
+ * stream of updates, so the coalescing machinery a high-frequency component
120
+ * needs would be pure overhead here. Once real `progress` is available, the
121
+ * region becomes a standard `role="progressbar"` instead, which is
122
+ * self-describing via `aria-valuenow` with no extra live-region wiring
123
+ * needed. `status="error"` renders `[part="error"]` as `role="alert"` — an
124
+ * assertive, one-shot failure notice, the same native-role shortcut
125
+ * `<lyra-live-region>`'s own `mode="assertive"` maps to, without requiring
126
+ * the announcer machinery here either.
127
+ *
128
+ * @customElement lyra-document-preview
129
+ * @slot unsupported - Escape hatch: when populated, its content renders
130
+ * *instead of* the generic download fallback for any `mime-type` this
131
+ * component doesn't natively support (i.e. whenever format dispatch would
132
+ * otherwise fall through to "generic"). Ignored while `mime-type` resolves
133
+ * to `text`/`image` dispatch, or while `status` is `"converting"`/`"error"`.
134
+ * @event lyra-download - `detail: { src, filename }` — fired when the
135
+ * generic-download fallback's link is activated. The browser download
136
+ * itself needs no JS (a plain `<a download>` handles it); this is purely
137
+ * for a host that wants to observe/log the download.
138
+ * @event lyra-render-error - `detail: { error }` — fired when this
139
+ * component's own `text/*`/`application/json` `fetch(src)` fails. Distinct
140
+ * from `status="error"`, which is entirely host-driven (see the class
141
+ * doc).
142
+ * @csspart base - The root container.
143
+ * @csspart header - The row above the body, holding `filename`. Hidden entirely when `filename` is unset.
144
+ * @csspart filename - The filename text.
145
+ * @csspart body - The wrapper around whichever content is currently showing (text/image preview, the generic fallback, the spinner, or the error message).
146
+ * @csspart spinner - The converting/loading indicator — indeterminate (`role="status"`) or, once numeric progress is known, a determinate `role="progressbar"`. Used both for `status="converting"` and for this component's own in-flight text fetch.
147
+ * @csspart error - The error message region (`role="alert"`) — used both for `status="error"` and for a failed text fetch.
148
+ * @csspart download-link - The `<a download>` affordance in the generic fallback. Only rendered when `src` is set.
149
+ */
150
+ export class LyraDocumentPreview extends LyraElement {
151
+ constructor() {
152
+ super(...arguments);
153
+ /** URL to fetch (for `text`/`application/json`) or display (`image`, or as
154
+ * the generic fallback's download `href`). Optional — gracefully absent
155
+ * while, e.g., a conversion is still in progress. */
156
+ this.src = '';
157
+ /** Drives format dispatch — see the class doc. */
158
+ this.mimeType = '';
159
+ /** Shown in the header and used as the download link's suggested filename. */
160
+ this.filename = '';
161
+ /** Host-owned lifecycle state. `"converting"` shows the spinner regardless
162
+ * of `mime-type`/`src`; `"error"` shows `errorMessage` regardless of
163
+ * either. `"idle"`/`"ready"` both resume normal format dispatch — this
164
+ * component doesn't require a host that has no conversion step to ever
165
+ * set `"ready"` explicitly. */
166
+ this.status = 'idle';
167
+ /** Shown (via `[part="error"]`) while `status="error"`. */
168
+ this.errorMessage = '';
169
+ /** A CSS length (e.g. `"24rem"`); once set, `[part="body"]` scrolls
170
+ * internally past this height instead of growing the page — same
171
+ * contract as `<lyra-json-viewer>`'s identically-named prop. */
172
+ this.maxHeight = '';
173
+ this.hasUnsupportedSlot = false;
174
+ this.textFetch = IDLE_TEXT_FETCH;
175
+ // Bumped on every fetchText() call so a stale in-flight fetch (superseded
176
+ // by a newer src/mime-type/status before it settles) can detect it's no
177
+ // longer current and skip writing its result over a more recent one --
178
+ // same guard <lyra-tool-result-view>'s resolve() uses.
179
+ this.fetchGeneration = 0;
180
+ this.onUnsupportedSlotChange = (e) => {
181
+ this.hasUnsupportedSlot = e.target.assignedElements({ flatten: true }).length > 0;
182
+ };
183
+ this.onDownloadClick = () => {
184
+ this.emit('lyra-download', { src: this.src, filename: this.filename });
185
+ };
186
+ }
187
+ static { this.styles = [LyraElement.styles, styles, srOnly]; }
188
+ willUpdate(changed) {
189
+ if (!this.hasUpdated) {
190
+ this.hasUnsupportedSlot = Array.from(this.children).some((el) => el.getAttribute('slot') === 'unsupported');
191
+ }
192
+ const shouldFetchText = classifyFormat(this.mimeType) === 'text' &&
193
+ this.src !== '' &&
194
+ this.status !== 'converting' &&
195
+ this.status !== 'error';
196
+ if (shouldFetchText) {
197
+ // Refetch when the target itself changed, or when this just became
198
+ // fetchable (e.g. a "converting" -> "ready" transition) and nothing
199
+ // has been fetched yet -- but not on every unrelated property change.
200
+ if (!this.hasUpdated ||
201
+ changed.has('src') ||
202
+ changed.has('mimeType') ||
203
+ (changed.has('status') && this.textFetch.kind === 'idle')) {
204
+ void this.fetchText(this.src);
205
+ }
206
+ }
207
+ else if (this.textFetch.kind !== 'idle') {
208
+ // No longer applicable (format changed away from text, src cleared,
209
+ // or status moved to converting/error) -- invalidate any in-flight
210
+ // fetch and drop the stale result so a later re-entry starts clean.
211
+ this.fetchGeneration++;
212
+ this.textFetch = IDLE_TEXT_FETCH;
213
+ }
214
+ }
215
+ async fetchText(url) {
216
+ const generation = ++this.fetchGeneration;
217
+ this.textFetch = { kind: 'loading' };
218
+ try {
219
+ const response = await fetch(url);
220
+ if (!response.ok)
221
+ throw new Error(`${response.status} ${response.statusText}`);
222
+ const text = await response.text();
223
+ if (generation !== this.fetchGeneration)
224
+ return;
225
+ this.textFetch = { kind: 'loaded', text };
226
+ }
227
+ catch (error) {
228
+ if (generation !== this.fetchGeneration)
229
+ return;
230
+ const message = error instanceof Error ? error.message : 'Failed to load document.';
231
+ this.textFetch = { kind: 'error', message };
232
+ this.emit('lyra-render-error', { error });
233
+ }
234
+ }
235
+ /** Renders `[part="spinner"]` -- indeterminate (`role="status"` + a
236
+ * visually-hidden label, per the class doc's accessibility note) when
237
+ * `progressValue` is absent, or a `role="progressbar"` once it's a finite
238
+ * 0-100 number. Shared by the host-driven `"converting"` state and this
239
+ * component's own in-flight text fetch (which never has a numeric
240
+ * progress of its own to report). */
241
+ renderSpinner(label, progressValue) {
242
+ const hasProgress = progressValue != null && Number.isFinite(progressValue);
243
+ if (hasProgress) {
244
+ const clamped = Math.min(100, Math.max(0, progressValue));
245
+ const rounded = Math.round(clamped);
246
+ return html `
247
+ <div
248
+ part="spinner"
249
+ role="progressbar"
250
+ aria-valuenow=${rounded}
251
+ aria-valuemin="0"
252
+ aria-valuemax="100"
253
+ aria-label=${label}
254
+ >
255
+ <span class="ring determinate" style=${`--lyra-document-preview-progress:${clamped}`}></span>
256
+ <span class="spinner-text">${rounded}%</span>
257
+ </div>
258
+ `;
259
+ }
260
+ return html `
261
+ <div part="spinner" role="status">
262
+ <span class="ring" aria-hidden="true"></span>
263
+ <span class="sr-only">${label}</span>
264
+ </div>
265
+ `;
266
+ }
267
+ renderError(message) {
268
+ return html `<div part="error" role="alert">${message || 'Something went wrong.'}</div>`;
269
+ }
270
+ renderTextPreview() {
271
+ if (this.src === '')
272
+ return html `<pre class="text"></pre>`;
273
+ switch (this.textFetch.kind) {
274
+ case 'loaded':
275
+ return html `<pre class="text">${this.textFetch.text}</pre>`;
276
+ case 'error':
277
+ return this.renderError(this.textFetch.message);
278
+ case 'loading':
279
+ case 'idle':
280
+ default:
281
+ return this.renderSpinner('Loading document…');
282
+ }
283
+ }
284
+ renderImagePreview() {
285
+ if (this.src === '')
286
+ return html `<p class="empty-note">No image to display.</p>`;
287
+ return html `<img src=${this.src} alt=${this.filename || 'Document preview'} />`;
288
+ }
289
+ renderDownloadFallback() {
290
+ const label = this.filename || 'this file';
291
+ return html `
292
+ <div class="fallback">
293
+ <span class="fallback-icon" aria-hidden="true">${fileGlyph()}</span>
294
+ <p class="fallback-text">Preview not available for ${label}.</p>
295
+ ${this.src !== ''
296
+ ? html `
297
+ <a
298
+ part="download-link"
299
+ href=${this.src}
300
+ download=${this.filename || ''}
301
+ @click=${this.onDownloadClick}
302
+ >
303
+ ${downloadIcon()}<span>Download</span>
304
+ </a>
305
+ `
306
+ : nothing}
307
+ </div>
308
+ `;
309
+ }
310
+ /** The `<slot>` element renders unconditionally (not just while
311
+ * `hasUnsupportedSlot`) so a slot-assignment change is always observable
312
+ * via `slotchange` -- same reasoning as `<lyra-chat-message>`'s
313
+ * always-rendered optional slots. */
314
+ renderGenericFallback() {
315
+ return html `
316
+ <slot name="unsupported" @slotchange=${this.onUnsupportedSlotChange}></slot>
317
+ ${this.hasUnsupportedSlot ? nothing : this.renderDownloadFallback()}
318
+ `;
319
+ }
320
+ renderBody() {
321
+ if (this.status === 'converting')
322
+ return this.renderSpinner('Converting document…', this.progress);
323
+ if (this.status === 'error')
324
+ return this.renderError(this.errorMessage);
325
+ switch (classifyFormat(this.mimeType)) {
326
+ case 'text':
327
+ return this.renderTextPreview();
328
+ case 'image':
329
+ return this.renderImagePreview();
330
+ default:
331
+ return this.renderGenericFallback();
332
+ }
333
+ }
334
+ render() {
335
+ return html `
336
+ <div part="base" style=${this.maxHeight ? `--lyra-document-preview-max-height:${this.maxHeight}` : nothing}>
337
+ <div part="header" ?hidden=${!this.filename}>
338
+ <span part="filename" title=${this.filename}>${this.filename}</span>
339
+ </div>
340
+ <div part="body">${this.renderBody()}</div>
341
+ </div>
342
+ `;
343
+ }
344
+ }
345
+ __decorate([
346
+ property()
347
+ ], LyraDocumentPreview.prototype, "src", void 0);
348
+ __decorate([
349
+ property({ attribute: 'mime-type' })
350
+ ], LyraDocumentPreview.prototype, "mimeType", void 0);
351
+ __decorate([
352
+ property()
353
+ ], LyraDocumentPreview.prototype, "filename", void 0);
354
+ __decorate([
355
+ property({ reflect: true })
356
+ ], LyraDocumentPreview.prototype, "status", void 0);
357
+ __decorate([
358
+ property({ type: Number })
359
+ ], LyraDocumentPreview.prototype, "progress", void 0);
360
+ __decorate([
361
+ property({ attribute: 'error-message' })
362
+ ], LyraDocumentPreview.prototype, "errorMessage", void 0);
363
+ __decorate([
364
+ property({ attribute: 'max-height' })
365
+ ], LyraDocumentPreview.prototype, "maxHeight", void 0);
366
+ __decorate([
367
+ state()
368
+ ], LyraDocumentPreview.prototype, "hasUnsupportedSlot", void 0);
369
+ __decorate([
370
+ state()
371
+ ], LyraDocumentPreview.prototype, "textFetch", void 0);
372
+ defineElement('document-preview', LyraDocumentPreview);
@@ -0,0 +1 @@
1
+ export declare const styles: import("lit").CSSResult;
@@ -0,0 +1,191 @@
1
+ import { css } from 'lit';
2
+ export const styles = css `
3
+ :host {
4
+ display: block;
5
+ /* Consumer-tunable scroll cap on [part='body'] -- 'none' means the
6
+ preview grows with its content until a caller opts into an internal
7
+ scrollbar, same contract as lyra-json-viewer's identical
8
+ --lyra-json-viewer-max-height. */
9
+ --lyra-document-preview-max-height: none;
10
+ /* No shared --wa-*/--lyra-* monospace token exists to resolve through
11
+ (same gap lyra-json-viewer's own --lyra-json-viewer-font documents) --
12
+ contained here so a host page can retheme it. */
13
+ --lyra-document-preview-font: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
14
+ }
15
+
16
+ [part='base'] {
17
+ display: flex;
18
+ flex-direction: column;
19
+ box-sizing: border-box;
20
+ border: 1px solid var(--lyra-color-border);
21
+ border-radius: var(--lyra-radius);
22
+ background: var(--lyra-color-surface);
23
+ overflow: hidden;
24
+ }
25
+
26
+ [part='header'] {
27
+ display: flex;
28
+ align-items: center;
29
+ gap: var(--lyra-space-s);
30
+ padding: var(--lyra-space-s) var(--lyra-space-m);
31
+ border-block-end: 1px solid var(--lyra-color-border);
32
+ background: var(--lyra-color-surface);
33
+ }
34
+ [part='header'][hidden] {
35
+ display: none;
36
+ }
37
+ [part='filename'] {
38
+ overflow: hidden;
39
+ text-overflow: ellipsis;
40
+ white-space: nowrap;
41
+ font-weight: 600;
42
+ font-size: 0.875rem;
43
+ color: var(--lyra-color-text);
44
+ }
45
+
46
+ [part='body'] {
47
+ display: flex;
48
+ flex-direction: column;
49
+ align-items: center;
50
+ justify-content: center;
51
+ min-block-size: 10rem;
52
+ max-block-size: var(--lyra-document-preview-max-height);
53
+ box-sizing: border-box;
54
+ overflow: auto;
55
+ flex: 1 1 auto;
56
+ }
57
+
58
+ /* -- text/*, application/json: plain, scrollable <pre> -----------------
59
+ No syntax highlighting -- see the class doc for why that's intentionally
60
+ out of scope here. */
61
+ pre.text {
62
+ align-self: stretch;
63
+ box-sizing: border-box;
64
+ margin: 0;
65
+ padding: var(--lyra-space-m);
66
+ font-family: var(--lyra-document-preview-font);
67
+ font-size: 0.8125rem;
68
+ line-height: 1.6;
69
+ white-space: pre;
70
+ overflow: auto;
71
+ color: var(--lyra-color-text);
72
+ }
73
+
74
+ /* -- image/* -------------------------------------------------------- */
75
+ [part='body'] img {
76
+ display: block;
77
+ max-inline-size: 100%;
78
+ max-block-size: 100%;
79
+ object-fit: contain;
80
+ }
81
+
82
+ .empty-note {
83
+ margin: 0;
84
+ padding: var(--lyra-space-m);
85
+ color: var(--lyra-color-text-quiet);
86
+ font-size: 0.875rem;
87
+ }
88
+
89
+ /* -- generic download fallback ------------------------------------- */
90
+ .fallback {
91
+ display: flex;
92
+ flex-direction: column;
93
+ align-items: center;
94
+ gap: var(--lyra-space-s);
95
+ padding: var(--lyra-space-l);
96
+ text-align: center;
97
+ }
98
+ .fallback-icon {
99
+ display: inline-flex;
100
+ font-size: 2rem;
101
+ color: var(--lyra-color-text-quiet);
102
+ }
103
+ .fallback-icon svg {
104
+ display: block;
105
+ }
106
+ .fallback-text {
107
+ margin: 0;
108
+ color: var(--lyra-color-text-quiet);
109
+ font-size: 0.875rem;
110
+ }
111
+ [part='download-link'] {
112
+ display: inline-flex;
113
+ align-items: center;
114
+ gap: var(--lyra-space-xs);
115
+ padding: var(--lyra-space-xs) var(--lyra-space-m);
116
+ border-radius: var(--lyra-radius);
117
+ background: var(--lyra-color-brand);
118
+ color: var(--lyra-color-on-brand);
119
+ font: inherit;
120
+ font-weight: 600;
121
+ font-size: 0.8125rem;
122
+ text-decoration: none;
123
+ cursor: pointer;
124
+ transition: background-color var(--lyra-transition-fast);
125
+ }
126
+ [part='download-link']:hover {
127
+ background: color-mix(in srgb, var(--lyra-color-brand) 85%, black);
128
+ }
129
+ [part='download-link']:focus-visible {
130
+ outline: var(--lyra-focus-ring-width) solid var(--lyra-focus-ring-color);
131
+ outline-offset: var(--lyra-focus-ring-offset);
132
+ }
133
+ [part='download-link'] svg {
134
+ display: block;
135
+ }
136
+
137
+ /* -- spinner (converting / loading text) ----------------------------- */
138
+ [part='spinner'] {
139
+ display: flex;
140
+ flex-direction: column;
141
+ align-items: center;
142
+ gap: var(--lyra-space-s);
143
+ padding: var(--lyra-space-l);
144
+ }
145
+ .ring {
146
+ display: inline-block;
147
+ inline-size: 2rem;
148
+ block-size: 2rem;
149
+ border-radius: 50%;
150
+ border: 3px solid var(--lyra-color-border);
151
+ border-block-start-color: var(--lyra-color-brand);
152
+ animation: lyra-document-preview-spin 0.8s linear infinite;
153
+ }
154
+ /* Determinate progress reuses the same ring shape but holds a fixed
155
+ rotation instead of spinning -- conic-gradient renders the actual fill,
156
+ so the ring visually communicates a real fraction rather than motion. */
157
+ .ring.determinate {
158
+ animation: none;
159
+ border-color: transparent;
160
+ background: conic-gradient(
161
+ var(--lyra-color-brand) calc(var(--lyra-document-preview-progress, 0) * 1%),
162
+ var(--lyra-color-border) 0
163
+ );
164
+ -webkit-mask: radial-gradient(farthest-side, transparent calc(100% - 3px), #000 calc(100% - 3px));
165
+ mask: radial-gradient(farthest-side, transparent calc(100% - 3px), #000 calc(100% - 3px));
166
+ }
167
+ .spinner-text {
168
+ color: var(--lyra-color-text-quiet);
169
+ font-size: 0.8125rem;
170
+ font-variant-numeric: tabular-nums;
171
+ }
172
+ @keyframes lyra-document-preview-spin {
173
+ to {
174
+ transform: rotate(360deg);
175
+ }
176
+ }
177
+ @media (prefers-reduced-motion: reduce) {
178
+ .ring {
179
+ animation: none !important;
180
+ }
181
+ }
182
+
183
+ /* -- error ------------------------------------------------------------ */
184
+ [part='error'] {
185
+ margin: 0;
186
+ padding: var(--lyra-space-l);
187
+ color: var(--lyra-color-danger);
188
+ font-size: 0.875rem;
189
+ text-align: center;
190
+ }
191
+ `;
@@ -2,7 +2,7 @@
2
2
  // reliably trigger spreadsheet formula evaluation) — guarding it forces text rendering on
3
3
  // ordinary negative numbers/currency. Per OWASP CSV-injection guidance, '-' is intentionally
4
4
  // excluded here.
5
- const UNSAFE_LEADING = /^[=+@\t\r]/;
5
+ const UNSAFE_LEADING = /^[=+@\t\r\n]/;
6
6
  const NEEDS_QUOTING = /[",\r\n]/;
7
7
  /** Escapes a CSV field: quotes as needed, guards against formula injection. */
8
8
  export function escapeCsvField(value) {
@@ -83,7 +83,9 @@ export class LyraExportButton extends LyraElement {
83
83
  disconnectedCallback() {
84
84
  super.disconnectedCallback();
85
85
  this.cleanup?.();
86
+ this.cleanup = undefined;
86
87
  document.removeEventListener('pointerdown', this.onDocPointer);
88
+ this.open = false;
87
89
  }
88
90
  openMenu() {
89
91
  if (this.open)
@@ -1,7 +1,10 @@
1
1
  import { type TemplateResult, type PropertyValues } from 'lit';
2
2
  import { LyraElement } from '../../internal/lyra-element.js';
3
3
  import '../skeleton/skeleton.js';
4
- type FlagUrlResolver = (code: string) => Promise<string | undefined>;
4
+ type FlagVariant = 'compact' | 'standard' | 'detailed';
5
+ type FlagUrlResolver = (code: string, options?: {
6
+ variant?: FlagVariant;
7
+ }) => Promise<string | undefined>;
5
8
  /**
6
9
  * Resolves the optional peer dependency `@aceshooting/lyra-flags`'s `flagUrl`
7
10
  * via the given importer (a real dynamic import by default). Uncached and
@@ -31,10 +34,19 @@ export declare function loadFlagUrl(importFlags?: () => Promise<{
31
34
  * `src` instead to skip the peer-package round trip (and its loading-skeleton
32
35
  * flash) entirely.
33
36
  *
37
+ * The ~65 flags whose design includes a detailed coat of arms/seal/emblem (e.g. `es`, `pt`) ship
38
+ * three fidelity tiers; choose one with `variant`: `"compact"` (a tiny WebP raster for icon-scale
39
+ * use — menu items, language selectors, dense lists), the default `"standard"` (icon-optimized
40
+ * vector for card/row sizes), or `"detailed"` (the pristine full-detail vector for hero-scale
41
+ * display). A no-op for every other code — all tiers resolve to the same file. See `variant`'s own
42
+ * doc.
43
+ *
34
44
  * @customElement lyra-flag
35
45
  * @example <lyra-flag country="fr"></lyra-flag>
36
46
  * @example <lyra-flag language="en" label="English"></lyra-flag>
37
47
  * @example <lyra-flag src=${frUrl} label="French"></lyra-flag>
48
+ * @example <lyra-flag country="es" variant="compact"></lyra-flag>
49
+ * @example <lyra-flag country="es" variant="detailed"></lyra-flag>
38
50
  * @csspart image - The underlying <img>.
39
51
  */
40
52
  export declare class LyraFlag extends LyraElement {
@@ -53,14 +65,39 @@ export declare class LyraFlag extends LyraElement {
53
65
  */
54
66
  src?: string;
55
67
  /**
56
- * Accessible label / `alt` text. Defaults to the uppercase *resolved country
57
- * code* for a `language`-only element (e.g. `language="en"`) that's the
58
- * mapped country (`"GB"`), not the language tag itself (`"EN"`). Has no
59
- * default when only `src` is given (no country/language to derive one from).
68
+ * Accessible label / `alt` text. Defaults to a localized, human-readable
69
+ * region name derived from the *resolved country code* via
70
+ * `Intl.DisplayNames` (e.g. `"United Kingdom"`) for a `language`-only
71
+ * element (e.g. `language="en"`) that's the mapped country's display name,
72
+ * not the language tag itself. Falls back to the bare uppercase code if
73
+ * `Intl.DisplayNames` can't resolve it. Has no default when only `src` is
74
+ * given (no country/language to derive one from).
60
75
  */
61
76
  label?: string;
62
77
  /** Render as a circular flag. */
63
78
  round: boolean;
79
+ /**
80
+ * Which fidelity tier to load, for the ~65 `country`/`language` codes whose source art embeds a
81
+ * coat of arms/seal/emblem (for every other code all tiers are the same file, so this is a safe
82
+ * no-op):
83
+ * - `"compact"` — a tiny WebP raster for icon-scale use (menu items, language selectors, dense
84
+ * lists; ~12–28px), where the emblem detail is invisible anyway.
85
+ * - `"standard"` (default) — the icon-optimized vector, for card/row sizes (~28–96px).
86
+ * - `"detailed"` — the pristine, full-detail vector, for rendering larger than icon scale (e.g.
87
+ * a hero display) where the extra illustrative detail is actually visible.
88
+ *
89
+ * Has no effect when `src` is set — a pre-resolved URL is used as-is regardless. Takes precedence
90
+ * over the deprecated `detailed` boolean.
91
+ */
92
+ variant?: FlagVariant;
93
+ /**
94
+ * @deprecated Use `variant="detailed"` instead. Kept as an alias for one minor cycle; when
95
+ * `variant` is unset, `detailed` still maps to the detailed tier. Removed in the next major.
96
+ */
97
+ detailed: boolean;
98
+ /** The effective tier to request: an explicit `variant` wins; otherwise the deprecated
99
+ * `detailed` boolean is honored; otherwise `"standard"`. */
100
+ private get effectiveVariant();
64
101
  private resolvedSrc?;
65
102
  /** True while the lazy-loaded `@aceshooting/lyra-flags` peer resolver is in flight. */
66
103
  private loading;