@aceshooting/lyra-ui 1.2.0 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (384) hide show
  1. package/README.md +98 -14
  2. package/custom-elements.json +30279 -12124
  3. package/dist/components/app-rail/app-rail-item.d.ts +30 -0
  4. package/dist/components/app-rail/app-rail-item.js +68 -0
  5. package/dist/components/app-rail/app-rail-item.styles.d.ts +1 -0
  6. package/dist/components/app-rail/app-rail-item.styles.js +65 -0
  7. package/dist/components/app-rail/app-rail.d.ts +168 -0
  8. package/dist/components/app-rail/app-rail.js +419 -0
  9. package/dist/components/app-rail/app-rail.styles.d.ts +1 -0
  10. package/dist/components/app-rail/app-rail.styles.js +128 -0
  11. package/dist/components/attachment-chip/attachment-chip.d.ts +141 -0
  12. package/dist/components/attachment-chip/attachment-chip.js +356 -0
  13. package/dist/components/attachment-chip/attachment-chip.styles.d.ts +1 -0
  14. package/dist/components/attachment-chip/attachment-chip.styles.js +184 -0
  15. package/dist/components/attachment-trigger/attachment-trigger.d.ts +96 -0
  16. package/dist/components/attachment-trigger/attachment-trigger.js +270 -0
  17. package/dist/components/attachment-trigger/attachment-trigger.styles.d.ts +1 -0
  18. package/dist/components/attachment-trigger/attachment-trigger.styles.js +90 -0
  19. package/dist/components/chart/bar-chart.js +2 -18
  20. package/dist/components/chart/box-plot.d.ts +25 -1
  21. package/dist/components/chart/box-plot.js +147 -7
  22. package/dist/components/chart/box-plot.styles.js +13 -0
  23. package/dist/components/chart/bubble-chart.js +2 -18
  24. package/dist/components/chart/chart-loader.d.ts +44 -13
  25. package/dist/components/chart/chart-loader.js +65 -18
  26. package/dist/components/chart/chart.d.ts +55 -12
  27. package/dist/components/chart/chart.js +247 -49
  28. package/dist/components/chart/doughnut-chart.js +2 -18
  29. package/dist/components/chart/histogram-bin.d.ts +7 -1
  30. package/dist/components/chart/histogram-bin.js +32 -14
  31. package/dist/components/chart/histogram.js +8 -16
  32. package/dist/components/chart/line-chart.js +2 -18
  33. package/dist/components/chart/lite-chart.d.ts +134 -3
  34. package/dist/components/chart/lite-chart.js +382 -67
  35. package/dist/components/chart/lite-chart.styles.js +9 -0
  36. package/dist/components/chart/pie-chart.js +2 -18
  37. package/dist/components/chart/polar-area-chart.js +2 -18
  38. package/dist/components/chart/radar-chart.js +2 -18
  39. package/dist/components/chart/scatter-chart.js +2 -18
  40. package/dist/components/chat-composer/chat-composer.d.ts +133 -0
  41. package/dist/components/chat-composer/chat-composer.js +366 -0
  42. package/dist/components/chat-composer/chat-composer.styles.d.ts +1 -0
  43. package/dist/components/chat-composer/chat-composer.styles.js +145 -0
  44. package/dist/components/chat-message/chat-message.d.ts +141 -0
  45. package/dist/components/chat-message/chat-message.js +331 -0
  46. package/dist/components/chat-message/chat-message.styles.d.ts +1 -0
  47. package/dist/components/chat-message/chat-message.styles.js +203 -0
  48. package/dist/components/checkbox/checkbox.d.ts +117 -0
  49. package/dist/components/checkbox/checkbox.js +353 -0
  50. package/dist/components/checkbox/checkbox.styles.d.ts +1 -0
  51. package/dist/components/checkbox/checkbox.styles.js +77 -0
  52. package/dist/components/chip/chip-group.d.ts +56 -0
  53. package/dist/components/chip/chip-group.js +130 -0
  54. package/dist/components/chip/chip-group.styles.d.ts +1 -0
  55. package/dist/components/chip/chip-group.styles.js +57 -0
  56. package/dist/components/chip/chip.d.ts +64 -0
  57. package/dist/components/chip/chip.js +122 -0
  58. package/dist/components/chip/chip.styles.d.ts +1 -0
  59. package/dist/components/chip/chip.styles.js +115 -0
  60. package/dist/components/citation-badge/citation-badge.d.ts +113 -0
  61. package/dist/components/citation-badge/citation-badge.js +318 -0
  62. package/dist/components/citation-badge/citation-badge.styles.d.ts +1 -0
  63. package/dist/components/citation-badge/citation-badge.styles.js +96 -0
  64. package/dist/components/code-block/code-block.d.ts +127 -0
  65. package/dist/components/code-block/code-block.js +382 -0
  66. package/dist/components/code-block/code-block.styles.d.ts +1 -0
  67. package/dist/components/code-block/code-block.styles.js +187 -0
  68. package/dist/components/code-block/code-loader.d.ts +87 -0
  69. package/dist/components/code-block/code-loader.js +142 -0
  70. package/dist/components/combobox/combobox.d.ts +65 -6
  71. package/dist/components/combobox/combobox.js +258 -48
  72. package/dist/components/combobox/combobox.styles.js +3 -3
  73. package/dist/components/combobox/option.d.ts +5 -1
  74. package/dist/components/combobox/option.js +35 -0
  75. package/dist/components/context-meter/context-meter.d.ts +53 -0
  76. package/dist/components/context-meter/context-meter.js +159 -0
  77. package/dist/components/context-meter/context-meter.styles.d.ts +1 -0
  78. package/dist/components/context-meter/context-meter.styles.js +114 -0
  79. package/dist/components/conversation-item/conversation-item.d.ts +125 -0
  80. package/dist/components/conversation-item/conversation-item.js +331 -0
  81. package/dist/components/conversation-item/conversation-item.styles.d.ts +1 -0
  82. package/dist/components/conversation-item/conversation-item.styles.js +155 -0
  83. package/dist/components/date-picker/calendar-core.d.ts +24 -0
  84. package/dist/components/date-picker/calendar-core.js +51 -4
  85. package/dist/components/date-picker/date-input.d.ts +100 -9
  86. package/dist/components/date-picker/date-input.js +383 -66
  87. package/dist/components/date-picker/date-picker.d.ts +35 -4
  88. package/dist/components/date-picker/date-picker.js +171 -44
  89. package/dist/components/dialog/confirm.d.ts +40 -0
  90. package/dist/components/dialog/confirm.js +76 -0
  91. package/dist/components/dialog/dialog.d.ts +129 -0
  92. package/dist/components/dialog/dialog.js +288 -0
  93. package/dist/components/dialog/dialog.styles.d.ts +1 -0
  94. package/dist/components/dialog/dialog.styles.js +96 -0
  95. package/dist/components/dock-panel/dock-panel.d.ts +142 -0
  96. package/dist/components/dock-panel/dock-panel.js +359 -0
  97. package/dist/components/dock-panel/dock-panel.styles.d.ts +1 -0
  98. package/dist/components/dock-panel/dock-panel.styles.js +159 -0
  99. package/dist/components/document-preview/document-preview.d.ts +143 -0
  100. package/dist/components/document-preview/document-preview.js +388 -0
  101. package/dist/components/document-preview/document-preview.styles.d.ts +1 -0
  102. package/dist/components/document-preview/document-preview.styles.js +191 -0
  103. package/dist/components/empty/empty.d.ts +1 -2
  104. package/dist/components/empty/empty.js +18 -12
  105. package/dist/components/empty/empty.styles.js +0 -3
  106. package/dist/components/export-button/csv.js +1 -1
  107. package/dist/components/export-button/export-button.d.ts +12 -0
  108. package/dist/components/export-button/export-button.js +35 -5
  109. package/dist/components/export-button/export-button.styles.js +5 -1
  110. package/dist/components/file-input/accept.js +2 -0
  111. package/dist/components/file-input/file-input.d.ts +10 -1
  112. package/dist/components/file-input/file-input.js +36 -5
  113. package/dist/components/flag/flag.d.ts +29 -13
  114. package/dist/components/flag/flag.js +54 -14
  115. package/dist/components/flag/flag.styles.js +1 -1
  116. package/dist/components/flag/language-map.d.ts +4 -1
  117. package/dist/components/flag/language-map.js +6 -3
  118. package/dist/components/gauge/gauge.d.ts +10 -1
  119. package/dist/components/gauge/gauge.js +41 -13
  120. package/dist/components/generation-status/generation-status.d.ts +117 -0
  121. package/dist/components/generation-status/generation-status.js +327 -0
  122. package/dist/components/generation-status/generation-status.styles.d.ts +1 -0
  123. package/dist/components/generation-status/generation-status.styles.js +84 -0
  124. package/dist/components/graph/graph.d.ts +37 -3
  125. package/dist/components/graph/graph.js +132 -20
  126. package/dist/components/heatmap/calendar-grid.d.ts +19 -7
  127. package/dist/components/heatmap/calendar-grid.js +42 -18
  128. package/dist/components/heatmap/heatmap-scale.d.ts +11 -1
  129. package/dist/components/heatmap/heatmap-scale.js +14 -2
  130. package/dist/components/heatmap/heatmap.d.ts +227 -12
  131. package/dist/components/heatmap/heatmap.js +488 -93
  132. package/dist/components/json-viewer/json-viewer.d.ts +70 -0
  133. package/dist/components/json-viewer/json-viewer.js +361 -0
  134. package/dist/components/json-viewer/json-viewer.styles.d.ts +1 -0
  135. package/dist/components/json-viewer/json-viewer.styles.js +177 -0
  136. package/dist/components/kbd/kbd.d.ts +77 -0
  137. package/dist/components/kbd/kbd.js +231 -0
  138. package/dist/components/kbd/kbd.styles.d.ts +1 -0
  139. package/dist/components/kbd/kbd.styles.js +52 -0
  140. package/dist/components/live-region/live-region.d.ts +90 -0
  141. package/dist/components/live-region/live-region.js +189 -0
  142. package/dist/components/live-region/live-region.styles.d.ts +1 -0
  143. package/dist/components/live-region/live-region.styles.js +10 -0
  144. package/dist/components/map/map.d.ts +32 -7
  145. package/dist/components/map/map.js +133 -32
  146. package/dist/components/markdown/markdown-loader.d.ts +58 -0
  147. package/dist/components/markdown/markdown-loader.js +77 -0
  148. package/dist/components/markdown/markdown.d.ts +119 -0
  149. package/dist/components/markdown/markdown.js +389 -0
  150. package/dist/components/markdown/markdown.styles.d.ts +1 -0
  151. package/dist/components/markdown/markdown.styles.js +88 -0
  152. package/dist/components/media-card/media-card.d.ts +130 -0
  153. package/dist/components/media-card/media-card.js +273 -0
  154. package/dist/components/media-card/media-card.styles.d.ts +1 -0
  155. package/dist/components/media-card/media-card.styles.js +132 -0
  156. package/dist/components/mention-popover/mention-popover.d.ts +203 -0
  157. package/dist/components/mention-popover/mention-popover.js +493 -0
  158. package/dist/components/mention-popover/mention-popover.styles.d.ts +1 -0
  159. package/dist/components/mention-popover/mention-popover.styles.js +101 -0
  160. package/dist/components/menu/menu-item.d.ts +91 -0
  161. package/dist/components/menu/menu-item.js +206 -0
  162. package/dist/components/menu/menu-item.styles.d.ts +1 -0
  163. package/dist/components/menu/menu-item.styles.js +75 -0
  164. package/dist/components/menu/menu.d.ts +167 -0
  165. package/dist/components/menu/menu.js +461 -0
  166. package/dist/components/menu/menu.styles.d.ts +1 -0
  167. package/dist/components/menu/menu.styles.js +67 -0
  168. package/dist/components/model-select/model-select.d.ts +170 -0
  169. package/dist/components/model-select/model-select.js +588 -0
  170. package/dist/components/model-select/model-select.styles.d.ts +1 -0
  171. package/dist/components/model-select/model-select.styles.js +203 -0
  172. package/dist/components/model-settings-panel/model-settings-panel.d.ts +93 -0
  173. package/dist/components/model-settings-panel/model-settings-panel.js +209 -0
  174. package/dist/components/model-settings-panel/model-settings-panel.styles.d.ts +1 -0
  175. package/dist/components/model-settings-panel/model-settings-panel.styles.js +82 -0
  176. package/dist/components/playback/playback.d.ts +19 -3
  177. package/dist/components/playback/playback.js +109 -33
  178. package/dist/components/playback/playback.styles.js +6 -1
  179. package/dist/components/responsive-panel/responsive-panel.d.ts +163 -0
  180. package/dist/components/responsive-panel/responsive-panel.js +363 -0
  181. package/dist/components/responsive-panel/responsive-panel.styles.d.ts +1 -0
  182. package/dist/components/responsive-panel/responsive-panel.styles.js +103 -0
  183. package/dist/components/result-card/result-card.d.ts +50 -0
  184. package/dist/components/result-card/result-card.js +89 -0
  185. package/dist/components/result-card/result-card.styles.d.ts +1 -0
  186. package/dist/components/result-card/result-card.styles.js +49 -0
  187. package/dist/components/result-card/result-field.d.ts +36 -0
  188. package/dist/components/result-card/result-field.js +87 -0
  189. package/dist/components/result-card/result-field.styles.d.ts +1 -0
  190. package/dist/components/result-card/result-field.styles.js +32 -0
  191. package/dist/components/select/select.d.ts +84 -4
  192. package/dist/components/select/select.js +251 -36
  193. package/dist/components/skeleton/skeleton.d.ts +3 -0
  194. package/dist/components/skeleton/skeleton.js +7 -1
  195. package/dist/components/skeleton/skeleton.styles.js +5 -4
  196. package/dist/components/slider/slider.d.ts +141 -0
  197. package/dist/components/slider/slider.js +467 -0
  198. package/dist/components/slider/slider.styles.d.ts +1 -0
  199. package/dist/components/slider/slider.styles.js +87 -0
  200. package/dist/components/source-card/source-card.d.ts +104 -0
  201. package/dist/components/source-card/source-card.js +195 -0
  202. package/dist/components/source-card/source-card.styles.d.ts +1 -0
  203. package/dist/components/source-card/source-card.styles.js +69 -0
  204. package/dist/components/source-list/source-list.d.ts +63 -0
  205. package/dist/components/source-list/source-list.js +130 -0
  206. package/dist/components/source-list/source-list.styles.d.ts +1 -0
  207. package/dist/components/source-list/source-list.styles.js +59 -0
  208. package/dist/components/sparkline/sparkline.js +58 -20
  209. package/dist/components/split/split.d.ts +224 -5
  210. package/dist/components/split/split.js +617 -43
  211. package/dist/components/split/split.styles.js +47 -0
  212. package/dist/components/stat/stat.d.ts +15 -4
  213. package/dist/components/stat/stat.js +53 -12
  214. package/dist/components/stream-status/stream-status.d.ts +126 -0
  215. package/dist/components/stream-status/stream-status.js +292 -0
  216. package/dist/components/stream-status/stream-status.styles.d.ts +1 -0
  217. package/dist/components/stream-status/stream-status.styles.js +103 -0
  218. package/dist/components/streaming-text/streaming-text.d.ts +104 -0
  219. package/dist/components/streaming-text/streaming-text.js +224 -0
  220. package/dist/components/streaming-text/streaming-text.styles.d.ts +1 -0
  221. package/dist/components/streaming-text/streaming-text.styles.js +63 -0
  222. package/dist/components/switch/switch.d.ts +103 -0
  223. package/dist/components/switch/switch.js +250 -0
  224. package/dist/components/switch/switch.styles.d.ts +1 -0
  225. package/dist/components/switch/switch.styles.js +75 -0
  226. package/dist/components/table/table.d.ts +89 -5
  227. package/dist/components/table/table.js +243 -26
  228. package/dist/components/table/table.styles.js +6 -1
  229. package/dist/components/tabs/tabs.d.ts +74 -0
  230. package/dist/components/tabs/tabs.js +254 -0
  231. package/dist/components/tabs/tabs.styles.d.ts +1 -0
  232. package/dist/components/tabs/tabs.styles.js +74 -0
  233. package/dist/components/thinking-panel/thinking-panel.d.ts +123 -0
  234. package/dist/components/thinking-panel/thinking-panel.js +260 -0
  235. package/dist/components/thinking-panel/thinking-panel.styles.d.ts +1 -0
  236. package/dist/components/thinking-panel/thinking-panel.styles.js +123 -0
  237. package/dist/components/time-range/time-range.d.ts +59 -2
  238. package/dist/components/time-range/time-range.js +163 -67
  239. package/dist/components/toast/toast-item.d.ts +12 -2
  240. package/dist/components/toast/toast-item.js +106 -44
  241. package/dist/components/toast/toast-item.styles.js +59 -28
  242. package/dist/components/toast/toast.js +17 -5
  243. package/dist/components/toast/toaster.js +10 -1
  244. package/dist/components/tool-approval-dialog/tool-approval-dialog.d.ts +131 -0
  245. package/dist/components/tool-approval-dialog/tool-approval-dialog.js +329 -0
  246. package/dist/components/tool-approval-dialog/tool-approval-dialog.styles.d.ts +1 -0
  247. package/dist/components/tool-approval-dialog/tool-approval-dialog.styles.js +160 -0
  248. package/dist/components/tool-call-chip/tool-call-chip.d.ts +105 -0
  249. package/dist/components/tool-call-chip/tool-call-chip.js +349 -0
  250. package/dist/components/tool-call-chip/tool-call-chip.styles.d.ts +1 -0
  251. package/dist/components/tool-call-chip/tool-call-chip.styles.js +203 -0
  252. package/dist/components/tool-param-form/tool-param-form.d.ts +206 -0
  253. package/dist/components/tool-param-form/tool-param-form.js +610 -0
  254. package/dist/components/tool-param-form/tool-param-form.styles.d.ts +1 -0
  255. package/dist/components/tool-param-form/tool-param-form.styles.js +75 -0
  256. package/dist/components/tool-result-dialog/tool-result-dialog.d.ts +122 -0
  257. package/dist/components/tool-result-dialog/tool-result-dialog.js +358 -0
  258. package/dist/components/tool-result-dialog/tool-result-dialog.styles.d.ts +1 -0
  259. package/dist/components/tool-result-dialog/tool-result-dialog.styles.js +176 -0
  260. package/dist/components/tool-result-view/registry.d.ts +73 -0
  261. package/dist/components/tool-result-view/registry.js +89 -0
  262. package/dist/components/tool-result-view/tool-result-view.d.ts +58 -0
  263. package/dist/components/tool-result-view/tool-result-view.js +152 -0
  264. package/dist/components/tool-result-view/tool-result-view.styles.d.ts +1 -0
  265. package/dist/components/tool-result-view/tool-result-view.styles.js +13 -0
  266. package/dist/components/tool-select-dialog/tool-select-dialog.d.ts +151 -0
  267. package/dist/components/tool-select-dialog/tool-select-dialog.js +350 -0
  268. package/dist/components/tool-select-dialog/tool-select-dialog.styles.d.ts +1 -0
  269. package/dist/components/tool-select-dialog/tool-select-dialog.styles.js +191 -0
  270. package/dist/components/tree/tree-node.d.ts +15 -3
  271. package/dist/components/tree/tree-node.js +20 -7
  272. package/dist/components/tree/tree.d.ts +25 -10
  273. package/dist/components/tree/tree.js +39 -31
  274. package/dist/components/typing-indicator/typing-indicator.d.ts +70 -0
  275. package/dist/components/typing-indicator/typing-indicator.js +108 -0
  276. package/dist/components/typing-indicator/typing-indicator.styles.d.ts +1 -0
  277. package/dist/components/typing-indicator/typing-indicator.styles.js +132 -0
  278. package/dist/components/virtual-list/virtual-list.d.ts +210 -0
  279. package/dist/components/virtual-list/virtual-list.js +607 -0
  280. package/dist/components/virtual-list/virtual-list.styles.d.ts +1 -0
  281. package/dist/components/virtual-list/virtual-list.styles.js +56 -0
  282. package/dist/components/widget/widget.d.ts +5 -4
  283. package/dist/components/widget/widget.js +54 -120
  284. package/dist/components/widget/widget.styles.js +8 -2
  285. package/dist/components/word-cloud/word-cloud-layout.d.ts +7 -0
  286. package/dist/components/word-cloud/word-cloud-layout.js +29 -2
  287. package/dist/components/word-cloud/word-cloud.d.ts +28 -2
  288. package/dist/components/word-cloud/word-cloud.js +69 -19
  289. package/dist/components/word-cloud/word-cloud.styles.js +16 -3
  290. package/dist/internal/anchored-validity.d.ts +1 -0
  291. package/dist/internal/anchored-validity.js +86 -0
  292. package/dist/internal/announcer.d.ts +57 -0
  293. package/dist/internal/announcer.js +71 -0
  294. package/dist/internal/form-associated.d.ts +8 -0
  295. package/dist/internal/form-associated.js +98 -15
  296. package/dist/internal/group-by-recency.d.ts +50 -0
  297. package/dist/internal/group-by-recency.js +80 -0
  298. package/dist/internal/numbers.d.ts +12 -0
  299. package/dist/internal/numbers.js +26 -0
  300. package/dist/internal/overlay-manager.d.ts +51 -0
  301. package/dist/internal/overlay-manager.js +523 -0
  302. package/dist/internal/positioner.js +27 -3
  303. package/dist/internal/rtl.d.ts +23 -0
  304. package/dist/internal/rtl.js +28 -0
  305. package/dist/internal/safe-url.d.ts +12 -0
  306. package/dist/internal/safe-url.js +41 -0
  307. package/dist/internal/scroll-lock.d.ts +10 -5
  308. package/dist/internal/scroll-lock.js +30 -14
  309. package/dist/internal/tokens.styles.js +22 -10
  310. package/dist/lyra.d.ts +133 -31
  311. package/dist/lyra.js +96 -26
  312. package/llms-full.txt +4546 -183
  313. package/llms.txt +21 -5
  314. package/package.json +41 -6
  315. package/dist/components/chart/bar-chart.stories.d.ts +0 -5
  316. package/dist/components/chart/bar-chart.stories.js +0 -20
  317. package/dist/components/chart/box-plot.stories.d.ts +0 -5
  318. package/dist/components/chart/box-plot.stories.js +0 -29
  319. package/dist/components/chart/bubble-chart.stories.d.ts +0 -5
  320. package/dist/components/chart/bubble-chart.stories.js +0 -26
  321. package/dist/components/chart/chart.stories.d.ts +0 -32
  322. package/dist/components/chart/chart.stories.js +0 -141
  323. package/dist/components/chart/doughnut-chart.stories.d.ts +0 -5
  324. package/dist/components/chart/doughnut-chart.stories.js +0 -26
  325. package/dist/components/chart/histogram.stories.d.ts +0 -5
  326. package/dist/components/chart/histogram.stories.js +0 -17
  327. package/dist/components/chart/line-chart.stories.d.ts +0 -22
  328. package/dist/components/chart/line-chart.stories.js +0 -99
  329. package/dist/components/chart/lite-chart.stories.d.ts +0 -14
  330. package/dist/components/chart/lite-chart.stories.js +0 -114
  331. package/dist/components/chart/pie-chart.stories.d.ts +0 -5
  332. package/dist/components/chart/pie-chart.stories.js +0 -26
  333. package/dist/components/chart/polar-area-chart.stories.d.ts +0 -5
  334. package/dist/components/chart/polar-area-chart.stories.js +0 -20
  335. package/dist/components/chart/radar-chart.stories.d.ts +0 -5
  336. package/dist/components/chart/radar-chart.stories.js +0 -20
  337. package/dist/components/chart/scatter-chart.stories.d.ts +0 -5
  338. package/dist/components/chart/scatter-chart.stories.js +0 -31
  339. package/dist/components/combobox/combobox.stories.d.ts +0 -24
  340. package/dist/components/combobox/combobox.stories.js +0 -102
  341. package/dist/components/date-picker/date-input.stories.d.ts +0 -10
  342. package/dist/components/date-picker/date-input.stories.js +0 -48
  343. package/dist/components/date-picker/date-picker.stories.d.ts +0 -10
  344. package/dist/components/date-picker/date-picker.stories.js +0 -25
  345. package/dist/components/empty/empty.stories.d.ts +0 -7
  346. package/dist/components/empty/empty.stories.js +0 -34
  347. package/dist/components/export-button/export-button.stories.d.ts +0 -7
  348. package/dist/components/export-button/export-button.stories.js +0 -37
  349. package/dist/components/file-input/file-input.stories.d.ts +0 -7
  350. package/dist/components/file-input/file-input.stories.js +0 -19
  351. package/dist/components/flag/flag.stories.d.ts +0 -6
  352. package/dist/components/flag/flag.stories.js +0 -31
  353. package/dist/components/gauge/gauge.stories.d.ts +0 -8
  354. package/dist/components/gauge/gauge.stories.js +0 -19
  355. package/dist/components/graph/graph.stories.d.ts +0 -8
  356. package/dist/components/graph/graph.stories.js +0 -68
  357. package/dist/components/heatmap/heatmap.stories.d.ts +0 -27
  358. package/dist/components/heatmap/heatmap.stories.js +0 -179
  359. package/dist/components/map/map.stories.d.ts +0 -15
  360. package/dist/components/map/map.stories.js +0 -135
  361. package/dist/components/playback/playback.stories.d.ts +0 -7
  362. package/dist/components/playback/playback.stories.js +0 -16
  363. package/dist/components/select/select.stories.d.ts +0 -21
  364. package/dist/components/select/select.stories.js +0 -91
  365. package/dist/components/skeleton/skeleton.stories.d.ts +0 -5
  366. package/dist/components/skeleton/skeleton.stories.js +0 -16
  367. package/dist/components/sparkline/sparkline.stories.d.ts +0 -11
  368. package/dist/components/sparkline/sparkline.stories.js +0 -39
  369. package/dist/components/split/split.stories.d.ts +0 -7
  370. package/dist/components/split/split.stories.js +0 -36
  371. package/dist/components/stat/stat.stories.d.ts +0 -9
  372. package/dist/components/stat/stat.stories.js +0 -81
  373. package/dist/components/table/table.stories.d.ts +0 -12
  374. package/dist/components/table/table.stories.js +0 -67
  375. package/dist/components/time-range/time-range.stories.d.ts +0 -8
  376. package/dist/components/time-range/time-range.stories.js +0 -26
  377. package/dist/components/toast/toast.stories.d.ts +0 -8
  378. package/dist/components/toast/toast.stories.js +0 -72
  379. package/dist/components/tree/tree.stories.d.ts +0 -9
  380. package/dist/components/tree/tree.stories.js +0 -52
  381. package/dist/components/widget/widget.stories.d.ts +0 -9
  382. package/dist/components/widget/widget.stories.js +0 -74
  383. package/dist/components/word-cloud/word-cloud.stories.d.ts +0 -10
  384. package/dist/components/word-cloud/word-cloud.stories.js +0 -55
