@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
@@ -28,6 +28,22 @@ export async function loadFlagUrl(importFlags = () => import('@aceshooting/lyra-
28
28
  return null;
29
29
  }
30
30
  }
31
+ /**
32
+ * Resolves an ISO 3166-1 alpha-2 region code to a human-readable, localized
33
+ * display name (e.g. `'FR'` -> `'France'`) via `Intl.DisplayNames`, for use as
34
+ * the default accessible name (`alt`) instead of a bare code read
35
+ * letter-by-letter by most screen readers. Falls back to the uppercase code
36
+ * itself if `Intl.DisplayNames` throws (unrecognized region) or isn't
37
+ * available in the current runtime.
38
+ */
39
+ function displayNameFor(code) {
40
+ try {
41
+ return new Intl.DisplayNames([navigator.language], { type: 'region' }).of(code.toUpperCase()) ?? code.toUpperCase();
42
+ }
43
+ catch {
44
+ return code.toUpperCase();
45
+ }
46
+ }
31
47
  let flagUrlResolver;
32
48
  /**
33
49
  * Lazily loads the optional peer dependency '@aceshooting/lyra-flags' once per
@@ -40,6 +56,17 @@ function loadFlagUrlResolver() {
40
56
  }
41
57
  return flagUrlResolver;
42
58
  }
59
+ /**
60
+ * @internal Test-only seam: overrides (or, with `undefined`, clears) the module-level cache that
61
+ * `willUpdate()` reads through `loadFlagUrlResolver()`. The real `@aceshooting/lyra-flags` peer's
62
+ * `flagUrl(code)` never actually rejects (unknown codes just resolve `undefined`), so this is the
63
+ * only way to exercise a resolver-function rejection — e.g. a network failure fetching a flag
64
+ * asset — without uninstalling the real package. Not part of the public API; not re-exported from
65
+ * the root barrel.
66
+ */
67
+ export function __setFlagUrlResolverForTesting(value) {
68
+ flagUrlResolver = value;
69
+ }
43
70
  /**
44
71
  * `<lyra-flag>` — a country/language flag.
45
72
  *
@@ -59,10 +86,19 @@ function loadFlagUrlResolver() {
59
86
  * `src` instead to skip the peer-package round trip (and its loading-skeleton
60
87
  * flash) entirely.
61
88
  *
89
+ * The ~65 flags whose design includes a detailed coat of arms/seal/emblem (e.g. `es`, `pt`) ship
90
+ * three fidelity tiers; choose one with `variant`: `"compact"` (a tiny WebP raster for icon-scale
91
+ * use — menu items, language selectors, dense lists), the default `"standard"` (icon-optimized
92
+ * vector for card/row sizes), or `"detailed"` (the pristine full-detail vector for hero-scale
93
+ * display). A no-op for every other code — all tiers resolve to the same file. See `variant`'s own
94
+ * doc.
95
+ *
62
96
  * @customElement lyra-flag
63
97
  * @example <lyra-flag country="fr"></lyra-flag>
64
98
  * @example <lyra-flag language="en" label="English"></lyra-flag>
65
99
  * @example <lyra-flag src=${frUrl} label="French"></lyra-flag>
100
+ * @example <lyra-flag country="es" variant="compact"></lyra-flag>
101
+ * @example <lyra-flag country="es" variant="detailed"></lyra-flag>
66
102
  * @csspart image - The underlying <img>.
67
103
  */
