@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
@@ -4,10 +4,12 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
4
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
5
  return c > 3 && r && Object.defineProperty(target, key, r), r;
6
6
  };
7
- import { html } from 'lit';
8
- import { property, state } from 'lit/decorators.js';
7
+ import { html, nothing } from 'lit';
8
+ import { property, state, query } from 'lit/decorators.js';
9
9
  import { LyraElement } from '../../internal/lyra-element.js';
10
+ import { activateOverlay } from '../../internal/overlay-manager.js';
10
11
  import { defineElement } from '../../internal/prefix.js';
12
+ import { lockScroll } from '../../internal/scroll-lock.js';
11
13
  import { isRtl } from '../../internal/rtl.js';
12
14
  import { styles } from './split.styles.js';
13
15
  const KEYBOARD_STEP = 2;
@@ -20,11 +22,60 @@ const NO_MAX_PX = 1_000_000;
20
22
  * `<lyra-split>` — resizable panels for dashboard layouts. Direct light-DOM
21
23
  * children are the panels; a divider is auto-inserted between each pair.
22
24
  *
25
+ * Optionally, one pane can opt in to responsive collapse via `collapse`
26
+ * (`"start"`/`"end"`, default `"none"` — no behavior change when unset): as
27
+ * the split's own container narrows past `railBreakpoint` that pane clamps
28
+ * to a fixed `railWidth`, and past the narrower `floatBreakpoint` it instead
29
+ * becomes an absolutely-positioned overlay "floating card" above the other
30
+ * pane. This component only handles the width-collapse mechanics and
31
+ * signals the current state — via the `collapseState`-derived
32
+ * `data-collapse-state` attribute (set on both the host and the collapsing
33
+ * panel itself) and the `lyra-split-collapse-change` event — it renders no
34
+ * icon-only/collapsed UI of its own; slotted content is expected to adapt to
35
+ * its own clamped width (e.g. via its own container query).
36
+ *
37
+ * `collapseState` is a public accessor with force/auto semantics mirroring
38
+ * `<lyra-app-rail>`'s `mode`: it's normally derived automatically from the
39
+ * measured container width (via a `ResizeObserver` on `[part="base"]`)
40
+ * whenever it crosses `railBreakpoint`/`floatBreakpoint`, but assigning it a
41
+ * concrete `'wide'`/`'rail'`/`'floating'` value pins it there and stops that
42
+ * automatic tracking — useful for a consumer-driven toggle (e.g. a button
43
+ * that forces `'floating'` regardless of width). Assigning the write-only
44
+ * `'auto'` sentinel releases the pin and immediately re-derives the state
45
+ * from the current measured width, resuming automatic tracking. `'auto'` is
46
+ * never a value this getter returns.
47
+ *
48
+ * The `'floating'` state is a hidden-by-default drawer, gated by `open`
49
+ * (mirrors `<lyra-app-rail>`'s mobile overlay): while `collapseState` is
50
+ * `'floating'` and `open` is `false` (the default), the collapsing panel
51
+ * renders nothing — `hidden`, out of the accessibility tree, not just
52
+ * visually hidden — instead of the always-visible overlay card this state
53
+ * rendered before `open` existed. Setting `open = true` reveals it as a
54
+ * focus-trapped floating panel with a `[part="backdrop"]` scrim; Escape or a
55
+ * backdrop click set `open` back to `false`. `open` is preserved (not reset)
56
+ * while `collapseState` isn't `'floating'`, but no drawer chrome renders
57
+ * until it is again — except that leaving `'floating'` while `open` is
58
+ * `true` (a breakpoint crossing back to `'wide'`/`'rail'`, or a forced
59
+ * reassignment) also closes it, the same way `<lyra-app-rail>` closes its
60
+ * mobile overlay when leaving `'mobile'` while open.
61
+ *
23
62
  * @customElement lyra-split
24
63
  * @event lyra-resize - `detail: { sizes }`, fired on every drag step/release
25
64
  * and every keyboard step.
65
+ * @event lyra-split-collapse-change - `detail: { state }` (`SplitCollapseChangeDetail`),
66
+ * fired whenever the responsive `collapseState` actually transitions between
67
+ * `'wide'`/`'rail'`/`'floating'` — whether from a breakpoint crossing or an
68
+ * explicit `collapseState` assignment. Only relevant when `collapse` isn't
69
+ * `"none"`; never fires otherwise. Not fired for a redundant reassignment
70
+ * to the state already in effect.
71
+ * @event lyra-split-constraints-invalid - `detail: SplitConstraintIssueDetail`,
72
+ * fired once when the configured panel minimums/maximums cannot describe a
73
+ * layout that fits the track. The splitter rejects that infeasible set for
74
+ * interaction and falls back to a normalized percent minimum.
26
75
  * @slot - Panels to arrange side by side (or stacked, when `orientation="vertical"`); each direct child becomes one resizable panel.
27
- * @csspart base, divider
76
+ * @csspart base - The flex layout wrapper (`position: relative`, so the `'floating'` collapse state can anchor to it).
77
+ * @csspart divider - Each divider between two panels; carries `aria-disabled="true"` and is drag/keyboard-inert while its adjacent panel is collapsed (`'rail'`/`'floating'`).
78
+ * @csspart backdrop - The `'floating'` drawer's scrim. Only rendered while `collapseState === 'floating'` and `open`.
28
79
  */
29
80
  export class LyraSplit extends LyraElement {
30
81
  constructor() {
@@ -38,21 +89,76 @@ export class LyraSplit extends LyraElement {
38
89
  * localStorage persistence stay percent-based regardless — only the
39
90
  * effective clamp bounds change for a constrained panel. */
40
91
  this.panelConstraints = [];
92
+ /** Opts a pane in to responsive collapse: `'start'` is the first light-DOM
93
+ * panel (index 0), `'end'` is the last. Both are LOGICAL positions, same
94
+ * as CSS `inset-inline-start`/`-end` — see the `collapsingIndex` getter
95
+ * for why that already resolves to the same physical index under RTL for
96
+ * this component (panels are never re-`order`ed for RTL, only the drag
97
+ * delta sign mirrors). Default `'none'`: none of the collapse behavior
98
+ * below applies, and rendering/behavior is identical to before this
99
+ * property existed. */
100
+ this.collapse = 'none';
101
+ /** Fixed CSS length the collapsing pane clamps to in the `'rail'` state. */
102
+ this.railWidth = '3.5rem';
103
+ /** Container width (px, measured on `[part="base"]`) below which the
104
+ * collapsing pane switches from its normal percent width to the fixed
105
+ * `railWidth` (`'rail'` state). Must stay above `floatBreakpoint`. */
106
+ this.railBreakpoint = 640;
107
+ /** Container width (px) below which the collapsing pane instead becomes an
108
+ * absolutely-positioned overlay above the other pane (`'floating'` state). */
109
+ this.floatBreakpoint = 400;
110
+ /** Whether the `'floating'` collapse state's drawer is shown. Only
111
+ * meaningful while `collapseState` is `'floating'` — the value is
112
+ * preserved (not reset) while another state is active, but no drawer
113
+ * chrome renders until `collapseState` is `'floating'` again. Defaults to
114
+ * `false`: the collapsing pane renders nothing while floating until a
115
+ * consumer opts in by setting this (or it's forced open programmatically)
116
+ * — see the class doc. */
117
+ this.open = false;
41
118
  this.panelCount = 0;
119
+ this._collapseState = 'wide';
120
+ // Whether ResizeObserver-driven measurement is currently ignored because a
121
+ // consumer forced a specific collapseState -- see the accessor doc.
122
+ this._forced = false;
123
+ // Derived from collapseState === 'floating' && open -- tracked as its own
124
+ // field (rather than recomputed inline everywhere) so willUpdate can detect
125
+ // the specific false->true/true->false transition regardless of which of
126
+ // the two source properties changed (mirrors lyra-app-rail's
127
+ // `overlayActive`).
128
+ this.overlayActive = false;
129
+ this.justOpened = false;
42
130
  // Keyed by pointerId so an interrupted or concurrent (multi-touch) drag on
43
131
  // one divider never reads or clobbers another pointer's drag state.
44
132
  this.drags = new Map();
133
+ // Panels `updated()` last applied inline flex/order (and, while collapsing,
134
+ // position/inset/inline-size) styles to — tracked so a panel removed from
135
+ // the slot (e.g. a DOM node later reused elsewhere) gets those
136
+ // lyra-split-authored styles cleared instead of carrying them around stale
137
+ // forever.
138
+ this.stylizedPanels = new Set();
139
+ this.constraintIssueKey = '';
45
140
  this.onSlotChange = () => {
46
141
  this.panelCount = this.children.length;
47
142
  this.ensureSizes();
48
143
  };
144
+ this.onBackdropClick = () => {
145
+ this.overlayHandle?.dismissBackdrop();
146
+ };
49
147
  this.onPointerDown = (e, index) => {
50
- const base = this.renderRoot.querySelector('[part="base"]');
148
+ // The divider adjacent to a currently rail/floating-collapsed pane isn't
149
+ // draggable — mirrors the `[part="divider"][aria-disabled="true"]`
150
+ // `pointer-events: none` in split.styles.ts (belt-and-suspenders: this
151
+ // guard also covers a synthetic/programmatic pointerdown that CSS
152
+ // wouldn't stop).
153
+ if (this.isDividerDisabled(index))
154
+ return;
155
+ // The divider that dispatched this is itself a child of [part="base"],
156
+ // so baseEl is guaranteed to be already rendered here.
51
157
  this.drags.set(e.pointerId, {
52
158
  index,
53
159
  startPos: this.orientation === 'vertical' ? e.clientY : e.clientX,
54
- startSizes: [...this.sizes],
55
- base,
160
+ base: this.baseEl,
161
+ appliedDelta: 0,
56
162
  });
57
163
  e.target.setPointerCapture(e.pointerId);
58
164
  window.addEventListener('pointermove', this.onPointerMove);
@@ -70,14 +176,40 @@ export class LyraSplit extends LyraElement {
70
176
  return;
71
177
  const total = this.orientation === 'vertical' ? drag.base.clientHeight : drag.base.clientWidth;
72
178
  const pos = this.orientation === 'vertical' ? e.clientY : e.clientX;
73
- let deltaPercent = ((pos - drag.startPos) / total) * 100;
179
+ let cumulativeDelta = ((pos - drag.startPos) / total) * 100;
74
180
  // Panels are ordered along the inline axis via CSS `order`, so under RTL
75
181
  // `flex-direction: row` already renders panel[i] to the *right* of
76
182
  // panel[i+1] — a physically-rightward drag has to shrink index instead
77
183
  // of growing it to keep matching the visible panel under the pointer.
78
184
  if (this.orientation === 'horizontal' && isRtl(this))
79
- deltaPercent = -deltaPercent;
80
- const paired = this.clampPair(drag.startSizes, drag.index, deltaPercent, total);
185
+ cumulativeDelta = -cumulativeDelta;
186
+ // Clamp against the *current* live sizes, not this pointer's own drag-start
187
+ // snapshot -- two adjacent dividers dragged concurrently share one panel
188
+ // between them, and each clamp pass must see whatever the other pointer's
189
+ // move has *just* written, or the two independently-clamped pairs can each
190
+ // stay individually valid while their shared panel drifts past what either
191
+ // pair alone would allow, letting the total exceed 100%. Since the clamp
192
+ // basis is now the live, already-partially-applied `this.sizes` instead of
193
+ // a fixed drag-start snapshot, only the *incremental* delta since the last
194
+ // move may be applied here (not the cumulative-since-drag-start delta a
195
+ // snapshot-based clamp would use).
196
+ const incremental = cumulativeDelta - drag.appliedDelta;
197
+ const priorValue = this.sizes[drag.index];
198
+ const paired = this.clampPair(this.sizes, drag.index, incremental, total);
199
+ // Accumulate this move's own *realized* increment (post-clamp) onto the
200
+ // running total, rather than recomputing an absolute "total since
201
+ // drag-start" diff against a fixed startSizes snapshot. clampPair can
202
+ // cap the actual move short of what was requested (e.g. a drag
203
+ // saturating a panel's min/panelConstraints bound), so the realized
204
+ // portion still has to be tracked instead of the raw request -- that
205
+ // part of round 1's fix stands. But an absolute since-start diff also
206
+ // silently absorbs any change a DIFFERENT concurrent pointer's drag
207
+ // makes to this same shared panel between this pointer's own moves
208
+ // (adjacent dividers share one panel: divider i's index+1 panel is
209
+ // divider i+1's index panel), corrupting this pointer's next incremental
210
+ // calculation. Summing only this move's own delta (paired vs. the value
211
+ // immediately prior to *this* clamp) avoids both bugs at once.
212
+ drag.appliedDelta += paired[drag.index] - priorValue;
81
213
  // Merge only this drag's pair into the live sizes so a concurrent drag
82
214
  // on another divider (different pointerId) isn't clobbered.
83
215
  const next = [...this.sizes];
@@ -99,6 +231,9 @@ export class LyraSplit extends LyraElement {
99
231
  }
100
232
  };
101
233
  this.onDividerKeyDown = (e, index) => {
234
+ // Same rail/floating-adjacent guard as onPointerDown.
235
+ if (this.isDividerDisabled(index))
236
+ return;
102
237
  // Mirror the same swap as onPointerMove for horizontal+RTL.
103
238
  const rtl = this.orientation === 'horizontal' && isRtl(this);
104
239
  const forwardKey = this.orientation === 'vertical' ? 'ArrowDown' : rtl ? 'ArrowLeft' : 'ArrowRight';
@@ -114,11 +249,48 @@ export class LyraSplit extends LyraElement {
114
249
  };
115
250
  }
116
251
  static { this.styles = [LyraElement.styles, styles]; }
252
+ // `collapseState` needs a custom accessor (force/auto semantics -- see the
253
+ // class doc) rather than the usual @property()-generated one -- registered
254
+ // here, alongside the decorator-declared properties below, the same way
255
+ // lyra-app-rail's `mode` is. `reflect: true` still applies: LitElement's
256
+ // update loop reflects any `reflect`-flagged property to its attribute
257
+ // generically by reading `this[name]` after render, regardless of whether
258
+ // that property has a custom or auto-generated accessor. `attribute` is
259
+ // spelled out (unlike `mode`, a single word whose Lit-default lowercase
260
+ // form already reads fine) so the reflected attribute stays kebab-case,
261
+ // matching this file's other attribute-reflected properties.
262
+ static { this.properties = {
263
+ collapseState: { reflect: true, attribute: 'collapse-state', noAccessor: true },
264
+ }; }
117
265
  connectedCallback() {
118
266
  super.connectedCallback();
119
267
  this.panelCount = this.children.length;
120
268
  this.ensureSizes();
121
269
  this.loadPersisted();
270
+ // No-op on first mount (`baseEl` doesn't exist until the first render —
271
+ // `firstUpdated()` below arms it then) but does the real work on a
272
+ // reconnect, whose shadow DOM content survives disconnect. Mirrors
273
+ // lite-chart.ts's identical connectedCallback/firstUpdated split for its
274
+ // own ResizeObserver.
275
+ if (this.collapse !== 'none')
276
+ this.armCollapseObserver();
277
+ // A reconnect (e.g. a drag-and-drop reparent keeping this same element
278
+ // instance) fires disconnectedCallback then connectedCallback
279
+ // synchronously with no update in between, so willUpdate never reruns to
280
+ // notice the floating drawer is still active -- restore its shared
281
+ // registration and scroll lock. Mirrors lyra-app-rail's identical
282
+ // reconnect handling for its mobile overlay.
283
+ if (this.hasUpdated && this.overlayActive) {
284
+ if (this.overlayHandle?.isActive()) {
285
+ this.overlayHandle.resume();
286
+ }
287
+ else {
288
+ this.activateFloatingOverlay();
289
+ }
290
+ if (!this.releaseScrollLock)
291
+ this.releaseScrollLock = lockScroll(this.ownerDocument);
292
+ queueMicrotask(() => this.overlayHandle?.focusInitial());
293
+ }
122
294
  }
123
295
  disconnectedCallback() {
124
296
  super.disconnectedCallback();
@@ -128,6 +300,106 @@ export class LyraSplit extends LyraElement {
128
300
  window.removeEventListener('pointerup', this.onPointerUp);
129
301
  window.removeEventListener('pointercancel', this.onPointerUp);
130
302
  window.removeEventListener('lostpointercapture', this.onPointerUp);
303
+ this.collapseResizeObserver?.disconnect();
304
+ this.releaseScrollLock?.();
305
+ this.releaseScrollLock = undefined;
306
+ this.overlayHandle?.suspend();
307
+ }
308
+ firstUpdated() {
309
+ if (this.collapse !== 'none')
310
+ this.armCollapseObserver();
311
+ }
312
+ /** Both branches here derive one reactive property from another with no
313
+ * DOM measurement involved, so they belong in `willUpdate()` rather than
314
+ * `updated()`: setting a reactive property from `updated()`/
315
+ * `firstUpdated()` schedules a *second* update on top of the one that
316
+ * just finished, which Lit's dev-mode console flags ("scheduled an
317
+ * update ... after an update completed"). Both of these were real and
318
+ * reproducible in normal usage, not just test artifacts --
319
+ * `ensureSizes()` on any direct `sizes` assignment whose length doesn't
320
+ * match `panelCount` (e.g. a consumer correcting a stale layout), and the
321
+ * `collapseState` reset on every `collapse` -> `'none'` transition. The
322
+ * `collapse !== 'none'` re-arm path in `syncCollapseObserver()` still
323
+ * needs a freshly measured container width and stays in `updated()` --
324
+ * see `armCollapseObserver()`'s own doc comment for why *that* one is the
325
+ * documented exception instead (mirrors virtual-list.ts's
326
+ * `attachContainerListeners()`). */
327
+ willUpdate(changed) {
328
+ if (changed.has('sizes') || this.sizes.length === 0)
329
+ this.ensureSizes();
330
+ if (changed.has('collapse') && this.collapse === 'none') {
331
+ this.resetCollapseState();
332
+ }
333
+ if (changed.has('open') || changed.has('collapseState')) {
334
+ const next = this._collapseState === 'floating' && this.open;
335
+ if (next !== this.overlayActive) {
336
+ this.overlayActive = next;
337
+ if (next) {
338
+ this.justOpened = true;
339
+ this.activateFloatingOverlay();
340
+ }
341
+ else {
342
+ this.deactivateFloatingOverlay();
343
+ }
344
+ }
345
+ }
346
+ }
347
+ /**
348
+ * The collapsing pane's current responsive state. Always one of the three
349
+ * real states — never `'auto'` — reflecting either the live measured
350
+ * width or, once forced, whatever was last assigned. See the class doc for
351
+ * the full force/auto contract (mirrors `<lyra-app-rail>`'s `mode`).
352
+ */
353
+ get collapseState() {
354
+ return this._collapseState;
355
+ }
356
+ set collapseState(next) {
357
+ if (next === 'auto') {
358
+ this._forced = false;
359
+ this.updateCollapseState(this.currentMeasuredWidth());
360
+ return;
361
+ }
362
+ this._forced = true;
363
+ this.applyCollapseStateChange(next);
364
+ }
365
+ /** The container width (px) `[part="base"]` is measured at right now --
366
+ * used to re-derive `collapseState` immediately when a forced value is
367
+ * released back to `'auto'`, outside of the `ResizeObserver`'s own
368
+ * (async, entry-driven) callback. Mirrors the synchronous initial read
369
+ * `armCollapseObserver()` already does when it (re-)arms. */
370
+ currentMeasuredWidth() {
371
+ return this.baseEl?.clientWidth ?? 0;
372
+ }
373
+ /** Resets `collapseState` back to its `'wide'` default and releases any
374
+ * force, bypassing the public accessor's pin/event-emit side effects --
375
+ * used only for the `collapse -> 'none'` housekeeping reset in
376
+ * `willUpdate()`, which is purely internal bookkeeping (the feature is
377
+ * off entirely), not a state transition a consumer forced or observed. */
378
+ resetCollapseState() {
379
+ this._forced = false;
380
+ if (this._collapseState === 'wide')
381
+ return;
382
+ const old = this._collapseState;
383
+ this._collapseState = 'wide';
384
+ this.requestUpdate('collapseState', old);
385
+ }
386
+ /** Applies an actual `collapseState` transition (no-op if `next` matches
387
+ * the current value): updates the field, triggers Lit's reflect/re-render
388
+ * via `requestUpdate`, and fires `lyra-split-collapse-change`. Shared by
389
+ * both the `ResizeObserver`-driven measurement path (`updateCollapseState`)
390
+ * and the accessor's forced-value assignment, so the two never duplicate
391
+ * this logic. Leaving `'floating'` while `open` is still `true` also
392
+ * closes the drawer -- mirrors `<lyra-app-rail>` closing its mobile
393
+ * overlay when `mode` leaves `'mobile'` while open. */
394
+ applyCollapseStateChange(next) {
395
+ if (next === this._collapseState)
396
+ return;
397
+ const old = this._collapseState;
398
+ this._collapseState = next;
399
+ this.requestUpdate('collapseState', old);
400
+ this.emit('lyra-split-collapse-change', { state: next });
401
+ if (next !== 'floating' && this.open)
402
+ this.open = false;
131
403
  }
132
404
  get storageFullKey() {
133
405
  return this.storageKey ? `lyra-split:${this.storageKey}:${this.panelCount}` : undefined;
@@ -206,26 +478,164 @@ export class LyraSplit extends LyraElement {
206
478
  * container resize between calls is always picked up — same live read
207
479
  * `onPointerMove` already does via `drag.base.clientWidth/clientHeight`. */
208
480
  getContainerSize() {
209
- const base = this.renderRoot.querySelector('[part="base"]');
210
- if (!base)
481
+ if (!this.baseEl)
211
482
  return 0;
212
- return this.orientation === 'vertical' ? base.clientHeight : base.clientWidth;
483
+ return this.orientation === 'vertical' ? this.baseEl.clientHeight : this.baseEl.clientWidth;
213
484
  }
214
- /** Resolves panel `index`'s effective percent min/max for this clamp pass:
215
- * a `panelConstraints` entry's px bound converted against the live
216
- * `containerSize`, or the component's plain percent `min` (no upper
217
- * bound) when the panel carries no constraint for that side. */
218
- percentBounds(index, containerSize) {
219
- const constraint = this.panelConstraints[index];
220
- let min = this.min;
221
- let max = Infinity;
222
- if (constraint && containerSize > 0) {
223
- if (constraint.minPx != null)
224
- min = (constraint.minPx / containerSize) * 100;
225
- if (constraint.maxPx != null)
226
- max = (constraint.maxPx / containerSize) * 100;
485
+ /** The physical panel index `collapse: 'start' | 'end'` resolves to, or
486
+ * `-1` when collapse is off (`'none'`) or there are fewer than 2 panels
487
+ * to collapse one of. Panels are laid out via ascending inline `order`
488
+ * (see `updated()`) and that ordering is never re-swapped for RTL only
489
+ * the drag/keyboard *delta sign* mirrors for RTL, exactly like
490
+ * `onPointerMove`/`onDividerKeyDown` so panel index 0 already renders
491
+ * at the logical inline-start edge under both LTR and RTL (confirmed by
492
+ * the pointer-drag RTL test elsewhere in this file: panel 0 renders on
493
+ * the visual *right*, i.e. the RTL inline-start side). `'start'` therefore
494
+ * always resolves to index 0 and `'end'` to `panelCount - 1`, regardless
495
+ * of `isRtl(this)` consulting it here would swap collapse onto the
496
+ * panel that visually sits at the *other* logical edge, which would be a
497
+ * bug against this component's own RTL rendering, not a fix for one.
498
+ */
499
+ get collapsingIndex() {
500
+ if (this.collapse === 'none' || this.panelCount < 2)
501
+ return -1;
502
+ return this.collapse === 'start' ? 0 : this.panelCount - 1;
503
+ }
504
+ /** Whether a pane is actually collapsed (rail or floating) right now —
505
+ * `false` whenever `collapse === 'none'`, since `collapseState` then
506
+ * never leaves its `'wide'` default. */
507
+ get collapseActive() {
508
+ return this.collapsingIndex !== -1 && this.collapseState !== 'wide';
509
+ }
510
+ /** Dragging/keyboard-resizing is disabled on the one divider immediately
511
+ * adjacent to the currently-collapsed pane (its other side has nothing
512
+ * meaningful to resize against while the pane is rail/floating-width). */
513
+ isDividerDisabled(index) {
514
+ if (!this.collapseActive)
515
+ return false;
516
+ const adjacent = this.collapsingIndex === 0 ? 0 : this.panelCount - 2;
517
+ return index === adjacent;
518
+ }
519
+ /** Classifies a measured container width into the collapsing pane's
520
+ * responsive state and, only on an actual transition, applies it (via the
521
+ * same `applyCollapseStateChange()` the accessor's forced-value path
522
+ * uses). Gated behind `_forced` so a pinned `collapseState` is never
523
+ * silently overwritten by a subsequent resize — this is also what the
524
+ * accessor's `'auto'` release calls (with the current measured width) to
525
+ * re-derive the state without duplicating the width-vs-breakpoint logic. */
526
+ updateCollapseState(width) {
527
+ if (this.collapse === 'none')
528
+ return;
529
+ if (this._forced)
530
+ return;
531
+ const next = width < this.floatBreakpoint ? 'floating' : width < this.railBreakpoint ? 'rail' : 'wide';
532
+ this.applyCollapseStateChange(next);
533
+ }
534
+ /** Creates (idempotently) and (re-)observes `[part="base"]` with the
535
+ * collapse-state `ResizeObserver` — a no-op until `baseEl` exists (see
536
+ * `firstUpdated()`/`connectedCallback()`). Mirrors lite-chart.ts's own
537
+ * ResizeObserver setup, including reading the box size synchronously
538
+ * once so the very first render doesn't sit at the stale `'wide'` default
539
+ * until the (async) first callback fires — same rationale as
540
+ * lyra-virtual-list's `containerResizeObserver` synchronous initial read. */
541
+ armCollapseObserver() {
542
+ if (!this.collapseResizeObserver) {
543
+ this.collapseResizeObserver = new ResizeObserver((entries) => {
544
+ const box = entries[0]?.contentBoxSize?.[0];
545
+ const width = box ? box.inlineSize : (this.baseEl?.getBoundingClientRect().width ?? 0);
546
+ this.updateCollapseState(width);
547
+ });
548
+ }
549
+ if (this.baseEl) {
550
+ this.collapseResizeObserver.observe(this.baseEl);
551
+ this.updateCollapseState(this.baseEl.clientWidth);
552
+ }
553
+ }
554
+ /** Reacts to a live `collapse` property change (as opposed to the
555
+ * connect/first-render arming above): turns the observer on/off. The
556
+ * `collapseState` reset for the `'none'` case lives in `willUpdate()`
557
+ * instead (see its doc comment) so no stale rail/floating styling
558
+ * survives switching collapse off, without the extra render pass a
559
+ * property set here would cost. */
560
+ syncCollapseObserver() {
561
+ if (this.collapse === 'none') {
562
+ this.collapseResizeObserver?.disconnect();
563
+ return;
227
564
  }
228
- return { min, max };
565
+ this.armCollapseObserver();
566
+ }
567
+ /** The safe fallback for a shared percent minimum. A value above the
568
+ * available share is still useful as a consumer intent, but it cannot be
569
+ * honored for every panel at once, so reduce it proportionally. */
570
+ normalizedDefaultMin() {
571
+ if (this.panelCount <= 0)
572
+ return 0;
573
+ const requested = Number.isFinite(this.min) ? Math.max(0, this.min) : 0;
574
+ // Leave one keyboard step of aggregate slack after rejecting an
575
+ // infeasible configuration, so an equal starting layout remains
576
+ // resizable instead of merely becoming a different frozen layout.
577
+ const available = Math.max(0, 100 - KEYBOARD_STEP);
578
+ return Math.min(requested, available / this.panelCount);
579
+ }
580
+ /** Resolves all panel bounds together so aggregate feasibility is checked
581
+ * before an individual divider is asked to clamp a pair. An invalid set is
582
+ * rejected as a whole: interaction uses the safe shared minimum instead of
583
+ * exposing a divider whose minimum is greater than its maximum. */
584
+ resolveConstraintBounds(containerSize) {
585
+ const fallbackMin = this.normalizedDefaultMin();
586
+ const fallback = Array.from({ length: this.panelCount }, () => ({ min: fallbackMin, max: Infinity }));
587
+ if (this.panelCount <= 0)
588
+ return { bounds: [], usePanelConstraints: true };
589
+ const bounds = [];
590
+ let minimumTotal = 0;
591
+ let maximumTotal = 0;
592
+ let hasUnboundedMaximum = false;
593
+ let issueReason;
594
+ for (let index = 0; index < this.panelCount; index++) {
595
+ const constraint = this.panelConstraints[index];
596
+ let min = Number.isFinite(this.min) ? Math.max(0, this.min) : 0;
597
+ let max = Infinity;
598
+ if (constraint) {
599
+ if (constraint.minPx != null && Number.isFinite(constraint.minPx) && constraint.minPx >= 0 && containerSize > 0) {
600
+ min = (constraint.minPx / containerSize) * 100;
601
+ }
602
+ if (constraint.maxPx != null && Number.isFinite(constraint.maxPx) && constraint.maxPx >= 0 && containerSize > 0) {
603
+ max = (constraint.maxPx / containerSize) * 100;
604
+ }
605
+ if ((constraint.minPx != null && (!Number.isFinite(constraint.minPx) || constraint.minPx < 0)) ||
606
+ (constraint.maxPx != null && (!Number.isFinite(constraint.maxPx) || constraint.maxPx < 0))) {
607
+ issueReason ??= 'minimum-exceeds-maximum';
608
+ }
609
+ }
610
+ if (min > max)
611
+ issueReason ??= 'minimum-exceeds-maximum';
612
+ bounds.push({ min, max });
613
+ minimumTotal += min;
614
+ if (Number.isFinite(max))
615
+ maximumTotal += max;
616
+ else
617
+ hasUnboundedMaximum = true;
618
+ }
619
+ if (issueReason == null && minimumTotal > 100 + 1e-9)
620
+ issueReason = 'minimum-total';
621
+ if (issueReason == null && !hasUnboundedMaximum && maximumTotal < 100 - 1e-9)
622
+ issueReason = 'maximum-total';
623
+ if (issueReason == null)
624
+ return { bounds, usePanelConstraints: true };
625
+ return {
626
+ bounds: fallback,
627
+ usePanelConstraints: false,
628
+ issue: {
629
+ reason: issueReason,
630
+ panelCount: this.panelCount,
631
+ minimumTotal,
632
+ maximumTotal: hasUnboundedMaximum ? null : maximumTotal,
633
+ containerSize,
634
+ },
635
+ };
636
+ }
637
+ percentBounds(index, containerSize) {
638
+ return this.resolveConstraintBounds(containerSize).bounds[index] ?? { min: 0, max: Infinity };
229
639
  }
230
640
  clampPair(sizes, i, delta, containerSize = 0) {
231
641
  const next = [...sizes];
@@ -254,45 +664,191 @@ export class LyraSplit extends LyraElement {
254
664
  if (commit)
255
665
  this.persist();
256
666
  }
667
+ /** The collapsing pane's light-DOM element itself — the `'floating'`
668
+ * drawer's focus-trap/backdrop target. There's no separate shadow-DOM
669
+ * panel to trap focus within (unlike `<lyra-app-rail>`'s `[part="panel"]`):
670
+ * the slotted panel *is* the floating drawer, just repositioned via
671
+ * inline styles in `updated()`. */
672
+ get floatingPanelEl() {
673
+ const index = this.collapsingIndex;
674
+ return index === -1 ? null : (this.children[index] ?? null);
675
+ }
676
+ activateFloatingOverlay() {
677
+ this.releaseScrollLock ??= lockScroll(this.ownerDocument);
678
+ this.overlayHandle = activateOverlay({
679
+ host: this,
680
+ panel: () => this.floatingPanelEl,
681
+ onEscape: () => (this.open = false),
682
+ onBackdrop: () => (this.open = false),
683
+ });
684
+ }
685
+ deactivateFloatingOverlay() {
686
+ this.releaseScrollLock?.();
687
+ this.releaseScrollLock = undefined;
688
+ this.overlayHandle?.deactivate();
689
+ this.overlayHandle = undefined;
690
+ }
257
691
  updated(changed) {
258
- if (changed.has('sizes') || this.sizes.length === 0)
259
- this.ensureSizes();
692
+ if (changed.has('collapse'))
693
+ this.syncCollapseObserver();
694
+ const constraintResolution = this.resolveConstraintBounds(this.getContainerSize());
695
+ const issue = constraintResolution.issue;
696
+ const issueKey = issue
697
+ ? `${issue.reason}:${issue.panelCount}:${issue.minimumTotal}:${issue.maximumTotal ?? 'unbounded'}`
698
+ : '';
699
+ if (issueKey !== this.constraintIssueKey) {
700
+ this.constraintIssueKey = issueKey;
701
+ if (issue)
702
+ this.emit('lyra-split-constraints-invalid', issue);
703
+ }
260
704
  const panels = [...this.children];
705
+ const current = new Set(panels);
706
+ // A panel that dropped out of the slot (removed from the light DOM)
707
+ // still carries whatever inline flex/order (and, while collapsing,
708
+ // position/inset/inline-size) this method last applied to it — clear
709
+ // those before that DOM node potentially gets reused elsewhere (e.g.
710
+ // re-slotted into another split/container).
711
+ for (const stale of this.stylizedPanels) {
712
+ if (!current.has(stale)) {
713
+ stale.style.removeProperty('flex');
714
+ stale.style.removeProperty('order');
715
+ stale.style.removeProperty('position');
716
+ stale.style.removeProperty('inset-block');
717
+ stale.style.removeProperty('inset-inline-start');
718
+ stale.style.removeProperty('inset-inline-end');
719
+ stale.style.removeProperty('inline-size');
720
+ stale.hidden = false;
721
+ delete stale.dataset.collapseState;
722
+ }
723
+ }
724
+ // Resolved once per pass rather than per panel: which physical index (if
725
+ // any) is actually collapsed right now — `-1` covers both `collapse ===
726
+ // 'none'` (the default) and a `collapse !== 'none'` pane that's still in
727
+ // its normal `'wide'` state, so every panel below falls straight through
728
+ // to the exact pre-existing (non-collapse) styling in either case.
729
+ const collapsingIndex = this.collapseActive ? this.collapsingIndex : -1;
261
730
  panels.forEach((panel, i) => {
262
731
  const percent = this.sizes[i] ?? 0;
263
- const constraint = this.panelConstraints[i];
264
- // clamp() mixes units natively, so a constrained panel stays pinned
265
- // between its px bounds across container resizes with no extra
266
- // ResizeObserver the browser re-evaluates it on every layout pass.
267
- panel.style.flex =
268
- constraint && (constraint.minPx != null || constraint.maxPx != null)
269
- ? `0 0 clamp(${constraint.minPx ?? NO_MIN_PX}px, ${percent}%, ${constraint.maxPx ?? NO_MAX_PX}px)`
270
- : `0 0 ${percent}%`;
732
+ const constraint = constraintResolution.usePanelConstraints ? this.panelConstraints[i] : undefined;
733
+ // Collapse-only inline styles are always cleared first, then
734
+ // re-applied below only for the panel(s) that need them this pass —
735
+ // simpler than diffing which of the 5 properties changed.
736
+ panel.style.removeProperty('position');
737
+ panel.style.removeProperty('inset-block');
738
+ panel.style.removeProperty('inset-inline-start');
739
+ panel.style.removeProperty('inset-inline-end');
740
+ panel.style.removeProperty('inline-size');
741
+ panel.hidden = false;
742
+ if (collapsingIndex === i && this.collapseState === 'rail') {
743
+ // Fixed rail width instead of the normal clamp()/percent flex-basis.
744
+ panel.style.flex = `0 0 ${this.railWidth}`;
745
+ }
746
+ else if (collapsingIndex === i && this.collapseState === 'floating' && !this.open) {
747
+ // Hidden-by-default drawer (see the class doc): rendering nothing
748
+ // (not just visually collapsed, so it's out of the accessibility
749
+ // tree too) until a consumer sets `open`. The pane still vacates the
750
+ // flex flow the same way the open/floating branch below does, via
751
+ // `hidden`'s UA `display: none` rather than `position: absolute`, so
752
+ // the other pane below still grows to fill the space regardless of
753
+ // which of the two branches applied.
754
+ panel.style.flex = 'none';
755
+ panel.hidden = true;
756
+ }
757
+ else if (collapsingIndex === i && this.collapseState === 'floating') {
758
+ // `this.open` is true here. Lifted out of the flex flow entirely as
759
+ // an overlay card, anchored to its own logical start/end edge,
760
+ // spanning the full cross-axis extent — [part="base"] carries
761
+ // `position: relative` for this to anchor against (see
762
+ // split.styles.ts). Sized at its own normal percent width (i.e. what
763
+ // it would render at in the `'wide'` state), so there's no visual
764
+ // size jump the moment it un-floats.
765
+ panel.style.flex = 'none';
766
+ panel.style.position = 'absolute';
767
+ panel.style.setProperty('inset-block', '0');
768
+ panel.style.setProperty(collapsingIndex === 0 ? 'inset-inline-start' : 'inset-inline-end', '0');
769
+ panel.style.setProperty('inline-size', `${percent}%`);
770
+ }
771
+ else if (collapsingIndex !== -1 && i !== collapsingIndex) {
772
+ // The pane(s) sharing the split with a currently rail/floating
773
+ // collapsed pane: grow to fill whatever space that pane no longer
774
+ // occupies (its full percent-basis space while floating, or
775
+ // percent-basis-minus-railWidth while railed), proportionally to
776
+ // their own relative `sizes` share for a 3+-panel split.
777
+ panel.style.flex = `${percent} 1 0%`;
778
+ }
779
+ else {
780
+ // clamp() mixes units natively, so a constrained panel stays pinned
781
+ // between its px bounds across container resizes with no extra
782
+ // ResizeObserver — the browser re-evaluates it on every layout pass.
783
+ panel.style.flex =
784
+ constraint && (constraint.minPx != null || constraint.maxPx != null)
785
+ ? `0 0 clamp(${constraint.minPx ?? NO_MIN_PX}px, ${percent}%, ${constraint.maxPx ?? NO_MAX_PX}px)`
786
+ : `0 0 ${percent}%`;
787
+ }
271
788
  panel.style.order = String(i * 2);
789
+ if (collapsingIndex === i) {
790
+ panel.dataset.collapseState = this.collapseState;
791
+ }
792
+ else {
793
+ delete panel.dataset.collapseState;
794
+ }
272
795
  });
796
+ this.stylizedPanels = current;
797
+ // Host-level marker (mirrors the per-panel `dataset.collapseState`
798
+ // above) for simple external CSS targeting of the whole component's
799
+ // current state, e.g. `lyra-split[data-collapse-state="rail"] + aside`.
800
+ // Absent whenever there's nothing collapsed to report (`collapse ===
801
+ // 'none'` or still `'wide'`), same as the per-panel marker.
802
+ if (collapsingIndex !== -1) {
803
+ this.setAttribute('data-collapse-state', this.collapseState);
804
+ }
805
+ else {
806
+ this.removeAttribute('data-collapse-state');
807
+ }
808
+ // Runs after this render (not willUpdate) so the floating panel's
809
+ // repositioned geometry above has already landed before the focus call
810
+ // below can rely on it -- mirrors lyra-app-rail's/lyra-dialog's identical
811
+ // ordering rationale for their own overlay's initial focus.
812
+ if (this.justOpened) {
813
+ this.justOpened = false;
814
+ this.overlayHandle?.focusInitial();
815
+ }
273
816
  }
274
817
  render() {
275
818
  const dividers = [];
819
+ const bounds = this.resolveConstraintBounds(this.getContainerSize()).bounds;
276
820
  for (let i = 0; i < this.panelCount - 1; i++) {
277
- // The achievable max for this divider is bounded by its two adjacent
278
- // panels, not the whole track — pushing past it would starve a panel
279
- // further down the line even though this pair still has room.
280
- const valueMax = (this.sizes[i] ?? 0) + (this.sizes[i + 1] ?? 0) - this.min;
821
+ // The achievable range is bounded by both adjacent panels, not the
822
+ // whole track — pushing past it would starve the partner even though
823
+ // this pair still has room. Keep max >= min for imperfect persisted or
824
+ // consumer-supplied starting sizes.
825
+ const pairTotal = (this.sizes[i] ?? 0) + (this.sizes[i + 1] ?? 0);
826
+ const a = bounds[i] ?? { min: 0, max: Infinity };
827
+ const b = bounds[i + 1] ?? { min: 0, max: Infinity };
828
+ const valueMin = Math.max(a.min, pairTotal - b.max);
829
+ const valueMax = Math.max(valueMin, Math.min(a.max, pairTotal - b.min));
830
+ const disabled = this.isDividerDisabled(i);
281
831
  dividers.push(html `<div
282
832
  part="divider"
283
833
  role="separator"
284
834
  aria-label="Resize divider between panel ${i + 1} and panel ${i + 2}"
285
835
  aria-orientation=${this.orientation === 'vertical' ? 'horizontal' : 'vertical'}
286
836
  aria-valuenow=${Math.round(this.sizes[i] ?? 0)}
287
- aria-valuemin=${this.min}
837
+ aria-valuemin=${Math.round(valueMin)}
288
838
  aria-valuemax=${Math.round(valueMax)}
289
- tabindex="0"
839
+ aria-disabled=${disabled ? 'true' : nothing}
840
+ tabindex=${disabled ? '-1' : '0'}
290
841
  style=${`order:${i * 2 + 1}`}
291
842
  @pointerdown=${(e) => this.onPointerDown(e, i)}
292
843
  @keydown=${(e) => this.onDividerKeyDown(e, i)}
293
844
  ></div>`);
294
845
  }
295
- return html `<div part="base"><slot @slotchange=${this.onSlotChange}></slot>${dividers}</div>`;
846
+ const showBackdrop = this.collapseState === 'floating' && this.open;
847
+ return html `<div part="base">
848
+ <slot @slotchange=${this.onSlotChange}></slot>
849
+ ${dividers}
850
+ ${showBackdrop ? html `<div part="backdrop" @click=${this.onBackdropClick}></div>` : nothing}
851
+ </div>`;
296
852
  }
297
853
  }
298
854
  __decorate([
@@ -310,7 +866,25 @@ __decorate([
310
866
  __decorate([
311
867
  property({ attribute: false })
312
868
  ], LyraSplit.prototype, "panelConstraints", void 0);
869
+ __decorate([
870
+ property({ reflect: true })
871
+ ], LyraSplit.prototype, "collapse", void 0);
872
+ __decorate([
873
+ property({ attribute: 'rail-width' })
874
+ ], LyraSplit.prototype, "railWidth", void 0);
875
+ __decorate([
876
+ property({ type: Number, attribute: 'rail-breakpoint' })
877
+ ], LyraSplit.prototype, "railBreakpoint", void 0);
878
+ __decorate([
879
+ property({ type: Number, attribute: 'float-breakpoint' })
880
+ ], LyraSplit.prototype, "floatBreakpoint", void 0);
881
+ __decorate([
882
+ property({ type: Boolean, reflect: true })
883
+ ], LyraSplit.prototype, "open", void 0);
313
884
  __decorate([
314
885
  state()
315
886
  ], LyraSplit.prototype, "panelCount", void 0);
887
+ __decorate([
888
+ query('[part="base"]')
889
+ ], LyraSplit.prototype, "baseEl", void 0);
316
890
  defineElement('split', LyraSplit);