@@ -1,5 +1,4 @@
1
1
  import { type TemplateResult, type PropertyValues } from 'lit';
2
- import type { Map as MaplibreMap, StyleSpecification } from 'maplibre-gl';
3
2
  import { LyraElement } from '../../internal/lyra-element.js';
4
3
  import '../skeleton/skeleton.js';
5
4
  export interface LegendEntry {
@@ -30,20 +29,34 @@ export interface MapMarker {
30
29
  /**
31
30
  * Rendered as the marker's popup content via maplibre-gl's
32
31
  * `Popup.setHTML()` -- parsed as raw markup, inline event handlers
33
- * included. Only ever pass trusted content; sanitize anything derived
34
- * from user input before assigning it here.
32
+ * included. This is the library's one explicit unsafe-HTML escape hatch:
33
+ * only ever pass trusted content, and sanitize anything derived from user
34
+ * input before assigning it here. Prefer `label` (rendered via the safe
35
+ * `Popup.setText()`) whenever the content is plain text.
35
36
  */
36
- html?: string;
37
+ unsafeHtml?: string;
37
38
  }
38
39
  /**
39
40
  * `<lyra-map>` — a maplibre-gl wrapper with a declarative legend and
40
41
  * choropleth GeoJSON layer, plus a raw `map` escape hatch. Requires the
41
42
  * optional peer dep `maplibre-gl` (consumers also import its CSS once).
42
43
  *
44
+ * The underlying `maplibregl.Map` — and the WebGL context it opens — isn't
45
+ * constructed until this element is first visible in the viewport (tracked
46
+ * via `IntersectionObserver`), even once the `maplibre-gl` peer dependency
47
+ * has finished loading. Browsers hard-cap concurrent WebGL contexts per
48
+ * page, so a grid/dashboard of many `<lyra-map>` instances only constructs
49
+ * the ones actually on-screen instead of racing to exhaust that budget the
50
+ * instant each one mounts. `map` stays `undefined` (and `lyra-map-load`
51
+ * doesn't fire) until construction actually happens.
52
+ *
43
53
  * @customElement lyra-map
44
54
  * @event lyra-map-load - Fired once the underlying maplibregl.Map loads.
45
55
  * @event lyra-map-click - `detail: { lngLat, feature? }`.
46
- * @csspart base, container, legend, legend-swatch
56
+ * @csspart base - The map wrapper.
57
+ * @csspart container - The maplibre container.
58
+ * @csspart legend - The map legend.
59
+ * @csspart legend-swatch - A legend color swatch.
47
60
  *
48
61
  * ⚠️ The default `mapStyle` (when unset) uses OpenStreetMap's demo tile
49
62
  * server, which is not suitable for production traffic — see the
@@ -54,12 +67,14 @@ export declare class LyraMap extends LyraElement {
54
67
  static styles: import("lit").CSSResultGroup[];
55
68
  center: [number, number];
56
69
  zoom: number;
57
- mapStyle: StyleSpecification | string;
70
+ mapStyle: import('maplibre-gl').StyleSpecification | string;
58
71
  legend: LegendEntry[];
59
72
  choropleth?: ChoroplethLayer;
60
73
  markers: MapMarker[];
61
74
  /** True until the lazy-loaded `maplibre-gl` peer dependency has settled (success or failure). */
62
75
  private loading;
76
+ private visible;
77
+ private intersectionObserver?;
63
78
  private containerEl?;
64
79
  private _map?;
65
80
  private _styleLoaded;
@@ -67,11 +82,21 @@ export declare class LyraMap extends LyraElement {
67
82
  private _appliedFillLayerId?;
68
83
  private _maplibreModule?;
69
84
  private _markerInstances;
85
+ private _markerColors;
70
86
  private _connectGeneration;
71
87
  /** The raw `maplibregl.Map` instance — escape hatch for anything this wrapper doesn't expose. */
72
- get map(): MaplibreMap | undefined;
88
+ get map(): import('maplibre-gl').Map | undefined;
73
89
  connectedCallback(): void;
74
90
  disconnectedCallback(): void;
91
+ /**
92
+ * Constructs the underlying `maplibregl.Map` — called once both the
93
+ * lazy-loaded `maplibre-gl` module has resolved and this element has been
94
+ * observed intersecting the viewport, whichever settles last. Idempotent
95
+ * (a no-op once `_map` already exists), so it's safe to call from both the
96
+ * `connectedCallback()` load path and the visibility path in `updated()`
97
+ * below without risking a double construction.
98
+ */
99
+ private tryConstructMap;
75
100
  protected updated(changed: PropertyValues): void;
76
101
  private applyChoropleth;
77
102
  /** Removes whatever choropleth layer/source is currently applied, if any. */
@@ -65,10 +65,22 @@ function sanitizeSwatchColor(color) {
65
65
  * choropleth GeoJSON layer, plus a raw `map` escape hatch. Requires the
66
66
  * optional peer dep `maplibre-gl` (consumers also import its CSS once).
67
67
  *
68
+ * The underlying `maplibregl.Map` — and the WebGL context it opens — isn't
69
+ * constructed until this element is first visible in the viewport (tracked
70
+ * via `IntersectionObserver`), even once the `maplibre-gl` peer dependency
71
+ * has finished loading. Browsers hard-cap concurrent WebGL contexts per
72
+ * page, so a grid/dashboard of many `<lyra-map>` instances only constructs
73
+ * the ones actually on-screen instead of racing to exhaust that budget the
74
+ * instant each one mounts. `map` stays `undefined` (and `lyra-map-load`
75
+ * doesn't fire) until construction actually happens.
76
+ *
68
77
  * @customElement lyra-map
69
78
  * @event lyra-map-load - Fired once the underlying maplibregl.Map loads.
70
79
  * @event lyra-map-click - `detail: { lngLat, feature? }`.
71
- * @csspart base, container, legend, legend-swatch
80
+ * @csspart base - The map wrapper.
81
+ * @csspart container - The maplibre container.
82
+ * @csspart legend - The map legend.
83
+ * @csspart legend-swatch - A legend color swatch.
72
84
  *
73
85
  * ⚠️ The default `mapStyle` (when unset) uses OpenStreetMap's demo tile
74
86
  * server, which is not suitable for production traffic — see the
@@ -85,6 +97,14 @@ export class LyraMap extends LyraElement {
85
97
  this.markers = [];
86
98
  /** True until the lazy-loaded `maplibre-gl` peer dependency has settled (success or failure). */
87
99
  this.loading = true;
100
+ // Gates the actual `new mod.Map(...)` construction (see `tryConstructMap()`)
101
+ // -- starts `false` so a `<lyra-map>` mounted off-screen doesn't open a
102
+ // WebGL context before it's ever seen, and only flips `true` once the
103
+ // IntersectionObserver below reports this element actually intersecting
104
+ // the viewport. Defaults `true` outright when `IntersectionObserver` isn't
105
+ // available at all (fail open, matching `lyra-chart`'s own fallback)
106
+ // rather than gating construction on an observer that will never fire.
107
+ this.visible = typeof IntersectionObserver === 'undefined';
88
108
  // Tracks whether the style has fired its initial 'load' (i.e. addSource/
89
109
  // addLayer/setPaintProperty are now safe to call), rather than re-querying
90
110
  // `this._map.isStyleLoaded()`: that also reflects in-flight *tile* loading
@@ -93,6 +113,14 @@ export class LyraMap extends LyraElement {
93
113
  // choropleth updates from ever re-running.
94
114
  this._styleLoaded = false;
95
115
  this._markerInstances = new Map();
116
+ // The installed maplibre-gl's `Marker` class has no `setColor()` (verified
117
+ // against its shipped `.d.ts` -- `color` is only ever consumed by the
118
+ // constructor), so an id-matched marker whose `color` changes can't be
119
+ // mutated in place; it has to be torn down and reconstructed instead. This
120
+ // tracks the color each currently-live marker instance was last
121
+ // constructed with, keyed the same as `_markerInstances`, so `applyMarkers`
122
+ // can detect that mismatch without re-deriving it from the DOM.
123
+ this._markerColors = new Map();
96
124
  // Bumped on every connectedCallback and captured by value in its
97
125
  // loadMaplibre().then() closure below. A disconnect immediately followed
98
126
  // by a reconnect (fast remounts, route/tab switches, etc.) before that
@@ -113,6 +141,17 @@ export class LyraMap extends LyraElement {
113
141
  connectedCallback() {
114
142
  super.connectedCallback();
115
143
  const generation = ++this._connectGeneration;
144
+ // A reconnect always tears the map down in disconnectedCallback() below,
145
+ // so it needs its own fresh visibility read rather than trusting
146
+ // whatever `visible` was left at from before the previous disconnect.
147
+ this.visible = typeof IntersectionObserver === 'undefined';
148
+ if (typeof IntersectionObserver !== 'undefined') {
149
+ this.intersectionObserver = new IntersectionObserver((entries) => {
150
+ if (entries[0]?.isIntersecting)
151
+ this.visible = true;
152
+ });
153
+ this.intersectionObserver.observe(this);
154
+ }
116
155
  void loadMaplibre().then(async (mod) => {
117
156
  // A newer connectedCallback (disconnect + reconnect) already
118
157
  // superseded this attempt while loadMaplibre()'s cached promise was
@@ -136,28 +175,7 @@ export class LyraMap extends LyraElement {
136
175
  // cycle that happened during the `await` above.
137
176
  if (generation !== this._connectGeneration || !this.containerEl || !this.isConnected)
138
177
  return;
139
- this._map = new mod.Map({
140
- container: this.containerEl,
141
- style: this.mapStyle,
142
- center: this.center,
143
- zoom: this.zoom,
144
- });
145
- this._map.on('load', () => {
146
- this._styleLoaded = true;
147
- this.applyChoropleth();
148
- this.applyMarkers();
149
- this.emit('lyra-map-load');
150
- });
151
- this._map.on('click', (e) => {
152
- const fillLayerId = this._appliedFillLayerId;
153
- const features = fillLayerId && this._map.getLayer(fillLayerId)
154
- ? this._map.queryRenderedFeatures(e.point, { layers: [fillLayerId] })
155
- : [];
156
- this.emit('lyra-map-click', {
157
- lngLat: [e.lngLat.lng, e.lngLat.lat],
158
- feature: features[0],
159
- });
160
- });
178
+ this.tryConstructMap();
161
179
  });
162
180
  }
163
181
  disconnectedCallback() {
@@ -167,15 +185,59 @@ export class LyraMap extends LyraElement {
167
185
  this._styleLoaded = false;
168
186
  this._appliedChoroplethSourceId = undefined;
169
187
  this._appliedFillLayerId = undefined;
188
+ this.intersectionObserver?.disconnect();
189
+ this.intersectionObserver = undefined;
170
190
  for (const marker of this._markerInstances.values())
171
191
  marker.remove();
172
192
  this._markerInstances.clear();
193
+ this._markerColors.clear();
194
+ }
195
+ /**
196
+ * Constructs the underlying `maplibregl.Map` — called once both the
197
+ * lazy-loaded `maplibre-gl` module has resolved and this element has been
198
+ * observed intersecting the viewport, whichever settles last. Idempotent
199
+ * (a no-op once `_map` already exists), so it's safe to call from both the
200
+ * `connectedCallback()` load path and the visibility path in `updated()`
201
+ * below without risking a double construction.
202
+ */
203
+ tryConstructMap() {
204
+ if (this._map || !this._maplibreModule || !this.containerEl || !this.visible || !this.isConnected)
205
+ return;
206
+ const mod = this._maplibreModule;
207
+ this._map = new mod.Map({
208
+ container: this.containerEl,
209
+ style: this.mapStyle,
210
+ center: this.center,
211
+ zoom: this.zoom,
212
+ });
213
+ this._map.on('load', () => {
214
+ this._styleLoaded = true;
215
+ this.applyChoropleth();
216
+ this.applyMarkers();
217
+ this.emit('lyra-map-load');
218
+ });
219
+ this._map.on('click', (e) => {
220
+ const fillLayerId = this._appliedFillLayerId;
221
+ const features = fillLayerId && this._map.getLayer(fillLayerId)
222
+ ? this._map.queryRenderedFeatures(e.point, { layers: [fillLayerId] })
223
+ : [];
224
+ this.emit('lyra-map-click', {
225
+ lngLat: [e.lngLat.lng, e.lngLat.lat],
226
+ feature: features[0],
227
+ });
228
+ });
173
229
  }
174
230
  updated(changed) {
175
231
  if (this.loading)
176
232
  this.setAttribute('aria-busy', 'true');
177
233
  else
178
234
  this.removeAttribute('aria-busy');
235
+ // Became visible after the maplibre-gl module had already loaded (the
236
+ // reverse order — module loads first, visibility follows — is the
237
+ // common case and is instead handled at the end of the
238
+ // `loadMaplibre().then()` chain in connectedCallback() above).
239
+ if (changed.has('visible') && this.visible)
240
+ this.tryConstructMap();
179
241
  if (changed.has('mapStyle') && this._map) {
180
242
  // A style change wipes every layer/source maplibre-gl knows about, so
181
243
  // the previously-applied choropleth bookkeeping is stale the instant
@@ -224,7 +286,16 @@ export class LyraMap extends LyraElement {
224
286
  existingSource.setData(geojson);
225
287
  }
226
288
  else {
227
- this._map.addSource(sourceId, { type: 'geojson', data: geojson, promoteId: 'id' });
289
+ // No `promoteId` -- maplibre-gl falls back to its own default id
290
+ // resolution (the standard top-level GeoJSON `Feature.id`, when
291
+ // present). A hardcoded `promoteId: 'id'` here would instead require
292
+ // every feature to *also* duplicate its id inside `properties.id`,
293
+ // silently discarding the real top-level `id` otherwise and breaking
294
+ // `feature.id` on `lyra-map-click` for the common case. Nothing in this
295
+ // component actually needs feature-state promotion today; if that's
296
+ // added later it should be driven by an explicit, documented
297
+ // `ChoroplethLayer` option (e.g. `idField`), not a silent default.
298
+ this._map.addSource(sourceId, { type: 'geojson', data: geojson });
228
299
  }
229
300
  this._appliedChoroplethSourceId = sourceId;
230
301
  // An `interpolate` expression needs at least one [value, color] stop pair
@@ -281,31 +352,57 @@ export class LyraMap extends LyraElement {
281
352
  if (!map || !mod)
282
353
  return;
283
354
  const visible = new Set();
355
+ // Markers with no `id` used to key solely by `lngLat`, so two different
356
+ // id-less markers placed at the exact same coordinates collided onto one
357
+ // `_markerInstances` entry. An occurrence index (reset per render, per
358
+ // coordinate) makes same-coordinate id-less markers distinct while
359
+ // staying stable/consistent across re-renders as long as their relative
360
+ // order in `this.markers` doesn't change.
361
+ const coordCounts = new Map();
284
362
  for (const m of this.markers) {
285
- const key = m.id ?? `${m.lngLat[0]},${m.lngLat[1]}`;
363
+ let key = m.id;
364
+ if (key == null) {
365
+ const coordKey = `${m.lngLat[0]},${m.lngLat[1]}`;
366
+ const occurrence = coordCounts.get(coordKey) ?? 0;
367
+ coordCounts.set(coordKey, occurrence + 1);
368
+ key = `${coordKey}#${occurrence}`;
369
+ }
286
370
  visible.add(key);
287
- const existing = this._markerInstances.get(key);
371
+ let existing = this._markerInstances.get(key);
372
+ if (existing && this._markerColors.get(key) !== m.color) {
373
+ // `color` is baked into the marker's SVG at construction time with
374
+ // no way to mutate it afterwards -- fall through to the "no existing
375
+ // marker" branch below to reconstruct it instead. Note: this closes
376
+ // any popup the user currently has open on this marker (a fresh,
377
+ // closed Popup is built for the new instance) -- an accepted, narrow
378
+ // side effect of the reconstruction fallback, not a bug.
379
+ existing.remove();
380
+ this._markerInstances.delete(key);
381
+ this._markerColors.delete(key);
382
+ existing = undefined;
383
+ }
288
384
  if (!existing) {
289
385
  const marker = new mod.Marker(m.color ? { color: m.color } : undefined).setLngLat(m.lngLat);
290
- if (m.html || m.label) {
386
+ if (m.unsafeHtml || m.label) {
291
387
  const popup = new mod.Popup({ offset: 12 });
292
- if (m.html)
293
- popup.setHTML(m.html);
388
+ if (m.unsafeHtml)
389
+ popup.setHTML(m.unsafeHtml);
294
390
  else if (m.label)
295
391
  popup.setText(m.label);
296
392
  marker.setPopup(popup);
297
393
  }
298
394
  marker.addTo(map);
299
395
  this._markerInstances.set(key, marker);
396
+ this._markerColors.set(key, m.color);
300
397
  }
301
398
  else {
302
399
  existing.setLngLat(m.lngLat);
303
400
  const popup = existing.getPopup();
304
- if (m.html) {
401
+ if (m.unsafeHtml) {
305
402
  if (popup)
306
- popup.setHTML(m.html);
403
+ popup.setHTML(m.unsafeHtml);
307
404
  else
308
- existing.setPopup(new mod.Popup({ offset: 12 }).setHTML(m.html));
405
+ existing.setPopup(new mod.Popup({ offset: 12 }).setHTML(m.unsafeHtml));
309
406
  }
310
407
  else if (m.label) {
311
408
  if (popup)
@@ -322,6 +419,7 @@ export class LyraMap extends LyraElement {
322
419
  if (!visible.has(key)) {
323
420
  marker.remove();
324
421
  this._markerInstances.delete(key);
422
+ this._markerColors.delete(key);
325
423
  }
326
424
  }
327
425
  }
@@ -372,6 +470,9 @@ __decorate([
372
470
  __decorate([
373
471
  state()
374
472
  ], LyraMap.prototype, "loading", void 0);
473
+ __decorate([
474
+ state()
475
+ ], LyraMap.prototype, "visible", void 0);
375
476
  __decorate([
376
477
  query('[part="container"]')
377
478
  ], LyraMap.prototype, "containerEl", void 0);
@@ -0,0 +1,58 @@
1
+ import type * as MarkedModule from 'marked';
2
+ import type DOMPurifyApi from 'dompurify';
3
+ /**
4
+ * The two optional peers `<lyra-markdown>` needs, loaded independently (see
5
+ * `loadMarkdownAndSanitizer()`). Either half can be `undefined` on its own —
6
+ * a consumer who only installs `marked` (having explicitly opted out of
7
+ * sanitization via `sanitize="false"`) is a valid, supported combination.
8
+ */
9
+ export interface MarkdownDeps {
10
+ marked: typeof MarkedModule | undefined;
11
+ DOMPurify: typeof DOMPurifyApi | undefined;
12
+ }
13
+ /**
14
+ * Independently loads the optional peer dependencies `marked` (Markdown
15
+ * parsing) and `dompurify` (HTML sanitizing), mirroring `chart-loader.ts`'s
16
+ * `loadChartAndZoom()` shape for two independent optional peers. A partial
17
+ * install — most usefully `marked` alone, for a consumer who has explicitly
18
+ * set `sanitize="false"` and doesn't need `dompurify` at all — degrades to
19
+ * "that one half is missing" rather than failing outright. Exported (in
20
+ * addition to the cached `loadMarkdownDeps()` below) so both failure paths —
21
+ * and the real caught error each one logs — are directly testable without
22
+ * needing to actually uninstall either package.
23
+ */
24
+ export declare function loadMarkdownAndSanitizer(importMarked?: () => Promise<typeof MarkedModule>, importDompurify?: () => Promise<{
25
+ default: typeof DOMPurifyApi;
26
+ }>): Promise<MarkdownDeps>;
27
+ /**
28
+ * Lazily loads `marked` + `dompurify` once per page (see
29
+ * `loadMarkdownAndSanitizer()` for why each is loaded and caught
30
+ * independently). Cached the same way `chart-loader.ts`/`map-loader.ts`
31
+ * cache their promise, so every `<lyra-markdown>` instance on a page shares
32
+ * one load.
33
+ *
34
+ * The dynamic `import()` inside `loadMarkdownAndSanitizer()` is always
35
+ * asynchronous — even when both peers are already installed and resolve
36
+ * without error — so every `<lyra-markdown>` that calls this from
37
+ * `connectedCallback()` paints its plain-text fallback (`data-fallback` on
38
+ * the `content` part) for at least one microtask before the real rendered
39
+ * output replaces it. That window is unconditional, not just a failure
40
+ * path: it ends only once this promise settles. A consumer that wants to
41
+ * skip it can set `eager-load` on `<lyra-markdown>`, which calls
42
+ * `getMarkdownDepsIfLoaded()` below instead of awaiting this function —
43
+ * see that property's doc for what "already warm" means in practice.
44
+ */
45
+ export declare function loadMarkdownDeps(): Promise<MarkdownDeps>;
46
+ /**
47
+ * Synchronous companion to `loadMarkdownDeps()`: returns the same
48
+ * module-level cached `MarkdownDeps` if some earlier call to
49
+ * `loadMarkdownDeps()` — from any `<lyra-markdown>` instance on the page, or
50
+ * a consumer priming it directly at startup — has already settled by the
51
+ * time this is called, or `undefined` if the cache isn't warm yet (nothing
52
+ * has called `loadMarkdownDeps()` before, or it's still in flight). Used by
53
+ * `eager-load` to skip the dynamic `import()`'s async hop in the common case
54
+ * where the peers are already loaded; it cannot make the *very first*
55
+ * `<lyra-markdown>` on a page synchronous, since that first call is what
56
+ * populates the cache in the first place.
57
+ */
58
+ export declare function getMarkdownDepsIfLoaded(): MarkdownDeps | undefined;
@@ -0,0 +1,77 @@
1
+ let deps;
2
+ // Populated the instant `deps` settles (inside `loadMarkdownDeps()` below) so
3
+ // `getMarkdownDepsIfLoaded()` can hand one back synchronously -- the whole
4
+ // point of that function, since `deps` itself is a Promise and awaiting it
5
+ // always costs at least one microtask, even once already resolved.
6
+ let resolvedDeps;
7
+ /**
8
+ * Independently loads the optional peer dependencies `marked` (Markdown
9
+ * parsing) and `dompurify` (HTML sanitizing), mirroring `chart-loader.ts`'s
10
+ * `loadChartAndZoom()` shape for two independent optional peers. A partial
11
+ * install — most usefully `marked` alone, for a consumer who has explicitly
12
+ * set `sanitize="false"` and doesn't need `dompurify` at all — degrades to
13
+ * "that one half is missing" rather than failing outright. Exported (in
14
+ * addition to the cached `loadMarkdownDeps()` below) so both failure paths —
15
+ * and the real caught error each one logs — are directly testable without
16
+ * needing to actually uninstall either package.
17
+ */
18
+ export async function loadMarkdownAndSanitizer(importMarked = () => import('marked'), importDompurify = () => import('dompurify')) {
19
+ let marked;
20
+ try {
21
+ marked = await importMarked();
22
+ }
23
+ catch (err) {
24
+ console.warn('<lyra-markdown> needs the optional peer dependency `marked` to parse Markdown — install it with `pnpm add marked`:', err);
25
+ }
26
+ let DOMPurify;
27
+ try {
28
+ DOMPurify = (await importDompurify()).default;
29
+ }
30
+ catch (err) {
31
+ console.warn('<lyra-markdown> needs the optional peer dependency `dompurify` to sanitize rendered HTML — install it ' +
32
+ 'with `pnpm add dompurify`. Until then, content only renders when `sanitize="false"` is explicitly set:', err);
33
+ }
34
+ return { marked, DOMPurify };
35
+ }
36
+ /**
37
+ * Lazily loads `marked` + `dompurify` once per page (see
38
+ * `loadMarkdownAndSanitizer()` for why each is loaded and caught
39
+ * independently). Cached the same way `chart-loader.ts`/`map-loader.ts`
40
+ * cache their promise, so every `<lyra-markdown>` instance on a page shares
41
+ * one load.
42
+ *
43
+ * The dynamic `import()` inside `loadMarkdownAndSanitizer()` is always
44
+ * asynchronous — even when both peers are already installed and resolve
45
+ * without error — so every `<lyra-markdown>` that calls this from
46
+ * `connectedCallback()` paints its plain-text fallback (`data-fallback` on
47
+ * the `content` part) for at least one microtask before the real rendered
48
+ * output replaces it. That window is unconditional, not just a failure
49
+ * path: it ends only once this promise settles. A consumer that wants to
50
+ * skip it can set `eager-load` on `<lyra-markdown>`, which calls
51
+ * `getMarkdownDepsIfLoaded()` below instead of awaiting this function —
52
+ * see that property's doc for what "already warm" means in practice.
53
+ */
54
+ export function loadMarkdownDeps() {
55
+ if (!deps) {
56
+ deps = loadMarkdownAndSanitizer().then((resolved) => {
57
+ resolvedDeps = resolved;
58
+ return resolved;
59
+ });
60
+ }
61
+ return deps;
62
+ }
63
+ /**
64
+ * Synchronous companion to `loadMarkdownDeps()`: returns the same
65
+ * module-level cached `MarkdownDeps` if some earlier call to
66
+ * `loadMarkdownDeps()` — from any `<lyra-markdown>` instance on the page, or
67
+ * a consumer priming it directly at startup — has already settled by the
68
+ * time this is called, or `undefined` if the cache isn't warm yet (nothing
69
+ * has called `loadMarkdownDeps()` before, or it's still in flight). Used by
70
+ * `eager-load` to skip the dynamic `import()`'s async hop in the common case
71
+ * where the peers are already loaded; it cannot make the *very first*
72
+ * `<lyra-markdown>` on a page synchronous, since that first call is what
73
+ * populates the cache in the first place.
74
+ */
75
+ export function getMarkdownDepsIfLoaded() {
76
+ return resolvedDeps;
77
+ }
@@ -0,0 +1,119 @@
1
+ import { type TemplateResult, type PropertyValues } from 'lit';
2
+ import { LyraElement } from '../../internal/lyra-element.js';
3
+ /**
4
+ * `<lyra-markdown>` — sanitized Markdown-to-HTML rendering (GFM tables,
5
+ * fenced code blocks, links, blockquotes) built on the optional peer
6
+ * dependencies `marked` (parsing) and `dompurify` (sanitizing), both
7
+ * lazy-loaded via `markdown-loader.ts` on first connect.
8
+ *
9
+ * Rendering never ships unsanitized or broken markup silently:
10
+ * - If `marked` fails to load, or throws while parsing malformed input, the
11
+ * component falls back to plain text (`white-space: pre-wrap`, no HTML
12
+ * parsing at all) and fires `lyra-render-error`.
13
+ * - If `sanitize` is `true` (the default) and `dompurify` fails to load, the
14
+ * component *also* falls back to plain text + `lyra-render-error` — it
15
+ * never renders marked's raw HTML output when sanitization was requested
16
+ * (or defaulted to) but is unavailable, even though `marked` itself loaded
17
+ * fine.
18
+ * - If `sanitize` is explicitly `false`, marked's raw output renders as-is
19
+ * regardless of whether `dompurify` is installed — the consumer opted out
20
+ * of sanitization, so `dompurify`'s absence is irrelevant to that path.
21
+ *
22
+ * That same plain-text fallback rendering (`data-fallback` on the `content`
23
+ * part) is also, unconditionally and by default, a brief *transient* state on
24
+ * every connect, not just a failure path: `connectedCallback()`'s dynamic
25
+ * `import()` of `marked`/`dompurify` (see `markdown-loader.ts`) is
26
+ * asynchronous, so the very first paint of any `<lyra-markdown>` on a page
27
+ * shows plain text for at least one microtask — even when both peers are
28
+ * already installed and load without error — until that import resolves and
29
+ * a second render replaces it with the real Markdown output. Set
30
+ * `eager-load` to skip that window once the shared dependency cache is
31
+ * already warm; see that property's doc for exactly what "warm" requires.
32
+ *
33
+ * `heading`/`code`/`blockquote`/`table`/`link`/`image` tokens are rendered
34
+ * through a `marked` renderer override that injects `part="..."` attributes
35
+ * directly into the produced HTML — a single pass, not a second DOM walk
36
+ * after insertion.
37
+ *
38
+ * @customElement lyra-markdown
39
+ * @event lyra-link-click - Fired (and the click prevented) when a rendered
40
+ * link's `href` starts with `internal-link-prefix`. `detail: { href:
41
+ * string, internal: true }`. Ordinary external links navigate normally
42
+ * (in `link-target`) and never fire this event.
43
+ * @event lyra-render-error - Fired whenever rendering falls back to plain
44
+ * text. `detail: { error: unknown }`.
45
+ * @csspart content - The wrapper around the rendered (or plain-text
46
+ * fallback) output.
47
+ * @csspart heading - Every rendered `<h1>`–`<h6>` (shifted by
48
+ * `heading-offset`).
49
+ * @csspart code-block - Every rendered fenced/indented `<pre>`.
50
+ * @csspart link - Every rendered `<a>`.
51
+ * @csspart table - Every rendered `<table>`.
52
+ * @csspart blockquote - Every rendered `<blockquote>`.
53
+ * @csspart img - Every rendered `<img>`.
54
+ */
55
+ export declare class LyraMarkdown extends LyraElement {
56
+ static styles: import("lit").CSSResultGroup[];
57
+ /** The Markdown source to render. */
58
+ content: string;
59
+ /** Sanitize marked's HTML output with DOMPurify before rendering. See the
60
+ * class doc for what happens when this is `true` (the default) but the
61
+ * `dompurify` peer isn't installed. */
62
+ sanitize: boolean;
63
+ /** Enable GitHub-flavored Markdown (tables, strikethrough, autolinks, task lists). */
64
+ gfm: boolean;
65
+ /** `target` applied to every rendered `<a>`, with `rel="noopener
66
+ * noreferrer"` always added alongside it whenever a `target` is emitted.
67
+ * `'_blank'` (the default) preserves today's exact output. Set to `null`
68
+ * (or the empty string, e.g. via the `link-target=""` attribute) to omit
69
+ * `target`/`rel` entirely, so rendered links open in the same tab. */
70
+ linkTarget: string | null;
71
+ /** When set, a rendered link whose `href` starts with this prefix is
72
+ * treated as internal — its click is intercepted and reported via
73
+ * `lyra-link-click` instead of navigating. Empty (the default) means
74
+ * every link is treated as external. */
75
+ internalLinkPrefix: string;
76
+ /** Added to every rendered heading's source `token.depth` before emitting
77
+ * `<h${depth}>` — e.g. `heading-offset="2"` renders a source `#` as
78
+ * `<h3>` and a source `##` as `<h4>`. The result is clamped to `[1, 6]`
79
+ * (a source `######` with a positive offset stays at `<h6>` rather than
80
+ * overflowing past the HTML heading levels; the floor at `1` is
81
+ * defensive, since this property is meant to be additive-only). `0`
82
+ * (the default) preserves today's exact `<h${token.depth}>` output. */
83
+ headingOffset: number;
84
+ /** When `true`, `connectedCallback()` skips awaiting `loadMarkdownDeps()`'s
85
+ * dynamic `import()` if the shared `marked`/`dompurify` module cache (see
86
+ * `markdown-loader.ts`'s `getMarkdownDepsIfLoaded()`) has *already*
87
+ * resolved — e.g. because an earlier `<lyra-markdown>` instance on the
88
+ * page already finished loading, or the consumer primed the cache
89
+ * directly by calling `loadMarkdownDeps()` themselves at startup — and
90
+ * renders synchronously instead. When the cache isn't warm yet (most
91
+ * notably: the very first `<lyra-markdown>` ever connected on a page,
92
+ * since nothing has called `loadMarkdownDeps()` before it), this still
93
+ * falls back to the normal async path — a dynamic `import()` can't be
94
+ * made synchronous, so this is a fast path for the common "already warm"
95
+ * case, not a hard guarantee. `false` (the default) is byte-identical to
96
+ * today: always the async `import()`, fallback-text window included. */
97
+ eagerLoad: boolean;
98
+ /** Forward-compatible hint for a dedicated streaming renderer expected to
99
+ * build on this component later (coalescing partial tokens as they
100
+ * arrive) — setting it has no rendering effect yet. Reflects so a
101
+ * consumer can already target `lyra-markdown[streaming]` in CSS ahead of
102
+ * that behavior landing. */
103
+ streaming: boolean;
104
+ private renderedHtml;
105
+ private deps?;
106
+ connectedCallback(): void;
107
+ protected willUpdate(changed: PropertyValues): void;
108
+ protected updated(): void;
109
+ private renderMarkdown;
110
+ private applyFallback;
111
+ private parseMarkdown;
112
+ private onContentClick;
113
+ render(): TemplateResult;
114
+ }
115
+ declare global {
116
+ interface HTMLElementTagNameMap {
117
+ 'lyra-markdown': LyraMarkdown;
118
+ }
119
+ }