68
104
  export class LyraFlag extends LyraElement {
@@ -70,6 +106,11 @@ export class LyraFlag extends LyraElement {
70
106
  super(...arguments);
71
107
  /** Render as a circular flag. */
72
108
  this.round = false;
109
+ /**
110
+ * @deprecated Use `variant="detailed"` instead. Kept as an alias for one minor cycle; when
111
+ * `variant` is unset, `detailed` still maps to the detailed tier. Removed in the next major.
112
+ */
113
+ this.detailed = false;
73
114
  /** True while the lazy-loaded `@aceshooting/lyra-flags` peer resolver is in flight. */
74
115
  this.loading = true;
75
116
  /**
@@ -81,6 +122,11 @@ export class LyraFlag extends LyraElement {
81
122
  this.resolveToken = 0;
82
123
  }
83
124
  static { this.styles = [LyraElement.styles, styles]; }
125
+ /** The effective tier to request: an explicit `variant` wins; otherwise the deprecated
126
+ * `detailed` boolean is honored; otherwise `"standard"`. */
127
+ get effectiveVariant() {
128
+ return this.variant ?? (this.detailed ? 'detailed' : 'standard');
129
+ }
84
130
  get code() {
85
131
  if (this.country) {
86
132
  return ALPHA2_RE.test(this.country) ? this.country.toLowerCase() : undefined;
@@ -96,8 +142,14 @@ export class LyraFlag extends LyraElement {
96
142
  // undefined -> undefined (no-op to Lit), so none of `changed.has(...)`
97
143
  // would otherwise ever become true for a `<lyra-flag>` that never
98
144
  // receives one, leaving `loading` stuck at its initial `true` forever.
99
- if (this.hasUpdated && !changed.has('country') && !changed.has('language') && !changed.has('src'))
145
+ if (this.hasUpdated &&
146
+ !changed.has('country') &&
147
+ !changed.has('language') &&
148
+ !changed.has('src') &&
149
+ !changed.has('variant') &&
150
+ !changed.has('detailed')) {
100
151
  return;
152
+ }
101
153
  const token = ++this.resolveToken; // invalidates any in-flight peer resolution either way
102
154
  if (this.src) {
103
155
  this.resolvedSrc = undefined;
@@ -111,13 +163,21 @@ export class LyraFlag extends LyraElement {
111
163
  return;
112
164
  }
113
165
  this.loading = true;
166
+ const variant = this.effectiveVariant;
114
167
  void loadFlagUrlResolver()
115
- .then((resolve) => resolve?.(code))
168
+ .then((resolve) => resolve?.(code, variant === 'standard' ? undefined : { variant }))
116
169
  .then((url) => {
117
170
  if (token !== this.resolveToken)
118
171
  return; // superseded by a later country/language/src change
119
172
  this.resolvedSrc = url;
120
173
  this.loading = false;
174
+ })
175
+ .catch((err) => {
176
+ if (token !== this.resolveToken)
177
+ return; // superseded by a later country/language/src change
178
+ console.warn(`<lyra-flag> failed to resolve a flag URL for "${code}":`, err);
179
+ this.resolvedSrc = undefined;
180
+ this.loading = false;
121
181
  });
122
182
  }
123
183
  updated() {
@@ -132,7 +192,8 @@ export class LyraFlag extends LyraElement {
132
192
  const url = this.src ?? this.resolvedSrc;
133
193
  if (!url)
134
194
  return html ``;
135
- const alt = this.label ?? (this.code ?? '').toUpperCase();
195
+ const code = this.code;
196
+ const alt = this.label ?? (code ? displayNameFor(code) : '');
136
197
  return html `<img part="image" src=${url} alt=${alt} loading="lazy" decoding="async" />`;
137
198
  }
138
199
  }
@@ -151,6 +212,12 @@ __decorate([
151
212
  __decorate([
152
213
  property({ type: Boolean, reflect: true })
153
214
  ], LyraFlag.prototype, "round", void 0);
215
+ __decorate([
216
+ property()
217
+ ], LyraFlag.prototype, "variant", void 0);
218
+ __decorate([
219
+ property({ type: Boolean, reflect: true })
220
+ ], LyraFlag.prototype, "detailed", void 0);
154
221
  __decorate([
155
222
  state()
156
223
  ], LyraFlag.prototype, "resolvedSrc", void 0);
@@ -57,28 +57,37 @@ export class LyraGauge extends LyraElement {
57
57
  }
58
58
  static { this.styles = [LyraElement.styles, styles]; }
59
59
  get ratio() {
60
- if (isNaN(this.value) || isNaN(this.min) || isNaN(this.max))
60
+ if (!Number.isFinite(this.value) || !Number.isFinite(this.min) || !Number.isFinite(this.max))
61
61
  return 0;
62
- const span = this.max - this.min || 1;
63
- return Math.min(1, Math.max(0, (this.value - this.min) / span));
62
+ const lo = Math.min(this.min, this.max);
63
+ const hi = Math.max(this.min, this.max);
64
+ const span = hi - lo || 1;
65
+ return Math.min(1, Math.max(0, (this.value - lo) / span));
64
66
  }
65
67
  willUpdate() {
66
68
  this.setAttribute('role', 'meter');
67
- if (!isNaN(this.value) && !isNaN(this.min) && !isNaN(this.max)) {
68
- const clamped = Math.min(this.max, Math.max(this.min, this.value));
69
+ const finiteTrio = Number.isFinite(this.value) && Number.isFinite(this.min) && Number.isFinite(this.max);
70
+ // Normalize a reversed min > max domain the same way `ratio` does, so the
71
+ // announced aria-value* trio always agrees with the visual fill instead
72
+ // of aria-valuenow pinning to one bound regardless of `value` (and
73
+ // aria-valuemin/valuemax reporting an inverted, invalid ARIA range).
74
+ const lo = Number.isFinite(this.min) && Number.isFinite(this.max) ? Math.min(this.min, this.max) : this.min;
75
+ const hi = Number.isFinite(this.min) && Number.isFinite(this.max) ? Math.max(this.min, this.max) : this.max;
76
+ if (finiteTrio) {
77
+ const clamped = Math.min(hi, Math.max(lo, this.value));
69
78
  this.setAttribute('aria-valuenow', String(clamped));
70
79
  }
71
80
  else {
72
81
  this.removeAttribute('aria-valuenow');
73
82
  }
74
- if (isNaN(this.min))
83
+ if (Number.isFinite(lo))
84
+ this.setAttribute('aria-valuemin', String(lo));
85
+ else
75
86
  this.removeAttribute('aria-valuemin');
87
+ if (Number.isFinite(hi))
88
+ this.setAttribute('aria-valuemax', String(hi));
76
89
  else
77
- this.setAttribute('aria-valuemin', String(this.min));
78
- if (isNaN(this.max))
79
90
  this.removeAttribute('aria-valuemax');
80
- else
81
- this.setAttribute('aria-valuemax', String(this.max));
82
91
  if (this.label)
83
92
  this.setAttribute('aria-label', this.label);
84
93
  else
@@ -0,0 +1,109 @@
1
+ import { type TemplateResult, type PropertyValues } from 'lit';
2
+ import { LyraElement } from '../../internal/lyra-element.js';
3
+ /**
4
+ * `<lyra-generation-status>` — a compact, ticking status readout shown
5
+ * alongside an in-progress AI response: elapsed time, token count, and
6
+ * token-throughput, plus a built-in Stop button. Renders as e.g.
7
+ * `12.3s · 340 tokens · 27 tok/s [Stop]`.
8
+ *
9
+ * This is deliberately a *different* concern than the already-landed
10
+ * `<lyra-stream-status>`: that component is about transport/connection
11
+ * health (idle/connecting/streaming/stalled, heartbeat-aware stall
12
+ * detection), while this one is a user-facing metrics readout for a
13
+ * generation that both components' hosts typically already know is
14
+ * healthily in progress. Neither imports or depends on the other, and a
15
+ * consumer building a full generation UI is expected to compose both side by
16
+ * side rather than pick one.
17
+ *
18
+ * `active` drives an internal ~1s `setInterval` ticker that recomputes the
19
+ * elapsed-time display (a plain interval is sufficient here -- unlike
20
+ * `<lyra-stream-status>`'s stall timer, this never needs to be armed with a
21
+ * precise deadline, only to refresh a display roughly once a second). The
22
+ * elapsed clock's start instant is `started-at` when set (an epoch-ms
23
+ * timestamp -- lets a host that already knows exactly when generation began,
24
+ * e.g. from its own request-dispatch timestamp, feed that in directly and
25
+ * survive this component being created slightly later than that instant);
26
+ * when `started-at` is unset, this component falls back to capturing
27
+ * `Date.now()` itself at the moment `active` flips from `false`/unset to
28
+ * `true`, so the ticker still starts from a sensible instant with zero
29
+ * required host bookkeeping. The ticker is cleared whenever `active` becomes
30
+ * `false` and on disconnect; the display is left at whatever it last showed
31
+ * (frozen, not reset to zero) -- a static "Generated in 12.3s" reads better
32
+ * as a completed-state summary than the readout blanking out the instant
33
+ * generation ends.
34
+ *
35
+ * `tokens-per-second`, when the host supplies it directly (e.g. from its own
36
+ * smoothed/windowed rate calculation), is always used as-is. When omitted,
37
+ * this component derives a live figure itself from `token-count` divided by
38
+ * elapsed seconds -- but only once at least one full second of elapsed time
39
+ * has accumulated, since dividing by a sub-second elapsed window can produce
40
+ * wildly-swinging, misleading early readings (e.g. 3 tokens in 40ms reading
41
+ * as "75 tok/s"). A host that wants a stable figure from the very first tick
42
+ * should supply `tokens-per-second` itself. The tokens segment and the
43
+ * throughput segment are independently optional: either, both, or neither
44
+ * may render depending on what's available, per each property's own doc.
45
+ *
46
+ * Accessibility: this readout ticks roughly once per second while active,
47
+ * which is exactly the kind of high-frequency update
48
+ * `<lyra-live-region>`/`Announcer` (`../../internal/announcer.js`) exists to
49
+ * *prevent* from being read aloud verbatim -- routing a per-second numeric
50
+ * tick through even a throttled announcer would still narrate a new number
51
+ * to a screen-reader user roughly once every throttle window for as long as
52
+ * generation runs, which is noise, not information. This component
53
+ * therefore carries no `role="status"`/`aria-live` of its own and never
54
+ * announces anything; a host that wants generation-start/-end announced
55
+ * should pair this with something that announces state *transitions* (e.g.
56
+ * `<lyra-typing-indicator>`'s mount-time announcement), not this ticking
57
+ * readout. The one genuinely actionable, infrequent control here -- the Stop
58
+ * button -- gets a normal, always-present `aria-label`, no different from
59
+ * any other icon-only button in this library.
60
+ *
61
+ * @customElement lyra-generation-status
62
+ * @event lyra-stop - The built-in Stop button was clicked. No detail payload.
63
+ * @csspart base - The root inline layout container.
64
+ * @csspart elapsed - The elapsed-time segment, e.g. `"12.3s"`. Always rendered (reads `"0.0s"` before the component has ever been active).
65
+ * @csspart tokens - The token-count segment, e.g. `"340 tokens"`. Only rendered when `token-count` is set.
66
+ * @csspart throughput - The throughput segment, e.g. `"27 tok/s"`. Only rendered when a value is available (host-supplied or derived; see the class doc).
67
+ * @csspart stop-button - The built-in Stop button. Only rendered while `show-stop` is true.
68
+ */
69
+ export declare class LyraGenerationStatus extends LyraElement {
70
+ static styles: import("lit").CSSResultGroup[];
71
+ /** Whether generation is currently in progress. The elapsed-time ticker
72
+ * runs only while this is `true` (see the class doc). */
73
+ active: boolean;
74
+ /** Epoch-ms timestamp of when generation began. Optional -- when unset
75
+ * while `active` is `true`, this component captures the current time
76
+ * itself the moment `active` becomes `true` and counts from there instead
77
+ * (see the class doc). */
78
+ startedAt?: number;
79
+ /** Running token count so far. Omitted from the readout entirely (no
80
+ * `tokens` segment) while unset. */
81
+ tokenCount?: number;
82
+ /** Host-computed tokens/sec figure, used as-is when set. When unset, this
83
+ * component derives a live figure from `token-count` and elapsed time
84
+ * itself once one is available -- see the class doc for the exact rule
85
+ * and why. */
86
+ tokensPerSecond?: number;
87
+ /** Whether the built-in Stop button renders at all. */
88
+ showStop: boolean;
89
+ private elapsedMs;
90
+ private tickTimer?;
91
+ private fallbackStartMs?;
92
+ disconnectedCallback(): void;
93
+ protected willUpdate(changed: PropertyValues): void;
94
+ protected updated(changed: PropertyValues): void;
95
+ private startTicker;
96
+ private stopTicker;
97
+ private computeElapsedMs;
98
+ /** `tokens-per-second` when set; otherwise a derived figure once enough
99
+ * elapsed time has accumulated for it to be meaningful; otherwise
100
+ * `undefined` (the throughput segment doesn't render at all). */
101
+ private get effectiveTokensPerSecond();
102
+ private onStopClick;
103
+ render(): TemplateResult;
104
+ }
105
+ declare global {
106
+ interface HTMLElementTagNameMap {
107
+ 'lyra-generation-status': LyraGenerationStatus;
108
+ }
109
+ }
@@ -0,0 +1,273 @@
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 { styles } from './generation-status.styles.js';
12
+ // Mirrors the shared icon set's viewBox/stroke conventions
13
+ // (internal/icons.ts's chevronIcon()/closeIcon()/etc.) without adding a
14
+ // stop glyph to that module -- it's off limits here -- so this one-off icon
15
+ // still reads as part of the same visual language as the rest of the
16
+ // library's inline icons. Identical shape to `<lyra-chat-composer>`'s own
17
+ // local `stopIcon()` (the conventional filled-square "stop generating"
18
+ // glyph), duplicated rather than imported since these are two independently
19
+ // consumable components with no dependency between them.
20
+ function stopIcon() {
21
+ return svg `
22
+ <svg
23
+ width="1em"
24
+ height="1em"
25
+ viewBox="0 0 24 24"
26
+ fill="currentColor"
27
+ stroke="none"
28
+ aria-hidden="true"
29
+ focusable="false"
30
+ ><rect x="6" y="6" width="12" height="12" rx="1.5"></rect></svg>
31
+ `;
32
+ }
33
+ /** `4200` -> `"4.2s"`; `65000` -> `"1m 5s"`. Sub-minute durations get one
34
+ * decimal place of seconds (the common case: most single generations finish
35
+ * in single-digit seconds, where whole-second precision would look static
36
+ * between ticks); once a full minute is reached, `"Xm Ys"` reads better than
37
+ * a fractional-minute or a 3-4 digit seconds count. The `59.95` cutoff (not
38
+ * a plain `60`) exists so a value that *rounds* to `"60.0s"` at one-decimal
39
+ * precision is displayed as `"1m 0s"` instead -- without it, the two
40
+ * branches could each independently round the same instant to a different
41
+ * minute. */
42
+ function formatElapsed(ms) {
43
+ const totalSeconds = Math.max(0, ms) / 1000;
44
+ if (totalSeconds < 59.95) {
45
+ return `${(Math.round(totalSeconds * 10) / 10).toFixed(1)}s`;
46
+ }
47
+ const wholeSeconds = Math.round(totalSeconds);
48
+ const minutes = Math.floor(wholeSeconds / 60);
49
+ const seconds = wholeSeconds % 60;
50
+ return `${minutes}m ${seconds}s`;
51
+ }
52
+ /** `340` -> `"340 tokens"`; `1` -> `"1 token"`. Same plain singular/plural
53
+ * ternary `<lyra-json-viewer>`'s array/object summary already uses -- this
54
+ * library has no general i18n/pluralization system (see
55
+ * `<lyra-source-list>`'s class doc for that stance), but a two-way English
56
+ * ternary for one fixed noun is a different, much smaller thing than a
57
+ * general pluralization engine, and reads better than an unconditional
58
+ * "1 tokens". */
59
+ function formatTokenCount(count) {
60
+ const rounded = Math.max(0, Math.round(count));
61
+ return `${rounded} ${rounded === 1 ? 'token' : 'tokens'}`;
62
+ }
63
+ /** `27.4` -> `"27 tok/s"`; `3.2` -> `"3.2 tok/s"`. Same shape as this file's
64
+ * `formatElapsed`/`<lyra-tool-call-chip>`'s `formatDuration`: the low end of
65
+ * the range (where a whole-number rounding would flatten every early
66
+ * reading to the same "0" or "1") gets one decimal place, while anything at
67
+ * or above 10 tok/s rounds to a whole number, which is plenty precise for a
68
+ * live-updating throughput figure. */
69
+ function formatThroughput(value) {
70
+ const clamped = Math.max(0, value);
71
+ const rounded = clamped < 10 ? Math.round(clamped * 10) / 10 : Math.round(clamped);
72
+ return `${rounded} tok/s`;
73
+ }
74
+ /**
75
+ * `<lyra-generation-status>` — a compact, ticking status readout shown
76
+ * alongside an in-progress AI response: elapsed time, token count, and
77
+ * token-throughput, plus a built-in Stop button. Renders as e.g.
78
+ * `12.3s · 340 tokens · 27 tok/s [Stop]`.
79
+ *
80
+ * This is deliberately a *different* concern than the already-landed
81
+ * `<lyra-stream-status>`: that component is about transport/connection
82
+ * health (idle/connecting/streaming/stalled, heartbeat-aware stall
83
+ * detection), while this one is a user-facing metrics readout for a
84
+ * generation that both components' hosts typically already know is
85
+ * healthily in progress. Neither imports or depends on the other, and a
86
+ * consumer building a full generation UI is expected to compose both side by
87
+ * side rather than pick one.
88
+ *
89
+ * `active` drives an internal ~1s `setInterval` ticker that recomputes the
90
+ * elapsed-time display (a plain interval is sufficient here -- unlike
91
+ * `<lyra-stream-status>`'s stall timer, this never needs to be armed with a
92
+ * precise deadline, only to refresh a display roughly once a second). The
93
+ * elapsed clock's start instant is `started-at` when set (an epoch-ms
94
+ * timestamp -- lets a host that already knows exactly when generation began,
95
+ * e.g. from its own request-dispatch timestamp, feed that in directly and
96
+ * survive this component being created slightly later than that instant);
97
+ * when `started-at` is unset, this component falls back to capturing
98
+ * `Date.now()` itself at the moment `active` flips from `false`/unset to
99
+ * `true`, so the ticker still starts from a sensible instant with zero
100
+ * required host bookkeeping. The ticker is cleared whenever `active` becomes
101
+ * `false` and on disconnect; the display is left at whatever it last showed
102
+ * (frozen, not reset to zero) -- a static "Generated in 12.3s" reads better
103
+ * as a completed-state summary than the readout blanking out the instant
104
+ * generation ends.
105
+ *
106
+ * `tokens-per-second`, when the host supplies it directly (e.g. from its own
107
+ * smoothed/windowed rate calculation), is always used as-is. When omitted,
108
+ * this component derives a live figure itself from `token-count` divided by
109
+ * elapsed seconds -- but only once at least one full second of elapsed time
110
+ * has accumulated, since dividing by a sub-second elapsed window can produce
111
+ * wildly-swinging, misleading early readings (e.g. 3 tokens in 40ms reading
112
+ * as "75 tok/s"). A host that wants a stable figure from the very first tick
113
+ * should supply `tokens-per-second` itself. The tokens segment and the
114
+ * throughput segment are independently optional: either, both, or neither
115
+ * may render depending on what's available, per each property's own doc.
116
+ *
117
+ * Accessibility: this readout ticks roughly once per second while active,
118
+ * which is exactly the kind of high-frequency update
119
+ * `<lyra-live-region>`/`Announcer` (`../../internal/announcer.js`) exists to
120
+ * *prevent* from being read aloud verbatim -- routing a per-second numeric
121
+ * tick through even a throttled announcer would still narrate a new number
122
+ * to a screen-reader user roughly once every throttle window for as long as
123
+ * generation runs, which is noise, not information. This component
124
+ * therefore carries no `role="status"`/`aria-live` of its own and never
125
+ * announces anything; a host that wants generation-start/-end announced
126
+ * should pair this with something that announces state *transitions* (e.g.
127
+ * `<lyra-typing-indicator>`'s mount-time announcement), not this ticking
128
+ * readout. The one genuinely actionable, infrequent control here -- the Stop
129
+ * button -- gets a normal, always-present `aria-label`, no different from
130
+ * any other icon-only button in this library.
131
+ *
132
+ * @customElement lyra-generation-status
133
+ * @event lyra-stop - The built-in Stop button was clicked. No detail payload.
134
+ * @csspart base - The root inline layout container.
135
+ * @csspart elapsed - The elapsed-time segment, e.g. `"12.3s"`. Always rendered (reads `"0.0s"` before the component has ever been active).
136
+ * @csspart tokens - The token-count segment, e.g. `"340 tokens"`. Only rendered when `token-count` is set.
137
+ * @csspart throughput - The throughput segment, e.g. `"27 tok/s"`. Only rendered when a value is available (host-supplied or derived; see the class doc).
138
+ * @csspart stop-button - The built-in Stop button. Only rendered while `show-stop` is true.
139
+ */
140
+ export class LyraGenerationStatus extends LyraElement {
141
+ constructor() {
142
+ super(...arguments);
143
+ /** Whether generation is currently in progress. The elapsed-time ticker
144
+ * runs only while this is `true` (see the class doc). */
145
+ this.active = false;
146
+ /** Whether the built-in Stop button renders at all. */
147
+ this.showStop = true;
148
+ // Recomputed on activation and on every ~1s tick; frozen (not reset) once
149
+ // `active` goes false -- see the class doc's "ticker" paragraph.
150
+ this.elapsedMs = 0;
151
+ this.onStopClick = () => {
152
+ this.emit('lyra-stop');
153
+ };
154
+ }
155
+ static { this.styles = [LyraElement.styles, styles]; }
156
+ disconnectedCallback() {
157
+ super.disconnectedCallback();
158
+ this.stopTicker();
159
+ }
160
+ // Recomputing `elapsedMs` here (rather than in `updated()`) matters: Lit
161
+ // runs `willUpdate()` *before* render, as part of the same update pass, so
162
+ // a property set here is picked up by this same render with no extra
163
+ // cycle. Setting a reactive property from inside `updated()` instead would
164
+ // schedule a *second* update after the first has already completed (Lit
165
+ // warns about exactly this in dev mode) -- meaning a caller doing
166
+ // `el.active = true; await el.updateComplete;` would still observe the
167
+ // stale pre-activation `elapsedMs` once that first promise resolves.
168
+ //
169
+ // `changed.has('active')` fires on the very first update too when the
170
+ // element mounts already `active` (the parsed-attribute/property value
171
+ // differs from the `false` field-initializer default that was seen first)
172
+ // -- same mechanism `<lyra-stream-status>`'s `onPhaseChanged` relies on to
173
+ // arm its stall timer on a `phase="streaming"` mount, so mounting this
174
+ // component already active correctly seeds `elapsedMs` with no separate
175
+ // first-update special case needed.
176
+ willUpdate(changed) {
177
+ if (changed.has('active') && this.active) {
178
+ if (this.startedAt == null)
179
+ this.fallbackStartMs = Date.now();
180
+ this.elapsedMs = this.computeElapsedMs();
181
+ }
182
+ else if (this.active && changed.has('startedAt')) {
183
+ // A `started-at` that arrives (or changes) mid-generation should
184
+ // immediately re-baseline the displayed elapsed time rather than wait
185
+ // up to ~1s for the next tick.
186
+ this.elapsedMs = this.computeElapsedMs();
187
+ }
188
+ }
189
+ // Starting/stopping the interval is a genuine side effect (not a reactive-
190
+ // property write), so it belongs in `updated()`, unlike the `elapsedMs`
191
+ // computation above.
192
+ updated(changed) {
193
+ if (changed.has('active')) {
194
+ if (this.active)
195
+ this.startTicker();
196
+ else
197
+ this.stopTicker();
198
+ }
199
+ }
200
+ startTicker() {
201
+ this.stopTicker();
202
+ // Setting `elapsedMs` here (unlike inside `updated()`, see that method's
203
+ // doc) is fine: an interval callback is a wholly separate future task,
204
+ // not a continuation of an in-progress Lit update, so this starts a
205
+ // normal, self-contained update cycle rather than a same-tick "second
206
+ // update" scheduled mid-render.
207
+ this.tickTimer = setInterval(() => {
208
+ this.elapsedMs = this.computeElapsedMs();
209
+ }, 1000);
210
+ }
211
+ stopTicker() {
212
+ if (this.tickTimer !== undefined) {
213
+ clearInterval(this.tickTimer);
214
+ this.tickTimer = undefined;
215
+ }
216
+ }
217
+ computeElapsedMs() {
218
+ const start = this.startedAt ?? this.fallbackStartMs;
219
+ return start == null ? 0 : Math.max(0, Date.now() - start);
220
+ }
221
+ /** `tokens-per-second` when set; otherwise a derived figure once enough
222
+ * elapsed time has accumulated for it to be meaningful; otherwise
223
+ * `undefined` (the throughput segment doesn't render at all). */
224
+ get effectiveTokensPerSecond() {
225
+ if (this.tokensPerSecond != null && Number.isFinite(this.tokensPerSecond)) {
226
+ return this.tokensPerSecond;
227
+ }
228
+ if (this.tokenCount != null && Number.isFinite(this.tokenCount)) {
229
+ const elapsedSeconds = this.elapsedMs / 1000;
230
+ if (elapsedSeconds >= 1)
231
+ return this.tokenCount / elapsedSeconds;
232
+ }
233
+ return undefined;
234
+ }
235
+ render() {
236
+ const hasTokens = this.tokenCount != null && Number.isFinite(this.tokenCount);
237
+ const throughput = this.effectiveTokensPerSecond;
238
+ const hasThroughput = throughput !== undefined;
239
+ return html `
240
+ <div part="base">
241
+ <span part="elapsed">${formatElapsed(this.elapsedMs)}</span>
242
+ ${hasTokens ? html `<span part="tokens">${formatTokenCount(this.tokenCount)}</span>` : nothing}
243
+ ${hasThroughput ? html `<span part="throughput">${formatThroughput(throughput)}</span>` : nothing}
244
+ ${this.showStop
245
+ ? html `
246
+ <button part="stop-button" type="button" aria-label="Stop generating" @click=${this.onStopClick}>
247
+ ${stopIcon()}
248
+ </button>
249
+ `
250
+ : nothing}
251
+ </div>
252
+ `;
253
+ }
254
+ }
255
+ __decorate([
256
+ property({ type: Boolean, reflect: true })
257
+ ], LyraGenerationStatus.prototype, "active", void 0);
258
+ __decorate([
259
+ property({ type: Number, attribute: 'started-at' })
260
+ ], LyraGenerationStatus.prototype, "startedAt", void 0);
261
+ __decorate([
262
+ property({ type: Number, attribute: 'token-count' })
263
+ ], LyraGenerationStatus.prototype, "tokenCount", void 0);
264
+ __decorate([
265
+ property({ type: Number, attribute: 'tokens-per-second' })
266
+ ], LyraGenerationStatus.prototype, "tokensPerSecond", void 0);
267
+ __decorate([
268
+ property({ type: Boolean, attribute: 'show-stop' })
269
+ ], LyraGenerationStatus.prototype, "showStop", void 0);
270
+ __decorate([
271
+ state()
272
+ ], LyraGenerationStatus.prototype, "elapsedMs", void 0);
273
+ defineElement('generation-status', LyraGenerationStatus);
@@ -0,0 +1 @@
1
+ export declare const styles: import("lit").CSSResult;
@@ -0,0 +1,84 @@
1
+ import { css } from 'lit';
2
+ export const styles = css `
3
+ :host {
4
+ display: inline-flex;
5
+ vertical-align: middle;
6
+ max-inline-size: 100%;
7
+ }
8
+
9
+ [part='base'] {
10
+ display: inline-flex;
11
+ align-items: center;
12
+ max-inline-size: 100%;
13
+ font-size: 0.8125rem;
14
+ line-height: 1.3;
15
+ color: var(--lyra-color-text-quiet);
16
+ }
17
+
18
+ [part='elapsed'] {
19
+ /* Full-strength text, not the quieter --lyra-color-text-quiet the rest
20
+ of the readout uses -- elapsed time is the one figure this component
21
+ always shows (tokens/throughput are optional), so it gets the higher-
22
+ contrast treatment to read as the primary value at a glance. */
23
+ color: var(--lyra-color-text);
24
+ font-variant-numeric: tabular-nums;
25
+ white-space: nowrap;
26
+ }
27
+ [part='tokens'],
28
+ [part='throughput'] {
29
+ font-variant-numeric: tabular-nums;
30
+ white-space: nowrap;
31
+ }
32
+
33
+ /* Segments are joined with a middot rather than a flex gap + separate
34
+ separator element, so a segment that doesn't render (tokens/throughput
35
+ are both optional, see the class doc) never leaves a dangling
36
+ double-gap -- the dot only ever appears immediately before a segment
37
+ that's actually present. */
38
+ [part='tokens']::before,
39
+ [part='throughput']::before {
40
+ content: '·';
41
+ margin-inline: 0.4em;
42
+ opacity: 0.6;
43
+ }
44
+
45
+ [part='stop-button'] {
46
+ flex: 0 0 auto;
47
+ display: inline-flex;
48
+ align-items: center;
49
+ justify-content: center;
50
+ /* Same "shrink the shared icon-button token for a compact inline
51
+ control" idiom as lyra-attachment-chip's retry-/remove-button. */
52
+ min-inline-size: min(var(--lyra-icon-button-size), 1.75rem);
53
+ min-block-size: min(var(--lyra-icon-button-size), 1.75rem);
54
+ margin-inline-start: var(--lyra-space-s);
55
+ padding: 0;
56
+ border: 1px solid var(--lyra-color-border);
57
+ border-radius: 50%;
58
+ background: var(--lyra-color-surface);
59
+ color: var(--lyra-color-text);
60
+ cursor: pointer;
61
+ -webkit-tap-highlight-color: transparent;
62
+ transition:
63
+ background-color var(--lyra-transition-fast),
64
+ border-color var(--lyra-transition-fast),
65
+ color var(--lyra-transition-fast);
66
+ }
67
+ [part='stop-button']:hover {
68
+ border-color: var(--lyra-color-brand);
69
+ color: var(--lyra-color-brand);
70
+ }
71
+ [part='stop-button']:focus-visible {
72
+ outline: var(--lyra-focus-ring-width) solid var(--lyra-focus-ring-color);
73
+ outline-offset: var(--lyra-focus-ring-offset);
74
+ }
75
+ [part='stop-button'] svg {
76
+ display: block;
77
+ }
78
+
79
+ @media (prefers-reduced-motion: reduce) {
80
+ [part='stop-button'] {
81
+ transition: none !important;
82
+ }
83
+ }
84
+ `;