@aceshooting/lyra-ui 5.2.0 → 6.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 (853) hide show
  1. package/CHANGELOG.md +4024 -0
  2. package/README.md +7 -6
  3. package/custom-elements.json +4330 -1600
  4. package/dist/ai/types.contract.js +1 -0
  5. package/dist/ai/types.contract.js.map +1 -1
  6. package/dist/components/agent-tools/activity-feed/activity-feed.class.d.ts.map +1 -1
  7. package/dist/components/agent-tools/activity-feed/activity-feed.class.js.map +1 -1
  8. package/dist/components/agent-tools/agent-run/agent-run.class.d.ts.map +1 -1
  9. package/dist/components/agent-tools/agent-run/agent-run.class.js.map +1 -1
  10. package/dist/components/agent-tools/agent-trace/agent-trace.class.d.ts.map +1 -1
  11. package/dist/components/agent-tools/agent-trace/agent-trace.class.js.map +1 -1
  12. package/dist/components/agent-tools/artifact-panel/artifact-panel.class.d.ts +4 -2
  13. package/dist/components/agent-tools/artifact-panel/artifact-panel.class.d.ts.map +1 -1
  14. package/dist/components/agent-tools/artifact-panel/artifact-panel.class.js +3 -1
  15. package/dist/components/agent-tools/artifact-panel/artifact-panel.class.js.map +1 -1
  16. package/dist/components/agent-tools/browser-frame/browser-frame.class.d.ts +7 -3
  17. package/dist/components/agent-tools/browser-frame/browser-frame.class.d.ts.map +1 -1
  18. package/dist/components/agent-tools/browser-frame/browser-frame.class.js.map +1 -1
  19. package/dist/components/agent-tools/commit-card/commit-card.class.d.ts.map +1 -1
  20. package/dist/components/agent-tools/commit-card/commit-card.class.js.map +1 -1
  21. package/dist/components/agent-tools/compare-panel/compare-panel.class.d.ts.map +1 -1
  22. package/dist/components/agent-tools/compare-panel/compare-panel.class.js.map +1 -1
  23. package/dist/components/agent-tools/confirm-bar/confirm-bar.class.d.ts +36 -4
  24. package/dist/components/agent-tools/confirm-bar/confirm-bar.class.d.ts.map +1 -1
  25. package/dist/components/agent-tools/confirm-bar/confirm-bar.class.js +68 -19
  26. package/dist/components/agent-tools/confirm-bar/confirm-bar.class.js.map +1 -1
  27. package/dist/components/agent-tools/confirm-bar/confirm-bar.d.ts +1 -0
  28. package/dist/components/agent-tools/confirm-bar/confirm-bar.d.ts.map +1 -1
  29. package/dist/components/agent-tools/confirm-bar/confirm-bar.js +1 -0
  30. package/dist/components/agent-tools/confirm-bar/confirm-bar.js.map +1 -1
  31. package/dist/components/agent-tools/confirm-bar/confirm-bar.styles.d.ts.map +1 -1
  32. package/dist/components/agent-tools/confirm-bar/confirm-bar.styles.js +10 -29
  33. package/dist/components/agent-tools/confirm-bar/confirm-bar.styles.js.map +1 -1
  34. package/dist/components/agent-tools/context-inspector/context-inspector.class.d.ts.map +1 -1
  35. package/dist/components/agent-tools/context-inspector/context-inspector.class.js.map +1 -1
  36. package/dist/components/agent-tools/eval-dataset/eval-dataset.class.d.ts +7 -7
  37. package/dist/components/agent-tools/eval-dataset/eval-dataset.class.d.ts.map +1 -1
  38. package/dist/components/agent-tools/eval-dataset/eval-dataset.class.js +14 -13
  39. package/dist/components/agent-tools/eval-dataset/eval-dataset.class.js.map +1 -1
  40. package/dist/components/agent-tools/eval-dataset/eval-dataset.d.ts +1 -1
  41. package/dist/components/agent-tools/eval-dataset/eval-dataset.d.ts.map +1 -1
  42. package/dist/components/agent-tools/eval-dataset/eval-dataset.js +1 -1
  43. package/dist/components/agent-tools/eval-dataset/eval-dataset.js.map +1 -1
  44. package/dist/components/agent-tools/eval-result/eval-result.class.d.ts +11 -9
  45. package/dist/components/agent-tools/eval-result/eval-result.class.d.ts.map +1 -1
  46. package/dist/components/agent-tools/eval-result/eval-result.class.js +9 -7
  47. package/dist/components/agent-tools/eval-result/eval-result.class.js.map +1 -1
  48. package/dist/components/agent-tools/eval-result/eval-result.d.ts +1 -1
  49. package/dist/components/agent-tools/eval-result/eval-result.d.ts.map +1 -1
  50. package/dist/components/agent-tools/eval-result/eval-result.js +1 -1
  51. package/dist/components/agent-tools/eval-result/eval-result.js.map +1 -1
  52. package/dist/components/agent-tools/evaluation-run/evaluation-run.class.d.ts.map +1 -1
  53. package/dist/components/agent-tools/evaluation-run/evaluation-run.class.js +6 -6
  54. package/dist/components/agent-tools/evaluation-run/evaluation-run.class.js.map +1 -1
  55. package/dist/components/agent-tools/policy-summary/policy-summary.class.d.ts.map +1 -1
  56. package/dist/components/agent-tools/policy-summary/policy-summary.class.js.map +1 -1
  57. package/dist/components/agent-tools/result-card/result-card.class.d.ts.map +1 -1
  58. package/dist/components/agent-tools/result-card/result-card.class.js.map +1 -1
  59. package/dist/components/agent-tools/result-card/result-field.class.d.ts.map +1 -1
  60. package/dist/components/agent-tools/result-card/result-field.class.js.map +1 -1
  61. package/dist/components/agent-tools/span-waterfall/span-waterfall.class.d.ts.map +1 -1
  62. package/dist/components/agent-tools/span-waterfall/span-waterfall.class.js +1 -0
  63. package/dist/components/agent-tools/span-waterfall/span-waterfall.class.js.map +1 -1
  64. package/dist/components/agent-tools/stack-trace/stack-trace-parse.d.ts.map +1 -1
  65. package/dist/components/agent-tools/stack-trace/stack-trace-parse.js +1 -0
  66. package/dist/components/agent-tools/stack-trace/stack-trace-parse.js.map +1 -1
  67. package/dist/components/agent-tools/stack-trace/stack-trace.class.d.ts.map +1 -1
  68. package/dist/components/agent-tools/stack-trace/stack-trace.class.js.map +1 -1
  69. package/dist/components/agent-tools/task-list/task-list.class.d.ts.map +1 -1
  70. package/dist/components/agent-tools/task-list/task-list.class.js.map +1 -1
  71. package/dist/components/agent-tools/terminal/terminal.class.d.ts.map +1 -1
  72. package/dist/components/agent-tools/terminal/terminal.class.js +1 -1
  73. package/dist/components/agent-tools/terminal/terminal.class.js.map +1 -1
  74. package/dist/components/agent-tools/test-results/test-results.class.d.ts.map +1 -1
  75. package/dist/components/agent-tools/test-results/test-results.class.js +1 -1
  76. package/dist/components/agent-tools/test-results/test-results.class.js.map +1 -1
  77. package/dist/components/agent-tools/thinking-panel/thinking-panel.class.d.ts.map +1 -1
  78. package/dist/components/agent-tools/thinking-panel/thinking-panel.class.js.map +1 -1
  79. package/dist/components/agent-tools/tool-approval-dialog/tool-approval-dialog.class.d.ts +47 -5
  80. package/dist/components/agent-tools/tool-approval-dialog/tool-approval-dialog.class.d.ts.map +1 -1
  81. package/dist/components/agent-tools/tool-approval-dialog/tool-approval-dialog.class.js +90 -15
  82. package/dist/components/agent-tools/tool-approval-dialog/tool-approval-dialog.class.js.map +1 -1
  83. package/dist/components/agent-tools/tool-approval-dialog/tool-approval-dialog.d.ts +2 -1
  84. package/dist/components/agent-tools/tool-approval-dialog/tool-approval-dialog.d.ts.map +1 -1
  85. package/dist/components/agent-tools/tool-approval-dialog/tool-approval-dialog.js +2 -1
  86. package/dist/components/agent-tools/tool-approval-dialog/tool-approval-dialog.js.map +1 -1
  87. package/dist/components/agent-tools/tool-approval-dialog/tool-approval-dialog.styles.d.ts.map +1 -1
  88. package/dist/components/agent-tools/tool-approval-dialog/tool-approval-dialog.styles.js +6 -26
  89. package/dist/components/agent-tools/tool-approval-dialog/tool-approval-dialog.styles.js.map +1 -1
  90. package/dist/components/agent-tools/tool-call-chip/tool-call-chip.class.d.ts.map +1 -1
  91. package/dist/components/agent-tools/tool-call-chip/tool-call-chip.class.js.map +1 -1
  92. package/dist/components/agent-tools/tool-param-form/tool-param-form.class.d.ts.map +1 -1
  93. package/dist/components/agent-tools/tool-param-form/tool-param-form.class.js +12 -11
  94. package/dist/components/agent-tools/tool-param-form/tool-param-form.class.js.map +1 -1
  95. package/dist/components/agent-tools/tool-result-dialog/tool-result-dialog.class.d.ts.map +1 -1
  96. package/dist/components/agent-tools/tool-result-dialog/tool-result-dialog.class.js.map +1 -1
  97. package/dist/components/agent-tools/tool-result-view/tool-result-view.class.d.ts.map +1 -1
  98. package/dist/components/agent-tools/tool-result-view/tool-result-view.class.js.map +1 -1
  99. package/dist/components/agent-tools/tool-select-dialog/tool-select-dialog.class.d.ts.map +1 -1
  100. package/dist/components/agent-tools/tool-select-dialog/tool-select-dialog.class.js.map +1 -1
  101. package/dist/components/agent-tools/tool-timeline/tool-timeline.class.d.ts.map +1 -1
  102. package/dist/components/agent-tools/tool-timeline/tool-timeline.class.js.map +1 -1
  103. package/dist/components/agent-tools/trace-tree/trace-tree.class.d.ts.map +1 -1
  104. package/dist/components/agent-tools/trace-tree/trace-tree.class.js +5 -2
  105. package/dist/components/agent-tools/trace-tree/trace-tree.class.js.map +1 -1
  106. package/dist/components/charts/chart/box-plot.class.d.ts.map +1 -1
  107. package/dist/components/charts/chart/box-plot.class.js.map +1 -1
  108. package/dist/components/charts/chart/chart.class.d.ts.map +1 -1
  109. package/dist/components/charts/chart/chart.class.js +0 -3
  110. package/dist/components/charts/chart/chart.class.js.map +1 -1
  111. package/dist/components/charts/chart/histogram-bin.js +3 -3
  112. package/dist/components/charts/chart/histogram-bin.js.map +1 -1
  113. package/dist/components/charts/chart/lite-chart.class.d.ts +5 -1
  114. package/dist/components/charts/chart/lite-chart.class.d.ts.map +1 -1
  115. package/dist/components/charts/chart/lite-chart.class.js +13 -8
  116. package/dist/components/charts/chart/lite-chart.class.js.map +1 -1
  117. package/dist/components/conversation/agent-workspace/agent-workspace.class.d.ts.map +1 -1
  118. package/dist/components/conversation/agent-workspace/agent-workspace.class.js +5 -0
  119. package/dist/components/conversation/agent-workspace/agent-workspace.class.js.map +1 -1
  120. package/dist/components/conversation/audio-visualizer/audio-visualizer.class.d.ts.map +1 -1
  121. package/dist/components/conversation/audio-visualizer/audio-visualizer.class.js.map +1 -1
  122. package/dist/components/conversation/branch-picker/branch-picker.class.d.ts.map +1 -1
  123. package/dist/components/conversation/branch-picker/branch-picker.class.js.map +1 -1
  124. package/dist/components/conversation/chat-composer/chat-composer.class.d.ts.map +1 -1
  125. package/dist/components/conversation/chat-composer/chat-composer.class.js.map +1 -1
  126. package/dist/components/conversation/chat-message/chat-message.class.d.ts.map +1 -1
  127. package/dist/components/conversation/chat-message/chat-message.class.js.map +1 -1
  128. package/dist/components/conversation/chat-viewport/chat-viewport.class.d.ts.map +1 -1
  129. package/dist/components/conversation/chat-viewport/chat-viewport.class.js.map +1 -1
  130. package/dist/components/conversation/checkpoint/checkpoint.class.d.ts.map +1 -1
  131. package/dist/components/conversation/checkpoint/checkpoint.class.js.map +1 -1
  132. package/dist/components/conversation/code-block/code-block-core.class.d.ts +0 -1
  133. package/dist/components/conversation/code-block/code-block-core.class.d.ts.map +1 -1
  134. package/dist/components/conversation/code-block/code-block-core.class.js +6 -8
  135. package/dist/components/conversation/code-block/code-block-core.class.js.map +1 -1
  136. package/dist/components/conversation/code-block/code-block.class.d.ts.map +1 -1
  137. package/dist/components/conversation/code-block/code-block.class.js.map +1 -1
  138. package/dist/components/conversation/code-block/greycat-language.d.ts +5 -0
  139. package/dist/components/conversation/code-block/greycat-language.d.ts.map +1 -1
  140. package/dist/components/conversation/code-block/greycat-language.js +48 -6
  141. package/dist/components/conversation/code-block/greycat-language.js.map +1 -1
  142. package/dist/components/conversation/conversation-item/conversation-item.class.d.ts.map +1 -1
  143. package/dist/components/conversation/conversation-item/conversation-item.class.js.map +1 -1
  144. package/dist/components/conversation/generation-status/generation-status.class.d.ts.map +1 -1
  145. package/dist/components/conversation/generation-status/generation-status.class.js.map +1 -1
  146. package/dist/components/conversation/handoff-divider/handoff-divider.class.d.ts.map +1 -1
  147. package/dist/components/conversation/handoff-divider/handoff-divider.class.js.map +1 -1
  148. package/dist/components/conversation/markdown/markdown-core.class.d.ts.map +1 -1
  149. package/dist/components/conversation/markdown/markdown-core.class.js +4 -1
  150. package/dist/components/conversation/markdown/markdown-core.class.js.map +1 -1
  151. package/dist/components/conversation/markdown/markdown-shared.d.ts.map +1 -1
  152. package/dist/components/conversation/markdown/markdown-shared.js +1 -0
  153. package/dist/components/conversation/markdown/markdown-shared.js.map +1 -1
  154. package/dist/components/conversation/markdown/markdown.class.d.ts.map +1 -1
  155. package/dist/components/conversation/markdown/markdown.class.js +1 -4
  156. package/dist/components/conversation/markdown/markdown.class.js.map +1 -1
  157. package/dist/components/conversation/message-actions/message-actions.class.d.ts.map +1 -1
  158. package/dist/components/conversation/message-actions/message-actions.class.js.map +1 -1
  159. package/dist/components/conversation/message-feedback/message-feedback.class.d.ts +5 -3
  160. package/dist/components/conversation/message-feedback/message-feedback.class.d.ts.map +1 -1
  161. package/dist/components/conversation/message-feedback/message-feedback.class.js.map +1 -1
  162. package/dist/components/conversation/model-select/model-select.class.d.ts.map +1 -1
  163. package/dist/components/conversation/model-select/model-select.class.js +7 -10
  164. package/dist/components/conversation/model-select/model-select.class.js.map +1 -1
  165. package/dist/components/conversation/model-settings-panel/model-settings-panel.class.d.ts.map +1 -1
  166. package/dist/components/conversation/model-settings-panel/model-settings-panel.class.js.map +1 -1
  167. package/dist/components/conversation/push-to-talk/push-to-talk.class.d.ts.map +1 -1
  168. package/dist/components/conversation/push-to-talk/push-to-talk.class.js.map +1 -1
  169. package/dist/components/conversation/stream-status/stream-status.class.d.ts.map +1 -1
  170. package/dist/components/conversation/stream-status/stream-status.class.js.map +1 -1
  171. package/dist/components/conversation/streaming-text/streaming-text.class.d.ts.map +1 -1
  172. package/dist/components/conversation/streaming-text/streaming-text.class.js.map +1 -1
  173. package/dist/components/conversation/suggestion-chips/suggestion-chips.class.d.ts.map +1 -1
  174. package/dist/components/conversation/suggestion-chips/suggestion-chips.class.js.map +1 -1
  175. package/dist/components/conversation/thread-list/thread-list.class.d.ts +16 -3
  176. package/dist/components/conversation/thread-list/thread-list.class.d.ts.map +1 -1
  177. package/dist/components/conversation/thread-list/thread-list.class.js +27 -7
  178. package/dist/components/conversation/thread-list/thread-list.class.js.map +1 -1
  179. package/dist/components/conversation/transcript-feed/transcript-feed.class.d.ts.map +1 -1
  180. package/dist/components/conversation/transcript-feed/transcript-feed.class.js +2 -1
  181. package/dist/components/conversation/transcript-feed/transcript-feed.class.js.map +1 -1
  182. package/dist/components/conversation/typing-indicator/typing-indicator.class.d.ts.map +1 -1
  183. package/dist/components/conversation/typing-indicator/typing-indicator.class.js.map +1 -1
  184. package/dist/components/conversation/usage-badge/usage-badge.class.d.ts.map +1 -1
  185. package/dist/components/conversation/usage-badge/usage-badge.class.js.map +1 -1
  186. package/dist/components/conversation/voice-picker/voice-picker.class.d.ts.map +1 -1
  187. package/dist/components/conversation/voice-picker/voice-picker.class.js +7 -5
  188. package/dist/components/conversation/voice-picker/voice-picker.class.js.map +1 -1
  189. package/dist/components/conversation/widget-renderer/resolve.js +2 -2
  190. package/dist/components/conversation/widget-renderer/resolve.js.map +1 -1
  191. package/dist/components/conversation/widget-renderer/widget-renderer.class.d.ts.map +1 -1
  192. package/dist/components/conversation/widget-renderer/widget-renderer.class.js +3 -3
  193. package/dist/components/conversation/widget-renderer/widget-renderer.class.js.map +1 -1
  194. package/dist/components/data/calendar/calendar.class.d.ts +3 -1
  195. package/dist/components/data/calendar/calendar.class.d.ts.map +1 -1
  196. package/dist/components/data/calendar/calendar.class.js +1 -0
  197. package/dist/components/data/calendar/calendar.class.js.map +1 -1
  198. package/dist/components/data/calendar/calendar.styles.js +3 -3
  199. package/dist/components/data/context-meter/context-meter.class.d.ts.map +1 -1
  200. package/dist/components/data/context-meter/context-meter.class.js.map +1 -1
  201. package/dist/components/data/document-library/document-library.class.d.ts +6 -5
  202. package/dist/components/data/document-library/document-library.class.d.ts.map +1 -1
  203. package/dist/components/data/document-library/document-library.class.js +2 -3
  204. package/dist/components/data/document-library/document-library.class.js.map +1 -1
  205. package/dist/components/data/env-list/env-list.class.d.ts.map +1 -1
  206. package/dist/components/data/env-list/env-list.class.js.map +1 -1
  207. package/dist/components/data/file-tree/file-tree.class.d.ts.map +1 -1
  208. package/dist/components/data/file-tree/file-tree.class.js.map +1 -1
  209. package/dist/components/data/flow-canvas/flow-canvas.class.d.ts +8 -1
  210. package/dist/components/data/flow-canvas/flow-canvas.class.d.ts.map +1 -1
  211. package/dist/components/data/flow-canvas/flow-canvas.class.js +17 -12
  212. package/dist/components/data/flow-canvas/flow-canvas.class.js.map +1 -1
  213. package/dist/components/data/flow-canvas/flow-canvas.styles.d.ts.map +1 -1
  214. package/dist/components/data/flow-canvas/flow-canvas.styles.js +2 -1
  215. package/dist/components/data/flow-canvas/flow-canvas.styles.js.map +1 -1
  216. package/dist/components/data/flow-controls/flow-controls.class.d.ts.map +1 -1
  217. package/dist/components/data/flow-controls/flow-controls.class.js.map +1 -1
  218. package/dist/components/data/flow-minimap/flow-minimap.class.d.ts.map +1 -1
  219. package/dist/components/data/flow-minimap/flow-minimap.class.js.map +1 -1
  220. package/dist/components/data/flow-node/flow-node.class.d.ts.map +1 -1
  221. package/dist/components/data/flow-node/flow-node.class.js.map +1 -1
  222. package/dist/components/data/flow-run-overlay/flow-run-overlay.class.d.ts.map +1 -1
  223. package/dist/components/data/flow-run-overlay/flow-run-overlay.class.js +1 -1
  224. package/dist/components/data/flow-run-overlay/flow-run-overlay.class.js.map +1 -1
  225. package/dist/components/data/gauge/gauge.class.d.ts.map +1 -1
  226. package/dist/components/data/gauge/gauge.class.js.map +1 -1
  227. package/dist/components/data/graph-query-builder/graph-query-builder.class.d.ts +0 -1
  228. package/dist/components/data/graph-query-builder/graph-query-builder.class.d.ts.map +1 -1
  229. package/dist/components/data/graph-query-builder/graph-query-builder.class.js +0 -2
  230. package/dist/components/data/graph-query-builder/graph-query-builder.class.js.map +1 -1
  231. package/dist/components/data/heatmap/calendar-grid.d.ts.map +1 -1
  232. package/dist/components/data/heatmap/calendar-grid.js +8 -2
  233. package/dist/components/data/heatmap/calendar-grid.js.map +1 -1
  234. package/dist/components/data/heatmap/heatmap.class.d.ts +6 -2
  235. package/dist/components/data/heatmap/heatmap.class.d.ts.map +1 -1
  236. package/dist/components/data/heatmap/heatmap.class.js +4 -4
  237. package/dist/components/data/heatmap/heatmap.class.js.map +1 -1
  238. package/dist/components/data/pagination/pagination.class.d.ts.map +1 -1
  239. package/dist/components/data/pagination/pagination.class.js.map +1 -1
  240. package/dist/components/data/query-builder/query-builder.class.d.ts.map +1 -1
  241. package/dist/components/data/query-builder/query-builder.class.js.map +1 -1
  242. package/dist/components/data/sequence-strip/sequence-strip.class.d.ts.map +1 -1
  243. package/dist/components/data/sequence-strip/sequence-strip.class.js.map +1 -1
  244. package/dist/components/data/sparkline/sparkline.class.d.ts.map +1 -1
  245. package/dist/components/data/sparkline/sparkline.class.js +4 -2
  246. package/dist/components/data/sparkline/sparkline.class.js.map +1 -1
  247. package/dist/components/data/stat/stat.class.d.ts.map +1 -1
  248. package/dist/components/data/stat/stat.class.js.map +1 -1
  249. package/dist/components/data/table/table.class.d.ts +16 -4
  250. package/dist/components/data/table/table.class.d.ts.map +1 -1
  251. package/dist/components/data/table/table.class.js +35 -33
  252. package/dist/components/data/table/table.class.js.map +1 -1
  253. package/dist/components/data/timeline/timeline-item.class.d.ts.map +1 -1
  254. package/dist/components/data/timeline/timeline-item.class.js +5 -2
  255. package/dist/components/data/timeline/timeline-item.class.js.map +1 -1
  256. package/dist/components/data/timeline/timeline-item.styles.d.ts.map +1 -1
  257. package/dist/components/data/timeline/timeline-item.styles.js +6 -0
  258. package/dist/components/data/timeline/timeline-item.styles.js.map +1 -1
  259. package/dist/components/data/timeline/timeline.class.d.ts.map +1 -1
  260. package/dist/components/data/timeline/timeline.class.js.map +1 -1
  261. package/dist/components/data/tree/tree-item.d.ts +24 -0
  262. package/dist/components/data/tree/tree-item.d.ts.map +1 -0
  263. package/dist/components/data/tree/tree-item.js +5 -0
  264. package/dist/components/data/tree/tree-item.js.map +1 -0
  265. package/dist/components/data/tree/tree-node.class.d.ts +1 -1
  266. package/dist/components/data/tree/tree-node.class.d.ts.map +1 -1
  267. package/dist/components/data/tree/tree-node.class.js.map +1 -1
  268. package/dist/components/data/tree/tree.class.d.ts +2 -21
  269. package/dist/components/data/tree/tree.class.d.ts.map +1 -1
  270. package/dist/components/data/tree/tree.class.js +5 -2
  271. package/dist/components/data/tree/tree.class.js.map +1 -1
  272. package/dist/components/data/word-cloud/word-cloud-layout.d.ts +7 -2
  273. package/dist/components/data/word-cloud/word-cloud-layout.d.ts.map +1 -1
  274. package/dist/components/data/word-cloud/word-cloud-layout.js.map +1 -1
  275. package/dist/components/data/word-cloud/word-cloud.class.d.ts +3 -3
  276. package/dist/components/data/word-cloud/word-cloud.class.d.ts.map +1 -1
  277. package/dist/components/data/word-cloud/word-cloud.class.js.map +1 -1
  278. package/dist/components/forms/button/button.class.d.ts +5 -0
  279. package/dist/components/forms/button/button.class.d.ts.map +1 -1
  280. package/dist/components/forms/button/button.class.js +5 -0
  281. package/dist/components/forms/button/button.class.js.map +1 -1
  282. package/dist/components/forms/button/button.styles.d.ts.map +1 -1
  283. package/dist/components/forms/button/button.styles.js +6 -2
  284. package/dist/components/forms/button/button.styles.js.map +1 -1
  285. package/dist/components/forms/checkbox/checkbox.class.d.ts.map +1 -1
  286. package/dist/components/forms/checkbox/checkbox.class.js.map +1 -1
  287. package/dist/components/forms/checkbox-group/checkbox-group.class.d.ts.map +1 -1
  288. package/dist/components/forms/checkbox-group/checkbox-group.class.js.map +1 -1
  289. package/dist/components/forms/code-editor/code-editor.class.d.ts.map +1 -1
  290. package/dist/components/forms/code-editor/code-editor.class.js.map +1 -1
  291. package/dist/components/forms/color-picker/color-picker.class.d.ts +4 -0
  292. package/dist/components/forms/color-picker/color-picker.class.d.ts.map +1 -1
  293. package/dist/components/forms/color-picker/color-picker.class.js +6 -0
  294. package/dist/components/forms/color-picker/color-picker.class.js.map +1 -1
  295. package/dist/components/forms/color-picker/color-picker.styles.d.ts.map +1 -1
  296. package/dist/components/forms/color-picker/color-picker.styles.js +20 -2
  297. package/dist/components/forms/color-picker/color-picker.styles.js.map +1 -1
  298. package/dist/components/forms/combobox/combobox.class.d.ts +7 -2
  299. package/dist/components/forms/combobox/combobox.class.d.ts.map +1 -1
  300. package/dist/components/forms/combobox/combobox.class.js +15 -5
  301. package/dist/components/forms/combobox/combobox.class.js.map +1 -1
  302. package/dist/components/forms/combobox/combobox.styles.d.ts.map +1 -1
  303. package/dist/components/forms/combobox/combobox.styles.js +15 -2
  304. package/dist/components/forms/combobox/combobox.styles.js.map +1 -1
  305. package/dist/components/forms/combobox/option.class.d.ts.map +1 -1
  306. package/dist/components/forms/combobox/option.class.js.map +1 -1
  307. package/dist/components/forms/date-picker/date-input.class.d.ts.map +1 -1
  308. package/dist/components/forms/date-picker/date-input.class.js +6 -7
  309. package/dist/components/forms/date-picker/date-input.class.js.map +1 -1
  310. package/dist/components/forms/date-picker/date-picker.class.d.ts +4 -0
  311. package/dist/components/forms/date-picker/date-picker.class.d.ts.map +1 -1
  312. package/dist/components/forms/date-picker/date-picker.class.js +6 -0
  313. package/dist/components/forms/date-picker/date-picker.class.js.map +1 -1
  314. package/dist/components/forms/date-picker/date-picker.styles.d.ts.map +1 -1
  315. package/dist/components/forms/date-picker/date-picker.styles.js +15 -0
  316. package/dist/components/forms/date-picker/date-picker.styles.js.map +1 -1
  317. package/dist/components/forms/emoji-picker/emoji-data-loader.d.ts +1 -1
  318. package/dist/components/forms/emoji-picker/emoji-data-loader.d.ts.map +1 -1
  319. package/dist/components/forms/emoji-picker/emoji-picker.class.d.ts +11 -16
  320. package/dist/components/forms/emoji-picker/emoji-picker.class.d.ts.map +1 -1
  321. package/dist/components/forms/emoji-picker/emoji-picker.class.js +14 -5
  322. package/dist/components/forms/emoji-picker/emoji-picker.class.js.map +1 -1
  323. package/dist/components/forms/emoji-picker/emoji-picker.styles.d.ts.map +1 -1
  324. package/dist/components/forms/emoji-picker/emoji-picker.styles.js +30 -7
  325. package/dist/components/forms/emoji-picker/emoji-picker.styles.js.map +1 -1
  326. package/dist/components/forms/emoji-picker/emoji-types.d.ts +14 -0
  327. package/dist/components/forms/emoji-picker/emoji-types.d.ts.map +1 -0
  328. package/dist/components/forms/emoji-picker/emoji-types.js +5 -0
  329. package/dist/components/forms/emoji-picker/emoji-types.js.map +1 -0
  330. package/dist/components/forms/icon-button/icon-button.class.d.ts +25 -3
  331. package/dist/components/forms/icon-button/icon-button.class.d.ts.map +1 -1
  332. package/dist/components/forms/icon-button/icon-button.class.js +89 -4
  333. package/dist/components/forms/icon-button/icon-button.class.js.map +1 -1
  334. package/dist/components/forms/icon-button/icon-button.styles.d.ts.map +1 -1
  335. package/dist/components/forms/icon-button/icon-button.styles.js +6 -2
  336. package/dist/components/forms/icon-button/icon-button.styles.js.map +1 -1
  337. package/dist/components/forms/input/input.class.d.ts +5 -0
  338. package/dist/components/forms/input/input.class.d.ts.map +1 -1
  339. package/dist/components/forms/input/input.class.js +5 -0
  340. package/dist/components/forms/input/input.class.js.map +1 -1
  341. package/dist/components/forms/input/input.styles.d.ts.map +1 -1
  342. package/dist/components/forms/input/input.styles.js +7 -2
  343. package/dist/components/forms/input/input.styles.js.map +1 -1
  344. package/dist/components/forms/input/number-input.class.d.ts.map +1 -1
  345. package/dist/components/forms/input/number-input.class.js.map +1 -1
  346. package/dist/components/forms/input/time-input.class.d.ts.map +1 -1
  347. package/dist/components/forms/input/time-input.class.js.map +1 -1
  348. package/dist/components/forms/locale-picker/locale-picker.class.d.ts +229 -0
  349. package/dist/components/forms/locale-picker/locale-picker.class.d.ts.map +1 -0
  350. package/dist/components/forms/locale-picker/locale-picker.class.js +633 -0
  351. package/dist/components/forms/locale-picker/locale-picker.class.js.map +1 -0
  352. package/dist/components/forms/locale-picker/locale-picker.d.ts +3 -0
  353. package/dist/components/forms/locale-picker/locale-picker.d.ts.map +1 -0
  354. package/dist/components/forms/locale-picker/locale-picker.js +6 -0
  355. package/dist/components/forms/locale-picker/locale-picker.js.map +1 -0
  356. package/dist/components/forms/locale-picker/locale-picker.styles.d.ts +2 -0
  357. package/dist/components/forms/locale-picker/locale-picker.styles.d.ts.map +1 -0
  358. package/dist/components/forms/locale-picker/locale-picker.styles.js +213 -0
  359. package/dist/components/forms/locale-picker/locale-picker.styles.js.map +1 -0
  360. package/dist/components/forms/phone-input/phone-input.class.d.ts +11 -0
  361. package/dist/components/forms/phone-input/phone-input.class.d.ts.map +1 -1
  362. package/dist/components/forms/phone-input/phone-input.class.js +13 -0
  363. package/dist/components/forms/phone-input/phone-input.class.js.map +1 -1
  364. package/dist/components/forms/phone-input/phone-input.styles.d.ts.map +1 -1
  365. package/dist/components/forms/phone-input/phone-input.styles.js +39 -3
  366. package/dist/components/forms/phone-input/phone-input.styles.js.map +1 -1
  367. package/dist/components/forms/radio/radio-group.class.d.ts.map +1 -1
  368. package/dist/components/forms/radio/radio-group.class.js +1 -0
  369. package/dist/components/forms/radio/radio-group.class.js.map +1 -1
  370. package/dist/components/forms/radio/radio.class.d.ts.map +1 -1
  371. package/dist/components/forms/radio/radio.class.js.map +1 -1
  372. package/dist/components/forms/rubric-form/rubric-form.class.d.ts +0 -1
  373. package/dist/components/forms/rubric-form/rubric-form.class.d.ts.map +1 -1
  374. package/dist/components/forms/rubric-form/rubric-form.class.js +0 -2
  375. package/dist/components/forms/rubric-form/rubric-form.class.js.map +1 -1
  376. package/dist/components/forms/select/select.class.d.ts +5 -2
  377. package/dist/components/forms/select/select.class.d.ts.map +1 -1
  378. package/dist/components/forms/select/select.class.js +17 -9
  379. package/dist/components/forms/select/select.class.js.map +1 -1
  380. package/dist/components/forms/select/select.styles.d.ts.map +1 -1
  381. package/dist/components/forms/select/select.styles.js +13 -2
  382. package/dist/components/forms/select/select.styles.js.map +1 -1
  383. package/dist/components/forms/slider/slider.class.d.ts.map +1 -1
  384. package/dist/components/forms/slider/slider.class.js.map +1 -1
  385. package/dist/components/forms/swatch-picker/swatch-picker.class.d.ts +12 -3
  386. package/dist/components/forms/swatch-picker/swatch-picker.class.d.ts.map +1 -1
  387. package/dist/components/forms/swatch-picker/swatch-picker.class.js +14 -3
  388. package/dist/components/forms/swatch-picker/swatch-picker.class.js.map +1 -1
  389. package/dist/components/forms/swatch-picker/swatch-picker.styles.d.ts.map +1 -1
  390. package/dist/components/forms/swatch-picker/swatch-picker.styles.js +32 -9
  391. package/dist/components/forms/swatch-picker/swatch-picker.styles.js.map +1 -1
  392. package/dist/components/forms/switch/switch.class.d.ts.map +1 -1
  393. package/dist/components/forms/switch/switch.class.js.map +1 -1
  394. package/dist/components/forms/textarea/textarea.class.d.ts.map +1 -1
  395. package/dist/components/forms/textarea/textarea.class.js.map +1 -1
  396. package/dist/components/forms/time-range/time-range.class.d.ts +8 -1
  397. package/dist/components/forms/time-range/time-range.class.d.ts.map +1 -1
  398. package/dist/components/forms/time-range/time-range.class.js +11 -1
  399. package/dist/components/forms/time-range/time-range.class.js.map +1 -1
  400. package/dist/components/forms/time-range/time-range.styles.d.ts.map +1 -1
  401. package/dist/components/forms/time-range/time-range.styles.js +42 -13
  402. package/dist/components/forms/time-range/time-range.styles.js.map +1 -1
  403. package/dist/components/forms/token-input/token-input.class.d.ts +14 -1
  404. package/dist/components/forms/token-input/token-input.class.d.ts.map +1 -1
  405. package/dist/components/forms/token-input/token-input.class.js +21 -4
  406. package/dist/components/forms/token-input/token-input.class.js.map +1 -1
  407. package/dist/components/forms/token-input/token-input.styles.d.ts.map +1 -1
  408. package/dist/components/forms/token-input/token-input.styles.js +36 -2
  409. package/dist/components/forms/token-input/token-input.styles.js.map +1 -1
  410. package/dist/components/layout/app-rail/app-rail-item.class.d.ts.map +1 -1
  411. package/dist/components/layout/app-rail/app-rail-item.class.js.map +1 -1
  412. package/dist/components/layout/app-rail/app-rail.class.d.ts +11 -4
  413. package/dist/components/layout/app-rail/app-rail.class.d.ts.map +1 -1
  414. package/dist/components/layout/app-rail/app-rail.class.js +20 -6
  415. package/dist/components/layout/app-rail/app-rail.class.js.map +1 -1
  416. package/dist/components/layout/breadcrumb/breadcrumb-item.class.d.ts.map +1 -1
  417. package/dist/components/layout/breadcrumb/breadcrumb-item.class.js.map +1 -1
  418. package/dist/components/layout/breadcrumb/breadcrumb.class.d.ts.map +1 -1
  419. package/dist/components/layout/breadcrumb/breadcrumb.class.js.map +1 -1
  420. package/dist/components/layout/button-group/button-group.class.d.ts.map +1 -1
  421. package/dist/components/layout/button-group/button-group.class.js.map +1 -1
  422. package/dist/components/layout/card/card.class.d.ts.map +1 -1
  423. package/dist/components/layout/card/card.class.js.map +1 -1
  424. package/dist/components/layout/carousel/carousel-item.class.d.ts.map +1 -1
  425. package/dist/components/layout/carousel/carousel-item.class.js.map +1 -1
  426. package/dist/components/layout/carousel/carousel.class.d.ts.map +1 -1
  427. package/dist/components/layout/carousel/carousel.class.js.map +1 -1
  428. package/dist/components/layout/command-palette/command-palette.class.d.ts.map +1 -1
  429. package/dist/components/layout/command-palette/command-palette.class.js +6 -3
  430. package/dist/components/layout/command-palette/command-palette.class.js.map +1 -1
  431. package/dist/components/layout/control-group/control-group.class.d.ts +16 -0
  432. package/dist/components/layout/control-group/control-group.class.d.ts.map +1 -1
  433. package/dist/components/layout/control-group/control-group.class.js +19 -0
  434. package/dist/components/layout/control-group/control-group.class.js.map +1 -1
  435. package/dist/components/layout/control-group/control-group.styles.d.ts.map +1 -1
  436. package/dist/components/layout/control-group/control-group.styles.js +8 -3
  437. package/dist/components/layout/control-group/control-group.styles.js.map +1 -1
  438. package/dist/components/layout/dashboard-grid/dashboard-grid.class.d.ts +3 -0
  439. package/dist/components/layout/dashboard-grid/dashboard-grid.class.d.ts.map +1 -1
  440. package/dist/components/layout/dashboard-grid/dashboard-grid.class.js +4 -1
  441. package/dist/components/layout/dashboard-grid/dashboard-grid.class.js.map +1 -1
  442. package/dist/components/layout/dashboard-grid/dashboard-grid.styles.d.ts.map +1 -1
  443. package/dist/components/layout/dashboard-grid/dashboard-grid.styles.js +2 -1
  444. package/dist/components/layout/dashboard-grid/dashboard-grid.styles.js.map +1 -1
  445. package/dist/components/layout/details/accordion.class.d.ts.map +1 -1
  446. package/dist/components/layout/details/accordion.class.js.map +1 -1
  447. package/dist/components/layout/details/details.class.d.ts.map +1 -1
  448. package/dist/components/layout/details/details.class.js.map +1 -1
  449. package/dist/components/layout/dock-panel/dock-panel.class.d.ts.map +1 -1
  450. package/dist/components/layout/dock-panel/dock-panel.class.js +1 -1
  451. package/dist/components/layout/dock-panel/dock-panel.class.js.map +1 -1
  452. package/dist/components/layout/drilldown-panel/drilldown-panel.class.d.ts.map +1 -1
  453. package/dist/components/layout/drilldown-panel/drilldown-panel.class.js +1 -1
  454. package/dist/components/layout/drilldown-panel/drilldown-panel.class.js.map +1 -1
  455. package/dist/components/layout/filter-bar/filter-bar.class.d.ts.map +1 -1
  456. package/dist/components/layout/filter-bar/filter-bar.class.js +1 -1
  457. package/dist/components/layout/filter-bar/filter-bar.class.js.map +1 -1
  458. package/dist/components/layout/menu/menu-item.class.d.ts.map +1 -1
  459. package/dist/components/layout/menu/menu-item.class.js.map +1 -1
  460. package/dist/components/layout/menu/menu.class.d.ts.map +1 -1
  461. package/dist/components/layout/menu/menu.class.js +16 -4
  462. package/dist/components/layout/menu/menu.class.js.map +1 -1
  463. package/dist/components/layout/reorder-list/reorder-item.class.d.ts +66 -0
  464. package/dist/components/layout/reorder-list/reorder-item.class.d.ts.map +1 -0
  465. package/dist/components/layout/reorder-list/reorder-item.class.js +120 -0
  466. package/dist/components/layout/reorder-list/reorder-item.class.js.map +1 -0
  467. package/dist/components/layout/reorder-list/reorder-item.d.ts +2 -0
  468. package/dist/components/layout/reorder-list/reorder-item.d.ts.map +1 -0
  469. package/dist/components/layout/reorder-list/reorder-item.js +5 -0
  470. package/dist/components/layout/reorder-list/reorder-item.js.map +1 -0
  471. package/dist/components/{data/data-grid/data-grid.styles.d.ts → layout/reorder-list/reorder-item.styles.d.ts} +1 -1
  472. package/dist/components/layout/reorder-list/reorder-item.styles.d.ts.map +1 -0
  473. package/dist/components/layout/reorder-list/reorder-item.styles.js +62 -0
  474. package/dist/components/layout/reorder-list/reorder-item.styles.js.map +1 -0
  475. package/dist/components/layout/reorder-list/reorder-list.class.d.ts +103 -0
  476. package/dist/components/layout/reorder-list/reorder-list.class.d.ts.map +1 -0
  477. package/dist/components/layout/reorder-list/reorder-list.class.js +256 -0
  478. package/dist/components/layout/reorder-list/reorder-list.class.js.map +1 -0
  479. package/dist/components/layout/reorder-list/reorder-list.d.ts +3 -0
  480. package/dist/components/layout/reorder-list/reorder-list.d.ts.map +1 -0
  481. package/dist/components/layout/reorder-list/reorder-list.js +6 -0
  482. package/dist/components/layout/reorder-list/reorder-list.js.map +1 -0
  483. package/dist/components/layout/reorder-list/reorder-list.styles.d.ts +2 -0
  484. package/dist/components/layout/reorder-list/reorder-list.styles.d.ts.map +1 -0
  485. package/dist/components/layout/reorder-list/reorder-list.styles.js +12 -0
  486. package/dist/components/layout/reorder-list/reorder-list.styles.js.map +1 -0
  487. package/dist/components/layout/responsive-panel/responsive-panel.class.d.ts.map +1 -1
  488. package/dist/components/layout/responsive-panel/responsive-panel.class.js.map +1 -1
  489. package/dist/components/layout/scroller/scroller.class.d.ts.map +1 -1
  490. package/dist/components/layout/scroller/scroller.class.js.map +1 -1
  491. package/dist/components/layout/segmented/segmented.class.d.ts.map +1 -1
  492. package/dist/components/layout/segmented/segmented.class.js.map +1 -1
  493. package/dist/components/layout/split/split.class.d.ts +0 -11
  494. package/dist/components/layout/split/split.class.d.ts.map +1 -1
  495. package/dist/components/layout/split/split.class.js +25 -25
  496. package/dist/components/layout/split/split.class.js.map +1 -1
  497. package/dist/components/layout/stepper/stepper.class.d.ts +0 -7
  498. package/dist/components/layout/stepper/stepper.class.d.ts.map +1 -1
  499. package/dist/components/layout/stepper/stepper.class.js +1 -10
  500. package/dist/components/layout/stepper/stepper.class.js.map +1 -1
  501. package/dist/components/layout/tabs/tabs.class.d.ts.map +1 -1
  502. package/dist/components/layout/tabs/tabs.class.js +2 -2
  503. package/dist/components/layout/tabs/tabs.class.js.map +1 -1
  504. package/dist/components/layout/virtual-list/virtual-list.class.d.ts +7 -1
  505. package/dist/components/layout/virtual-list/virtual-list.class.d.ts.map +1 -1
  506. package/dist/components/layout/virtual-list/virtual-list.class.js +10 -4
  507. package/dist/components/layout/virtual-list/virtual-list.class.js.map +1 -1
  508. package/dist/components/layout/virtual-list/virtual-list.styles.d.ts.map +1 -1
  509. package/dist/components/layout/virtual-list/virtual-list.styles.js +2 -1
  510. package/dist/components/layout/virtual-list/virtual-list.styles.js.map +1 -1
  511. package/dist/components/layout/widget/widget.class.d.ts.map +1 -1
  512. package/dist/components/layout/widget/widget.class.js.map +1 -1
  513. package/dist/components/media/animated-image/animated-image.class.d.ts.map +1 -1
  514. package/dist/components/media/animated-image/animated-image.class.js.map +1 -1
  515. package/dist/components/media/animation/animation.class.d.ts.map +1 -1
  516. package/dist/components/media/animation/animation.class.js +4 -1
  517. package/dist/components/media/animation/animation.class.js.map +1 -1
  518. package/dist/components/media/attachment-chip/attachment-chip.class.d.ts.map +1 -1
  519. package/dist/components/media/attachment-chip/attachment-chip.class.js +1 -1
  520. package/dist/components/media/attachment-chip/attachment-chip.class.js.map +1 -1
  521. package/dist/components/media/attachment-trigger/attachment-trigger.class.d.ts.map +1 -1
  522. package/dist/components/media/attachment-trigger/attachment-trigger.class.js +5 -2
  523. package/dist/components/media/attachment-trigger/attachment-trigger.class.js.map +1 -1
  524. package/dist/components/media/av-player/av-player.class.d.ts.map +1 -1
  525. package/dist/components/media/av-player/av-player.class.js.map +1 -1
  526. package/dist/components/media/avatar/avatar.class.d.ts.map +1 -1
  527. package/dist/components/media/avatar/avatar.class.js.map +1 -1
  528. package/dist/components/media/avatar-group/avatar-group.class.d.ts.map +1 -1
  529. package/dist/components/media/avatar-group/avatar-group.class.js.map +1 -1
  530. package/dist/components/media/file-icon/file-icon.class.d.ts.map +1 -1
  531. package/dist/components/media/file-icon/file-icon.class.js.map +1 -1
  532. package/dist/components/media/file-icon/file-type-metadata.js +1 -1
  533. package/dist/components/media/file-icon/file-type-metadata.js.map +1 -1
  534. package/dist/components/media/file-input/file-input.class.d.ts.map +1 -1
  535. package/dist/components/media/file-input/file-input.class.js.map +1 -1
  536. package/dist/components/media/flag/flag.class.d.ts.map +1 -1
  537. package/dist/components/media/flag/flag.class.js.map +1 -1
  538. package/dist/components/media/flag/language-map.js +1 -1
  539. package/dist/components/media/flag/language-map.js.map +1 -1
  540. package/dist/components/media/image-comparer/image-comparer.class.d.ts.map +1 -1
  541. package/dist/components/media/image-comparer/image-comparer.class.js.map +1 -1
  542. package/dist/components/media/image-viewer/image-viewer.class.d.ts.map +1 -1
  543. package/dist/components/media/image-viewer/image-viewer.class.js.map +1 -1
  544. package/dist/components/media/lightbox/lightbox.class.d.ts.map +1 -1
  545. package/dist/components/media/lightbox/lightbox.class.js.map +1 -1
  546. package/dist/components/media/map/map.class.d.ts.map +1 -1
  547. package/dist/components/media/map/map.class.js.map +1 -1
  548. package/dist/components/media/media-card/media-card.class.d.ts.map +1 -1
  549. package/dist/components/media/media-card/media-card.class.js.map +1 -1
  550. package/dist/components/media/playback/playback.class.d.ts.map +1 -1
  551. package/dist/components/media/playback/playback.class.js.map +1 -1
  552. package/dist/components/media/qr-code/qr-code.class.d.ts.map +1 -1
  553. package/dist/components/media/qr-code/qr-code.class.js +0 -3
  554. package/dist/components/media/qr-code/qr-code.class.js.map +1 -1
  555. package/dist/components/media/zoomable-frame/zoomable-frame.class.d.ts.map +1 -1
  556. package/dist/components/media/zoomable-frame/zoomable-frame.class.js +1 -1
  557. package/dist/components/media/zoomable-frame/zoomable-frame.class.js.map +1 -1
  558. package/dist/components/overlays/badge/badge.class.d.ts +2 -0
  559. package/dist/components/overlays/badge/badge.class.d.ts.map +1 -1
  560. package/dist/components/overlays/badge/badge.class.js +2 -0
  561. package/dist/components/overlays/badge/badge.class.js.map +1 -1
  562. package/dist/components/overlays/badge/badge.styles.d.ts.map +1 -1
  563. package/dist/components/overlays/badge/badge.styles.js +4 -1
  564. package/dist/components/overlays/badge/badge.styles.js.map +1 -1
  565. package/dist/components/overlays/callout/callout.class.d.ts.map +1 -1
  566. package/dist/components/overlays/callout/callout.class.js.map +1 -1
  567. package/dist/components/overlays/chip/chip-group.class.d.ts.map +1 -1
  568. package/dist/components/overlays/chip/chip-group.class.js.map +1 -1
  569. package/dist/components/overlays/chip/chip.class.d.ts +4 -2
  570. package/dist/components/overlays/chip/chip.class.d.ts.map +1 -1
  571. package/dist/components/overlays/chip/chip.class.js +3 -1
  572. package/dist/components/overlays/chip/chip.class.js.map +1 -1
  573. package/dist/components/overlays/chip/chip.styles.d.ts.map +1 -1
  574. package/dist/components/overlays/chip/chip.styles.js +17 -2
  575. package/dist/components/overlays/chip/chip.styles.js.map +1 -1
  576. package/dist/components/overlays/dialog/dialog.class.d.ts.map +1 -1
  577. package/dist/components/overlays/dialog/dialog.class.js.map +1 -1
  578. package/dist/components/overlays/drawer/drawer.class.d.ts.map +1 -1
  579. package/dist/components/overlays/drawer/drawer.class.js.map +1 -1
  580. package/dist/components/overlays/empty/empty.class.d.ts.map +1 -1
  581. package/dist/components/overlays/empty/empty.class.js.map +1 -1
  582. package/dist/components/overlays/kbd/kbd.class.d.ts.map +1 -1
  583. package/dist/components/overlays/kbd/kbd.class.js.map +1 -1
  584. package/dist/components/overlays/overlay/popover.class.d.ts +3 -1
  585. package/dist/components/overlays/overlay/popover.class.d.ts.map +1 -1
  586. package/dist/components/overlays/overlay/popover.class.js.map +1 -1
  587. package/dist/components/overlays/overlay/tooltip.class.d.ts.map +1 -1
  588. package/dist/components/overlays/overlay/tooltip.class.js.map +1 -1
  589. package/dist/components/overlays/progress/progress-bar.class.d.ts.map +1 -1
  590. package/dist/components/overlays/progress/progress-bar.class.js.map +1 -1
  591. package/dist/components/overlays/progress/progress-ring.class.d.ts.map +1 -1
  592. package/dist/components/overlays/progress/progress-ring.class.js.map +1 -1
  593. package/dist/components/overlays/rating/rating.class.d.ts.map +1 -1
  594. package/dist/components/overlays/rating/rating.class.js +1 -1
  595. package/dist/components/overlays/rating/rating.class.js.map +1 -1
  596. package/dist/components/overlays/skeleton/skeleton.class.d.ts.map +1 -1
  597. package/dist/components/overlays/skeleton/skeleton.class.js.map +1 -1
  598. package/dist/components/overlays/spinner/spinner.class.d.ts.map +1 -1
  599. package/dist/components/overlays/spinner/spinner.class.js.map +1 -1
  600. package/dist/components/overlays/toast/toast-item.class.d.ts.map +1 -1
  601. package/dist/components/overlays/toast/toast-item.class.js.map +1 -1
  602. package/dist/components/overlays/toast/toast.class.d.ts.map +1 -1
  603. package/dist/components/overlays/toast/toast.class.js.map +1 -1
  604. package/dist/components/retrieval/chunk-inspector/chunk-inspector.class.d.ts.map +1 -1
  605. package/dist/components/retrieval/chunk-inspector/chunk-inspector.class.js.map +1 -1
  606. package/dist/components/retrieval/citation-badge/citation-badge.class.d.ts.map +1 -1
  607. package/dist/components/retrieval/citation-badge/citation-badge.class.js.map +1 -1
  608. package/dist/components/retrieval/community-card/community-card.class.d.ts.map +1 -1
  609. package/dist/components/retrieval/community-card/community-card.class.js.map +1 -1
  610. package/dist/components/retrieval/entity-card/entity-card.class.d.ts.map +1 -1
  611. package/dist/components/retrieval/entity-card/entity-card.class.js.map +1 -1
  612. package/dist/components/retrieval/entity-chip/entity-chip.class.d.ts.map +1 -1
  613. package/dist/components/retrieval/entity-chip/entity-chip.class.js.map +1 -1
  614. package/dist/components/retrieval/entity-dossier/entity-dossier.class.d.ts.map +1 -1
  615. package/dist/components/retrieval/entity-dossier/entity-dossier.class.js.map +1 -1
  616. package/dist/components/retrieval/graph/graph-loader.d.ts +5 -5
  617. package/dist/components/retrieval/graph/graph-loader.d.ts.map +1 -1
  618. package/dist/components/retrieval/graph/graph-loader.js.map +1 -1
  619. package/dist/components/retrieval/graph/graph.class.d.ts +7 -3
  620. package/dist/components/retrieval/graph/graph.class.d.ts.map +1 -1
  621. package/dist/components/retrieval/graph/graph.class.js +9 -3
  622. package/dist/components/retrieval/graph/graph.class.js.map +1 -1
  623. package/dist/components/retrieval/graph-legend/graph-legend.class.d.ts.map +1 -1
  624. package/dist/components/retrieval/graph-legend/graph-legend.class.js.map +1 -1
  625. package/dist/components/retrieval/grounding-summary/grounding-summary.class.d.ts.map +1 -1
  626. package/dist/components/retrieval/grounding-summary/grounding-summary.class.js.map +1 -1
  627. package/dist/components/retrieval/ingestion-queue/ingestion-queue.class.d.ts.map +1 -1
  628. package/dist/components/retrieval/ingestion-queue/ingestion-queue.class.js.map +1 -1
  629. package/dist/components/retrieval/knowledge-base/knowledge-base.class.d.ts.map +1 -1
  630. package/dist/components/retrieval/knowledge-base/knowledge-base.class.js.map +1 -1
  631. package/dist/components/retrieval/knowledge-graph-explorer/knowledge-graph-explorer.class.d.ts +6 -3
  632. package/dist/components/retrieval/knowledge-graph-explorer/knowledge-graph-explorer.class.d.ts.map +1 -1
  633. package/dist/components/retrieval/knowledge-graph-explorer/knowledge-graph-explorer.class.js +8 -1
  634. package/dist/components/retrieval/knowledge-graph-explorer/knowledge-graph-explorer.class.js.map +1 -1
  635. package/dist/components/retrieval/memory-panel/memory-panel.class.d.ts.map +1 -1
  636. package/dist/components/retrieval/memory-panel/memory-panel.class.js.map +1 -1
  637. package/dist/components/retrieval/mind-map/mind-map.class.d.ts.map +1 -1
  638. package/dist/components/retrieval/mind-map/mind-map.class.js.map +1 -1
  639. package/dist/components/retrieval/neighbor-list/neighbor-list.class.d.ts.map +1 -1
  640. package/dist/components/retrieval/neighbor-list/neighbor-list.class.js.map +1 -1
  641. package/dist/components/retrieval/node-palette/node-palette.class.d.ts.map +1 -1
  642. package/dist/components/retrieval/node-palette/node-palette.class.js.map +1 -1
  643. package/dist/components/retrieval/path-strip/path-strip.class.d.ts.map +1 -1
  644. package/dist/components/retrieval/path-strip/path-strip.class.js.map +1 -1
  645. package/dist/components/retrieval/provenance-panel/provenance-panel.class.d.ts.map +1 -1
  646. package/dist/components/retrieval/provenance-panel/provenance-panel.class.js.map +1 -1
  647. package/dist/components/retrieval/retrieval-results/retrieval-results.class.d.ts +4 -2
  648. package/dist/components/retrieval/retrieval-results/retrieval-results.class.d.ts.map +1 -1
  649. package/dist/components/retrieval/retrieval-results/retrieval-results.class.js +14 -2
  650. package/dist/components/retrieval/retrieval-results/retrieval-results.class.js.map +1 -1
  651. package/dist/components/retrieval/retrieval-search/retrieval-search.class.d.ts.map +1 -1
  652. package/dist/components/retrieval/retrieval-search/retrieval-search.class.js.map +1 -1
  653. package/dist/components/retrieval/retrieval-trace/retrieval-trace.class.d.ts.map +1 -1
  654. package/dist/components/retrieval/retrieval-trace/retrieval-trace.class.js.map +1 -1
  655. package/dist/components/retrieval/source-card/source-card.class.d.ts.map +1 -1
  656. package/dist/components/retrieval/source-card/source-card.class.js.map +1 -1
  657. package/dist/components/retrieval/source-list/source-list.class.d.ts.map +1 -1
  658. package/dist/components/retrieval/source-list/source-list.class.js.map +1 -1
  659. package/dist/components/retrieval/source-picker/source-picker.class.d.ts.map +1 -1
  660. package/dist/components/retrieval/source-picker/source-picker.class.js.map +1 -1
  661. package/dist/components/utility/copy-button/copy-button.class.d.ts.map +1 -1
  662. package/dist/components/utility/copy-button/copy-button.class.js.map +1 -1
  663. package/dist/components/utility/diff-view/diff-view.class.d.ts +4 -1
  664. package/dist/components/utility/diff-view/diff-view.class.d.ts.map +1 -1
  665. package/dist/components/utility/diff-view/diff-view.class.js.map +1 -1
  666. package/dist/components/utility/divider/divider.class.d.ts.map +1 -1
  667. package/dist/components/utility/divider/divider.class.js.map +1 -1
  668. package/dist/components/utility/export-button/export-button.class.d.ts.map +1 -1
  669. package/dist/components/utility/export-button/export-button.class.js.map +1 -1
  670. package/dist/components/utility/format/format-bytes.class.d.ts.map +1 -1
  671. package/dist/components/utility/format/format-bytes.class.js.map +1 -1
  672. package/dist/components/utility/format/format-date.class.d.ts.map +1 -1
  673. package/dist/components/utility/format/format-date.class.js.map +1 -1
  674. package/dist/components/utility/format/format-number.class.d.ts.map +1 -1
  675. package/dist/components/utility/format/format-number.class.js.map +1 -1
  676. package/dist/components/utility/format/relative-time.class.d.ts.map +1 -1
  677. package/dist/components/utility/format/relative-time.class.js +4 -1
  678. package/dist/components/utility/format/relative-time.class.js.map +1 -1
  679. package/dist/components/utility/icon/icon.class.d.ts.map +1 -1
  680. package/dist/components/utility/icon/icon.class.js.map +1 -1
  681. package/dist/components/utility/intersection-observer/intersection-observer.class.d.ts.map +1 -1
  682. package/dist/components/utility/intersection-observer/intersection-observer.class.js.map +1 -1
  683. package/dist/components/utility/json-viewer/json-viewer.class.d.ts.map +1 -1
  684. package/dist/components/utility/json-viewer/json-viewer.class.js.map +1 -1
  685. package/dist/components/utility/known-date/known-date.class.d.ts.map +1 -1
  686. package/dist/components/utility/known-date/known-date.class.js +2 -2
  687. package/dist/components/utility/known-date/known-date.class.js.map +1 -1
  688. package/dist/components/utility/live-region/live-region.class.d.ts.map +1 -1
  689. package/dist/components/utility/live-region/live-region.class.js.map +1 -1
  690. package/dist/components/utility/mention-popover/mention-popover.class.d.ts.map +1 -1
  691. package/dist/components/utility/mention-popover/mention-popover.class.js +2 -2
  692. package/dist/components/utility/mention-popover/mention-popover.class.js.map +1 -1
  693. package/dist/components/utility/mutation-observer/mutation-observer.class.d.ts.map +1 -1
  694. package/dist/components/utility/mutation-observer/mutation-observer.class.js.map +1 -1
  695. package/dist/components/utility/poll-status/poll-status.class.d.ts.map +1 -1
  696. package/dist/components/utility/poll-status/poll-status.class.js.map +1 -1
  697. package/dist/components/utility/random-content/random-content.class.d.ts.map +1 -1
  698. package/dist/components/utility/random-content/random-content.class.js +3 -2
  699. package/dist/components/utility/random-content/random-content.class.js.map +1 -1
  700. package/dist/components/utility/resize-observer/resize-observer.class.d.ts.map +1 -1
  701. package/dist/components/utility/resize-observer/resize-observer.class.js.map +1 -1
  702. package/dist/components/utility/tour/tour.class.d.ts.map +1 -1
  703. package/dist/components/utility/tour/tour.class.js.map +1 -1
  704. package/dist/components/viewers/archive-viewer/archive-viewer.class.d.ts.map +1 -1
  705. package/dist/components/viewers/archive-viewer/archive-viewer.class.js.map +1 -1
  706. package/dist/components/viewers/calendar-viewer/calendar-viewer.class.d.ts.map +1 -1
  707. package/dist/components/viewers/calendar-viewer/calendar-viewer.class.js.map +1 -1
  708. package/dist/components/viewers/contact-viewer/contact-viewer.class.d.ts.map +1 -1
  709. package/dist/components/viewers/contact-viewer/contact-viewer.class.js.map +1 -1
  710. package/dist/components/viewers/contact-viewer/vcard.d.ts.map +1 -1
  711. package/dist/components/viewers/contact-viewer/vcard.js +11 -9
  712. package/dist/components/viewers/contact-viewer/vcard.js.map +1 -1
  713. package/dist/components/viewers/csv-viewer/csv-viewer.class.d.ts.map +1 -1
  714. package/dist/components/viewers/csv-viewer/csv-viewer.class.js.map +1 -1
  715. package/dist/components/viewers/dataset-viewer/dataset-viewer.class.d.ts.map +1 -1
  716. package/dist/components/viewers/dataset-viewer/dataset-viewer.class.js.map +1 -1
  717. package/dist/components/viewers/document-compare/document-compare.class.d.ts +9 -2
  718. package/dist/components/viewers/document-compare/document-compare.class.d.ts.map +1 -1
  719. package/dist/components/viewers/document-compare/document-compare.class.js.map +1 -1
  720. package/dist/components/viewers/document-preview/document-preview.class.d.ts.map +1 -1
  721. package/dist/components/viewers/document-preview/document-preview.class.js.map +1 -1
  722. package/dist/components/viewers/document-viewer/document-viewer.class.d.ts.map +1 -1
  723. package/dist/components/viewers/document-viewer/document-viewer.class.js.map +1 -1
  724. package/dist/components/viewers/docx-viewer/docx-viewer.class.d.ts.map +1 -1
  725. package/dist/components/viewers/docx-viewer/docx-viewer.class.js +2 -2
  726. package/dist/components/viewers/docx-viewer/docx-viewer.class.js.map +1 -1
  727. package/dist/components/viewers/ebook-viewer/ebook-viewer.class.d.ts.map +1 -1
  728. package/dist/components/viewers/ebook-viewer/ebook-viewer.class.js.map +1 -1
  729. package/dist/components/viewers/email-viewer/email-viewer.class.d.ts.map +1 -1
  730. package/dist/components/viewers/email-viewer/email-viewer.class.js.map +1 -1
  731. package/dist/components/viewers/geojson-view/geojson-view.class.d.ts +6 -0
  732. package/dist/components/viewers/geojson-view/geojson-view.class.d.ts.map +1 -1
  733. package/dist/components/viewers/geojson-view/geojson-view.class.js.map +1 -1
  734. package/dist/components/viewers/highlight-layer/highlight-layer.class.d.ts.map +1 -1
  735. package/dist/components/viewers/highlight-layer/highlight-layer.class.js +3 -3
  736. package/dist/components/viewers/highlight-layer/highlight-layer.class.js.map +1 -1
  737. package/dist/components/viewers/html-viewer/html-viewer.class.d.ts.map +1 -1
  738. package/dist/components/viewers/html-viewer/html-viewer.class.js.map +1 -1
  739. package/dist/components/viewers/include/include.class.d.ts.map +1 -1
  740. package/dist/components/viewers/include/include.class.js.map +1 -1
  741. package/dist/components/viewers/notebook-viewer/notebook-viewer.class.d.ts.map +1 -1
  742. package/dist/components/viewers/notebook-viewer/notebook-viewer.class.js +1 -1
  743. package/dist/components/viewers/notebook-viewer/notebook-viewer.class.js.map +1 -1
  744. package/dist/components/viewers/page-rail/page-rail.class.d.ts.map +1 -1
  745. package/dist/components/viewers/page-rail/page-rail.class.js.map +1 -1
  746. package/dist/components/viewers/pdf-viewer/pdf-viewer.class.d.ts.map +1 -1
  747. package/dist/components/viewers/pdf-viewer/pdf-viewer.class.js +5 -2
  748. package/dist/components/viewers/pdf-viewer/pdf-viewer.class.js.map +1 -1
  749. package/dist/components/viewers/pptx-viewer/pptx-viewer.class.d.ts.map +1 -1
  750. package/dist/components/viewers/pptx-viewer/pptx-viewer.class.js.map +1 -1
  751. package/dist/components/viewers/spreadsheet-viewer/spreadsheet-viewer.class.d.ts.map +1 -1
  752. package/dist/components/viewers/spreadsheet-viewer/spreadsheet-viewer.class.js.map +1 -1
  753. package/dist/components/viewers/svg-viewer/svg-viewer.class.d.ts.map +1 -1
  754. package/dist/components/viewers/svg-viewer/svg-viewer.class.js.map +1 -1
  755. package/dist/components/viewers/xml-viewer/xml-viewer.class.d.ts.map +1 -1
  756. package/dist/components/viewers/xml-viewer/xml-viewer.class.js +0 -0
  757. package/dist/components/viewers/xml-viewer/xml-viewer.class.js.map +1 -1
  758. package/dist/internal/anchor-target.js.map +1 -1
  759. package/dist/internal/anchored-validity.js +0 -1
  760. package/dist/internal/anchored-validity.js.map +1 -1
  761. package/dist/internal/ansi.d.ts.map +1 -1
  762. package/dist/internal/ansi.js +14 -7
  763. package/dist/internal/ansi.js.map +1 -1
  764. package/dist/internal/cell-range.d.ts.map +1 -1
  765. package/dist/internal/cell-range.js +1 -0
  766. package/dist/internal/cell-range.js.map +1 -1
  767. package/dist/internal/css-length.d.ts.map +1 -1
  768. package/dist/internal/css-length.js +1 -0
  769. package/dist/internal/css-length.js.map +1 -1
  770. package/dist/internal/form-associated.js.map +1 -1
  771. package/dist/internal/localization.d.ts +11 -1
  772. package/dist/internal/localization.d.ts.map +1 -1
  773. package/dist/internal/localization.js +24 -1
  774. package/dist/internal/localization.js.map +1 -1
  775. package/dist/internal/lyra-element.d.ts.map +1 -1
  776. package/dist/internal/lyra-element.js.map +1 -1
  777. package/dist/internal/numbers.d.ts.map +1 -1
  778. package/dist/internal/numbers.js +3 -1
  779. package/dist/internal/numbers.js.map +1 -1
  780. package/dist/internal/overlay-manager.d.ts.map +1 -1
  781. package/dist/internal/overlay-manager.js +13 -8
  782. package/dist/internal/overlay-manager.js.map +1 -1
  783. package/dist/internal/root-registration-allowlist.d.ts +1 -1
  784. package/dist/internal/root-registration-allowlist.d.ts.map +1 -1
  785. package/dist/internal/root-registration-allowlist.js +3 -1
  786. package/dist/internal/root-registration-allowlist.js.map +1 -1
  787. package/dist/internal/strip-host-title.js.map +1 -1
  788. package/dist/internal/text-quote.js +7 -7
  789. package/dist/internal/text-quote.js.map +1 -1
  790. package/dist/internal/tokens.styles.d.ts.map +1 -1
  791. package/dist/internal/tokens.styles.js +1 -0
  792. package/dist/internal/tokens.styles.js.map +1 -1
  793. package/dist/lyra.d.ts +11 -5
  794. package/dist/lyra.d.ts.map +1 -1
  795. package/dist/lyra.js +7 -3
  796. package/dist/lyra.js.map +1 -1
  797. package/dist/theme.css +1 -0
  798. package/llms/components/lr-app-rail-item.md +6 -3
  799. package/llms/components/lr-app-rail.md +6 -3
  800. package/llms/components/lr-badge.md +3 -0
  801. package/llms/components/lr-button.md +4 -1
  802. package/llms/components/lr-chip-group.md +4 -1
  803. package/llms/components/lr-chip.md +4 -1
  804. package/llms/components/lr-color-picker.md +7 -1
  805. package/llms/components/lr-combobox.md +5 -2
  806. package/llms/components/lr-confirm-bar.md +31 -4
  807. package/llms/components/lr-control-group.md +12 -4
  808. package/llms/components/lr-dashboard-grid.md +4 -1
  809. package/llms/components/lr-date-input.md +5 -1
  810. package/llms/components/lr-date-picker.md +5 -1
  811. package/llms/components/lr-emoji-picker.md +11 -6
  812. package/llms/components/lr-eval-dataset.md +1 -1
  813. package/llms/components/lr-eval-result.md +4 -4
  814. package/llms/components/lr-flag.md +9 -5
  815. package/llms/components/lr-flow-canvas.md +7 -1
  816. package/llms/components/lr-icon-button.md +18 -5
  817. package/llms/components/lr-input.md +4 -1
  818. package/llms/components/lr-locale-picker.md +90 -0
  819. package/llms/components/lr-number-input.md +4 -2
  820. package/llms/components/lr-option.md +5 -2
  821. package/llms/components/lr-phone-input.md +10 -3
  822. package/llms/components/lr-reorder-item.md +92 -0
  823. package/llms/components/lr-reorder-list.md +92 -0
  824. package/llms/components/lr-select.md +6 -3
  825. package/llms/components/lr-swatch-picker.md +15 -9
  826. package/llms/components/lr-tag.md +3 -0
  827. package/llms/components/lr-thread-list.md +11 -6
  828. package/llms/components/lr-time-input.md +4 -2
  829. package/llms/components/lr-time-range.md +8 -0
  830. package/llms/components/lr-token-input.md +16 -7
  831. package/llms/components/lr-tool-approval-dialog.md +30 -6
  832. package/llms/components/lr-virtual-list.md +5 -1
  833. package/llms/index.md +7 -5
  834. package/llms/shared.md +13 -4
  835. package/llms/tokens.md +4 -2
  836. package/llms-full.txt +421 -133
  837. package/llms.txt +4 -4
  838. package/package.json +10 -4
  839. package/vscode-css-data.json +246 -8
  840. package/vscode-html-data.json +533 -371
  841. package/web-types.json +868 -109
  842. package/dist/components/data/data-grid/data-grid.class.d.ts +0 -69
  843. package/dist/components/data/data-grid/data-grid.class.d.ts.map +0 -1
  844. package/dist/components/data/data-grid/data-grid.class.js +0 -123
  845. package/dist/components/data/data-grid/data-grid.class.js.map +0 -1
  846. package/dist/components/data/data-grid/data-grid.d.ts +0 -2
  847. package/dist/components/data/data-grid/data-grid.d.ts.map +0 -1
  848. package/dist/components/data/data-grid/data-grid.js +0 -5
  849. package/dist/components/data/data-grid/data-grid.js.map +0 -1
  850. package/dist/components/data/data-grid/data-grid.styles.d.ts.map +0 -1
  851. package/dist/components/data/data-grid/data-grid.styles.js +0 -15
  852. package/dist/components/data/data-grid/data-grid.styles.js.map +0 -1
  853. package/llms/components/lr-data-grid.md +0 -55
package/CHANGELOG.md ADDED
@@ -0,0 +1,4024 @@
1
+ # Changelog
2
+
3
+ ## 6.1.0
4
+
5
+ ### Minor Changes
6
+
7
+ - f9e1e18: Make `lr-app-rail`'s `lr-toggle` event cancelable: a listener calling `preventDefault()` keeps the
8
+ rail open/closed as it was. The one exception is the forced close that fires when `mode` leaves
9
+ `'mobile'` while open, which stays unconditional since it's a consistency fix-up rather than a
10
+ user dismissal.
11
+ - f9e1e18: Add themeable `--*-gap`/`--*-radius` CSS custom properties to `lr-input`, `lr-select`, and
12
+ `lr-combobox` (gap + radius), `lr-chip`/`lr-badge`/`lr-tag` (radius), and `lr-icon-button`
13
+ (radius) — extending the pattern `lr-button` already shipped, so these values can be retuned
14
+ without a `::part()` override. Every default is unchanged.
15
+ - f6d966e: Add an optional `country` field to `lr-locale-picker`'s `locales` catalog entries, letting a
16
+ consumer override a row's derived flag (e.g. showing Lebanon's flag for an `ar` row instead of
17
+ the library's default Saudi Arabia mapping).
18
+ - 3c9f478: Make `lr-reorder-list`'s `lr-reorder` event cancelable: a listener calling `preventDefault()`
19
+ holds the move (reflecting `pending` on the affected `lr-reorder-item`) until the host calls the
20
+ new `finalizePendingMove()`/`revertPendingMove()` methods — mirroring `lr-confirm-bar`'s cancelable
21
+ approve/deny pattern, for hosts that persist the new order asynchronously.
22
+ - f9e1e18: Make `lr-token-input`'s `lr-remove` event cancelable: a listener calling `preventDefault()` (for
23
+ example to run async removal validation, or to protect a token) keeps the token in place instead
24
+ of it being removed unconditionally. Scoped to direct removal; multi-candidate paste/edit flows
25
+ are unaffected.
26
+
27
+ ### Patch Changes
28
+
29
+ - a4c4825: Fix `lr-agent-workspace` never emitting its documented `lr-retrieval-select` event when a row is
30
+ selected in the built-in retrieval results, and leaking the internal `lr-retrieval-results`'s raw
31
+ `lr-select` event through under the wrong name instead.
32
+ - f9e1e18: Fix `lr-date-input`'s `selectionDirection` getter returning `undefined` instead of `null` before
33
+ the internal input has rendered, despite its declared `LyraDateInputSelectionDirection | null`
34
+ return type.
35
+ - 2dabe8e: Fix `lr-icon-button`'s bare-SVG-geometry fallback rendering slotted stroke-style icon path data
36
+ (no fill/stroke of its own) as a solid black shape instead of an outline, by giving
37
+ `[part="fallback"]` the same `fill`/`stroke`/`stroke-width`/`stroke-linecap`/`stroke-linejoin`
38
+ defaults `lr-icon`'s own wrapper svg already has.
39
+ - f9e1e18: Fix `lr-retrieval-results` and `lr-menu` leaking a wrapped child's own event under the wrong
40
+ name alongside the documented, consolidated one: `lr-retrieval-results` leaked `lr-virtual-list`'s
41
+ `lr-load-more` and `lr-chunk-inspector`'s `lr-chunk-open` (the latter also carrying an
42
+ undocumented extra `anchor` field); `lr-menu` leaked `lr-menu-item`'s raw `lr-menu-item-select`
43
+ alongside the documented `lr-menu-select`.
44
+ - cc90b3a: Fix two `lr-thread-list` bugs: a row click fired `lr-select` twice (the correct re-emit plus the
45
+ original bare event leaking through unstopped), and content slotted into `slot="empty"` rendered
46
+ unconditionally instead of only when the list has zero visible threads.
47
+
48
+ ## 6.0.0
49
+
50
+ ### Major Changes
51
+
52
+ - 5c93d1b: Remove `<lr-data-grid>`. It was a strict functional subset of `<lr-table>` (same `role="grid"` +
53
+ roving-tabindex + sort/select/loading pattern, with none of `<lr-table>`'s filtering, pagination,
54
+ inline editing, resize, grouping, expansion, heat-tint, sticky columns, or footers), implemented
55
+ independently with no shared code. Use `<lr-table>` instead:
56
+
57
+ - `DataGridColumn<T>`'s optional `value(row)` becomes `TableColumn<T>`'s required `cell(row)`.
58
+ - `<lr-data-grid>`'s `emptyText` string becomes `<lr-table>`'s `emptyHeading`/`emptyDescription`
59
+ pair (rendered via an internal `<lr-empty>`, not a plain text cell).
60
+ - `<lr-data-grid>` always mutated `selectedKey` and emitted `lr-selection-change` on row
61
+ click/activation; `<lr-table>` only does that when `selection-mode` is `"single"` or
62
+ `"multiple"` (default `"none"`, presentational) — listen on `lr-row-click` (`detail: { row }`)
63
+ instead if you don't need `<lr-table>`'s own selection bookkeeping.
64
+ - `accessibleLabel`/`aria-label` — unchanged; `<lr-table>` reads a plain `aria-label` attribute the
65
+ same way.
66
+
67
+ `<lr-eval-dataset>` and `<lr-eval-result>` composed `<lr-data-grid>` internally and now compose
68
+ `<lr-table>` instead. `<lr-eval-result>`'s public `columns` property changes type accordingly from
69
+ `DataGridColumn<EvalRunResult>[]` to `TableColumn<EvalRunResult>[]` — update any `value(row)`
70
+ column definitions you pass in to `cell(row)`.
71
+
72
+ ### Minor Changes
73
+
74
+ - 5c93d1b: Add a `3xs` size tier to `<lr-chip>`, one step below `2xs`, for dense inline count pills.
75
+ - 8e6e045: `lr-confirm-bar`: swap the hand-rolled `deny-button`/`approve-button` native `<button>`s for
76
+ `<lr-button>`, so `--lr-button-*` theming and a consumer's existing `lr-button` style fragments
77
+ reach them like every other button in an app. Adds a host-writable
78
+ `pending: 'approved' | 'denied' | null` property and makes `lr-approve`/`lr-deny` cancelable: a
79
+ listener calling `preventDefault()` sets `pending` to the decision being made (showing `loading`
80
+ on that button, `disabled` on the other) instead of resolving synchronously, so a host whose
81
+ approval hits a network call can keep the UI honest about being in flight. Finalize by setting
82
+ `.decision`, or bounce back by clearing `.pending` to `null`.
83
+
84
+ **Breaking (CSS only):** `::part(deny-button)`/`::part(approve-button)` now select an `<lr-button>`
85
+ host, not a native `<button>`.
86
+
87
+ Before:
88
+ lr-confirm-bar::part(deny-button) { padding: 4px 8px; border: ...; }
89
+ After (use the re-exported sub-parts):
90
+ lr-confirm-bar::part(deny-button-base) { padding: 4px 8px; border: ...; }
91
+
92
+ Runtime API (events, `tone`, `compact`, slots, the new `pending` property) is unchanged.
93
+
94
+ - 050c43c: Fix `<lr-control-group>` collapsing to 0 inline size when placed as an ordinary flex-basis:auto
95
+ child of a shrink-to-fit flex row (its own stated primary use case). The `@container`
96
+ narrow-allocation breakpoint is now opt-in via a new `responsive` property instead of always-on.
97
+ - 18e7b10: Add `--lr-dashboard-grid-cell-hover-outline-color` to `<lr-dashboard-grid>`, theming the mouse-hover preview outline on `[part="cell"]` independently of the shared `--lr-color-border-strong` token. Set it to `transparent` to opt out of the hover treatment entirely.
98
+ - bd2e594: Add `--lr-flow-canvas-node-hover-outline-color` to `<lr-flow-canvas>`, theming the mouse-hover preview outline on `[part="node"]` independently of the shared `--lr-color-border-strong` token. Set it to `transparent` to opt out of the hover treatment entirely.
99
+ - 76690c7: Add `--lr-button-gap` and `--lr-button-radius` custom properties to `<lr-button>`, so the
100
+ icon/label gap and corner radius are retunable without a `::part(base)` rule — matching the
101
+ retunable-without-`::part()` treatment `--lr-button-padding-block/-inline` and
102
+ `--lr-button-font-size` already have.
103
+ - f8810d7: Add `<lr-locale-picker>`: a closed-list locale switcher over the locale registry
104
+ (`getRegisteredLyraLocales()`) or an explicit `locales` catalog, form-associated and mirroring
105
+ `<lr-select>`'s hand-rolled listbox. Selecting a row emits a cancelable `lr-change` and, unless
106
+ vetoed, applies the pick via `setLyraLocale()`.
107
+ - 77377ed: Add `getRegisteredLyraLocales()` and `subscribeLyraLocaleRegistry()` so a consumer can enumerate
108
+ and live-track every locale registered via `registerLyraLocale()` (plus `'en'`) — the piece that
109
+ unblocks a locale-picker component built on top of the existing locale runtime.
110
+ - 0771a83: Add a `renderExcerpt` hook to `<lr-thread-list>`, rendering rich per-row excerpt content into the
111
+ row `<lr-conversation-item>`'s own `excerpt` slot — where it wins over the plain-string `excerpt`
112
+ property — for cases like a server-highlighted search-match snippet, without giving up the built-in
113
+ title layout and inline-rename affordance the way `renderRowContent` requires.
114
+ - 02cd69d: Add `<lr-reorder-item>`, one row of the new `<lr-reorder-list>` flat-list reorder primitive.
115
+ - 2cf4206: Add `<lr-reorder-list>`, a generic flat-list reorder primitive with move-up/move-down buttons and
116
+ a Ctrl/Cmd+ArrowUp/ArrowDown keyboard shortcut, emitting the full new order on every move.
117
+ - c6af1b7: `lr-tool-approval-dialog`: swap the hand-rolled `deny-button`/`approve-button` native `<button>`s
118
+ for `<lr-button>` (`variant="neutral"`/`"brand"`), so `--lr-button-*` theming and a consumer's
119
+ existing `lr-button` style fragments reach them like every other button in an app. Adds a
120
+ host-writable `pending: 'approve' | 'deny' | null` property and makes `lr-approve`/`lr-deny`
121
+ cancelable: a listener calling `preventDefault()` sets `pending` to the decision being made
122
+ (showing `loading` on that button, `disabled` on the other) instead of closing immediately, so a
123
+ host whose approval hits a network call can keep the dialog honest about being in flight.
124
+ Finalize by calling `close('approve'|'deny')`, or bounce back by clearing `.pending` to `null`.
125
+ While `pending` is set, Escape and backdrop dismissal are suppressed; `pending` itself resets to
126
+ `null` every time the dialog re-opens. The `edit-button` is unaffected.
127
+
128
+ **Breaking (CSS only):** `::part(deny-button)`/`::part(approve-button)` now select an `<lr-button>`
129
+ host, not a native `<button>`.
130
+
131
+ Before:
132
+ lr-tool-approval-dialog::part(deny-button) { padding: 4px 8px; border: ...; }
133
+ After (use the re-exported sub-parts):
134
+ lr-tool-approval-dialog::part(deny-button-base) { padding: 4px 8px; border: ...; }
135
+
136
+ Runtime API (events, `editable` and its editing behavior, slots, the new `pending` property) is
137
+ unchanged.
138
+
139
+ - 65d6a2b: Add `--lr-virtual-list-hover-outline-color` to `<lr-virtual-list>`, theming the mouse-hover preview outline on `[part="base"]` independently of the shared `--lr-color-border-strong` token. Set it to `transparent` to opt out of the hover treatment entirely.
140
+
141
+ ### Patch Changes
142
+
143
+ - 3fd9bbd: Regenerate the agent-tools reference docs and custom-elements manifest for the `lr-confirm-bar`/
144
+ `lr-tool-approval-dialog` `lr-button` swap and their new `pending` properties (see the sibling
145
+ changesets for the runtime changes themselves).
146
+ - 9ebb38c: `lr-icon-button`: restore rendering for slotted bare SVG geometry (`<path>`, `<circle>`, etc. with
147
+ no enclosing `<svg>`) when `icon` is unset. 5.2.0's natural-aspect-ratio change made the default
148
+ slot a sibling of the internal glyph instead of nesting it inside an SVG, which silently stopped
149
+ this narrow case from painting (no console error, no type error). A small whitelist of raw SVG
150
+ geometry tag names is now cloned into a real SVG-namespaced element the same way `<lr-icon>`'s own
151
+ custom-content slot already does — every other case (complete `<svg>`, `<img>`, custom elements) is
152
+ untouched, so the `createElementNS`-on-custom-elements bug 5.2.0 fixed for `<lr-flag>` cannot
153
+ regress.
154
+
155
+ ## 5.2.0
156
+
157
+ ### Minor Changes
158
+
159
+ - 602177a: `lr-button`: expose its per-size geometry and its outlined fill as custom properties, so a consumer
160
+ no longer needs a `::part(base)` rule to fit a button into a dense toolbar or to tint an outline.
161
+
162
+ - `--lr-button-padding-block`, `--lr-button-padding-inline` and `--lr-button-font-size` now carry
163
+ each `size` tier's padding/font-size (the `:host` defaults are the `m` tier). Every tier is now
164
+ pure custom-property re-assignment — matching `lr-input`, `lr-select`, `lr-combobox`,
165
+ `lr-segmented` and `lr-date-input` — so overriding one knob retunes the tier instead of fighting
166
+ the stylesheet.
167
+ - `--lr-button-min-height` carries the active tier's `min-block-size` floor (it resolves to that
168
+ tier's existing `--lr-button-size-*` token), and the new `--lr-button-height` pins an exact
169
+ height — flooring _and_ capping the button, e.g. to match a fixed toolbar row. It is deliberately
170
+ left undeclared by default so each tier's floor still applies when it is unset.
171
+ - `--lr-button-outlined-fill` (default `transparent`) tints `appearance="outlined"`. Like
172
+ `--lr-button-quiet-*` it is not swapped per `variant`. Note that the existing hover
173
+ `filter: brightness()` visibly brightens a tinted fill, where a transparent one showed no change.
174
+
175
+ `appearance="link"` continues to ignore all of these and render as zero-chrome inline text. With
176
+ every property unset, all six tiers render byte-identical to before.
177
+
178
+ - fe06b7d: `lr-card`: `interactive` now grants real activation semantics when `href` is not also set.
179
+ `[part='base']` becomes focusable (`tabindex="0"`), responds to Enter and Space (Space calls
180
+ `preventDefault()` so the page does not scroll under the focused card), and emits a new
181
+ `lr-card-activate` event (no detail) — so a clickable tile no longer needs a consumer-supplied
182
+ wrapper or a `::part(base)` hack to be keyboard-operable.
183
+
184
+ - The card deliberately carries **no** `role="button"`. A card is a container that routinely holds
185
+ slotted buttons and links, and `role="button"` around focusable descendants is the axe-core
186
+ `nested-interactive` violation this library's own a11y gate enforces (unlike `lr-chip`'s
187
+ `toggleable` mode, which can forbid focusable children and therefore can carry the role).
188
+ - Because of that, "did the user aim at the card or at a control inside it?" is answered at event
189
+ time: the handler walks `composedPath()` from the original target up to `[part='base']` and bails
190
+ out if anything on the way is itself a control (a link, button, form control, `[tabindex]`, or an
191
+ interactive `role`). A click on a slotted `lr-button` or `<a>` therefore never activates the card.
192
+ - With `href` set, the root is still a real `<a>`: native navigation remains the activation, no
193
+ extra `tabindex` is added, and `lr-card-activate` is never fired.
194
+ - Without `interactive`, the rendered output is unchanged — no `tabindex`, no listeners, no events.
195
+
196
+ - 76b4ef7: `lr-chat-composer` gains `appearance="plain"` (reflected, `'card' | 'plain'`, default `'card'`), so a
197
+ composer docked inside a chat panel, dialog footer or toolbar that already draws its own border
198
+ doesn't double the frame. `plain` drops `[part="base"]`'s border, background, padding and corner
199
+ radius; the row layout, disabled treatment and the send/stop button's own chrome are unaffected.
200
+
201
+ Focus stays visible either way. The card's only focus affordance is a border-color shift, and there
202
+ is no border left to recolor under `plain` (the internal textarea sets `outline: none`), so `plain`
203
+ swaps in an underline across the input row instead — drawn as an inset box-shadow from
204
+ `--lr-focus-ring-width`/`--lr-focus-ring-color`, so it costs no layout.
205
+
206
+ An unset composer renders byte-identically to before.
207
+
208
+ - 89dc89a: Add density and chrome-less escape hatches to six card-chrome components so an embedded card no
209
+ longer forces its own frame on a host that already draws one:
210
+
211
+ - `lr-agent-run`, `lr-entity-card`, `lr-source-card` each gain both a reflected `compact` boolean
212
+ (tighter padding/gap, tunable via `--lr-<component>-compact-padding` / `-gap`) and
213
+ `appearance="plain"` (drops border, background, padding and radius). `plain` wins over `compact`
214
+ when both are set.
215
+ - `lr-stack-trace` and `lr-flow-run-overlay` gain `appearance="plain"` — for nesting inside an
216
+ `lr-result-card` / `lr-agent-run` or a host toolbar that already draws a border, without doubling
217
+ the frame. `lr-flow-run-overlay`'s `plain` also drops its floating-surface shadow.
218
+ - `lr-file-input` gains a reflected `compact` boolean (tighter dropzone padding, gap and label
219
+ font, tunable via `--lr-file-input-compact-padding` / `-gap` / `-font-size`) so the dropzone fits
220
+ a toolbar or table cell.
221
+
222
+ All escapes default off; an unset component renders byte-identically to before. Interactive
223
+ affordances that live on child controls (agent-run's Cancel/Retry, stack-trace's copy/frame
224
+ buttons, source-card's title/toggle) keep their own chrome under `plain`.
225
+
226
+ - bca1353: `lr-flow-controls` gains `appearance="plain"` (reflected, `'card' | 'plain'`, default `'card'`), for
227
+ clusters placed in a host toolbar or panel that already draws its own surface. `plain` drops
228
+ `[part="base"]`'s border, background, padding, corner radius **and** its floating-surface
229
+ `box-shadow` — a lift shadow with no surface under it reads as a stray smudge — matching what
230
+ `lr-flow-run-overlay`'s `plain` already does.
231
+
232
+ The cluster keeps its layout, its `orientation` axis, every button's shared minimum hit area
233
+ (`--lr-icon-button-size`) and their hover/focus rings. No `compact` is offered: the padding is
234
+ already the smallest spacing step, and the only remaining room is that hit-area floor.
235
+
236
+ The existing `for`, `orientation` and `hideLock` properties are now documented too. An unset cluster
237
+ renders byte-identically to before.
238
+
239
+ - ddf52ba: `lr-flow-node` now exposes its card as a CSS part and gains a density escape:
240
+
241
+ - The bordered, filled card is reachable as `::part(card)` (it keeps its `.card` class, so nothing
242
+ that already targeted it changes).
243
+ - New reflected `compact` boolean tightens the card padding for dense canvases and palette previews,
244
+ tunable via `--lr-flow-node-compact-padding` (default `var(--lr-space-xs)`) and
245
+ `--lr-flow-node-compact-gap` (default `var(--lr-space-2xs)`). The border, background, shadow and
246
+ the `selected`/`status="running"` treatments all stay.
247
+
248
+ Two documentation/CSS bugs are fixed in passing: the `base` part is documented as what it actually
249
+ is (the row wrapping the handles and the card, carrying no chrome of its own), and a duplicated
250
+ `min-inline-size: 0` that overrode the card's own minimum width is removed — the documented
251
+ `--lr-flow-node-min-inline-size` custom property was dead until now and once again sets the card's
252
+ minimum inline size (default `11rem`).
253
+
254
+ An unset node renders as before apart from that restored minimum width.
255
+
256
+ - 81f615b: `lr-checkbox` / `lr-radio`: publish the label indent, and stop hard-sizing the radio's circle.
257
+
258
+ - **New `--lr-checkbox-label-indent` and `--lr-radio-label-indent`** carry the distance from the
259
+ control's start edge to the start of the label — the box/circle's own floor
260
+ (`min(--lr-icon-button-size, 1.75rem)`) plus the label gap (`--lr-space-s`), i.e. `2.25rem` at the
261
+ default tokens. Consumers composing per-option hint text under a checkbox previously had to
262
+ hardcode that `2.25rem` after reading it out of the shadow styles, where neither term was a public
263
+ contract, so the hint silently de-aligned on any retheme. `[part='base']`'s `gap` is now _derived
264
+ from_ the published property rather than repeating `--lr-space-s`, so the advertised value and the
265
+ rendered geometry cannot drift: setting the property moves the label. Rendering is byte-identical
266
+ when it is left unset.
267
+
268
+ **Read this before assuming it closes the filed case.** The property is declared on the
269
+ component's `:host`, so it is readable by the element itself and overridable from your own
270
+ stylesheet (`lr-checkbox { --lr-checkbox-label-indent: … }` beats a `:host` rule), but custom
271
+ properties inherit _down_, not sideways — a **sibling** `<p>` in your own tree can never read it
272
+ off the checkbox. What actually solves that case is the `--lr-theme-icon-button-size` bridge that
273
+ landed alongside this release: compute `calc(min(var(--lr-theme-icon-button-size, 2.5rem), 1.75rem)
274
+
275
+ - var(--lr-theme-space-s, 0.5rem))` on your own wrapper from tokens you control, and both the
276
+ control and your hint text stay aligned through a retheme. The new "Aligning per-option hint text"
277
+ stories show both halves. This is not an unfixed gap; please do not re-file it as one.
278
+
279
+ - **Bug fix — `lr-radio`'s `[part='circle']` was hard-sized**, with `inline-size`/`block-size` where
280
+ `lr-checkbox`'s `[part='box']` correctly uses `min-inline-size`/`min-block-size`. Since
281
+ `[part='base']` carries no box of its own, that circle _is_ the entire tap target for a label-less
282
+ radio, and a hard size can be smaller than its own content — an enlarged indicator overflowed it
283
+ instead of growing it. It is now a floor, matching `lr-checkbox` exactly. Default rendering is
284
+ unchanged (28×28 at the default tokens, above the WCAG 2.2 SC 2.5.8 24×24 minimum).
285
+
286
+ Note the residual, unchanged in this release: neither control guarantees the 24×24 minimum once
287
+ `--lr-icon-button-size` is themed below it — `min()` still tracks the token down 1:1. Both
288
+ controls behave identically here; a hard floor would need its own decision, since it would also
289
+ block a deliberately dense checkbox.
290
+
291
+ `lr-checkbox` deliberately still has no `hint`/`errorText` chrome of its own (see its class docs);
292
+ that omission is intentional and adding it would require a `form-control` wrapper that changes the
293
+ part structure for existing consumers.
294
+
295
+ - 6bf969f: Themeable code tab width, chat bubble geometry, and the code-block active-line outline color.
296
+
297
+ - `--lr-code-block-tab-size` (default `2`) sets the tab width of rendered code. It is honoured by
298
+ `lr-code-block`, `lr-code-block-core`, `lr-markdown`, and `lr-markdown-core`, and shares the
299
+ default of the existing `--lr-code-editor-tab-size`, so the editable and read-only code surfaces
300
+ agree. The markdown viewers declare it themselves because they are sibling elements of
301
+ `lr-code-block`, not descendants — one declaration could not have reached them. `lr-code-block`
302
+ reads the token rather than writing `tab-size` inline, so the override survives shiki's own
303
+ inline `style` on the highlighted `<pre>`. Note that a markdown code block wraps
304
+ (`white-space: pre-wrap`) while `lr-code-block` does not, so the same value can render
305
+ differently on a wrapped line, where tab stops restart.
306
+ - `--lr-chat-message-bubble-padding` (default `var(--lr-space-m)`) and
307
+ `--lr-chat-message-bubble-radius` (default `var(--lr-radius)`) reshape `lr-chat-message`'s
308
+ bubble. Use these instead of a `::part(bubble)` padding/radius override: an outer-tree `::part`
309
+ declaration outranks every rule inside the component's shadow tree, which silently suppressed
310
+ the per-`status` (`failed`, `streaming`) and per-role bubble treatments. The radius prop is
311
+ bubble-only — `collapse-button` and `retry-button` keep reading the shared `--lr-radius`.
312
+ - `--lr-code-block-active-line-outline-color` (default `var(--lr-color-brand)`) retints only the
313
+ outline of the line marked active by `active-highlight-id`, leaving the language pill, hover,
314
+ and focus surfaces on `--lr-color-brand`.
315
+
316
+ All three default to exactly today's rendering, so a consumer who overrides none of them sees no
317
+ visual change.
318
+
319
+ - fe06b7d: `lr-confirm-bar`: new reflected `compact` property that collapses the bar from a full card
320
+ (bordered, padded, `display: block` surface) into a chrome-less inline row, for a confirmation that
321
+ has to live inside an existing container — a table cell, a card's action row, a toolbar.
322
+
323
+ - The **host** flips to `inline-flex` under `[compact]`, not just `[part='base']`: restyling the
324
+ part alone still leaves a `display: block` host that breaks the row it was dropped into.
325
+ - The narrow-allocation container query is switched off with it (`container-type: normal`). A
326
+ compact bar is _expected_ to be narrow, so leaving the query live would fire it essentially
327
+ always and stretch the Deny/Approve buttons to fill — the opposite of the intent.
328
+ - Re-chrome it through `--lr-confirm-bar-compact-padding` (default `0`),
329
+ `--lr-confirm-bar-compact-gap` (default `var(--lr-space-s)`), `--lr-confirm-bar-compact-border`
330
+ (default `none`), `--lr-confirm-bar-compact-radius` (default `0`) and
331
+ `--lr-confirm-bar-compact-background` (default `transparent`).
332
+ - Everything else is unchanged: `lr-approve`/`lr-deny` shapes, `role="group"` and its heading
333
+ label, and the contract that focus moves synchronously to `[part='status']` _before_ the
334
+ Deny/Approve buttons unmount. Leaving `compact` unset renders exactly as before.
335
+
336
+ - 49e0738: `lr-conversation-item` gains a `compact` density flag
337
+
338
+ A reflected boolean `compact` (default `false`, matching `lr-empty`'s convention) tightens
339
+ `[part='base']`'s padding from `var(--lr-space-s) var(--lr-space-m)` to
340
+ `var(--lr-space-xs) var(--lr-space-s)`, its gap from `var(--lr-space-xs)` to `var(--lr-space-2xs)`,
341
+ and collapses `[part='content']`'s inter-line gap to `0`. Both tuned values sit behind the new
342
+ `--lr-conversation-item-compact-padding` / `--lr-conversation-item-compact-gap` custom properties —
343
+ declared as inline `var()` fallbacks at the point of use, never on `:host`, so a surrounding list can
344
+ retune every row at once from an ancestor. Unset, a row renders exactly as before.
345
+
346
+ Nothing else changes. In particular `[part='rename-button']` keeps its
347
+ `min-inline-size`/`min-block-size: var(--lr-icon-button-size)` floor under `compact`, so a density
348
+ flag can never silently drop a row's icon target below the shared minimum; the excerpt stays visible
349
+ (it is already single-line ellipsised and `hidden`-bindable per row) and the excerpt/timestamp font
350
+ sizes stay at their existing steps. `:host([compact]) [part='base']` is ordered before
351
+ `:host([active]) [part='base']`, which is equal specificity, so an active row keeps its background
352
+ and its promoted excerpt/timestamp contrast when both are set.
353
+
354
+ - 3737d4c: Add consumer-settable CSS custom properties for state-styled surfaces in the data and agent-tools
355
+ families that previously took their color straight from a library-wide `--lr-color-*` token with no
356
+ component-scoped indirection. Because CSS Shadow Parts forbids an attribute selector after `::part()`
357
+ (`::part(row)[aria-selected]` is invalid), these states could only be restyled by hijacking the
358
+ shared token, which repaints everything else that reads it. Each new property uses an inline
359
+ `var()` fallback to its old token value, so an unset consumer renders byte-identically to before:
360
+
361
+ - `lr-data-grid`: `--lr-data-grid-row-selected-bg` (selected row background).
362
+ - `lr-env-list`: `--lr-env-list-reveal-active-bg`, `--lr-env-list-reveal-active-border` (pressed
363
+ reveal toggle background/border).
364
+ - `lr-flow-node`: `--lr-flow-node-selected-border` (selected card border color).
365
+ - `lr-flow-canvas`: `--lr-flow-canvas-node-current-outline-color` (current node outline color).
366
+ - `lr-artifact-panel`: `--lr-artifact-panel-view-active-bg`, `--lr-artifact-panel-view-active-color`
367
+ (pressed preview/code toggle background/text).
368
+ - `lr-test-results`: `--lr-test-results-filter-active-bg`, `--lr-test-results-filter-active-border`,
369
+ `--lr-test-results-filter-active-color` (pressed status filter toggle).
370
+ - `lr-span-waterfall`: `--lr-span-waterfall-row-active-bg` (active row background).
371
+ - `lr-trace-tree`: `--lr-trace-tree-row-active-bg` (active row background).
372
+ - `lr-agent-trace`: `--lr-agent-trace-handoff-active-bg` (active handoff quick-jump entry background).
373
+ - `lr-policy-summary`: `--lr-policy-summary-count-allow-color`,
374
+ `--lr-policy-summary-count-deny-color`, `--lr-policy-summary-count-needs-review-color` (per-state
375
+ count text colors).
376
+
377
+ - 8e4e5cc: `<lr-filter-bar>` gains a `'text'` filter type, composing `<lr-input>` for an open-ended query, plus
378
+ an optional per-filter `debounce` (ms). A dashboard whose toolbar is a search box next to a few
379
+ dropdowns can now be a single filter bar — the search box participates in the same `value` object,
380
+ the same removable active-filter chips (shown verbatim, so a query containing a slash is no longer
381
+ mangled), the same reset button and `loading` state — and can delete its own hand-rolled debounce
382
+ timer. A pending debounce is flushed by the field's own change/blur and cancelled by `reset()`, a
383
+ chip removal, and disconnection, and the text field stays uncontrolled-with-sync so a re-render
384
+ mid-typing never disturbs the caret.
385
+ - f8bc916: Form controls: exact-height escape hatches and `start`/`end` adornment slots.
386
+
387
+ - `--lr-combobox-trigger-height` and `--lr-input-control-height` are new custom properties that pin
388
+ an exact control height — flooring _and_ capping the row — so `lr-select`, `lr-combobox` and
389
+ `lr-input` can be pixel-matched in one toolbar without a `::part()` rule. Both are deliberately
390
+ left undeclared by default, so each tier's existing `*-min-height` floor still applies when they
391
+ are unset. Because the component never declares them, they can also be set from an ancestor or an
392
+ outer-tree rule, not only inline on the element. On `lr-combobox` the hatch is a single-row
393
+ affordance: in `multiple` mode a tag row long enough to wrap overflows the pinned box visibly
394
+ (nothing is clipped), so leave it unset there.
395
+ - **Behaviour change:** `lr-select` declared `--lr-select-trigger-height: auto` on `:host`, which
396
+ made the `var()` fallback to `--lr-select-trigger-min-height` unreachable and left that property
397
+ dead at the default `m` tier (four extra specificity rules patched the floor back for
398
+ `xs`/`s`/`l`/`xl` only). The sentinel is now genuinely undeclared and the patch rules are gone, so
399
+ `--lr-select-trigger-min-height` is live at every tier. The visible consequence is that a
400
+ default-size `lr-select` trigger now honours the `2.5rem` floor it already declared — byte
401
+ identical to `lr-input`'s and `lr-combobox`'s own `m` floor, so the three controls line up.
402
+ `getComputedStyle(el).getPropertyValue('--lr-select-trigger-height')` now returns `''` rather than
403
+ `'auto'`; assert the rendered `min-block-size`/`block-size` instead.
404
+ - `lr-combobox` and `lr-date-input` gain `start`/`end` adornment slots with matching `start`/`end`
405
+ CSS parts, mirroring `lr-input`'s existing implementation: the wrappers are `hidden` while nothing
406
+ is slotted, and they inherit the control's own padding so no consumer spacing is needed. `end`
407
+ renders before the dropdown chevron (`lr-combobox`) and before the calendar toggle
408
+ (`lr-date-input`), so consumer content never sits outboard of the built-in trigger. Slotted
409
+ adornments are never collected as `lr-combobox` options.
410
+ - `lr-select` is deliberately excluded from `start`/`end`: its `[part='trigger']` is a native
411
+ `<button>`, whose content model forbids interactive descendants, and its `justify-content:
412
+ space-between` would push the label to the middle. `lr-date-input` is deliberately excluded from
413
+ the exact-height hatch: its row has no `min-block-size`, and its height is pinned transitively by
414
+ `--lr-icon-button-size` on the calendar button — capping it would crush the 24x24 target.
415
+
416
+ - 4a43cc0: `<lr-heatmap>`: `CalendarCellPos` now carries the resolved ISO `yyyy-mm-dd` `date` alongside
417
+ `week`/`weekday`. Every calendar-mode position handed to `cellText`, `cellColor` and
418
+ `cellInteractive` is populated — **including grid positions with no matching entry in `days`**
419
+ (a gap in a sparse calendar still sits on a real calendar day) — so a callback can key off the date
420
+ directly instead of re-deriving the grid's `firstWeekStart + week * 7 + weekday` anchor arithmetic,
421
+ which was the only way to answer "is this cell in the future?" before.
422
+
423
+ The date comes from a per-grid cache built once whenever the calendar grid is rebuilt, so it costs
424
+ an array read rather than a `Date` allocation per cell per repaint, and it is deliberately excluded
425
+ from the internal hover/focus position-equality check so repaint diffs are unchanged. Matrix mode's
426
+ `MatrixCellPos` is untouched, and `lr-cell-click`'s detail shape is unchanged.
427
+
428
+ `date` is a **required** field of `CalendarCellPos`. No API on this component accepts a
429
+ `CalendarCellPos` as input — it is purely a callback parameter type — so this is additive for every
430
+ supported use; the only way to notice it is hand-constructing a `CalendarCellPos` literal in
431
+ TypeScript, which now needs a `date`.
432
+
433
+ - 4a43cc0: `<lr-heatmap>`: `HeatmapLegendStop.color` is now optional, so a `legendStops` entry can be a
434
+ **caption-only** stop. A stop with no `color` (or an empty-string `color`) renders its
435
+ `[part="legend-stop-label"]` with **no `[part="legend-swatch"]` element in the DOM at all**, rather
436
+ than an empty 0.6rem swatch box — the shape a GitHub-style "Less ▢▢▢▢ More" key needs for the bare
437
+ captions bracketing its colored ramp. Colored stops are unchanged, and an all-colored `legendStops`
438
+ array renders exactly as before.
439
+
440
+ The trailing `valueLabel` caption that closes the legend row also gained
441
+ `part="legend-value-label"` (it was the one unaddressable node in `[part='legend']`), in both the
442
+ gradient and the `legendStops` branch. Nothing else in the legend markup changed.
443
+
444
+ - 4a43cc0: `<lr-heatmap>` gained `maxCellSize` (`max-cell-size`) and `minCellSize` (`min-cell-size`), bounding
445
+ the cell size `fit-to-width` derives from the host's measured width in **both** calendar and matrix
446
+ mode. Without a ceiling, a 5-week calendar or a 3-column matrix in a wide pane inflates into a few
447
+ giant blocks; without a raisable floor, a year-long calendar in a narrow pane collapses onto the
448
+ built-in 4px minimum.
449
+
450
+ Both are ignored while `fit-to-width` is unset — an explicit `cell-size` is an exact request and is
451
+ never clamped — and both default to unset, so an untouched consumer's geometry is byte-identical.
452
+ `min-cell-size` can only raise the built-in 4px floor, never lower it; when both are set and
453
+ `max-cell-size < min-cell-size` the ceiling wins. A non-finite or empty attribute means unset rather
454
+ than `0`.
455
+
456
+ Note that the canvas is sized from the _clamped_ cell size, so a capped grid leaves the host's
457
+ remaining width unfilled instead of stretching to it — align it with normal CSS on the host.
458
+
459
+ - 068cb85: `lr-icon-button` hosts natural-aspect-ratio content
460
+
461
+ The default slot is now rendered as a **sibling** of the built-in glyph instead of being piped
462
+ through `<lr-icon>`, and `<lr-icon>` is mounted only when `icon` is set. The button box is also
463
+ floored with `min-inline-size`/`min-block-size: var(--lr-icon-button-size)` instead of being pinned
464
+ to it, matching that token's documented contract (a minimum tappable box, not a fixed size).
465
+
466
+ Slotted content previously went through `lr-icon`'s node-cloning path, which rebuilds every
467
+ assigned node with `document.createElementNS('http://www.w3.org/2000/svg', localName)` — a slotted
468
+ custom element such as `<lr-flag>` became an SVG-namespaced element that never upgraded and never
469
+ painted. It now renders normally, at its own aspect ratio.
470
+
471
+ **Migration.** Slotted **bare SVG geometry** (`<path>`, `<circle>`, …) with no `icon` attribute
472
+ relied on the removed `<lr-icon>` wrapper to supply an SVG parent, and must now be wrapped
473
+ explicitly:
474
+
475
+ ```html
476
+ <!-- before -->
477
+ <lr-icon-button aria-label="Star"><path d="…"></path></lr-icon-button>
478
+ <!-- after -->
479
+ <lr-icon-button aria-label="Star"
480
+ ><lr-icon path="…"></lr-icon
481
+ ></lr-icon-button>
482
+ ```
483
+
484
+ A complete element — an `<svg>`, an `<img>`, an `<lr-flag>` — keeps working, renders more reliably,
485
+ and is no longer constrained to a 1:1 box: content larger than `--lr-icon-button-size` now grows the
486
+ button and keeps its own aspect ratio, while a small glyph still pads out to the full tappable
487
+ target on both axes.
488
+
489
+ - 9ed6aa8: Add component-scoped state-styling cssprops to eight layout/forms components, so a selected/active/current state can be restyled from outside without hijacking a library-wide `--lr-color-*` token (which repaints everything else reading it). `::part(x)[state]` is invalid CSS — an attribute selector cannot follow `::part()` — so hijacking the shared token used to be the only lever. Each new prop is an inline `var()` fallback (never declared on `:host`, which would re-stamp per instance and shadow any ancestor value), and every default is the exact token the rule used before, so an unset consumer renders byte-identically.
490
+
491
+ - `lr-app-rail-item`: `--lr-app-rail-item-current-bg`, `--lr-app-rail-item-current-color` for the `active`/`aria-current="page"` item.
492
+ - `lr-stepper`: `--lr-stepper-current-color`, `--lr-stepper-error-color`, `--lr-stepper-current-index-bg`, `--lr-stepper-current-index-color`.
493
+ - `lr-widget`: `--lr-widget-view-toggle-active-bg`, `--lr-widget-view-toggle-active-color` for the pressed view toggle.
494
+ - `lr-carousel`: `--lr-carousel-indicator-current-bg`, `--lr-carousel-indicator-current-border-color` for the current slide's indicator dot.
495
+ - `lr-breadcrumb-item`: `--lr-breadcrumb-current-color` for the current-page item.
496
+ - `lr-command-palette`: `--lr-command-palette-active-bg` for the active command row.
497
+ - `lr-time-range`: `--lr-time-range-preset-active-bg`, `--lr-time-range-preset-active-border-color`, `--lr-time-range-preset-active-color` for the active preset button.
498
+ - `lr-emoji-picker`: `--lr-emoji-picker-active-bg` for the keyboard-active and hovered emoji (both share one rule, so one hook retints both).
499
+
500
+ - cea6d8e: New `localeNativeName(tag)` helper next to `languageToCountry()` / `LANGUAGE_TO_COUNTRY`: it returns
501
+ a locale's endonym — its name written in that locale itself (`'fr'` → `français`, `'pt-BR'` →
502
+ `português (Brasil)`) — which is what a language switcher should list. It reads through the shared
503
+ memoized `Intl.DisplayNames` cache, so no name table ships and repeat lookups are free, and it
504
+ degrades to the tag itself for an unknown or structurally invalid tag instead of throwing. Paired
505
+ with `languageToCountry()` and `lr-popover`, it composes the locale-picker recipe shown in the new
506
+ Flag story.
507
+ - 184bfff: `lr-menu`: Escape from `header`/`footer` content closes the menu and refocuses the trigger
508
+ unconditionally, with no opt-in required.
509
+
510
+ That matches `<lr-popover>`, which already dismisses on Escape from arbitrary popup content, and it
511
+ is the only sensible contract for a region the component now positively invites you to fill: a
512
+ filter field you can Tab into but not Escape out of is a trap.
513
+
514
+ - `closeOnEscapeAnywhere` is **unchanged** — not deprecated, still `false` by default, and still
515
+ governing exactly one thing: Escape from non-item content slotted into the **default** slot.
516
+ Escape bubbling up from inside `[part='list']` is left entirely to the list's own handler.
517
+ - Arrow/ArrowUp/Home/End/Enter/Space from header/footer content keep their full native behavior;
518
+ the item-target gate that guarantees that is untouched, and nothing in the new region handler
519
+ calls `preventDefault()` for those keys.
520
+
521
+ - 184bfff: `lr-menu`: new `header` and `footer` slots for composed, non-menu-item content, rendered inside
522
+ `[part='popup']` but **outside** the `role="menu"` list — with matching `header`/`footer` CSS parts.
523
+
524
+ A filter field, a section title, an "Apply"/"Done" button and friends have always been a real use
525
+ case for this component (`closeOnEscapeAnywhere` exists for exactly that), but the only place to put
526
+ them was the default slot — i.e. inside `role="menu"`, where ARIA permits only
527
+ `menuitem`/`menuitemradio`/`menuitemcheckbox`/`group`/`separator` children. Anything else there is an
528
+ `aria-required-children` violation. The new slots give that content a valid home.
529
+
530
+ - Nothing about the default slot changes: item discovery, roving tabindex, type-ahead,
531
+ `closeOnEscapeAnywhere` and its `false` default all behave exactly as before, and `items` still
532
+ only ever contains `<lr-menu-item>`s no matter what the new slots hold.
533
+ - With neither slot filled the rendered result is unchanged — both wrappers collapse to no box at
534
+ all, `[part='list']` keeps its exact position and size inside the popup, and the host gains no
535
+ attribute of any kind.
536
+ - Emptiness is tracked from each slot's own `slotchange` (reflected as `data-has-header` /
537
+ `data-has-footer` / `data-list-empty` on the host) rather than with `:empty`, which can never match
538
+ a part that contains a slot: Chromium counts the whitespace-only text nodes Lit leaves there.
539
+ - Non-item content in the **default** slot keeps working exactly as it did, with no runtime warning,
540
+ but the new slots are now the supported place for it.
541
+
542
+ - 184bfff: `lr-menu`: Tab now moves focus into the `header`/`footer` regions instead of closing the menu, and
543
+ tabbing out of the popup's last focusable finally closes it.
544
+
545
+ Two halves of the same defect. `onListKeyDown` gated every key except Escape behind "is the event
546
+ target a real `<lr-menu-item>`?", so (a) Tab from an item always closed the menu — you could never
547
+ Tab _into_ composed content, in either direction, since Shift+Tab is `key === 'Tab'` too — and
548
+ (b) Tab from composed content did nothing at all: focus walked out of the popup while the menu
549
+ stayed open, an untested dismissal hole.
550
+
551
+ Tab handling therefore moves from `[part='list']` to `[part='popup']`, which also sees keydowns from
552
+ the new regions, and the menu now closes only when Tab would leave the popup entirely:
553
+
554
+ - Tab from an item with a focusable `footer` (or Shift+Tab with a focusable `header`) keeps the menu
555
+ open and lets the browser's own Tab advance carry focus into the region.
556
+ - Tab out of the last focusable in the popup — in either direction, from an item or from composed
557
+ content — closes the menu.
558
+ - **With no header/footer content, Tab closes exactly as before**, and non-item content in the
559
+ default slot stays deliberately Tab-unreachable from an item.
560
+ - `preventDefault()` is still never called for Tab, in any branch: native focus navigation proceeds
561
+ untouched, only the now-stale open state is cleared.
562
+
563
+ - fe06b7d: `lr-menu`: `show(focus?)` and `hide(options?)` are now public.
564
+
565
+ - `hide({ focusTrigger: true })` closes the menu **and** returns DOM focus to the `trigger`-slotted
566
+ element — the case the trigger alone cannot express, e.g. a slotted "Apply"/"Done" button inside
567
+ the menu, or a consumer-owned keyboard shortcut. `hide()` on its own closes without moving focus,
568
+ for dismissals where the interaction has already put focus somewhere the user chose.
569
+ - `show()` is promoted alongside it (rather than shipping an asymmetric API) and still accepts the
570
+ `'first' | 'last'` initial focus target.
571
+ - The roving-tabindex reset moved from `hide()` into `updated()`, so a bare `el.open = false` from
572
+ outside now resets `activeIndex` too. Previously that path left a stale `tabindex="0"` tab stop on
573
+ whichever item was last active, so Tab could land inside a closed menu. `hide()` stays thin and
574
+ `updated()` remains the single owner of positioning, listeners and the `lr-show`/`lr-hide` events;
575
+ focus restoration deliberately stays in `hide()` so `disconnectedCallback()`'s own `open = false`
576
+ teardown reset can never steal focus.
577
+
578
+ - 09bdfde: `lr-activity-feed`: make the virtualized entry rows actually styleable, by this component and by a
579
+ consumer.
580
+
581
+ At/above `virtualizeThreshold` the entries are produced by this component's `renderItem` but
582
+ committed into the embedded `<lr-virtual-list>`'s own shadow root, one boundary deeper than a
583
+ `[part='entry']` selector can reach — so every entry, icon, text and timestamp rule was silently
584
+ inert and a long feed rendered as unstyled rows. Each rule now pairs its plain selector (still
585
+ correct below the threshold, where the same template renders into this component's own shadow root)
586
+ with an `lr-virtual-list::part(…)` twin, and an `exportparts` forwarding declaration makes the same
587
+ parts reachable as `lr-activity-feed::part(entry)` etc. from a consuming stylesheet.
588
+
589
+ The tone dot is promoted from an internal class to a named `tone-dot` part, since a class selector
590
+ cannot cross a shadow boundary either. `::part()` cannot be followed by an attribute selector, so
591
+ the tone carries a second name in the dot's part list rather than being matched through
592
+ `[data-tone]` (`::part()` matches with `part~=` semantics, so both names select the same element).
593
+ New parts: `tone-dot`, plus `tone-dot-neutral`/`tone-dot-brand`/`tone-dot-success`/
594
+ `tone-dot-warning`/`tone-dot-danger`. The `data-tone` attributes are unchanged, and a consumer can
595
+ now retint a single tone instead of overriding a library-wide color token.
596
+
597
+ - 9150bb1: `lr-archive-viewer`: make the virtualized entry rows actually styleable, by this component and by a
598
+ consumer.
599
+
600
+ Entry rows are produced by this component's `renderItem` but committed into the embedded
601
+ `<lr-virtual-list>`'s own shadow root, one boundary deeper than a `[part='entry']` selector can
602
+ reach — so all five row-level rules were silently inert and the listing rendered as unstyled stacked
603
+ text with no row layout, no icon sizing, no truncation and no size column treatment. They now reach
604
+ through `lr-virtual-list::part(…)`, and an `exportparts` forwarding declaration makes the same parts
605
+ reachable as `lr-archive-viewer::part(entry)` etc. from a consuming stylesheet.
606
+
607
+ New part `entry-name-dir`: `::part()` cannot be followed by a descendant combinator, so the
608
+ directory-row emphasis that used to be written as a descendant selector now targets a second part
609
+ name on the name element itself. A directory row's name is `part="entry-name entry-name-dir"`, and
610
+ `::part()` matches with `part~=` semantics, so both names select it.
611
+
612
+ - 3e171e6: Fix `lr-av-player`'s transcript cue styling never applying, and make every cue-level part reachable
613
+ from a consumer stylesheet.
614
+
615
+ Cues are composed through `lr-virtual-list`, whose `renderItem` result is committed inside that
616
+ element's **own** shadow root — one boundary below the player's. A bare `[part='cue']` selector in
617
+ the player's stylesheet cannot cross that boundary, so every cue rule was silently inert and each
618
+ transcript row fell back to the raw browser button appearance: a grey background, a visible border,
619
+ `1px 6px` padding and centered text, with no timestamp or speaker treatment and no visual state for
620
+ the playing cue or the search matches. Every one of those rules now goes through
621
+ `lr-virtual-list::part(…)`.
622
+
623
+ `::part()` cannot be followed by an attribute selector, so the three cue states get their own part
624
+ names, added alongside `cue` as a part list (`::part()` carries `part~=` semantics, so both names
625
+ match the same element):
626
+
627
+ - **New:** `cue-current` — the row the playhead is inside.
628
+ - **New:** `cue-match` — a row matching the current search query.
629
+ - **New:** `cue-active-match` — the row holding the current search match.
630
+
631
+ The `aria-current`, `data-match` and `data-active-match` attributes are unchanged and still describe
632
+ each row's state.
633
+
634
+ This also makes two documented custom properties live for the first time:
635
+ `--lr-av-player-cue-current-bg` now retints the playing cue, and
636
+ `--lr-av-player-cue-active-match-color` now recolors the active search match's outline. Both
637
+ previously resolved against a rule that never matched anything.
638
+
639
+ The player forwards `cue`, `cue-current`, `cue-match`, `cue-active-match`, `cue-time`, `cue-speaker`
640
+ and `cue-text` through `exportparts`, so `lr-av-player::part(cue)` and friends work from a consumer
641
+ stylesheet for the first time.
642
+
643
+ - c0f00ac: `lr-csv-viewer` and `lr-spreadsheet-viewer`: make the documented `cell-highlight` part actually
644
+ visible, and reachable from a consumer stylesheet.
645
+
646
+ Both viewers already emitted `part="cell cell-highlight"` for a cell covered by a `highlights`
647
+ entry, but neither had a single CSS rule for it anywhere — a highlighted cell rendered
648
+ indistinguishably from a plain one. Highlighted cells render inside the internal
649
+ `<lr-virtual-list>`'s own shadow root (they are `renderItem`'s output), so the styling is applied
650
+ through `lr-virtual-list::part(cell-highlight)`, using the same outline tokens `lr-dataset-viewer`
651
+ gives its own `cell-highlight` so a highlight reads identically across the table viewers.
652
+
653
+ - New `--lr-csv-viewer-highlight-color` / `--lr-spreadsheet-viewer-highlight-color` custom
654
+ properties (default `var(--lr-color-brand)`) set the outline color; the active highlight sets it
655
+ inline to `var(--lr-color-warning, var(--lr-color-brand))`, so the active match is now
656
+ distinguishable from the other highlighted cells.
657
+ - A paired `:focus-visible` rule restores the shared focus ring, which the unconditional highlight
658
+ outline would otherwise swallow on this focusable cell.
659
+ - Both viewers now forward `exportparts` for `data-row`, `cell` and `cell-highlight` from the
660
+ internal `<lr-virtual-list>`, so `lr-csv-viewer::part(cell)` and friends reach the real rendered
661
+ rows instead of matching nothing.
662
+
663
+ - 99d5500: Fix `lr-chunk-inspector`'s entire chunk-row styling never applying above `virtualize-at`, and make
664
+ every row-level part reachable from a consumer stylesheet.
665
+
666
+ Past the threshold the row template becomes `lr-virtual-list`'s `renderItem`, whose result is
667
+ committed inside that element's **own** shadow root — one boundary below this component's. A bare
668
+ `[part='chunk']` selector cannot cross that boundary, so a long chunk list lost its row layout and
669
+ separators, the score line's size/color/tabular figures, the score bar and its tone-mapped fill, the
670
+ line clamp on the collapsed text preview, and the borderless brand styling on the open and
671
+ show-more buttons, which fell back to the raw browser button appearance. Both documented custom
672
+ properties (`--lr-chunk-inspector-current-bg`, `--lr-chunk-inspector-current-color`) were dead
673
+ there too. Every rule now pairs its original selector with an `lr-virtual-list::part(…)` arm, so
674
+ both rendering paths present identically — below the threshold the rows are still rendered into this
675
+ component's own shadow root, where the bare selector is the one that matches.
676
+
677
+ `::part()` cannot be followed by an attribute selector, and it cannot be followed into the matched
678
+ element's subtree either, so row state is now carried by an additional part name (added alongside
679
+ the base name as a part list — `::part()` carries `part~=` semantics, so both names match the same
680
+ element):
681
+
682
+ - **New:** `chunk-current` — the row matching `activeId`.
683
+ - **New:** `score-current` — that row's score line, previously reached through a descendant
684
+ selector no `::part()` can express.
685
+ - **New:** `score-fill-success`, `score-fill-warning`, `score-fill-danger` — the score bar fill in
686
+ each scoring tier.
687
+ - **New:** `text-clamped` — the text preview while still collapsed.
688
+
689
+ The `aria-current`, `data-tone` and `data-clamped` attributes are unchanged and still describe each
690
+ element's state.
691
+
692
+ While virtualized, the chunk row no longer carries its own `role="listitem"`: `lr-virtual-list`
693
+ already wraps every row it renders in one, and the nested duplicate left the inner list item with a
694
+ list-item rather than list parent — an invalid ARIA containment that axe flags.
695
+
696
+ The internal `lr-virtual-list` now forwards every row part through `exportparts`, so
697
+ `lr-chunk-inspector::part(chunk)` and friends work from a consumer stylesheet in both paths.
698
+
699
+ - 5bdb6d7: Fix `lr-notebook-viewer`'s cell and output styling never applying, and make every cell-level part
700
+ reachable from a consumer stylesheet.
701
+
702
+ Cells are composed through `lr-virtual-list`, whose `renderItem` result is committed inside that
703
+ element's **own** shadow root — one boundary below the viewer's. A bare `[part='cell']` selector in
704
+ the viewer's stylesheet cannot cross that boundary, so the rules for `cell`, `cell-gutter`,
705
+ `outputs`, `output` and `output-toggle` were all silently inert: cells rendered without their
706
+ two-column grid, padding and separator, the execution-count gutter without its monospace/quiet
707
+ treatment, stderr and error outputs untinted, and the show-all-output control as a raw browser
708
+ button. Every one of those rules now goes through `lr-virtual-list::part(…)`, including the
709
+ narrow-allocation `@container` block — container queries resolve through the flat tree, so they
710
+ still evaluate against the viewer's own `:host` container across the shadow boundary.
711
+
712
+ `::part()` cannot be followed by an attribute selector or a descendant combinator, so three states
713
+ and one descendant get their own part names, added alongside the existing ones as a part list
714
+ (`::part()` carries `part~=` semantics, so both names match the same element):
715
+
716
+ - **New:** `cell-active` — the cell an anchor currently targets. This is what
717
+ `--lr-notebook-viewer-active-bg` retints; that custom property had no effect until now.
718
+ - **New:** `output-error` — a stderr stream or an error output, carrying the danger tint.
719
+ - **New:** `error-output-label` — the label introducing an error output's traceback.
720
+
721
+ The `data-active`, `data-stream` and `data-output-type` attributes are unchanged and still describe
722
+ each element for scripting.
723
+
724
+ The viewer forwards `cell`, `cell-active`, `cell-gutter`, `cell-source`, `outputs`, `output`,
725
+ `output-error`, `error-output-label` and `output-toggle` through `exportparts`, so
726
+ `lr-notebook-viewer::part(cell)` and friends work from a consumer stylesheet for the first time.
727
+
728
+ - 2e3be2e: `lr-page-rail`: make the virtualized page rows actually styleable, by this component and by a
729
+ consumer.
730
+
731
+ Page rows are produced by this component's `renderItem` but committed into the embedded
732
+ `<lr-virtual-list>`'s own shadow root, one boundary deeper than a `[part='page']` selector can
733
+ reach — so all 13 row-level rules were silently inert and every page button rendered as a raw
734
+ browser `<button>` (UA background, UA border, UA padding) instead of the intended rail row. They now
735
+ reach through `lr-virtual-list::part(…)`, and an `exportparts` forwarding declaration makes the same
736
+ parts reachable as `lr-page-rail::part(page)` etc. from a consuming stylesheet.
737
+
738
+ `--lr-page-rail-current-bg` becomes live with this fix: it previously documented a background that
739
+ nothing applied. It now tints the current page row, and keeps it tinted while the row is hovered so
740
+ the current page stays identifiable under the pointer.
741
+
742
+ `::part()` cannot be followed by an attribute selector, so state variants carry a second part name
743
+ in the element's part list instead (`::part()` matches with `part~=` semantics, so both names select
744
+ the same element). New parts: `page-current` on the current page button (alongside `page`), and
745
+ `heat-dot-accent`/`heat-dot-success`/`heat-dot-warning`/`heat-dot-danger`/`heat-dot-neutral`/
746
+ `heat-dot-overflow` on the heat markers (alongside `heat-dot`). The `data-tone`/`data-overflow`
747
+ attributes are unchanged.
748
+
749
+ - 3217988: Fix `lr-pdf-viewer`'s page styling never applying, and make every page-level part reachable from a
750
+ consumer stylesheet.
751
+
752
+ Pages are composed through `lr-virtual-list`, whose `renderItem` result is committed inside that
753
+ element's **own** shadow root — one boundary below the viewer's. A bare `[part='page']` selector in
754
+ the viewer's stylesheet cannot cross that boundary, so the rules for `page`, `text-layer`, the page
755
+ canvas, the generated text runs, the selection tint, and both search-match states were all silently
756
+ inert: pages rendered without their centering/padding wrapper, the canvas without its border,
757
+ the text layer unpositioned, and search matches unhighlighted. Every one of those rules now goes
758
+ through `lr-virtual-list::part(…)`, including the RTL text-layer mirror.
759
+
760
+ Because `::part()` cannot be followed by a descendant combinator, two elements that were previously
761
+ addressed as descendants get their own names:
762
+
763
+ - **New:** `page-canvas` — the canvas a page's content is painted onto.
764
+ - **New:** `text-span` — one generated text run inside a page's text layer. The selection tint hangs
765
+ off this part (`::part(text-span)::selection`), since a highlight pseudo is matched against the
766
+ element the selected text originates in.
767
+
768
+ `search-match` / `search-match-active` are now matched directly by name (`::part()` already carries
769
+ `part~=` semantics), and the viewer forwards `page`, `page-canvas`, `text-layer`, `text-span`,
770
+ `search-match` and `search-match-active` through `exportparts`, so `lr-pdf-viewer::part(page)` and
771
+ friends work from a consumer stylesheet for the first time.
772
+
773
+ - 6f3db46: Fix `lr-retrieval-results`' row, selection and metadata styling never applying while virtualized,
774
+ and make every row-level part reachable from a consumer stylesheet.
775
+
776
+ Rows are composed through `lr-virtual-list`, whose `renderItem` result is committed inside that
777
+ element's **own** shadow root — one boundary below this component's. A bare `[part='row-body']`
778
+ selector in this component's stylesheet cannot cross that boundary, so the checkbox offset, the
779
+ row-body layout, the selected-row indicator and the whole metadata list were silently inert
780
+ whenever the list virtualized. `grouping="source"` always virtualizes, so every grouped consumer
781
+ saw an unstyled result set, and the documented `--lr-retrieval-results-selected-border` custom
782
+ property had nothing to recolor there. Each of those rules now pairs its original selector with an
783
+ `lr-virtual-list::part(…)` arm, so both rendering paths present identically — the flat path below
784
+ `virtualize-at` still renders these parts into this component's own shadow root, where the bare
785
+ selector is the one that matches.
786
+
787
+ `::part()` cannot be followed by an attribute selector, nor by a descendant combinator, so two
788
+ kinds of rule needed new part names:
789
+
790
+ - **New:** `row-body-selected` — added alongside `row-body` as a part list (`::part()` carries
791
+ `part~=` semantics, so both names match the same element) on the selected row. The `data-selected`
792
+ attribute is unchanged and still describes the row's state.
793
+ - **New:** `metadata-term` and `metadata-value` — the `<dt>`/`<dd>` inside a `metadata-entry`,
794
+ previously styled through a descendant selector that `::part()` cannot express. The trailing colon
795
+ after a metadata key is now `::part(metadata-term)::after`.
796
+
797
+ The group header in grouped mode also gains a separator matching the one this component's rows use;
798
+ `lr-virtual-list` supplies the rest of its appearance.
799
+
800
+ `exportparts` now forwards `select`, `row-body`, `row-body-selected`, `metadata`, `metadata-entry`,
801
+ `metadata-term` and `metadata-value` alongside the existing `row`/`group-header`, and forwards each
802
+ per-row `lr-chunk-inspector`'s own parts onward under a `chunk-` prefix (`chunk`, `chunk-current`,
803
+ `chunk-score`, `chunk-score-current`, `chunk-score-bar`, `chunk-score-fill`,
804
+ `chunk-score-fill-success`/`-warning`/`-danger`, `chunk-open-button`, `chunk-title`, `chunk-text`,
805
+ `chunk-text-clamped`, `chunk-toggle`) — those live two shadow hops deep and were unreachable from
806
+ outside the component entirely.
807
+
808
+ - 583f359: `lr-phone-input`: rebuild the country selector's closed state and add an opt-in `flags` API.
809
+
810
+ The old closed control was the bare native `<select>` showing each option's full
811
+ `"Country name (+code)"` text: long localized names clipped under the UA chevron (the trigger was
812
+ capped at 45% of the field), the calling code appeared twice (inside the option text and again in
813
+ `calling-code`), and the popup fell back to UA colors (a white panel in dark themes). The native
814
+ `<select>` is kept — its popup, localized full country names, keyboard type-ahead, and native
815
+ mobile pickers are irreplaceable and fully accessible — but it is now stretched invisibly over a
816
+ compact decorative trigger:
817
+
818
+ - New closed state: selected alpha-2 code (localized "Select" placeholder when no countries exist)
819
+ plus the shared design-system chevron, with a pointer cursor, a hover tint, and an inner
820
+ focus-visible ring so keyboard focus on the selector is distinguishable from focus on the
821
+ telephone input. No more clipping and no duplicated calling code.
822
+ - Popup options now pin `--lr-color-surface`/`--lr-color-text` so the open list follows the theme
823
+ in dark mode.
824
+ - New `flags` boolean attribute renders the selected country's flag in the trigger as
825
+ `<lr-flag variant="compact" aria-label="">` (decorative — the select already announces the
826
+ country). The `<lr-flag>` definition is registered lazily on first use, so nothing flag-related
827
+ is bundled while `flags` stays off; flag artwork keeps the standalone `<lr-flag>` contract
828
+ (install optional `@aceshooting/lyra-flags` + import
829
+ `components/media/flag/flag-peer.js` once). Without it the trigger simply omits the image.
830
+ - New CSS parts: `country` (selector region), `country-trigger`, `flag`, `country-code`
831
+ (`data-placeholder` when empty), `expand-icon`. Existing parts are unchanged in name, but
832
+ `country-select` is now the invisible overlay — a consumer rule that painted its text/background
833
+ should target `country-trigger`/`country-code` instead.
834
+
835
+ - e83deb1: Selected-state styling hooks for `lr-segmented` and `lr-tabs`, an exact-height hatch for the
836
+ `lr-segmented` track, and a marker legend row for `lr-sequence-strip`.
837
+
838
+ - `lr-segmented` gains `--lr-segmented-selected-bg`, `--lr-segmented-selected-color`,
839
+ `--lr-segmented-selected-font-weight`, `--lr-segmented-selected-shadow` and
840
+ `--lr-segmented-hover-color`. Recoloring the checked pill previously required hijacking
841
+ library-wide `--lr-color-surface`/`--lr-color-text`, which necessarily repainted hovered
842
+ _unselected_ segments too (they read the same tokens); `::part(segment)[aria-checked='true']` is
843
+ not valid CSS, so there was no other route. The hover color is now its own hook, so the two states
844
+ are independent.
845
+ - `lr-segmented` also gains `--lr-segmented-track-height`, pinning the track to an exact height at
846
+ every `size` tier for a row that must line up with a hard-sized toolbar control. It is genuinely
847
+ unset by default, so each tier keeps its `--lr-segmented-track-min-height` floor until you set it.
848
+ - `lr-tabs` gains `--lr-tabs-selected-color`, `--lr-tabs-indicator-color` and
849
+ `--lr-tabs-hover-color` for the same reason: the selected tab's text/underline and the hovered
850
+ tab's text no longer share `--lr-color-brand`/`--lr-color-text` with the rest of the library.
851
+ - `lr-sequence-strip` gains `markerLabel` (`marker-label`). When set alongside `show-legend` it adds
852
+ one trailing legend row — `[part="legend-marker-swatch"]`, a neutral chip (themeable via the new
853
+ `--lr-sequence-strip-legend-marker-bg`) carrying the cell's own bottom bar in
854
+ `--lr-sequence-strip-marker-color` — and the marker's count joins the strip's auto-generated
855
+ `aria-label` summary, so the visual legend keeps no entry without a spoken counterpart.
856
+
857
+ Every new custom property is an inline `var()` fallback resolving to the token the rule already
858
+ used, so an unset consumer renders exactly as before.
859
+
860
+ - 36dce60: Fill the sized-control cssprop gaps for `lr-date-input`, `lr-pagination`, `lr-known-date`,
861
+ `lr-chip`, `lr-avatar`, and `lr-avatar-group`, matching the per-tier theming surface
862
+ `lr-input`/`lr-select`/`lr-combobox` already expose.
863
+
864
+ - **`lr-avatar` / `lr-avatar-group` (visible bug fix):** the initials fallback and the "+N"
865
+ overflow badge were painted at a fixed `--lr-font-size-sm` at every `size`, so initials did not
866
+ scale with the avatar circle. They now scale via new per-tier `--lr-avatar-font-size` and
867
+ `--lr-avatar-group-badge-font-size` knobs (`sm`/`md`/`lg`). The `md` default is unchanged, so
868
+ existing avatars render identically.
869
+ - **`lr-date-input`:** adds a per-tier `--lr-date-input-control-min-height` floor and an exact-height
870
+ `--lr-date-input-control-height` hatch on the input row (it previously had neither). The calendar
871
+ toggle keeps its own 24x24 touch target even when the height hatch pins a shorter row.
872
+ - **`lr-known-date`:** adds a per-tier `--lr-known-date-field-min-height` floor and an exact-height
873
+ `--lr-known-date-field-height` hatch on each field input.
874
+ - **`lr-chip`:** the interactive tap-target floor is now the per-tier `--lr-chip-min-height` (was a
875
+ single hardcoded `1.5rem` shared by every tier), and a new `--lr-chip-height` hatch pins an exact
876
+ height. Interactive chips keep the 24px WCAG 2.2 SC 2.5.8 minimum at every tier; a `--lr-chip-height`
877
+ below that is for non-interactive chips only.
878
+ - **`lr-pagination`:** the nav buttons' and page input's inner padding is now the
879
+ `--lr-pagination-control-padding` knob (was a hardcoded `var(--lr-space-xs)`), kept uniform across
880
+ tiers so current rendering is unchanged.
881
+
882
+ All new knobs default to today's exact values, so unset consumers render byte-identical at every
883
+ tier (the `lr-avatar` `sm`/`lg` font-size fix is the sole deliberate exception).
884
+
885
+ - 6ab596d: `<lr-split>`: `rail-breakpoint` and `float-breakpoint` now accept a CSS length (`'640px'`,
886
+ `'68.75rem'`, `'3em'`) as well as the original bare pixel number, and a new
887
+ `collapse-breakpoint-basis="viewport"` measures both against the viewport via `matchMedia` instead
888
+ of the split's own `[part="base"]` allocation — for collapsing in step with a page-level `@media`
889
+ layout. Both thresholds are classified together on every change, so a fast resize crossing both at
890
+ once still lands on one correct state and fires `lr-split-collapse-change` once; under viewport
891
+ basis the first paint already carries the right `data-collapse-state` with no `ResizeObserver`
892
+ round-trip, and that initial state is not announced as a transition. Note `(max-width:)` is
893
+ inclusive while container basis compares strictly `<`, so switching basis shifts each crossing
894
+ point by 1px. An unparseable length (`'80vw'`, `'calc(…)'`, garbage) falls back to the documented
895
+ `640`/`400` defaults rather than switching collapse off, and the "rail must sit above float"
896
+ invariant is still enforced, in pixel space, under both bases.
897
+
898
+ Because both properties now accept a string, they use Lit's default string converter: reading
899
+ `el.railBreakpoint` after `rail-breakpoint="640"` returns `'640'` rather than `640` (matching how
900
+ `orientationBreakpoint` already behaves). Authored values and crossing behavior are unchanged.
901
+
902
+ - e1d4af8: `lr-stat` gains two layout axes and stops reserving space for an absent label.
903
+
904
+ - `appearance="card" | "plain"` (default `card`, reflected). `plain` removes the border,
905
+ background, padding, corner radius and the `block-size: 100%` stretch, so a stat can sit inline
906
+ in prose, a toolbar or a table cell instead of only as a card. A `plain` stat with a safe `href`
907
+ underlines its `[part="value"]` on hover/focus, since the card's border-color-shift affordance is
908
+ invisible with no border; the focus ring is unchanged. `plain` also wins over `compact` when both
909
+ are set, and drops `emphasis`'s accent edge (card chrome) while keeping its brand value tint.
910
+ - `orientation="vertical" | "horizontal"` (default `vertical`, reflected). `horizontal` lays label,
911
+ value + unit, trend, sub and caption out on a single wrapping baseline row; `[part="spark"]` and
912
+ `[part="rows"]` stay stacked on their own full-width line beneath it.
913
+ - `[part="label"]` is now `hidden` whenever `label` is empty, so a label-less stat no longer leaves
914
+ a blank gap above its value. A non-empty label is never hidden and its `aria-labelledby` pairing
915
+ with `[part="value"]` is unchanged.
916
+
917
+ - 3312708: Add component-scoped CSS custom properties for state styling across thirteen conversation, retrieval, viewer and media components. Each of these components previously painted a selected/active/current state straight from a library-wide `--lr-color-*` token, which left the state unrestylable from outside: `::part(x)[data-active]` is invalid CSS, so the only lever was hijacking the shared token — repainting every other surface on the page that read it.
918
+
919
+ Every new property uses the inline `var()` fallback form and is deliberately **not** declared on `:host`, so a value set on the element or any ancestor is honoured rather than shadowed. With none of them set, rendering is byte-identical to before.
920
+
921
+ - `lr-conversation-item` — `--lr-conversation-item-active-bg`, `--lr-conversation-item-active-color`
922
+ - `lr-push-to-talk` — `--lr-push-to-talk-recording-color`
923
+ - `lr-chunk-inspector` — `--lr-chunk-inspector-current-bg`, `--lr-chunk-inspector-current-color`
924
+ - `lr-retrieval-results` — `--lr-retrieval-results-selected-border`
925
+ - `lr-retrieval-trace` — `--lr-retrieval-trace-active-border`
926
+ - `lr-source-picker` — `--lr-source-picker-checked-bg`, `--lr-source-picker-checked-border`, `--lr-source-picker-mixed-bg`
927
+ - `lr-page-rail` — `--lr-page-rail-current-bg`
928
+ - `lr-notebook-viewer` — `--lr-notebook-viewer-active-bg`
929
+ - `lr-svg-viewer` — `--lr-svg-viewer-active-border`
930
+ - `lr-document-preview` — `--lr-document-preview-active-border`
931
+ - `lr-xml-viewer` — `--lr-xml-viewer-active-match-color`
932
+ - `lr-av-player` — `--lr-av-player-marker-active-color`, `--lr-av-player-cue-current-bg`, `--lr-av-player-cue-active-match-color`
933
+ - `lr-image-viewer` — `--lr-image-viewer-annotate-active-bg`, `--lr-image-viewer-annotate-active-border`, `--lr-image-viewer-highlight-active-color`
934
+
935
+ `--lr-conversation-item-active-*` and `--lr-chunk-inspector-current-*` are documented as contrast-sensitive pairs: each background is half of a WCAG-AA dependency with the text color rendered on it.
936
+
937
+ Also fixes a WCAG-AA contrast failure in `lr-chunk-inspector`: the current (`active-id`) chunk's score line rendered in `--lr-color-text-quiet`, which reaches only ~4.24:1 against the `--lr-color-brand-quiet` current-row background — under the 4.5:1 floor for normal-size text. It now uses full-strength text while current, matching the identical fix already carried by `lr-attachment-chip`, `lr-chat-message` and `lr-conversation-item`. Non-current rows keep the quiet treatment.
938
+
939
+ - 5e9a18e: `lr-table`: keep focus inside a persistent (`editable: 'always'`) cell editor when the rows are
940
+ re-sorted underneath it. Row rendering is keyed by row key, so a re-sort _moves_ the editor's
941
+ `<input>` node — the typed value rides along, but a DOM move drops focus on its own — so the table
942
+ now records the focused editor's cell and restores focus to it after the move. A row that has left
943
+ the rendered set entirely (paginated away, filtered out) only clears the record: focus is not yanked
944
+ to whichever unrelated row now occupies that position.
945
+ - 5e9a18e: `lr-table`: give a persistent (`editable: 'always'`) cell editor its own Enter/Escape semantics.
946
+ Enter commits and keeps focus in the field rather than closing an editor that has no closed state,
947
+ and Escape — which has nothing to cancel back to — is no longer cancelled, so an ancestor
948
+ dialog/popover still acts on it. A double-click editor's Enter-commits-and-closes and
949
+ Escape-cancels behavior is unchanged. Adds the accompanying `AlwaysOnEditors` story.
950
+ - 5e9a18e: `lr-table`: widen `TableColumn.editable` to `boolean | 'always'`. `true` keeps today's
951
+ double-click-to-open editor unchanged; the new `'always'` renders a persistent editor in every body
952
+ cell of that column from first paint, for settings/rate-style grids where double-clicking each cell
953
+ to change a value is the wrong interaction. Persistent editors are plain tab stops (no `tabindex` of
954
+ their own), exactly like the existing row-expand toggle, so the roving header/row tabindex model is
955
+ untouched; each one keeps its individually interpolated `tableEditCell` accessible name, and
956
+ double-clicking an `'always'` cell no longer opens a second, competing editor inside it.
957
+ - 5e9a18e: `lr-table`: a persistent (`editable: 'always'`) cell editor binds its `value` as a content attribute
958
+ rather than as the `.value` property, so native dirty-value-flag semantics apply — an out-of-band
959
+ `rows` update to a cell the user has already typed into no longer replaces the draft they are still
960
+ editing, while an untouched editor still picks up a new `rows` value normally. Double-click editors
961
+ (`editable: true`) keep the property binding and its deliberate re-assert, unchanged. `lr-cell-edit`
962
+ remains the only mutation channel; the table still never mutates `row`.
963
+ - 43ee7d0: `lr-table`: the empty state is now addressable, cells can carry a native tooltip, `table-layout` is
964
+ settable, and the selected row has its own background custom property.
965
+
966
+ - Every built-in `<lr-empty>` the table renders carries `part="empty"` and re-exports its own inner
967
+ parts as `empty-base`/`empty-icon`/`empty-heading`/`empty-description`/`empty-actions`, so the
968
+ empty state can be restyled from outside without replacing it. Note that the no-columns and
969
+ no-rows states return the empty element as the shadow root's own root, so `::part(base)` does not
970
+ apply in those two states — only in the filtered-to-zero one.
971
+ - A new `empty` slot replaces the built-in empty state wholesale on the two _data_-empty branches
972
+ (no rows at all, and filtered/paginated down to zero). The no-columns branch keeps its own
973
+ `noColumnsHeading` copy and is deliberately not slot-replaceable — it reports a configuration
974
+ problem, not an empty result set.
975
+ - New `emptyCompact` property (`empty-compact` attribute) overrides the built-in empty state's
976
+ `compact` density. Left unset it preserves today's per-branch behaviour exactly: spacious for the
977
+ whole-table states, compact for the in-table filtered-to-zero one.
978
+ - New `columns[].cellTitle(row)` renders the generated `<td>`'s native `title`, symmetrical with
979
+ `cellStyle`. Returning `undefined` or an empty string omits the attribute entirely rather than
980
+ rendering `title=""`, which would suppress an ancestor's own tooltip, and the attribute is
981
+ suppressed while that cell is in inline-edit mode so the tooltip cannot shadow the editor. Some
982
+ screen readers announce a `<td title>` as the cell's accessible name, so use it only for a longer
983
+ form of what the cell already shows.
984
+ - New `layout: 'auto' | 'fixed' = 'auto'` property (reflected) sets a floor for the table's
985
+ `table-layout`. `fixed` applies the fixed algorithm even with no column widths declared; the
986
+ default `auto` still resolves to fixed whenever a column declares a `width` or a drag-resize is in
987
+ flight, since resizing does not work under `table-layout: auto`. Under `fixed` with no declared
988
+ widths the first row determines every column's width — so revealing a `priority`-hidden column
989
+ re-measures all of them — and `columns[].minWidth`/`maxWidth` are ignored by the fixed algorithm.
990
+ - New `--lr-table-row-selected-bg` custom property (default `var(--lr-color-brand-quiet)`) recolors
991
+ the `aria-selected` row. Shadow Parts forbids an attribute selector after `::part()`, so
992
+ `::part(row)[aria-selected]` is invalid CSS and the selected row could previously only be
993
+ restyled by overriding the library-wide brand-quiet token. Unset, rendering is unchanged.
994
+
995
+ - 437bef5: `lr-table`: add a skeleton loading mode. A new `loadingAppearance: 'spinner' | 'skeleton'`
996
+ property (attribute `loading-appearance`, default `'spinner'` — unchanged output) controls how
997
+ `loading` renders. `'skeleton'` keeps the real `<colgroup>`, `<thead>`, filter field and
998
+ pagination footer in place and fills the table body with placeholder `<lr-skeleton>` rows, so a
999
+ cold load sketches the grid's shape and holds its column geometry instead of collapsing to a
1000
+ spinner and reflowing when the rows arrive. The placeholder row count comes from the new
1001
+ `skeletonRows` property (attribute `skeleton-rows`, default `0` = derive from the normalized
1002
+ `pageSize`, capped at 20, else 3). Exactly one `role="status"` live region announces the load —
1003
+ each placeholder opts out of its own announcement, so there is no per-cell live-region storm. A
1004
+ `priority`-hidden column is given no visible placeholder cell. New `skeleton` CSS part targets the
1005
+ placeholders.
1006
+ - bc8cb8b: Make the focus-ring and icon-button-size tokens themeable from an ancestor, and fill out
1007
+ `theme.css` with the inputs it was missing.
1008
+
1009
+ `--lr-focus-ring-width`, `--lr-focus-ring-offset` and `--lr-icon-button-size` were the only
1010
+ three tokens declared as bare literals instead of chaining through a `--lr-theme-*` input.
1011
+ That made them the only tokens genuinely unreachable for subtree theming: a `--lr-*` token is
1012
+ re-declared on **every** `LyraElement`'s `:host`, so a value set on an ancestor is shadowed at
1013
+ the first intervening lyra host and never reaches anything nested inside it. `--lr-theme-*`
1014
+ inputs are declared only at `:root` (in `theme.css`) and never in component shadow styles, so
1015
+ they _do_ inherit through nested shadow roots — which is why the bridge is the supported route.
1016
+ The three tokens now read `--lr-theme-focus-ring-width`, `--lr-theme-focus-ring-offset` and
1017
+ `--lr-theme-icon-button-size`, with their existing values as fallbacks, so nothing renders
1018
+ differently by default.
1019
+
1020
+ Keep a resolved `--lr-theme-icon-button-size` at or above 24px: it backs the hit area of
1021
+ `lr-date-input`, `lr-combobox`, `lr-input` and `lr-select`, and anything smaller fails
1022
+ WCAG 2.2 SC 2.5.8 (Target Size (Minimum)).
1023
+
1024
+ `src/theme.css` also gains the type scale, spacing scale, stacking layers, chart palette,
1025
+ the 16 ANSI terminal slots, the raised surface and both overlay scrims as real inputs — every
1026
+ one set to the exact value it already fell back to, so importing the sheet changes no computed
1027
+ value. Two fixes came with that:
1028
+
1029
+ - `.lr-dark` never set `--lr-theme-color-surface-raised`, so a `.lr-dark` page rendered raised
1030
+ surfaces at the light `#f6f8fa` while `prefers-color-scheme: dark` rendered them at `#22272e`.
1031
+ The dark block now mirrors the raised surface and the eight chart colors.
1032
+ - `--lr-color-overlay` and `--lr-color-overlay-strong` both read a single
1033
+ `--lr-theme-color-overlay` input, so defining that input flattened the strong scrim's `0.92`
1034
+ onto the plain scrim's value. `--lr-color-overlay-strong` now has its own
1035
+ `--lr-theme-color-overlay-strong` input, chained through the old one so a theme that sets only
1036
+ `--lr-theme-color-overlay` still tints both exactly as before.
1037
+
1038
+ - e9c4f22: `lr-thread-list` forwards a `compact` row density
1039
+
1040
+ A reflected boolean `compact` (default `false`) that sets `compact` on every data-mode row
1041
+ `<lr-conversation-item>`, mirroring how `editable` is already forwarded — the one-attribute way to
1042
+ tighten a whole sidebar, where previously the only lever was styling `::part(row-item-base)` and
1043
+ `::part(row-item-title)` by hand. The density itself lives on the row item; this property only
1044
+ forwards it, so both components stay in sync from one implementation.
1045
+
1046
+ Slotted mode (empty `threads` _with_ real slotted content) is a documented no-op: that mode renders
1047
+ host-supplied `<lr-conversation-item>`s as-is, so the host sets `compact` on its own items there —
1048
+ the same division of responsibility slotted mode already has for every other row property.
1049
+
1050
+ - b9d78b7: `lr-thread-list` now forwards the row `<lr-conversation-item>`'s own CSS parts out of data mode under
1051
+ a `row-item-*` namespace: `row-item-base`, `row-item-option`, `row-item-leading`, `row-item-content`,
1052
+ `row-item-title`, `row-item-title-input`, `row-item-rename-button`, `row-item-excerpt`,
1053
+ `row-item-meta`, `row-item-timestamp` and `row-item-actions`.
1054
+
1055
+ Data mode builds each row itself, two shadow roots down, so until now none of those eleven parts were
1056
+ reachable from outside — including the two declarations that set row height. Row density could only
1057
+ be changed with `lr-thread-list::part(row) { --lr-theme-space-s: … }`, a whole-subtree retheme that
1058
+ also shrank everything nested in the row (a `renderActions` menu's items dropped below the
1059
+ touch-target floor and had to be un-retheme'd inline). `lr-thread-list::part(row-item-base)
1060
+ { padding-block: … }` now sets row density with no token override and no collateral damage.
1061
+
1062
+ The existing `row-leading`/`row-content`/`row-meta`/`row-actions`/`row-wrapper` parts are unchanged;
1063
+ they wrap this component's render-callback output, which is a different surface from the item's own
1064
+ internals. Purely additive: an unstyled thread list renders identically.
1065
+
1066
+ - 9010a89: `lr-thread-list` exposes a `row-wrapper` CSS part around `wrapRow` output.
1067
+
1068
+ `wrapRow` was the one row hook with no library-added part -- `renderLeading`, `renderRowContent`,
1069
+ `renderMeta` and `renderActions` each get a `row-*` wrapper, so a host wrapping a whole row had to
1070
+ thread its own class through the callback to lay it out. Its return value is now placed inside a
1071
+ `part="row-wrapper"` block `<div>`, reachable from outside as `lr-thread-list::part(row-wrapper)`.
1072
+
1073
+ The wrapper is deliberately unstyled and block-level, and is added only when `wrapRow` is set: the
1074
+ box the internal `lr-virtual-list` measures for windowing is its own `[part="row"]` one level up,
1075
+ and an unstyled block box contributes exactly its child's height to it, so measured row heights are
1076
+ unchanged. The part is row-only -- group headers never pass through `wrapRow` and never carry it.
1077
+
1078
+ - 81af4b0: Add `sticky-groups` to `lr-thread-list`: the current date/custom group's header stays pinned to the
1079
+ top of the scroll viewport while its rows are in view, and is pushed off as the next group's header
1080
+ arrives. Group headers are ordinary virtualized rows, so this renders an `aria-hidden` copy into
1081
+ `lr-virtual-list`'s sticky layer — the real row keeps the `role="heading"` semantics and the tab
1082
+ order, while the pinned copy stays clickable and requests the same `lr-group-toggle` collapse. The
1083
+ band is exported as `::part(group-sticky)`, and the copy renders the same
1084
+ `group-header`/`group-toggle`/`group-label`/`group-icon` parts as the real header, so existing
1085
+ header styling applies to both. Default `false` renders exactly as before.
1086
+ - 81af4b0: Remove `lr-thread-list`'s reach into the internal `lr-virtual-list`'s shadow root. Arrowing past the
1087
+ rendered window now scrolls through the child's public `scrollContainer` and waits for its
1088
+ `lr-scroll` notification before moving focus, instead of mutating the scroll position of an element
1089
+ found by querying the child's render root and then dispatching a fabricated `scroll` event at it —
1090
+ which also raced the child's re-render rather than following it. Row lookup goes through a new
1091
+ `lr-virtual-list.renderedRows` accessor (the currently-windowed `[part="row"]` wrappers, in item
1092
+ order), added because a windowed list gives a host no other way to reach a row that may not have
1093
+ existed a frame earlier; `exportparts` forwards styling, not element references.
1094
+ - cea6d8e: `lr-token-input` can now edit a token in place. Set `editable` and each token becomes a roving tab
1095
+ stop that opens an inline editor on click, Enter, or F2: Enter commits and emits
1096
+ `lr-token-edit` with `{ value, previousValue, index }`, Escape reverts silently, and a blur commits
1097
+ without stealing focus back. New `token-label` and `token-editor` CSS parts (rendered only while
1098
+ `editable` is set) and a `--lr-token-input-editor-inline-size` custom property style the two states;
1099
+ with `editable` unset the token row renders exactly as before and stays non-focusable.
1100
+
1101
+ `delimiter` now accepts `null` — as a property, or via `delimiter="none"` / `delimiter=""` — so a
1102
+ token may contain commas verbatim (`Bash(git status:*)`): nothing is split and no keystroke is
1103
+ treated as a commit key. Removing the attribute restores the `,` default, and an empty delimiter no
1104
+ longer explodes a draft into one token per character.
1105
+
1106
+ - 0a5666d: `<lr-tree>` gains a `reorderable` opt-in for keyboard reordering. With it set, Ctrl/Cmd+ArrowUp /
1107
+ Ctrl/Cmd+ArrowDown on the focused row emits `lr-reorder` with
1108
+ `detail: { id, parentId, fromIndex, toIndex }` — sibling-scoped indices within the node's own
1109
+ parent's child list (`parentId` is `null` for a top-level item), so a reorder can never turn into
1110
+ a reparent at a subtree boundary. The keybinding matches `<lr-dashboard-grid>`'s existing
1111
+ `cells-draggable` keyboard move; Alt+Arrow was avoided because it is browser back/forward on
1112
+ Windows and Linux. `data` stays host-owned — the event is a request, and the move is announced
1113
+ through an internal `<lr-live-region>` (new `treeNodeMoved` message key).
1114
+
1115
+ Also fixes a pre-existing focus bug this surfaced: reassigning `data` in a way that merely
1116
+ _re-indexes_ the focused node (rather than removing it) dropped real DOM focus to `<body>`.
1117
+ Focus now follows the node, including for nested rows several shadow roots down.
1118
+
1119
+ `reorderable` is `false` by default — unset, markup and keyboard behaviour are unchanged and no
1120
+ `lr-reorder` is ever emitted. `<lr-file-tree>` deliberately does not forward it: its tree items are
1121
+ derived from `nodes` and keyed by filesystem path, an order it does not own.
1122
+
1123
+ - 8774f0d: Add `lr-virtual-list` position queries: `offsetForIndex(index)` returns the pixel top row `index`
1124
+ renders at (clamped to `0…items.length`, so `offsetForIndex(items.length)` is the total content
1125
+ height), and `indexAtOffset(px)` returns the row whose box contains that offset (`-1` for an empty
1126
+ list). Both work in the same coordinate space as the scroll container's `scrollTop`, so a host can
1127
+ do scroll-linked layout without duplicating the windowing math; in `row-height="auto"` mode an
1128
+ unmeasured row's offset stays estimate-based until its `ResizeObserver` measurement lands.
1129
+ - 8774f0d: Add `lr-virtual-list`'s sticky group header layer. Setting `renderStickyGroup` renders a
1130
+ `[part="sticky-group"]` overlay pinned to the top of the scroll viewport showing whichever `groups`
1131
+ entry the viewport is currently inside, pushed out by the overlap as the next group's header arrives
1132
+ rather than swapped abruptly. Native `position: sticky` on the rows themselves is structurally inert
1133
+ here, since every row is absolutely positioned and transform-offset by the windowing math.
1134
+
1135
+ The overlay is a visual copy of content that already exists in the list, so it is `aria-hidden`, its
1136
+ ordinary focusable content is forced to `tabindex="-1"` (the real row keeps sole ownership of the
1137
+ heading semantics and of the tab order), and it is `pointer-events: none` until a consumer opts in
1138
+ with `lr-virtual-list::part(sticky-group) { pointer-events: auto; }`. It is measured by its own
1139
+ `ResizeObserver` and never by the row observer, so a group header that is also a real row is not
1140
+ double-counted in `row-height="auto"` mode. A `groups` entry whose `label` is the empty string now
1141
+ renders no `[part="group"]` marker — it is a pure position anchor, for a host that renders its own
1142
+ group headers as rows. With `renderStickyGroup` unset, nothing about the rendered output changes.
1143
+
1144
+ - 8774f0d: Add `lr-virtual-list`'s public `scrollContainer` getter (the `[part="base"]` scroll box, `undefined`
1145
+ before the first render) and an `lr-scroll` event (`detail: { scrollTop, viewportHeight }`). The
1146
+ event is emitted from the animation frame that already coalesces native `scroll` events, so a burst
1147
+ of them produces at most one `lr-scroll` per frame and none at all when the position did not change.
1148
+ Together they let a host follow _sub-row_ scroll movement — which `lr-visible-range-changed`, firing
1149
+ only on index-range changes, cannot report — without reaching into the component's shadow root or
1150
+ dispatching synthetic `scroll` events at it.
1151
+
1152
+ ### Patch Changes
1153
+
1154
+ - 2e16fad: Fix `lr-artifact-panel`'s restore/copy/download header buttons rendering fully raw browser chrome
1155
+ (zero CSS at all) while the adjacent header buttons in the same row are fully themed, and give
1156
+ view-button its own hover/focus-visible to match its version-previous/version-next siblings.
1157
+ - c2ddee5: Fix `lr-av-player`'s playback-rate `<select>` rendering raw browser chrome with an unthemed
1158
+ (typically white) option popup regardless of theme -- it now resets native appearance, themes its
1159
+ option list, and gains hover/focus-visible states and a decorative chevron in place of the removed
1160
+ native one.
1161
+ - db4e0a5: Fix `lr-calendar`'s previous-month nav button never matching its own styling rule (it rendered with
1162
+ raw browser button chrome next to a fully themed next button) and add missing `:hover`/`:focus-visible`
1163
+ treatment to the nav buttons, day-grid cells, and agenda-event buttons.
1164
+ - bfaf7f9: `lr-checkbox-group`: document `value` as a read-out of child state, and warn on the two ways it is
1165
+ misused.
1166
+
1167
+ `value` shipped with no documentation at all while the generated docs listed it among settable
1168
+ properties, so it read as an input. It never was one: `sync()` recomputes it from the
1169
+ `<lr-checkbox>` children and assigns it on every child toggle, `slotchange`, `name`/`required`
1170
+ change, blur and `form.reset()` — and `connectedCallback()` syncs _before the first render_, so even
1171
+ a constructor-time or template-time `.value=` binding is discarded before it is ever observed. It
1172
+ now carries that contract in its JSDoc, and:
1173
+
1174
+ - assigning `value` from outside logs a `console.warn` naming the property and pointing at `checked`
1175
+ on the children (once per element — a repeat assignment is the same mistake, not new information);
1176
+ - a group with two or more children sharing a `value` logs a `console.warn` too. This is the _easy_
1177
+ mistake, not an exotic one: `<lr-checkbox>`'s `value` defaults to `'on'`, so five undifferentiated
1178
+ children yield `['on','on','on','on','on']` and a `FormData` that cannot say which was checked.
1179
+
1180
+ Both warnings follow the same plain-`console.warn` shape as the library's other authoring-mistake
1181
+ warnings (`lr-task-list` over-nesting, `lr-dashboard-grid` unmatched `cell-id`, `lr-flow-canvas`
1182
+ unrecognized child). No behavior changed for the normal children-drive-value flow, which warns not
1183
+ at all.
1184
+
1185
+ `value` was deliberately **not** made authoritative. Push-down is unimplementable without surprise
1186
+ while children default to `value = 'on'` (a host assigning `['on']` would check every
1187
+ undifferentiated child), and it would additionally need a re-entrancy guard and a pending-value
1188
+ retention path for children that have not upgraded yet. Recorded here so a later release can add a
1189
+ distinct `defaultValue` API without reversing anything documented now.
1190
+
1191
+ - 2a45da4: Fix four components (`lr-chunk-inspector`, `lr-community-card`, `lr-provenance-panel`,
1192
+ `lr-notebook-viewer`) whose real `<button>`s get UA-chrome reset (`border:none; background:
1193
+ transparent; cursor:pointer;`) but no hover or focus-visible of their own -- `lr-provenance-panel`'s
1194
+ disclosure header (`aria-expanded`/`aria-controls`) had zero visible keyboard focus indicator at all.
1195
+ - 1d121a9: Fix `lr-code-block`/`lr-code-block-core`'s shiki dark-theme override only activating on the OS-level
1196
+ `prefers-color-scheme` media query -- a consumer who sets `--lr-theme-color-*` explicitly, without the
1197
+ OS itself being in dark mode, now correctly gets the dark shiki syntax theme too, matching every other
1198
+ `--lr-color-*` token's consumer-overrides-first resolution.
1199
+ - 1372546: Fix `lr-color-picker`'s native color swatch -- the directly visible, directly focusable control --
1200
+ having no hover or focus-visible treatment, so tabbing to it fell through to the browser's raw
1201
+ default color-input focus ring.
1202
+ - f8bc916: `lr-combobox`: the `clearable` button now covers the filter axis as well as the selection.
1203
+
1204
+ Typing a query that matches nothing left the user with no affordance to clear it — the button was
1205
+ gated on a committed selection alone, and `clear()` early-returned on an empty selection. It now
1206
+ renders whenever there is something to clear on either axis, and each axis announces only its own
1207
+ change: clearing a selection still emits `input`/`change`/`lr-clear`, while clearing filter text
1208
+ emits `lr-filter` with an empty `value` and no spurious selection events.
1209
+
1210
+ The query half of the gate is scoped to states where the query is actually visible — the open
1211
+ listbox in single-select, or any time in `multiple` mode. A closed single-select shows the selected
1212
+ label rather than the query, so a stale query alone never surfaces a button offering to clear text
1213
+ the user cannot see.
1214
+
1215
+ - 77bfb28: Fix `lr-data-grid`'s sort-header focus ring targeting `<th>`, which can never itself receive
1216
+ keyboard focus (only its nested sort button can) -- tabbing to a sortable column header now shows
1217
+ the library's focus ring instead of the browser's raw default, and the sort button gains a
1218
+ matching hover state.
1219
+ - dfd6199: Fix `lr-date-picker`'s previous/next month-nav buttons having a hover state but no focus-visible ring
1220
+ -- the file's only focus-visible coverage was on day cells, leaving keyboard users with no visible
1221
+ indicator on the nav buttons.
1222
+ - 7c99e80: Route several stray hardcoded style values through design tokens so visually-identical states stay
1223
+ in sync across components:
1224
+
1225
+ - **Disabled controls** in `lr-node-palette`, `lr-flow-controls`, `lr-compare-panel`,
1226
+ `lr-graph-query-builder`, and `lr-rubric-form` now dim through the shared `--lr-opacity-disabled`
1227
+ token instead of one-off `0.4`/`0.5`/`0.6` literals, so every disabled control fades by the same
1228
+ amount (and rethemes with one property).
1229
+ - **Anchored popovers/menus/tooltips** (`lr-menu`, `lr-select`, `lr-combobox`, `lr-date-input`,
1230
+ `lr-model-select`, `lr-voice-picker`, `lr-mention-popover`, `lr-export-button`, `lr-tour`,
1231
+ `lr-tool-call-chip`, `lr-usage-badge`, `lr-citation-badge`, `lr-entity-chip`,
1232
+ `lr-knowledge-graph-explorer`) share a new `--lr-popover-viewport-clamp` token (default `92vw`,
1233
+ themeable via `--lr-theme-popover-viewport-clamp`). Previously these split between `92vw` and
1234
+ `90vw`, so two popovers side by side could clamp to different widths; they now clamp consistently.
1235
+ - **Solid-fill hover lift** on `lr-chat-composer`, `lr-tool-approval-dialog`, `lr-message-feedback`,
1236
+ `lr-tour`, and `lr-retrieval-search` now shares a new `--lr-hover-brightness` token (default
1237
+ `1.08`, themeable via `--lr-theme-hover-brightness`), replacing per-component `filter: brightness()`
1238
+ magic numbers. Note `lr-retrieval-search`'s submit button now _brightens_ on hover like every other
1239
+ brand button, where it previously darkened (`0.92`).
1240
+ - `lr-calendar`'s narrow-container day-cell floor now references the existing `--lr-size-4rem` token
1241
+ instead of a raw `4rem`, matching its wide-container sibling.
1242
+
1243
+ Also adds a new consumer override hook: `--lr-responsive-panel-sheet-max-block-size` (default `85dvh`,
1244
+ falling back to `85vh` where `dvh` is unsupported) lets you set the maximum height of an
1245
+ `lr-responsive-panel` `variant="bottom-sheet"` overlay, which previously had no override at all.
1246
+
1247
+ - ac5936a: Fix `lr-details`' summary -- the component's real, natively-focusable/clickable surface -- having no
1248
+ hover or focus-visible treatment at all. `lr-accordion-item` (which extends `lr-details` with no
1249
+ style override) is fixed by the same change.
1250
+ - 188335c: Sync the consumer-facing agent reference (`llms/`) with the part-reachability, density and composed
1251
+ -content work that just landed across the viewers, media, retrieval, agent-tools, layout,
1252
+ conversation and data families.
1253
+
1254
+ - Document the newly forwarded and newly named CSS parts on `lr-pdf-viewer`, `lr-archive-viewer`,
1255
+ `lr-page-rail`, `lr-notebook-viewer`, `lr-csv-viewer`, `lr-spreadsheet-viewer`,
1256
+ `lr-dataset-viewer`, `lr-av-player`, `lr-terminal`, `lr-ingestion-queue`, `lr-neighbor-list`,
1257
+ `lr-chunk-inspector`, `lr-retrieval-results` and `lr-activity-feed`, including why row state is
1258
+ published as an extra part name rather than an attribute on the part.
1259
+ - Replace the paragraphs that described `--lr-page-rail-current-bg`,
1260
+ `--lr-notebook-viewer-active-bg`, `--lr-av-player-cue-current-bg` and
1261
+ `--lr-av-player-cue-active-match-color` as declared-but-inert; all four now take effect.
1262
+ - Document `--lr-csv-viewer-highlight-color` and `--lr-spreadsheet-viewer-highlight-color`, and
1263
+ `--lr-trace-tree-row-active-color` (plus the pairing rule it forms with
1264
+ `--lr-trace-tree-row-active-bg`, and the knock-on note under `lr-agent-trace`).
1265
+ - Document `lr-menu`'s `header`/`footer` slots and parts, the revised Escape/Tab keyboard contract,
1266
+ and the narrowed scope of `closeOnEscapeAnywhere`.
1267
+ - Document `lr-table`'s `columns[].editable: 'always'` persistent editors, `lr-flow-node`'s
1268
+ `compact` and `card` part, `lr-flow-controls`' and `lr-chat-composer`'s `appearance`, and
1269
+ `lr-conversation-item`/`lr-thread-list`'s `compact`.
1270
+
1271
+ - 2be1ad5: Sync the consumer-facing agent reference (`llms/`) with the sticky group-header work on
1272
+ `lr-virtual-list` and `lr-thread-list`.
1273
+
1274
+ - Document `lr-virtual-list`'s `renderStickyGroup`, the `sticky-group` CSS part, and the four
1275
+ behaviors a consumer would otherwise get wrong: the band is `aria-hidden` with its focusable
1276
+ descendants forced to `tabindex="-1"` (so it is never a second tab stop or a second heading, and a
1277
+ focus-delegating custom element inside it must set its own), it is `pointer-events: none` until
1278
+ opted back in through `lr-virtual-list::part(sticky-group)`, it is never measured as a row, and it
1279
+ stays mounted but hidden above the first group so its scroll inset is measurable before the first
1280
+ jump.
1281
+ - Document that a `groups` entry with an **empty** `label` renders no marker and acts as a pure
1282
+ position anchor, and drop the stale claim that `groups` had no visible effect and that its marker
1283
+ carried `role="heading"`.
1284
+ - Document `offsetForIndex()`/`indexAtOffset()`, the `scrollContainer`/`renderedRows` getters, the
1285
+ `lr-scroll` event and its `VirtualListScroll` detail type, and add a sticky-group usage example.
1286
+ - Document `lr-thread-list`'s `stickyGroups` property (attribute `sticky-groups`) and the
1287
+ `group-sticky` exported part, including that the real header row keeps the
1288
+ `role="heading"`/`aria-level` semantics and the tab order while the pinned copy stays clickable.
1289
+
1290
+ - ed762ff: `lr-xml-viewer` treats `--lr-icon-button-size` as a floor
1291
+
1292
+ `lr-xml-viewer`'s node `[part='toggle']` is an interactive button that pinned the shared
1293
+ minimum-target token as a fixed `inline-size`/`block-size` with `padding: 0` and no floor — the
1294
+ opposite of what the token's own definition documents ("components pad out to this via
1295
+ `min-inline-size`/`min-block-size`, not by growing the glyph itself"). It now sizes its glyph box at
1296
+ `--lr-size-1-25rem` with `min-inline-size`/`min-block-size: var(--lr-icon-button-size)`, mirroring
1297
+ `lr-code-block`'s equivalent toggle, so lowering the token shrinks the hit area but never squashes
1298
+ the chevron.
1299
+
1300
+ - 4c59cc2: Fix `lr-image-viewer`'s fit-mode `<select>` rendering raw browser chrome with an unthemed option
1301
+ popup, and add missing hover/focus-visible to all three toolbar controls (fit-control, rotate-button,
1302
+ annotate-toggle) -- previously none of the three had either state.
1303
+ - 10c8b91: Fix `lr-input` (and `lr-time-input`, which renders through the same template/stylesheet) keeping
1304
+ native browser chrome in three cases: the search-cancel glyph only reset while `clearable` was set
1305
+ (the common non-clearable case kept it), `type="number"` never resetting the spin-button, and
1306
+ `type="time"` never touching its calendar-picker-indicator at all -- now restyled, not suppressed,
1307
+ since it's the only mouse/touch affordance to open the native time picker.
1308
+ - 0410eb7: Fix two factual errors in the shipped agent-facing reference (`llms/shared.md`, and the
1309
+ `llms.txt`/`llms-full.txt`/`llms/` artifacts generated from it): the internals section stated
1310
+ `LYRA_PREFIX = 'lyra'` when the constant is `'lr'` — on the same line that correctly showed
1311
+ `tag(name)` producing `` `lr-${name}` `` — and claimed a hardcoded count of 127 `Lyra*EventMap`
1312
+ types when there are now 181. The count is no longer stated as a number, so it cannot drift again.
1313
+ - 184bfff: `lr-menu`: axe coverage for a composed popup, stories moved onto the new `header`/`footer` slots,
1314
+ and the three shipped descriptions of what this component accepts finally agree.
1315
+
1316
+ - New axe assertion for a menu with a `header` `<input>` and a `footer` `<button>` — the exact shape
1317
+ that was an `aria-required-children` violation while the only place for it was inside
1318
+ `role="menu"`, and which no test covered.
1319
+ - `show() / hide({ focusTrigger: true })`'s Apply button moves to `slot="footer"`, and the filter
1320
+ field gets a new `header`-slot story. The old default-slot filter story stays, relabelled as the
1321
+ legacy shape it now is, so its `closeOnEscapeAnywhere` behavior remains covered.
1322
+ - The class doc's `@slot` tag said "menu items and `<hr>` only" while the interaction contract two
1323
+ paragraphs above it promised slotted controls "keep their own full default keyboard behavior" and
1324
+ `show()`/`hide()` named a slotted Apply button as a supported case. All three now describe the
1325
+ same component.
1326
+
1327
+ - 3c8a299: Add missing `:hover` to six agent-tools components (`lr-browser-frame`, `lr-commit-card`,
1328
+ `lr-terminal`, `lr-test-results`, `lr-compare-panel`, `lr-confirm-bar`) whose interactive buttons
1329
+ already had `cursor: pointer` and a correct focus-visible ring but no hover affordance for mouse
1330
+ users.
1331
+ - 4ac6c31: Add missing `:hover` to six components (`lr-stack-trace`, `lr-span-waterfall`, `lr-chat-viewport`,
1332
+ `lr-checkpoint`, `lr-push-to-talk`, `lr-transcript-feed`) whose interactive controls already had
1333
+ `cursor: pointer` and a correct focus-visible ring but no hover affordance for mouse users.
1334
+ - 696cc7f: Add missing `:hover` to six components (`lr-env-list`, `lr-graph-query-builder`, `lr-rubric-form`,
1335
+ `lr-chart`, `lr-scroller`, `lr-widget`) whose interactive controls already had `cursor: pointer` and a
1336
+ correct focus-visible ring but no hover affordance for mouse users; `lr-chart`'s reset-zoom-button also
1337
+ gains `font: inherit`, which it was missing entirely.
1338
+ - e1b9c22: Add missing `:hover` to six components (`lr-carousel`, `lr-dashboard-grid`, `lr-callout`,
1339
+ `lr-memory-panel`, `lr-neighbor-list`, `lr-path-strip`) whose interactive controls already had
1340
+ `cursor: pointer` and a correct focus-visible ring (where applicable) but no hover affordance for
1341
+ mouse users.
1342
+ - e73a243: Add missing `:hover` to six components (`lr-retrieval-results`, `lr-pdf-viewer`, `lr-ebook-viewer`,
1343
+ `lr-pptx-viewer`, `lr-email-viewer`, `lr-dataset-viewer`) whose interactive controls already had
1344
+ `cursor: pointer` and a correct focus-visible ring but no hover affordance for mouse users.
1345
+ - ae8e04e: Fix nine components (`lr-combobox`, `lr-eval-dataset`, `lr-command-palette`, `lr-table`,
1346
+ `lr-tool-select-dialog`, `lr-code-editor`, `lr-message-feedback`, `lr-model-select`, `lr-voice-picker`)
1347
+ whose native `<input>`/`<textarea>` themed background/color/border correctly but left `::placeholder`
1348
+ at the browser's fixed light-tuned default -- each field's placeholder text now uses
1349
+ `--lr-color-text-quiet`, with Firefox's reduced default `::placeholder` opacity undone on the
1350
+ `type="search"` fields.
1351
+ - e649e77: Fix `lr-node-palette`'s search field being the only `type="search"` field in its family with zero
1352
+ focus-ring styling (its siblings `lr-thread-list`/`lr-emoji-picker` already wire this), and reset the
1353
+ native search-cancel glyph to match.
1354
+ - e879ff6: Fix `<lr-split>` and `<lr-stepper>` reporting a stale `effectiveOrientation` (and
1355
+ `data-effective-orientation`) when `orientation-breakpoint-basis="viewport"` and the viewport
1356
+ crossed the breakpoint while the element was detached from the DOM. The media-query listener is
1357
+ torn down on disconnect and a plain reconnect schedules no Lit update, so the missed crossing was
1358
+ never noticed; reconnecting now re-reads the query and announces the crossing (including
1359
+ `lr-split-orientation-change` / `lr-stepper-orientation-change`) only when the matched state
1360
+ actually differs. A plain mount, and a reconnect that crossed nothing, stay silent as before.
1361
+ - c2ea153: Fix `lr-pagination`'s page-input and `lr-tool-param-form`'s numeric JSON-schema fields rendering the
1362
+ native spin-button inside a fixed-size control box -- the adjacent prev/next buttons (pagination) and
1363
+ form validation (tool-param-form) already provide stepping, so removing the spinner loses no
1364
+ functionality.
1365
+ - 94fa823: `lr-terminal`, `lr-ingestion-queue` and `lr-dataset-viewer`: forward the CSS parts rendered through
1366
+ their internal `<lr-virtual-list>` so a consumer can actually reach them.
1367
+
1368
+ All three already styled those parts correctly from their own stylesheets, but none forwarded
1369
+ `exportparts` from the `<lr-virtual-list>` element. Because the rows are `renderItem`'s output and
1370
+ therefore live inside that element's own shadow root, a consumer rule like
1371
+ `lr-terminal::part(line)` matched nothing at all — the documented parts were unreachable from
1372
+ outside the component.
1373
+
1374
+ - `lr-terminal` now exports `line`.
1375
+ - `lr-ingestion-queue` now exports `item`, `item-header`, `item-name`, `item-progress`,
1376
+ `item-meta`, `item-error`, `item-actions`, `retry-button` and `cancel-button`.
1377
+ - `lr-dataset-viewer` now exports `data-row`, `cell`, `cell-highlight` and `cell-highlight-action`.
1378
+
1379
+ No styling changed and no new parts were added.
1380
+
1381
+ - 56f7b65: Add a build-time guard against `::part()` CSS that parses but never matches.
1382
+
1383
+ Two classes of silently-inert rule are now caught by `pnpm lint` (a new
1384
+ `scripts/check-part-reachability.mjs` in the contract-policy chain), neither of which any existing
1385
+ check — TypeScript, the style policy, or a test that inspects stylesheet text — could see:
1386
+
1387
+ - **`cross-root-part`** — a component that mounts `<lr-virtual-list>` and hands it a
1388
+ `renderItem`/`renderGroup` callback renders those rows into _that element's_ shadow root, so a
1389
+ bare `[part='x']` selector in the composing component's own stylesheet can never match them. The
1390
+ checker cross-references the literal part names emitted from the callback (following the class
1391
+ members it reaches) against the bare `[part]` selectors in the sibling `*.styles.ts`, and reports
1392
+ any name that has no `lr-virtual-list::part(x)` rule anywhere in that file. Components that
1393
+ legitimately render the same part into both roots — below/above a virtualization threshold, or a
1394
+ directly-rendered header row — carry both selectors and are not flagged; a
1395
+ `policy-allow(cross-root-part):` comment covers anything else.
1396
+ - **`part-compound`** — per Selectors L4 a pseudo-element may only be followed by pseudo-classes, so
1397
+ `::part(a)[attr]`, `::part(a).cls`, `::part(a) .descendant` and `::part(a) > .child` parse and
1398
+ then match nothing. Every `*.styles.ts` is scanned for those shapes; `::part(a):hover`,
1399
+ `::part(a)::selection` and the part-list form `::part(a b)` remain valid and pass.
1400
+
1401
+ No component behavior changes; the library is clean under both rules today.
1402
+
1403
+ - cce32a2: `lr-neighbor-list`: make the virtualized relationship rows and group headers actually styleable, by
1404
+ this component and by a consumer.
1405
+
1406
+ Above `virtualizeAt` the rows are produced by this component's `renderItem` but committed into the
1407
+ embedded `<lr-virtual-list>`'s own shadow root, one boundary deeper than a `[part='row']` selector
1408
+ can reach — so every row, node-label, direction, relation, meta and expand-button rule was silently
1409
+ inert and a large neighborhood rendered as raw browser `<button>`s with no dividers. Each rule now
1410
+ pairs its plain selector (still correct at/below the threshold) with an `lr-virtual-list::part(…)`
1411
+ twin, and an `exportparts` forwarding declaration makes the same parts reachable as
1412
+ `lr-neighbor-list::part(node-label)` etc. from a consuming stylesheet.
1413
+
1414
+ Group headers were unstyled whenever the list virtualized: in that path the header is the internal
1415
+ virtual-list's own `group` part, which this component neither styled nor exported. It is now styled
1416
+ to match `group-header` and exported under that same name, so grouped rows present identically
1417
+ either side of the threshold.
1418
+
1419
+ The virtualized rows no longer nest a second `role="listitem"`/`part="row"` element inside the
1420
+ virtual-list's own row wrapper. `renderItem` returns just the row's content, exactly as the
1421
+ non-virtualized path's own wrapper receives it: the duplicate nesting both reported a `listitem`
1422
+ inside a `listitem` and made the row's padding and divider border apply twice, since `::part()`
1423
+ matches at any depth of the target shadow tree.
1424
+
1425
+ - 1e518e6: Fix `lr-playback`'s range slider only getting a pointer cursor in its disabled state, unlike the
1426
+ adjacent play button, and add a matching hover affordance.
1427
+ - 5e9a18e: `lr-table`: focus the cell editor that was actually just opened by a double-click. The autofocus
1428
+ looked up `[part="cell-editor"]` across the whole grid and focused whichever one came first in the
1429
+ DOM — indistinguishable from correct while only one editor could ever exist at a time, but wrong as
1430
+ soon as a column renders persistent (`editable: 'always'`) editors of its own. It is now scoped to
1431
+ the opening cell's own row and column.
1432
+ - 326973c: Fix `lr-thread-list` and `lr-emoji-picker`'s otherwise fully-themed search fields showing a raw
1433
+ gray browser "x" glyph (with its own hit target and hover behavior, ignoring every token applied to
1434
+ the field) once non-empty.
1435
+ - 9010a89: `lr-thread-list` and `lr-chat-viewport` now size their virtual list to their own height.
1436
+
1437
+ Both composed an `lr-virtual-list` without ever setting `--lr-virtual-list-height`, so the list
1438
+ scrolled inside that token's 24rem default no matter how tall the surrounding pane was -- a
1439
+ `<lr-thread-list>` in a 700px sidebar showed a 384px scroller with dead space underneath, and every
1440
+ consumer had to hand-set `--lr-virtual-list-height` to work around it. Both now fill the height they
1441
+ are given with no consumer CSS. `lr-thread-list` degrades safely: in a container with no resolvable
1442
+ height the internal viewport still renders at exactly the 24rem it does today (the shipped default
1443
+ becomes the list's flex-basis rather than a percentage that would collapse to zero or grow to the
1444
+ full un-virtualized content height). `lr-chat-viewport`'s virtual mode uses a percentage -- the
1445
+ slotted list lives in the consumer's light DOM, out of reach of `::part()` -- so it, like slotted
1446
+ mode's own scroll container, needs a height-bounded parent. A consumer rule or inline style setting
1447
+ `--lr-virtual-list-height` on the list still wins in both components.
1448
+
1449
+ Also fixes `lr-chat-viewport`'s virtual-mode layout rules, which were written as
1450
+ `:host(:has(> lr-virtual-list))`. `:has()` is invalid inside `:host()`, so those rules were silently
1451
+ dropped: in virtual mode `[part="scroll"]` kept the padding and `overflow-y: auto` it is documented
1452
+ to give up, and `[part="content"]` never got the height the slotted list sizes against.
1453
+
1454
+ - 3e1d4f8: Fix `lr-token-input`'s draft-input and inline token-editor leaving `::placeholder` at the browser's
1455
+ default color, and add missing `:hover`/`:focus-visible` to the per-token remove button.
1456
+ - 67a7881: Cover `lr-trace-tree`'s active row with an axe assertion. The active-row test group previously
1457
+ carried a comment explaining why no accessibility assertion could be made there — the default tint
1458
+ put the row's own secondary text below the WCAG AA contrast floor, so any axe run against a
1459
+ populated active row would have failed. With that fixed, the assertion now runs for real: a
1460
+ populated tree is asserted accessible with each status tone in turn made active, after first
1461
+ proving the fixture actually reached the `[data-active]` state so the check cannot pass vacuously.
1462
+ It was verified to bite by reverting the fix and confirming axe reports the exact contrast
1463
+ violations it is meant to catch. The active-row Storybook story now sets
1464
+ `--lr-trace-tree-row-active-bg` and `--lr-trace-tree-row-active-color` together and documents why
1465
+ they are a pair.
1466
+ - 67a7881: Fix `lr-trace-tree`'s active-row secondary text falling below the WCAG AA 4.5:1 contrast floor. The
1467
+ active (`activeSpanId`) row paints `--lr-color-brand-quiet`, against which `--lr-color-text-quiet`
1468
+ lands at ~4.25:1 — so `detail`, `duration`, `tokens-in`, `tokens-out`, `cost` and the `pending`
1469
+ status label were all failing while the row was active, even though every one of them passes
1470
+ comfortably against the plain row background. Those parts now render at full-strength
1471
+ `--lr-color-text` once the row is active (15.3:1 in light mode, 11.2:1 in dark), the same fix
1472
+ `lr-conversation-item` already carries for the identical bug. Darkening the active tint instead
1473
+ would have made it worse: every failing foreground is dark text.
1474
+
1475
+ This changes default rendering on the active row, which is intended — the previous default was a
1476
+ real accessibility failure. The new `--lr-trace-tree-row-active-color` custom property retunes it;
1477
+ it pairs with `--lr-trace-tree-row-active-bg`, and a consumer setting that to a dark tint in light
1478
+ mode should set both, because the defaults assume the active background stays on the same side of
1479
+ the lightness midpoint as the ambient surface.
1480
+
1481
+ - 67a7881: Raise `lr-trace-tree`'s active-row status labels to clear WCAG AA without flattening their hue.
1482
+ `[part='status-text']` on the active row now renders
1483
+ `color-mix(in srgb, var(--lr-color-<tone>) 75%, var(--lr-color-text))` for each semantic tone —
1484
+ success moves from 4.46:1 to 6.18:1 and `denied` from 4.28:1 to 5.96:1 against the default active
1485
+ tint, while `error` and `running` (which only barely cleared the floor) gain headroom too. Keeping
1486
+ the hue matters: an error row that stops being red once selected loses the fastest scan signal in a
1487
+ trace list.
1488
+
1489
+ The mix is applied to every semantic tone rather than only the two that fail at the shipped
1490
+ defaults, because a per-status carve-out is theme-fragile — a consumer retheming one `--lr-color-*`
1491
+ moves that ratio and would silently re-break. It is also theme-symmetric by construction:
1492
+ `--lr-color-text` flips with the color scheme, so the same declaration darkens the label in light
1493
+ mode and lightens it in dark mode. `[part='bar']` is deliberately untouched — it is a non-text
1494
+ graphic on a 3:1 floor it already passes, and scoping the mix to `[part='status-text']` avoids
1495
+ re-pointing a consumer's own `--lr-color-*` override inside one row.
1496
+
1497
+ - 4df6ca1: `lr-virtual-list` no longer traps a popup opened from inside a row underneath the rows that follow
1498
+ it. `[part="row"]` sets `will-change: transform`, which makes every row its own stacking context, and
1499
+ rows carried no `z-index` — so they painted in DOM order and each row painted over the previous one.
1500
+ A `lr-menu` dropdown rendered in a row (for example through `lr-thread-list`'s `renderActions`) was
1501
+ positioned, visible and hit-testable, yet painted _under_ the next rows: its own `z-index: 900` only
1502
+ orders siblings inside its row's context. The last row always looked correct, so small fixtures never
1503
+ caught it.
1504
+
1505
+ `[part="row"]:focus-within` now lifts the row to `var(--lr-layer-content)` — the same layer
1506
+ `[part="group"]` already uses — for exactly as long as something inside it holds focus. This also
1507
+ stops outward focus rings on a row being clipped by later rows. Nothing changes when no row holds
1508
+ focus.
1509
+
1510
+ - 8774f0d: Keep `lr-virtual-list`'s scroll-into-view clear of the sticky group band. With `renderStickyGroup`
1511
+ set, the band's measured height is applied as `scroll-padding-block-start` on the scroll container —
1512
+ so native keyboard and anchor scrolling get the same treatment — and subtracted from the
1513
+ top-aligned targets `active-id` and `scrollToIndex({ align: 'start' })` compute, which otherwise
1514
+ parked the target row underneath the band. `align: 'end'` is unaffected, since the band never
1515
+ covers the viewport's bottom edge. With `renderStickyGroup` unset the inset is zero and both scroll
1516
+ paths behave exactly as before, with no inline style on the container at all.
1517
+
1518
+ ## 5.1.0
1519
+
1520
+ ### Minor Changes
1521
+
1522
+ - 5f82bf7: Add role-scoped bubble cssprops to `lr-chat-message` — `--lr-chat-message-bubble-bg`,
1523
+ `--lr-chat-message-bubble-color`, `--lr-chat-message-user-bubble-bg`, and
1524
+ `--lr-chat-message-user-bubble-color` — so a consumer can retint one role's bubble fill/text
1525
+ without overriding the shared `--lr-color-brand-quiet`/`--lr-color-surface`/`--lr-color-text`
1526
+ tokens, which also drive unrelated parts of the component (e.g. `[part="collapse-button"]:hover`).
1527
+ All four default to exactly the values the bubble already used, so nothing changes for existing
1528
+ consumers who set none of them.
1529
+ - abd60dd: `lr-stepper`'s `orientation-breakpoint` now accepts a CSS length, not only a bare pixel number:
1530
+ `500`, `'500'`, `'500px'`, `'31.25rem'` and `'3em'` are all valid, and equal computed values behave
1531
+ identically.
1532
+
1533
+ `rem` resolves against the **document root**'s computed font size — exactly as a `rem` in a CSS
1534
+ `@media` query does, and deliberately _not_ against the stepper itself — so a breakpoint authored in
1535
+ `rem` stays numerically in step with the sibling `@media (max-width: …rem)` rule it has to agree
1536
+ with, instead of silently drifting from it when the root font size changes (browser zoom, a user
1537
+ font-size preference, an app base-size token). `em` resolves against the stepper's own computed font
1538
+ size. The length is re-resolved on every measurement and never cached, so those changes are picked
1539
+ up without any invalidation step on the consumer's side.
1540
+
1541
+ A value that isn't a usable length — `%`, `vw`, `calc()`, `'auto'`, an unparseable string — now
1542
+ behaves exactly as unset: no `ResizeObserver` is armed and no `data-effective-orientation` attribute
1543
+ appears, rather than arming a breakpoint that can never be crossed. For a viewport-relative
1544
+ breakpoint, leave `orientationBreakpoint` unset and drive `orientation` from your own `matchMedia()`
1545
+ controller; `orientationBreakpoint` measures the stepper's own allocated inline size, not the
1546
+ viewport.
1547
+
1548
+ The property's TypeScript type widens from `number | undefined` to `number | string | undefined`,
1549
+ and the `orientation-breakpoint` attribute is no longer coerced through Lit's `Number` converter.
1550
+ Every existing numeric usage — attribute or property — is unaffected. This mirrors the identical
1551
+ change to `lr-split`, whose `orientationBreakpoint`/`narrowOrientation` contract `lr-stepper`
1552
+ deliberately shares.
1553
+
1554
+ - 22cb935: `lr-heatmap` gains a `legendStops` property so the built-in legend can describe a custom
1555
+ `cellColor` domain. Because `cellColor` overrides a cell's color entirely, the legend's
1556
+ `--lr-heatmap-scale-lo`/`-hi` gradient bar could describe a ramp the grid no longer used, leaving a
1557
+ consumer to hide `::part(legend)` and hand-roll swatches.
1558
+
1559
+ `legendStops: HeatmapLegendStop[]` (`{ value, color, label? }`, `attribute: false`) renders a
1560
+ discrete key **instead of** that gradient bar — one `[part="legend-stop"]` per entry in array order,
1561
+ each a `[part="legend-swatch"]` in the entry's color plus a `[part="legend-stop-label"]`. Labels
1562
+ default to the component's own locale-aware numeric formatting of `value`, so an explicit `label` is
1563
+ only needed when the number isn't the right caption. `[part="legend-lo"]`/`[part="legend-hi"]` and
1564
+ the bar are omitted while stops are supplied; labeled `annotations` still render their
1565
+ `[part="legend-annotation"]` entries alongside them.
1566
+
1567
+ The stops are presentation only — they never feed back into the color ramp, the bucket math, the
1568
+ tooltip or the accessible name. Left unset (or empty), the legend renders exactly as before.
1569
+
1570
+ - ce2a423: `lr-combobox` now emits `lr-filter` (`detail: { value: string }`) on every user-driven change to its
1571
+ in-progress filter text, so consumers that need the live as-you-typed string — a "no matches for
1572
+ “x”" empty state, a debounced side effect — no longer have to reach into the component's shadow DOM
1573
+ for `[part="combobox-input"]`.
1574
+
1575
+ The name is deliberately not `lr-input`: on `lr-combobox` the host's `value` is the _committed
1576
+ selection_, so reusing `lr-input`'s event name would make one event name carry a different string on
1577
+ different components. `lr-filter` fires for user input only — picking a row, the clear button,
1578
+ `form.reset()`, dismissing the listbox, a programmatic `value` write and `setRangeText()` all blank
1579
+ the filter silently, mirroring how `<lr-input>`'s `lr-input` only reports user edits.
1580
+
1581
+ The `ComboboxFilterDetail` detail type is exported and `LyraComboboxEventMap` carries the new entry,
1582
+ so `addEventListener('lr-filter', …)` is typed.
1583
+
1584
+ - 7c46ced: `<lr-split>`'s `orientationBreakpoint` now accepts a CSS length string as well as a bare pixel
1585
+ number, so it can be authored in the same unit as the sibling CSS `@media` rule it has to agree
1586
+ with.
1587
+
1588
+ Accepted forms: `900` / `orientation-breakpoint="900"` (unchanged), `'900px'`, `'56.25rem'`, and
1589
+ `'3em'`. `rem` resolves against the **document root**'s font size — exactly as a `rem` in a CSS
1590
+ `@media` query does, not against the element — so a breakpoint written to match
1591
+ `@media (max-width: 56.25rem)` stays in sync with it across browser zoom, a user font-size
1592
+ preference, or an app-level base-size change. `em` resolves against the split's own computed font
1593
+ size. The length is re-resolved on **every** measurement rather than cached at first render, so a
1594
+ root font-size change moves the crossing width with no invalidation step.
1595
+
1596
+ Anything that isn't a resolvable length now behaves exactly as unset — no `ResizeObserver`, no
1597
+ `data-effective-orientation` marker — where before, a non-numeric attribute became `NaN` and armed
1598
+ observation for a threshold that could never be crossed. That deliberately includes `%`, `vw`/`vh`
1599
+ and `calc()`, which would mix a viewport-relative threshold into a measurement of the element's own
1600
+ allocation; drive `orientation` from your own `matchMedia()` controller for a viewport-relative
1601
+ breakpoint instead.
1602
+
1603
+ One visible consequence of dropping the `Number` attribute converter: reading `.orientationBreakpoint`
1604
+ back after setting the attribute now returns the authored string (`'900'`), not the number `900`.
1605
+ The resulting layout behavior is identical, and the property type is now `number | string`.
1606
+
1607
+ - 2be0a50: `<lr-split>` gains `orientationBreakpointBasis` (`"container"` by default, `"viewport"`
1608
+ opt-in), selecting whether `orientationBreakpoint` is compared against the component's own
1609
+ measured inline size or a `matchMedia('(max-width: …)')` query. Viewport basis lets sibling
1610
+ components in one row flip orientation together at a single shared breakpoint — impossible
1611
+ to express with a self-measured threshold when the row stacks via a CSS `@media` rule — and
1612
+ lets the browser resolve a `rem` breakpoint with real media-query semantics. Left unset,
1613
+ behavior is unchanged.
1614
+ - 96ea325: `<lr-stepper>` gains `orientationBreakpointBasis` (`"container"` by default, `"viewport"`
1615
+ opt-in), selecting whether `orientationBreakpoint` is compared against the stepper's own
1616
+ measured inline size or a `matchMedia('(max-width: …)')` query. Viewport basis is the only
1617
+ way a stepper with a fixed width in a row layout can react to that row stacking at a shared
1618
+ breakpoint. Left unset, behavior is unchanged.
1619
+ - b1ce3f6: `lr-sequence-strip`: add `showLegend` for a persistent category key.
1620
+
1621
+ The strip colors each cell by category, but the only way to read that mapping was to hover every
1622
+ cell one at a time — consumers were hand-rolling a swatch key underneath instead. `showLegend`
1623
+ (attribute `show-legend`, reflected, default `false`) now renders that key from the `categories`
1624
+ array the component already receives, as `legend` / `legend-item` / `legend-swatch` /
1625
+ `legend-label` CSS parts, with `--lr-sequence-strip-legend-swatch-size` to resize the chips.
1626
+
1627
+ The legend is deliberately static — it lists every `categories` entry whether or not any item uses
1628
+ it, and toggles nothing (`lr-graph-legend` remains the interactive, filtering legend). Because it
1629
+ only repeats the category names the strip already announces through `[part="base"]`'s `role="img"`
1630
+ summary, the whole legend is `aria-hidden`: visible on screen, announced exactly once. Left unset,
1631
+ rendering is unchanged.
1632
+
1633
+ - 3127d5e: Restructure the AI-agent-facing reference so a component lookup costs a few hundred tokens instead
1634
+ of the whole catalog, and close the gaps that made it unreliable.
1635
+
1636
+ **New published layout.** `llms/index.md` maps every tag to its import path and one-line purpose;
1637
+ `llms/components/<tag>.md` is a self-contained per-component reference addressed directly from the
1638
+ tag name; `llms/shared.md`, `llms/tokens.md`, `llms/peers.md` and `llms/migration.md` carry the
1639
+ library-wide contracts. `llms.txt` is now the entry index over all of it, and `llms-full.txt` keeps
1640
+ its role as the single-file concatenation. Everything is generated from per-family authored sources
1641
+ by `pnpm run llms` and diffed in CI, so the docs cannot drift from `custom-elements.json`.
1642
+
1643
+ **Corrected documentation that was wrong, not merely missing:**
1644
+
1645
+ - Import paths in the docs had not been updated for the family directory layout —
1646
+ `components/combobox/combobox.js` does not resolve; it is
1647
+ `components/forms/combobox/combobox.js`. CI now fails on any documented path that has no source
1648
+ module.
1649
+ - 26 components were documented twice with divergent content; the freshness check validated the
1650
+ weaker copy.
1651
+ - `lr-include` was documented with the wrong purpose, property semantics, event name and CSS parts.
1652
+ - Wrong or non-existent CSS parts on `lr-timeline`/`lr-timeline-item`, `lr-tour`, `lr-known-date`,
1653
+ `lr-random-content`, `lr-avatar-group`, `lr-breadcrumb`, `lr-swatch-picker`.
1654
+ - `lr-button` was missing the `quiet` appearance and the `2xs` size; `lr-attachment-trigger` was
1655
+ missing the `audio` capability; `lr-avatar` was documented as having no slots.
1656
+ - `lr-widget` event details are objects, not scalars; three overlay-color tokens do resolve to
1657
+ `var(--lr-color-overlay)`; `lr-histogram`'s `label` default is localized, not `'Frequency'`.
1658
+ - The root barrel skips 15 peer-gated tags, not 13 — `lr-knowledge-graph-explorer` and
1659
+ `lr-geojson-view` were undocumented omissions.
1660
+
1661
+ **Newly documented:** the `@aceshooting/lyra-ui/ai` provider-neutral data types, the `locale` and
1662
+ `strings` properties present on every element, the localization API surface
1663
+ (`setLyraLocale`/`getLyraLocale`/`resolveLyraString`/`LYRA_DEFAULT_STRINGS` and its 996 message
1664
+ keys), the full design-token catalog, framework integration (React/Vue/Angular/Svelte property and
1665
+ event binding), TypeScript usage (the 127 `Lyra*EventMap` types, the typed `addEventListener`,
1666
+ `HTMLElementTagNameMap`), SSR/declarative-shadow-DOM status, the component-to-peer-dependency table,
1667
+ editor tooling metadata, and `<lr-map>`'s OpenStreetMap demo-tile-server production hazard.
1668
+
1669
+ The freshness check now covers events, slots, CSS parts and themeable custom properties in addition
1670
+ to properties — it previously only checked properties, which is how 87 public names came to be
1671
+ documented nowhere.
1672
+
1673
+ ### Patch Changes
1674
+
1675
+ - 7bdefd2: `lr-time-input` now accepts `min`/`max` as attributes. It inherits both from `lr-input`, where they
1676
+ are declared `type: Number` for the `type="number"` contract, so a `min="09:00"` attribute parsed to
1677
+ `NaN` and reached the native `<input type="time">` as the literal string `"NaN"` — which the browser
1678
+ discards, silently dropping the bound. Only a direct property assignment worked, and it needed a
1679
+ TypeScript widening cast to do so.
1680
+
1681
+ `LyraTimeInput` now redeclares `min`/`max` with a converter that forwards the attribute verbatim, so
1682
+ `<lr-time-input min="09:00" max="17:00">` reaches the native input intact and its own constraint
1683
+ validation reports `rangeUnderflow`/`rangeOverflow` as it should. Seconds-precision bounds
1684
+ (`min="09:00:30"` alongside `step="1"`) work the same way, removing the attribute clears the bound,
1685
+ and both are typed `string | number | undefined` so an assignment no longer needs a cast.
1686
+
1687
+ `<lr-input type="number">` is unchanged: its `min`/`max` attributes still parse to numbers.
1688
+
1689
+ - 2724dec: Add an internal `resolveCssLength()` helper that resolves a CSS length (a bare/`px` number, `rem`,
1690
+ or `em`) to pixels, reading the document root font size at call time so a `rem`-authored threshold
1691
+ tracks browser zoom, a user font-size preference, or an app changing its base size. Units that only
1692
+ make sense against a different reference box (`%`, `vw`/`vh`, `ch`), absolute units, and
1693
+ `calc()`/`var()` expressions resolve to `undefined`, which callers treat as "unset".
1694
+
1695
+ No public API change yet — this is the shared groundwork for letting `lr-split` and `lr-stepper`
1696
+ accept `orientation-breakpoint` as a CSS length.
1697
+
1698
+ - 356f5fb: `lr-emoji-picker` now resolves its three geometry custom properties to real pixels before using
1699
+ them for the windowed layout. `--lr-emoji-picker-item-size`, `--lr-emoji-picker-gap`, and
1700
+ `--lr-emoji-picker-row-height` were read with `parseFloat(getComputedStyle(host).getPropertyValue(
1701
+ token))`, which hands back the property's computed _token stream_ rather than a length: the shipped
1702
+ `2.5rem` item size was used as `2.5px`, the `0.125rem` gap as `0.125px`, and the `calc()`-based
1703
+ default row height was unparseable and always fell back to a hardcoded `64`. The windowed grid
1704
+ therefore packed its column cap of 20 emoji into a row that could only paint five, and scrolled at a
1705
+ row pitch that did not match the painted rows.
1706
+
1707
+ Each token is now assigned to an off-flow probe box in the shadow root and read back as that box's
1708
+ used inline size, so the browser performs the unit math — `rem`, `em`, `ch`, `%`, `calc()`, any CSS
1709
+ length resolves correctly, and the item-size probe carries the same `--lr-icon-button-size` minimum
1710
+ the emoji buttons do, so the measured item size is the painted one. The result is cached and
1711
+ re-derived only when it can actually change: the probe boxes are themselves observed, so a token
1712
+ override applied after the first render, a theme swap, or a root/host font-size change updates the
1713
+ geometry without any per-frame measurement. Numeric fallbacks still cover the case where no box has
1714
+ been laid out yet.
1715
+
1716
+ Consumers no longer have to express these tokens in `px` for the windowed geometry to line up with
1717
+ what is painted.
1718
+
1719
+ - 4ddf1fb: Document `orientationBreakpointBasis` on `<lr-split>` and `<lr-stepper>`, and the four
1720
+ role-scoped bubble custom properties on `<lr-chat-message>`. Also corrects a claim that
1721
+ a `rem` inside a CSS `@media` query resolves against the document root's computed font
1722
+ size — it resolves against the browser's _initial_ font size, which is exactly why the
1723
+ `'viewport'` basis, and not `'container'`, is the one that matches a CSS `@media` rule.
1724
+ - 2a0cb74: Add an internal `OrientationBreakpointController` that owns orientation-breakpoint
1725
+ resolution, basis selection, and media-query lifecycle for the layout components. No
1726
+ consumer-visible change on its own.
1727
+ - 8057596: Fix `<lr-pdf-viewer>`'s `search()` throwing an uncaught `IndexSizeError` when a search term occurs
1728
+ more than once inside a single PDF.js text-layer node (e.g. a repeated substring within one text
1729
+ item's `<span>`). `paintSearchMatches()` computed every match's DOM range against a pristine,
1730
+ pre-painting snapshot of each text node, but wrapping the first match with `Range.surroundContents()`
1731
+ splits/shrinks that node out from under the second match's precomputed offset, so `setStart()`/
1732
+ `setEnd()` threw before the existing `surroundContents()` try/catch ever ran. Offsets for a node are
1733
+ now tracked against the node as it actually stands after each prior match is painted, so every
1734
+ repeated occurrence within one text-layer node is now correctly highlighted instead of crashing
1735
+ `search()`.
1736
+ - 415e61f: `<lr-code-editor>`: make `--lr-code-editor-tab-size` actually themeable.
1737
+
1738
+ The stylesheet read the token on the `textarea` part, but `render()` also wrote an inline
1739
+ `tab-size:${tabSize}` on that same element on every update, and an inline declaration always beats a
1740
+ rule — so the documented token was inert and a host-level override was silently ignored.
1741
+
1742
+ `render()` now writes the token itself, and only when `tabSize` was explicitly assigned. The
1743
+ resulting precedence, highest first: an explicitly set `tabSize` (property or `tab-size` attribute)
1744
+
1745
+ > a host-level `--lr-code-editor-tab-size` > the `:host` default of `2`. `tabSize` therefore remains
1746
+ > the primary knob and still wins wherever it is used; it just stops shadowing the token while it sits
1747
+ > at its default. The Tab key follows the same order, so the indent unit and the rendered tab stops
1748
+ > cannot disagree — except for a length-valued token (`40px`, `2ch`, …), which stays a purely visual
1749
+ > tab-stop metric and leaves the inserted-space count at `tabSize`.
1750
+
1751
+ ## 5.0.0
1752
+
1753
+ ### Major Changes
1754
+
1755
+ - 3abb16e: Reorganized `packages/lyra-ui/src/components/` into 11 named family subfolders (Conversation &
1756
+ Chat, Agent Tools & Observability, Retrieval & Knowledge Graphs, Forms & Inputs, Data Display,
1757
+ Charts, Layout & Navigation, Overlays & Feedback, Document & File Viewers, Media & Files, Utility)
1758
+ instead of a flat 212-directory list.
1759
+
1760
+ **Breaking:** any consumer importing an individual component's granular subpath (e.g.
1761
+ `@aceshooting/lyra-ui/components/combobox/combobox.js`) must add that component's family segment
1762
+ (`@aceshooting/lyra-ui/components/forms/combobox/combobox.js`). The root entry
1763
+ (`@aceshooting/lyra-ui`) and the `@aceshooting/lyra-ui/components/*` wildcard export are
1764
+ unaffected for consumers who only import the root barrel. See
1765
+ `packages/lyra-ui/scripts/component-families.json` for the full directory-to-family mapping.
1766
+
1767
+ ### Minor Changes
1768
+
1769
+ - 0ed6e71: Added a frame-coalesced `lr-viewport-change` event to `lr-graph`, firing at most once per
1770
+ animation frame for every source that can move a rendered node's screen position (pan/zoom, a
1771
+ `focusNode()`/`fit()` tween, or a simulation tick) so a consumer anchoring its own UI to a node's
1772
+ `getBoundingClientRect()` no longer needs to poll its own `requestAnimationFrame` loop.
1773
+ `--lr-graph-dimmed-opacity` now defaults to `0.35` (previously the inert `1`), so `dimmedNodeIds`/
1774
+ `dimmedLinkIds` are visible out of the box with no host styling required.
1775
+
1776
+ `lr-knowledge-graph-explorer` now computes and forwards `dimmedLinkIds` alongside
1777
+ `dimmedNodeIds`, switched its details-popover pan/zoom tracking from RAF polling to the new
1778
+ `lr-viewport-change` event, and added a `highlight: 'selection' | 'hover' | 'none' = 'selection'`
1779
+ property: `'hover'` also dims by the currently pointer-hovered node's neighborhood, `'none'` opts
1780
+ a host out of this component's own dimming entirely.
1781
+
1782
+ - bd501b7: Added `defaultSizes` to `lr-split` for an initialization-only fallback (a valid restored
1783
+ `storageKey` layout still wins, then `defaultSizes`, then equal distribution) that's never
1784
+ overwritten by a later reactive parent render. Added an opt-in `orientationBreakpoint`/
1785
+ `narrowOrientation` responsive-axis contract (mirrored below by `lr-stepper`): below the
1786
+ component's own measured inline size, `narrowOrientation` becomes the effective resize axis
1787
+ instead of the authored `orientation`, exposed via `effectiveOrientation`, a
1788
+ `data-effective-orientation` attribute, and `lr-split-orientation-change`. Extended
1789
+ `panelConstraints` with `minPercent`/`maxPercent`, combining with `minPx`/`maxPx` on the same side
1790
+ via the stricter bound.
1791
+ - 5319ed6: Added an opt-in `orientationBreakpoint`/`narrowOrientation` responsive-axis contract to
1792
+ `lr-stepper`, mirroring `lr-split`'s identically-named properties: below the stepper's own
1793
+ measured inline size, `narrowOrientation` becomes the effective layout/navigation axis instead of
1794
+ the authored `orientation`, exposed via `effectiveOrientation`, a `data-effective-orientation`
1795
+ attribute, and `lr-stepper-orientation-change`. Unset (the default), behavior is unchanged.
1796
+
1797
+ ## 4.2.0
1798
+
1799
+ ### Minor Changes
1800
+
1801
+ - f3ae130: Adds an `@aceshooting/lyra-ui/ai` entrypoint re-exporting the provider-neutral AI/agent data
1802
+ contracts from `src/ai/types.ts` (also re-exported as types from the root `lyra.ts` barrel), so
1803
+ consumers importing these shared types don't have to reach into `./ai/types` directly.
1804
+ - 46eb4d2: `<lr-diff-view>` gains a `contextLines` property: collapses a run of unchanged lines longer than
1805
+ `2 * contextLines` behind a single localized fold marker reporting how many lines it hides, keeping
1806
+ only `contextLines` lines of context immediately before/after each change (leading/trailing runs
1807
+ keep only their nearest `contextLines` lines) — the same context-window convention `git diff -U<n>`
1808
+ uses. Default `undefined` renders every line unconditionally, exactly as before this property
1809
+ existed. Works identically in both `unified` and `split` layout.
1810
+
1811
+ ### Patch Changes
1812
+
1813
+ - fffd101: `<lr-chart>` no longer tracks its resolved Chart.js draw-time chart-area geometry as a reactive
1814
+ `@state()` field — recording it during Chart.js's own draw pass could trigger a second synchronous
1815
+ Lit update mid-draw. It's now a plain private field with a microtask-coalesced `requestUpdate()`,
1816
+ so repeated geometry updates within the same draw pass collapse into a single re-render.
1817
+ - 273d5da: Fixed `lr-csv-viewer` and `lr-spreadsheet-viewer`: data rows rendered as unstyled stacked text
1818
+ instead of a proper grid, because their styling lived in a `[part='data-row']`/`[part='cell']`
1819
+ CSS selector scoped to the wrong shadow root (data rows render inside the nested
1820
+ `<lr-virtual-list>`'s own shadow tree via its `renderItem` callback, not the viewer's own). Only
1821
+ the header row, rendered directly by the viewer, was ever actually styled. Fixed with
1822
+ `lr-virtual-list::part(data-row)`/`::part(cell)` rules that correctly reach across that shadow
1823
+ boundary.
1824
+ - a15cb97: `<lr-notebook-viewer>` now interprets ANSI SGR color/style escape codes embedded in stream and error
1825
+ outputs (common in colorized Python tracebacks and console output), rendering them as styled spans
1826
+ via the same shared `internal/ansi.ts` parser `<lr-terminal>` uses, instead of showing the raw
1827
+ escape sequences as literal text.
1828
+ - ef988d8: `<lr-trace-tree>` now syncs `focusedId` from `activeSpanId` in `willUpdate()` instead of `updated()`,
1829
+ so the roving-tabindex target updates before render rather than one tick after it.
1830
+
1831
+ ## 4.1.0
1832
+
1833
+ ### Minor Changes
1834
+
1835
+ - b28758d: New `<lr-agent-run>` component: the top-level shell for one `AgentRun` (from `@aceshooting/lyra-ui/ai/types`) -- lifecycle-status badge, elapsed time, current step, model/cost summary, and built-in Cancel/Retry controls in a header, plus four named composition slots (`tasks`/`tools`/`reasoning`/`output`) for the run's actual content. Composes `lr-generation-status` for the live elapsed-time ticker while a run is in progress, `lr-usage-badge` for the cost summary, `lr-task-list` for the `tasks` slot's default content (mapped from `run.steps`), and `lr-badge`/`lr-empty` for the status pill and empty state -- no new step-rendering logic. Emits `lr-cancel`/`lr-retry` (`CancelEventDetail`/`RetryEventDetail`) rather than cancelling or retrying anything itself.
1836
+ - f33364d: New `<lr-agent-trace>` component: a provider-neutral agent/LLM trace view combining a span-kind
1837
+ filter row, a handoff quick-jump list, and the full trace hierarchy, all driven by one shared
1838
+ `LyraSpan[]` array. All trace rendering -- hierarchy, expand/collapse, keyboard navigation,
1839
+ duration bars, empty state -- is entirely `<lr-trace-tree>`'s own; this component only ever hands
1840
+ it a (possibly filtered) `spans` array plus pass-through properties, never building its own row
1841
+ markup. The filter row composes `<lr-graph-legend>` (the same type/visibility-toggle legend
1842
+ pattern already established for `<lr-graph>` node types, reused here for `LyraSpan.kind`
1843
+ visibility) and the handoff list composes `<lr-handoff-divider>` for each visible `'agent'`-kind
1844
+ span. Selection (`activeSpanId`) is controlled end-to-end for deep-linking: both a tree-row click
1845
+ and a handoff quick-jump activation update it and fire the identical `lr-span-select` `{ id }`
1846
+ shape.
1847
+ - eb3e833: New provider-neutral shared type surface at `@aceshooting/lyra-ui/ai/types`: `AgentStatus`,
1848
+ `AgentRun`, `AgentStep`, `ChatMessage`, `ToolInvocation`, `RetrievalQuery`, `RetrievalChunk`,
1849
+ `Citation`, `DocumentRef`, `GroundingAssessment`, and shared run-lifecycle/retrieval-progress/
1850
+ citation-select/tool-approval/cancel/retry/export event-detail types. A foundational types-only
1851
+ module (no runtime code, no new custom elements) for the upcoming retrieval, agent-run,
1852
+ knowledge-graph, dashboard, and evaluation component families -- structurally compatible with the
1853
+ prop shapes `lr-chat-message`, `lr-citation-badge`, `lr-tool-call-chip`, `lr-tool-result-view`,
1854
+ `lr-source-card`, `lr-attachment-chip`, and `lr-document-preview` already expose, so these types
1855
+ assign directly onto those components' own properties with no adapters. `ToolInvocation.status`
1856
+ reuses `lr-tool-call-chip`'s own `ToolCallStatus` union rather than the broader `AgentStatus`
1857
+ shape, since a single tool call's terminal state is exactly what that existing vocabulary already
1858
+ covers.
1859
+ - c2d8f05: `lyra-chat-message` gains a `failure` slot, only ever rendered while `status="failed"`. Left empty
1860
+ (the default), today's built-in failed-state UI is unchanged: the `[part="status-text"]` message,
1861
+ the `[part="retry-button"]`, and the `chatFailedAnnounce` live-region announcement all keep working
1862
+ exactly as before. Once the slot has assigned content, that built-in status text and retry button
1863
+ are suppressed -- the host is now fully responsible for its own failure presentation (e.g. a
1864
+ prominent, translated `role="alert"` banner with its own retry control), and the built-in
1865
+ live-region announcement is suppressed too, so a host's own alert content doesn't get double
1866
+ announced alongside a generic built-in one. The `failure` slot itself contributes no box
1867
+ (`display: contents`), so the host's content lays out exactly as authored without needing any
1868
+ `::part(failure)` override. Content assigned to it should carry `role="alert"` itself when it
1869
+ represents an actionable send failure -- this component has no way to add that role on the host's
1870
+ behalf. Programmatic focus is rescued to `[part="bubble"]` (mirroring the existing built-in retry
1871
+ button's own focus rescue) whenever the failure slot's content held focus and `status` changes away
1872
+ from `"failed"`, so a host's own retry control clearing the failed state never silently drops focus
1873
+ to `document.body`. The existing `lr-retry` event contract is untouched; a host's own retry control
1874
+ can dispatch it manually to stay consistent with listeners elsewhere in a conversation surface, but
1875
+ nothing requires it to.
1876
+ - 3f35f20: New `<lr-context-inspector>` component: an inspection view of the exact context assembled for a
1877
+ model call. Renders per-segment token estimates through an embedded `<lr-context-meter>`, source
1878
+ attribution through `<lr-citation-badge>`, and copy/export affordances through
1879
+ `<lr-copy-button>`/`<lr-export-button>` -- composing all four rather than re-implementing any of
1880
+ their rendering. Adds two small, purpose-built presentational features no existing primitive
1881
+ covers: a truncation-boundary marker for a segment cut short of its original content
1882
+ (`ContextInspectorSegment.truncated`/`omittedTokens`), and titled `<mark part="redaction">`
1883
+ highlighting for character ranges a segment's `text` already carries a redaction placeholder in
1884
+ (`ContextInspectorSegment.redactions`) -- this component never receives or renders unredacted
1885
+ content, only marks where a host-side redaction already happened. Pure projection: never fetches,
1886
+ estimates tokens, or performs redaction itself.
1887
+ - 607b832: Add `<lr-dashboard-grid>`, a responsive, keyboard-accessible widget-layout shell: a controlled
1888
+ `layout: DashboardCell[]` (grid-unit `x`/`y`/`w`/`h` + a widget descriptor) drives a CSS Grid,
1889
+ composing `<lr-widget>`/`<lr-widget-renderer>` for each cell's default content unless a
1890
+ light-DOM `[cell-id]` child is authored instead. Pointer drag/resize and Ctrl/Cmd+Arrow (move) /
1891
+ Ctrl/Cmd+Shift+Arrow (resize) keyboard equivalents both route through the same `collision`-policy
1892
+ resolution (`'reject'` the default, `'push'`, or `'overlap'`), emitting `lr-cell-move`/
1893
+ `lr-cell-resize`/`lr-collision`/`lr-layout-change` -- the component never mutates `layout` itself
1894
+ nor touches `localStorage`/network; the host applies (or ignores) every event and owns persistence
1895
+ entirely, matching `lr-flow-canvas`/`lr-table`'s own controlled-component convention. Below a
1896
+ ~40rem container allocation (`@container`, not the viewport), cells stack into a single flowing
1897
+ column instead of shrinking columns unreadably.
1898
+ - 21de4b4: `lyra-date-input` gains a `size: '2xs' | 'xs' | 's' | 'm' | 'l' | 'xl' = 'm'` property, matching
1899
+ `lyra-input`/`lyra-select`/`lyra-combobox`'s shared control-size scale. `size="s"` now renders the
1900
+ field at the same height/density as `lyra-input size="s"`, so a date field can sit flush beside a
1901
+ compact input or select in the same form row or toolbar. The calendar-toggle and clear buttons
1902
+ keep their existing minimum touch target at every tier instead of shrinking below it. The default
1903
+ `m` tier is pixel-identical to this component's previous, only rendering.
1904
+ - d44e979: New `<lr-document-compare>` component: side-by-side or inline comparison of two document versions,
1905
+ composed entirely from existing primitives -- `<lr-diff-view>` (the real two-string line diff,
1906
+ `view="diff"`, the default) and `<lr-document-preview>` (each version's own actual rendered
1907
+ content, `view="side-by-side"`). The side-by-side panes are independently scrollable, so this
1908
+ component adds two minimal, purpose-built coordination mechanisms scoped narrowly to that: a
1909
+ proportional scroll-position sync (`syncScroll`, default `true`, mirroring `<lr-compare-panel>`'s
1910
+ own proven algorithm) and highlight-anchor sync (activating a region highlight shared by `id`
1911
+ across both versions' `highlights` scrolls the other pane to its own matching highlight). A shared
1912
+ `anchor` property (matching `<lr-document-viewer>`'s own) drives both panes to the same target at
1913
+ once. New `DocumentCompareVersion` type extends the shared `DocumentRef` (from `@aceshooting/lyra-ui/ai/types`)
1914
+ with `text` (diffed directly, no fetch) and per-version `highlights`.
1915
+ - 7dfbed7: New `<lr-document-library>`: a searchable, filterable document inventory with versions, tags,
1916
+ owners, freshness, and bulk selection. Consumes the shared `DocumentRef` type from
1917
+ `@aceshooting/lyra-ui/ai/types` (`id`/`name`/`mimeType`/`uri`/`version`) as its base row shape,
1918
+ extended locally (`LibraryDocument`) with `tags`/`owner`/`updatedAt`/`freshness` -- the fields an
1919
+ inventory view needs that a provider-neutral document reference deliberately doesn't carry.
1920
+ Composes `<lr-table>` for the grid itself (`<lr-data-grid>` was evaluated and ruled out: it only
1921
+ supports a single `selectedKey` and stringifies every cell value, so it cannot host the checkbox/
1922
+ chip/icon content bulk selection, tags, and per-row type icons need; `<lr-table>` supports
1923
+ arbitrary cell content and `priority`-driven responsive column hiding), `<lr-chip>`/`<lr-chip-
1924
+ group>` for tags and the freshness badge, `<lr-file-icon>` for per-document type icons, `<lr-
1925
+ input type="search">` for free-text search, and `<lr-combobox multiple>` for a tag facet filter
1926
+ (AND semantics -- a document must carry every selected tag). Bulk selection renders a `<lr-
1927
+ checkbox>` per row plus a header select-all checkbox (indeterminate when some but not all visible
1928
+ rows are selected) independently of `<lr-table>`'s own built-in `selectionMode`, since that mode's
1929
+ click-anywhere-on-the-row toggle would conflict with the row's own name button opening the
1930
+ document. A controlled data view like this package's other orchestration-level list surfaces: no
1931
+ upload/sync/mutation logic of its own, only `lr-filter-change` / `lr-sort` / `lr-selection-change`
1932
+ / `lr-open` request-and-notification events. `selectedIds` referencing a document no longer present
1933
+ in `documents` is silently pruned (no event fires for that pruning, mirroring `<lr-chip-group>`'s
1934
+ identical silent-resync convention) rather than left dangling.
1935
+ - a012673: New `<lr-drilldown-panel>` component: controlled navigation from a chart/table datum to its related
1936
+ evidence, documents, entities, or agent runs. A navigation shell only -- an `lr-breadcrumb` trail
1937
+ over a host-owned `path`, plus, for whichever categories the current node actually has content for,
1938
+ the one existing primitive that already renders that content type (`lr-source-card` for evidence,
1939
+ `lr-document-preview` for documents, `lr-entity-card` for entities), wrapped in an `lr-tabs` strip
1940
+ only when more than one category has content. Agent-run content has no dedicated rendering primitive
1941
+ yet in this library, so it composes via a `runs` slot instead of inventing bespoke rendering.
1942
+ Activating a non-current breadcrumb step fires `lr-drilldown-navigate` (`detail: { id, index }`) --
1943
+ the component never mutates `path` itself.
1944
+ - a0bb717: New `<lr-entity-dossier>` component: a full knowledge-graph entity detail surface combining
1945
+ properties, relationships, supporting chunks, confidence, and provenance into one composed
1946
+ layout. A persistent header renders `<lr-entity-card>` (the entity's summary/properties) next to
1947
+ an optional confidence `<lr-stat>`, above an `<lr-tabs>` strip for Relationships
1948
+ (`<lr-neighbor-list>`), Supporting chunks (`<lr-chunk-inspector>`), and Provenance
1949
+ (`<lr-provenance-panel>`). Pure layout -- it never fetches, ranks, or mutates graph/document state,
1950
+ and never re-renders what any of those five composed components already render themselves; every
1951
+ one of their own events bubbles through unmodified rather than being re-declared as this
1952
+ component's own. Tab labels reuse the exact `localize()` keys the composed child underneath
1953
+ already uses for its own accessible name (`neighborListLabel`, `chunkInspectorLabel`,
1954
+ `provenancePanelLabel`), so no new localization keys were needed and a translated locale only has
1955
+ to cover each string once.
1956
+ - 5f2927f: New `<lr-eval-dataset>` component: dataset management for an evaluation suite -- a filterable,
1957
+ taggable list of `EvalExample` rows (`id`, `input`, `expectedOutput?`, `tags?`, `metadata?`) with
1958
+ add/remove/import/export affordances. Fully controlled, matching this library's established
1959
+ convention for the rest of the agentic-AI orchestration layer: `examples` is the host's own data,
1960
+ and the component never mutates it or performs any I/O itself -- every action fires an
1961
+ `lr-example-select` / `lr-example-add-request` / `lr-example-remove-request` /
1962
+ `lr-import-request` / `lr-export-request` event and the host decides how to act on it.
1963
+
1964
+ Composes `<lr-data-grid>` for the row list, `<lr-chip>`/`<lr-chip-group>` as a toggleable,
1965
+ OR-matched tag-browse filter, `<lr-file-input>` for the import affordance, and
1966
+ `<lr-export-button>` for the export affordance (its own built-in client-side download is
1967
+ suppressed so every configured format routes through `lr-export-request` uniformly). Ships with a
1968
+ searchable free-text filter, RTL and 320px-allocation coverage, and localized strings with
1969
+ `.strings` override support.
1970
+
1971
+ - f5870ef: New `<lr-eval-result>`: rubric scoring, human review, and comparison across a single evaluation
1972
+ example's runs (one per model or prompt version), LangSmith/Arize-eval-result style. Composes
1973
+ three existing primitives directly rather than re-deriving their behavior: `<lr-data-grid>` renders
1974
+ the `runs` comparison table (`columns` is a plain pass-through to its own `DataGridColumn[]`
1975
+ shape); `<lr-rubric-form>` is the human-review scoring surface for whichever run is selected,
1976
+ reading/writing that run's own `review` value and re-emitting its
1977
+ `lr-input`/`lr-validity-change`/`lr-submit`/`lr-skip` events as
1978
+ `lr-review-input`/`lr-review-validity-change`/`lr-review-submit`/`lr-review-skip` with the run id
1979
+ attached; `<lr-diff-view>` compares the selected run's output against `baselineRunId`'s output --
1980
+ `layout="split"` once they resolve to two distinct runs, `layout="unified"` (an all-equal diff,
1981
+ i.e. a plain read of the one run's output) once they resolve to the same run or no baseline
1982
+ resolves at all. `selectedRunId`/`baselineRunId` are both fully controlled (never mutated
1983
+ internally) and fall back to `runs[0]?.id` purely for rendering when unset, so the component
1984
+ renders something useful with zero configuration beyond `runs`; a `selectedRunId`/`baselineRunId`
1985
+ that matches no entry in `runs` degrades gracefully (the comparison grid still renders, the
1986
+ review/diff sections simply don't).
1987
+ - 3827a19: New `<lr-evaluation-run>` component: an evaluation batch's live progress. An overall
1988
+ `<lr-progress-bar>` counts terminal (done/error/cancelled) examples against the batch's `total`
1989
+ (or `examples.length` when unset), with running/failed count badges alongside it. Each example
1990
+ renders as its own `<lr-details>` disclosure showing input/output via `<lr-markdown>` or
1991
+ `<lr-code-block>` (per `inputFormat`/`outputFormat`), a composed `<lr-grounding-summary>` when the
1992
+ example carries a `GroundingAssessment` (plus optional evidence `citations`), and a composed
1993
+ `<lr-tool-timeline>` when it carries `toolTrace` entries -- this component defines no grounding-
1994
+ scoring or tool-call rendering of its own. `status` reuses the shared `AgentStatus` contract from
1995
+ `@aceshooting/lyra-ui/ai/types`, the same run-lifecycle vocabulary an agent step already uses.
1996
+ Nested `<lr-grounding-summary>`/`<lr-tool-timeline>` selection and approval events are intercepted
1997
+ and re-emitted as this component's own `lr-example-citation-select`/
1998
+ `lr-example-tool-approval-decide`, correlated with the originating example's `id` so a host never
1999
+ needs to walk the DOM to find out which example a nested interaction came from. Per-example
2000
+ disclosure toggling fires `lr-example-toggle`. A live region announces per-example status
2001
+ transitions (started/completed/failed/cancelled/needs input/needs approval), gated so a freshly-
2002
+ mounted run never announces its initial statuses.
2003
+ - 0669f01: New `<lr-filter-bar>` component: a row of composable dashboard filters, each declared by the host
2004
+ (`filters: FilterBarFilterDefinition[]`) rather than invented by this component -- every filter
2005
+ renders an existing Lyra input (`<lr-select>`/`<lr-combobox>` for closed choice sets,
2006
+ `<lr-date-input>` in single or `mode="range"` for dates), plus a `<lr-chip-group>` of removable
2007
+ `<lr-chip>`s summarizing the active filters, an `<lr-button>` reset action, and (while `loading`)
2008
+ an `<lr-spinner>` status indicator. Controlled, like every other Lyra data component: `value` is a
2009
+ plain, JSON-serializable `FilterBarValue` object the host reads/writes directly -- this component
2010
+ never touches `location`/`history`/storage itself, so turning `value` into (and back out of) a URL
2011
+ querystring or app-state store is entirely the host's own concern. `required`-flagged filters get
2012
+ live `invalidFilterIds`/`checkValidity()`/`reportValidity()` and a `lr-validity-change` event, with
2013
+ each filter's own inline error rendered by its already-chromed composed control rather than a
2014
+ second, duplicate label/hint/error frame. `reset()` restores every filter to its own
2015
+ `defaultValue` (or unset) and emits both the standard `lr-input` and a dedicated `lr-reset`,
2016
+ mirroring `<lr-combobox>`'s own `clear()`/`lr-clear` pattern.
2017
+ - c5a4786: New `<lr-graph-query-builder>` component: an editor for a single typed relationship/path filter
2018
+ (`GraphQuery`) over a knowledge graph -- start/end entity anchors, relationship-type and
2019
+ node-type "add" pickers (`<lr-select>`) with a removable active-filter chip display
2020
+ (`<lr-chip>`/`<lr-chip-group>`), a traversal direction, a min/max hop range, validation
2021
+ (`value`/`checkValidity()`/`reportValidity()`/`lr-validity-change`, form-associated via
2022
+ `ElementInternals` the same way `<lr-rubric-form>`/`<lr-tool-param-form>` are), and a
2023
+ host-persisted saved-query list (`savedQueries` + `lr-query-save`/`lr-query-load`/
2024
+ `lr-query-delete`). `GraphQuery` is a serializable, provider-neutral query model suitable for
2025
+ handing straight to a GraphRAG retrieval/traversal backend via `value` or the `lr-query-run`
2026
+ event's payload.
2027
+ - a5723c3: New `<lr-grounding-summary>` component: the claim-level scorecard for one generated answer,
2028
+ consuming `GroundingAssessment` from `@aceshooting/lyra-ui`'s `src/ai/types.ts` directly as its
2029
+ `assessment` property. Composes `lr-stat` for the supported/unsupported claim counts, citation
2030
+ coverage, and optional confidence numeric displays (tone-mapped via a `thresholds` property), and
2031
+ `lr-citation-badge` for an optional `citations` list linking each evidence entry back to its exact
2032
+ `span`. Activating a citation badge emits `lr-citation-select` (detail: `{ citation }`, the
2033
+ `CitationSelectEventDetail` shape from `src/ai/types.ts`) carrying the full citation record, in
2034
+ addition to the badge's own `lr-citation-activate` still bubbling through unmodified. Warnings
2035
+ render verbatim as caller-supplied data; every other label is localized via `this.localize()`.
2036
+ - 497c8d3: New `<lr-ingestion-queue>` component: a controlled list of documents moving through an ingestion
2037
+ pipeline (`queued` → `uploading` → `extracting` → `chunking` → `embedding` → `indexing`, plus the
2038
+ terminal `done`/`failed`/`cancelled` stages), each row composing `lr-badge` for its stage label,
2039
+ `lr-progress-bar` for in-flight progress, and chunk-count/embedding-status/attempt-count text.
2040
+ `lr-empty` renders the zero-items state. Presentation only -- this component runs no ingestion
2041
+ itself and never mutates `items`; retrying a `failed` row or cancelling any non-terminal row fires
2042
+ a controlled `lr-retry`/`lr-cancel` request event (`detail` extends the shared `RetryEventDetail`/
2043
+ `CancelEventDetail` from `src/ai/types.ts` with the `itemId` identifying which row) and waits for
2044
+ the host to supply an updated `items` array, the same request/response convention
2045
+ `<lr-thread-list>`'s row-action events already establish. At or above `virtualizeThreshold` items
2046
+ the list renders through an internal `<lr-virtual-list>` instead of a plain keyed list, matching
2047
+ `<lr-thread-list>`'s data mode and `<lr-activity-feed>`'s own `virtualizeThreshold` precedent.
2048
+ - 593e879: New `<lr-knowledge-base>` component: a knowledge-base source list showing sync status, indexing
2049
+ health, and permissions per source, plus an aggregate summary row. A controlled data view -- it
2050
+ never syncs or indexes anything itself, only presents `sources: KnowledgeSource[]` and emits
2051
+ request-only `lr-kb-create`/`lr-kb-sync`/`lr-kb-pause`/`lr-kb-delete` events for the host to act on
2052
+ and reflect back into a new `sources` value, mirroring `lr-thread-list`'s `lr-thread-pin`/
2053
+ `-archive`/`-delete` convention. Composes `lr-table` for the source list (its own interactive-cell
2054
+ click guarding keeps the per-row `lr-menu` from misfiring row activation), `lr-badge` for the
2055
+ sync-status/indexing-health/permission indicators, `lr-stat` for the aggregate summary, and
2056
+ `lr-menu` for the per-row Sync now/Pause sync/Delete source actions.
2057
+ - f04b670: Add `<lr-knowledge-graph-explorer>`, an orchestration-level knowledge-graph surface composing the
2058
+ existing `lr-graph` canvas with entity search, type filters (via `lr-graph-legend`), neighborhood
2059
+ expansion, pinned nodes, path finding between pins (via `lr-path-strip`), node selection, and a
2060
+ node-details popover (via `lr-popover.showAt()` and `lr-entity-card`/`lr-neighbor-list`). Composes
2061
+ existing primitives rather than re-implementing graph rendering. New events `lr-path-request` and
2062
+ `lr-pin-change`; every composed primitive's own event (`lr-node-click`, `lr-node-expand`,
2063
+ `lr-selection-change`, `lr-community-click`, `lr-relation-activate`, etc.) bubbles straight through
2064
+ unmodified.
2065
+ - 593e879: New `<lr-memory-panel>` component: an agent's working memory surface -- short-term context and
2066
+ long-term memories, each item's confidence and optional grounding provenance, and add/remove/forget
2067
+ actions gated behind an explicit confirmation step. Composes `<lr-provenance-panel>` for a per-item
2068
+ provenance breakdown (behind a disclosure toggle, only rendered when an item defines one) and
2069
+ `<lr-confirm-bar>` for every add/remove/forget confirmation, reusing this repo's existing inline
2070
+ confirmation pattern rather than inventing a new one. A memory item's confidence reuses
2071
+ `<lr-citation-badge>`'s own confidence vocabulary, tiered against `thresholds` the same way
2072
+ `<lr-chunk-inspector>` tiers a chunk's relevance score. `shortTerm`/`longTerm` are controlled and
2073
+ never mutated by the component -- approving a pending action only fires the matching `lr-add` /
2074
+ `lr-remove` / `lr-forget` event; the host applies the resulting state change.
2075
+ - ac4857d: Add `showAt(rect, options?)` to `<lr-popover>` and `<lr-tooltip>`, a virtual-anchor API that opens
2076
+ the overlay positioned against an arbitrary rectangle (`{ x, y, width?, height? }`, defaulting to a
2077
+ zero-size point) instead of the slotted `trigger`. This lets a canvas/SVG surface -- a `<lr-graph>`
2078
+ node, a chart datum, a text-selection range -- get flip/shift/RTL-aware positioning, Escape,
2079
+ light-dismiss, and (optional, via `options.returnFocusTo`) focus-return for free, without a
2080
+ consumer hand-rolling absolute positioning and dismissal logic around it. Both components remain
2081
+ fully backward compatible: a component that never calls `showAt()` behaves byte-identical to
2082
+ before. `place()` (`src/internal/positioner.ts`) is widened from `HTMLElement` to `Element |
2083
+ VirtualAnchor` to support this, with no behavior change for existing real-element anchors.
2084
+ - 823f19b: New `<lr-policy-summary>` component: a read-only list of guardrail, permission, privacy, and
2085
+ tool-policy decisions, each carrying an `allow` / `deny` / `needs-review` state and an
2086
+ always-visible, accessible explanation of why that decision was made -- never conveyed by color
2087
+ alone. Composes `<lr-badge>` for the compact per-decision state indicator and `<lr-callout
2088
+ inline>` for the explanation text, whose own `role="alert"`/`role="status"` semantics already
2089
+ carry the right urgency per state, plus `<lr-details>` for a decision's optional richer `detail`
2090
+ (matched rule text, policy id, cited evidence) behind progressive disclosure. `decisions` is
2091
+ controlled and never mutated by the component -- this is a summary surface, not an approval gate
2092
+ (see `<lr-tool-approval-dialog>`/`<lr-confirm-bar>` for that).
2093
+ - c6dd883: New `<lr-query-builder>` component: a composable structured-query builder for tabular/dashboard
2094
+ data queries -- a flat list of field/operator/value condition rows combined with one AND/OR
2095
+ combinator. Distinct from `<lr-graph-query-builder>`, which builds typed relationship/path
2096
+ queries over a knowledge graph -- a genuinely different data model that never shares a file or a
2097
+ value type with this one.
2098
+
2099
+ Fully controlled: a host supplies `fields` (available columns, each carrying a
2100
+ `QueryBuilderFieldType` of `string` / `number` / `boolean` / `date` / `enum` that determines its
2101
+ offered operators and value control) and a plain, serializable `value: { combinator, conditions }`
2102
+ object, the same controlled-plain-object-`value` convention as `<lr-rubric-form>`. Each row
2103
+ composes `<lr-select>` for the field and operator pickers and a value control chosen from the
2104
+ selected field's type: `<lr-input type="text">`, `<lr-input type="number">`, `<lr-select>` with
2105
+ True/False options, `<lr-date-input>`, or `<lr-select>`/a multi-select `<lr-combobox>` for `enum`
2106
+ fields (`eq`/`neq` vs. `in`/`notIn`). A unary operator (`isEmpty`/`isNotEmpty`) renders no value
2107
+ control. `<lr-icon-button icon="trash">` removes a row and `<lr-button>` appends one, both
2108
+ surfaced through public `addCondition()`/`removeCondition(id)` methods and `lr-add-condition`/
2109
+ `lr-remove-condition`/`lr-input` events -- the component never mutates `fields`/`value` in place
2110
+ or touches storage/network itself.
2111
+
2112
+ - b443be6: New `<lr-retrieval-results>` component: the orchestration-level ranked-chunk-list surface for
2113
+ retrieval/grounding workflows, consuming `RetrievalChunk[]` from `@aceshooting/lyra-ui/ai/types`.
2114
+ Composes an internal `<lr-chunk-inspector>` per row (reusing its score bar, tier coloring, title/
2115
+ page rendering, expandable text, and `compact` mode verbatim -- no hand-rolled chunk-card markup)
2116
+ and an internal `<lr-virtual-list>` for windowing once the result count is large or `grouping` is
2117
+ active. Adds deduplication by `id` (keeping the higher-scoring duplicate), optional grouping by
2118
+ `source.id` (bucketed, best-scoring group first, same convention `<lr-thread-list>`'s date grouping
2119
+ already uses), multi-selection via a per-row `<lr-checkbox>` (`selectedIds` controlled, `lr-select`
2120
+ emits the updated ids and matching chunks), pagination/infinite loading (`has-more`/`loading`
2121
+ forwarded to the internal `<lr-virtual-list>` while virtualized, or a `[part="load-more"]` button
2122
+ otherwise -- both paths emit `lr-load-more`), and a `compact`/`expanded` `presentation` switch.
2123
+ `metadata` (arbitrary `Record<string, unknown>`, not rendered by any existing primitive) shows as a
2124
+ plain key/value list in `expanded` presentation. A row's `lr-chunk-open` is forwarded verbatim for
2125
+ routing into `<lr-document-viewer>`.
2126
+ - 5f2927f: New `<lr-retrieval-search>` component: the query bar for a retrieval/RAG surface, composing
2127
+ `lr-input` (query text), `lr-segmented` (vector/keyword/hybrid mode), `lr-chip`/`lr-chip-group`
2128
+ (removable active-filter/scope chips), `lr-spinner` (loading), and `lr-empty` (empty results).
2129
+ Fully controlled and network-free -- `query`/`mode`/`filters`/`scope` are host-owned properties,
2130
+ and the component only emits `lr-search` (detail: a `RetrievalQuery` from `@aceshooting/lyra-ui`'s
2131
+ `src/ai/types.ts`) on Enter or the submit button; the host performs the actual retrieval and
2132
+ toggles `loading` around it. Because this component has no way to know when a request resolves,
2133
+ submitting again while already `loading` is treated as superseding the in-flight request:
2134
+ `lr-cancel` fires immediately before the new `lr-search`, and the submit button itself doubles as
2135
+ an explicit Cancel affordance while `loading`. Filter/scope chip removal updates this component's
2136
+ own copy first, then emits `lr-filters-change` with the complete next `{ filters, scope }` state,
2137
+ mirroring `lr-source-picker`'s existing round-trip convention.
2138
+ - 3d6479f: New `<lr-retrieval-trace>` component: a retrieval pipeline's stage timeline (query rewriting,
2139
+ embedding, retrieval, reranking, filtering), rendered through `<lr-span-waterfall>`'s existing
2140
+ time-scaled bar rendering rather than a new timeline widget -- each `RetrievalStage` projects to
2141
+ one `LyraSpan`, with `kind` mapped onto whichever existing `LyraSpan['kind']` fits best (`embed`
2142
+ -> `'embedding'`, `retrieve` -> `'retriever'`, `query-rewrite` -> `'llm'`, `rerank`/`filter` ->
2143
+ `'tool'`). Below the timeline, a disclosure list exposes each stage's expandable evidence panel:
2144
+ free-form text, retrieved/reranked/filtered chunks via a compact `<lr-chunk-inspector>` (`chunks`
2145
+ accepts `RetrievalChunk` from `@aceshooting/lyra-ui/ai/types` directly), and/or arbitrary stage
2146
+ metadata as a key/value list. Controlled `stages`/`activeStageId` properties; emits `lr-stage-select`
2147
+ and `lr-stage-toggle`. Never fetches, ranks, or computes retrieval results itself.
2148
+ - 5597050: `lyra-thread-list` gains a `renderActions?: (thread: ChatThread) => TemplateResult` data-mode
2149
+ property, an escape hatch for a fully custom per-row action surface (e.g. a `<lr-menu>` with
2150
+ Rename/Delete, a rename dialog, delete-confirmation state) that the existing `rowActions`'s closed
2151
+ `pin | archive | delete` set can't express. Its content is appended after any built-in `rowActions`
2152
+ buttons in the same row's `actions` slot -- additive, not a replacement, the same composition
2153
+ direction `wrapRow` already takes elsewhere on the row. Set `rowActions` to `[]` (its default) to
2154
+ use only the callback's content. `renderActions` is re-invoked per row on every render with the
2155
+ current thread (never memoized/stale) and its content sits as a DOM sibling of the row's own
2156
+ selectable region, so activating a custom action never also fires `lr-select` -- the same
2157
+ structural mechanism the built-in row-action buttons already rely on. Leaving `renderActions`
2158
+ unset leaves `rowActions`' rendered output byte-for-byte unchanged, and `wrapRow` continues to
2159
+ compose independently around the result either way.
2160
+ - c67e88b: New `<lr-tool-timeline>` component: a chronological list of an agent run's tool calls, rendering
2161
+ each entry through `<lr-tool-call-chip>` (name/status/duration) and `<lr-tool-result-view>`
2162
+ (args/result) -- both already built for exactly this -- plus one shared `<lr-tool-approval-dialog>`
2163
+ for entries gated behind a human decision. Its own job is strictly ordering and layout on top of
2164
+ those existing primitives: `entries` (a new `ToolTimelineEntry[]`, extending `ToolInvocation` from
2165
+ `@aceshooting/lyra-ui/ai/types` with `startedAt`/`endedAt`, `retryCount`, `redactedFields`,
2166
+ `needsApproval`, and `approved`) sorts ascending by `startedAt`, with untimed entries trailing in
2167
+ their original relative order; duration is derived from `startedAt`/`endedAt` and handed to the
2168
+ chip's own `durationMs`; a retry badge renders only while `retryCount > 0`; and per-entry
2169
+ `redactedFields` (dotted paths, or a bare `"args"`/`"result"`/`"error"` for a whole branch) mask
2170
+ sensitive values in the read-only detail view with a "Value hidden" placeholder -- the copy of
2171
+ `args` handed to the approval dialog is always the real, unredacted value, since approving a call
2172
+ requires seeing what will actually run. Activating a pending entry's chip opens the shared dialog;
2173
+ approving or denying it emits this component's own `lr-tool-approval-decide`
2174
+ (`{ invocationId, approved, args? }`, extending the shared `ToolApprovalEventDetail`) and never
2175
+ mutates `entries` itself -- a host applies the decision and re-assigns `entries`, and the dialog
2176
+ closes on its own if the entry under review disappears or resolves out from under it in the
2177
+ meantime.
2178
+
2179
+ ## 4.0.0
2180
+
2181
+ ### Major Changes
2182
+
2183
+ - cf2cbbb: Release 4.0.0 renames the public custom-element, event, and design-token prefixes from
2184
+ `lyra-*`/`--lyra-*` to `lr-*`/`--lr-*`. The package name, JavaScript `Lyra*` class names,
2185
+ and `lyra-ui` repository/package paths remain unchanged. This is a breaking migration:
2186
+ update element tags, library-specific event names, and CSS custom-property overrides.
2187
+
2188
+ ### Minor Changes
2189
+
2190
+ - cf2cbbb: New `lr-control-group` primitive: a responsive layout wrapper (`role="group"`, `flex-wrap: wrap`,
2191
+ `align-items: center`) for a row of mixed form controls and action buttons — a segmented switcher
2192
+ beside a select and an export button, for example. Distinct from `lr-button-group` (which
2193
+ stretches uniform-height buttons to a shared row height): `lr-control-group` centers children of
2194
+ differing intrinsic heights instead, since it makes no assumption about child type. Gap is
2195
+ themeable via `--lr-control-group-gap`.
2196
+ - aa1fb49: `lr-segmented` gains a `size: '2xs' | 'xs' | 's' | 'm' | 'l' | 'xl' = 'm'` property, matching
2197
+ `lr-select`/`lr-combobox`'s compact-form-control scale (`xs`-`xl`) plus `lr-input`'s `2xs`
2198
+ tier. `size="s"` now renders at the same control height as `lr-select size="s"`/
2199
+ `lr-combobox size="s"`, so a segmented metric switcher can sit flush beside a compact select or
2200
+ combobox in the same toolbar without consumer CSS reaching into `::part(base)`. The default `m`
2201
+ tier is pixel-identical to this component's previous, only rendering.
2202
+
2203
+ ### Patch Changes
2204
+
2205
+ - 5266832: Fixed `lr-select`'s `size="xs"`/`"s"`/`"l"`/`"xl"` to actually enforce their documented
2206
+ per-size minimum trigger height. A `var()` fallback bug meant `--lr-select-trigger-min-height`
2207
+ was silently dead code at every size — only padding and font-size ever varied, height did not.
2208
+ The default (`m`) tier's rendering is unchanged; a consumer-set `--lr-select-trigger-height`
2209
+ override still wins over the per-size floor, as before.
2210
+
2211
+ ## 3.9.0
2212
+
2213
+ ### Minor Changes
2214
+
2215
+ - abdd967: `lr-activity-feed` gains `renderText?: (entry: ActivityEntry) => TemplateResult`, overriding the
2216
+ default plain-text `[part="entry-text"]` rendering with arbitrary rich content — rendered markdown,
2217
+ or markdown plus a trailing tool-call chip list — identically whether or not the feed is currently
2218
+ virtualized, since both the plain and virtualized paths render every entry through the same
2219
+ internal template. Previously `ActivityEntry.text` could only ever render as plain escaped text,
2220
+ with no way to attach richer per-entry content.
2221
+ - b64d4d2: `lr-graph` gains `dimmedNodeIds`/`dimmedLinkIds` (controlled, mirroring
2222
+ `selectedNodeIds`/`selectedLinkIds`): a host can now apply a themeable low-opacity treatment to
2223
+ arbitrary nodes/links -- e.g. dimming every non-neighbor of a hovered node -- via a new
2224
+ `--lr-graph-dimmed-opacity` custom property, in both the `svg` (default) and `canvas` renderers.
2225
+ Previously the only way to express this was reaching into the shadow DOM; `1` (no-op) by default,
2226
+ so existing usage is unaffected.
2227
+ - 1d1935e: `lr-input` gains `'search'` as a documented `LyraInputType` member. It already worked at runtime
2228
+ via unchecked passthrough to the internal native `<input type="search">` (`type` has no runtime
2229
+ validation), but the exported type union didn't include it, so a consumer setting `type="search"`
2230
+ got no compile-time confirmation it was supported and no protection against a future stricter-typed
2231
+ release silently dropping it.
2232
+ - f6b4957: New `<lr-markdown-core>` entry point: a build-lean variant of `<lr-markdown>` for a consumer
2233
+ whose `languages` map already covers every language it renders, mirroring the existing
2234
+ `<lr-code-block>`/`<lr-code-block-core>` split. Its own module never imports shiki's ~200-
2235
+ language default dynamic-import table -- `<lr-markdown>`'s existing `languagesOnly` flag can't
2236
+ give a bundler that guarantee, since it's checked at runtime, not statically provable. Every other
2237
+ capability (GFM, heading anchors, text-quote highlights, math) is unchanged from `<lr-markdown>`;
2238
+ a fenced block whose language isn't in `languages` always renders the plain-text fallback.
2239
+ - 0a5227e: `lr-thread-list` gains `wrapRow?: (thread: ChatThread, row: TemplateResult) => TemplateResult`
2240
+ (data mode only): wraps each row's built-in `lr-conversation-item` with host-supplied content
2241
+ that has no home in the item's own `title`/`excerpt`/`meta`/`actions` surface — most notably a
2242
+ leading purpose icon, since `lr-conversation-item` has no default slot to receive one at all.
2243
+ Previously data mode forced an all-or-nothing choice between its built-in grouping/virtualization
2244
+ and a host's need for row content outside that surface, which only slotted mode (no grouping, no
2245
+ virtualization) could accommodate.
2246
+ - d3f2e13: `lr-usage-badge` gains `formatLatency?: (ms: number) => string`, overriding the built-in duration
2247
+ algorithm (which has no minutes/hours tier — `'{ms}ms'`, or one-decimal seconds above 1000ms) in
2248
+ both the visible strip and the tooltip row. Mirrors `lr-activity-feed`'s `formatTimestamp`
2249
+ convention. Previously a consumer whose latencies commonly exceed a minute (e.g. a long-running
2250
+ agent run) had no way to render its own duration scale instead of a bare seconds count.
2251
+
2252
+ ## 3.8.0
2253
+
2254
+ ### Minor Changes
2255
+
2256
+ - c4cb188: Adds `<lr-activity-feed>`: an append-only streaming log of granular agent actions, collapsing to
2257
+ a localized "Completed N steps" summary once the run is over. Implements the shared follow
2258
+ (stick-to-bottom) contract (`follow` property, `lr-follow-change` event) and virtualizes its body
2259
+ through an internal `<lr-virtual-list>` at/above `virtualizeThreshold` entries, using that
2260
+ component's `scrollToIndex()` method to drive its stick-to-bottom follow. `<lr-virtual-list>`
2261
+ also gains `aria-label` forwarding from the host element onto its internal `role="list"`
2262
+ container, usable independently of `<lr-activity-feed>`.
2263
+ - 5a0276e: Adds an internal, dependency-free ANSI/SGR parser (`src/internal/ansi.ts`, not a public export) —
2264
+ shared groundwork for `lr-terminal`'s streamed console-output rendering. No public API surface
2265
+ change on its own; ships alongside the `lr-terminal` component in the same release.
2266
+ - b92b5d4: Adds `<lr-artifact-panel>`: a shell around one generated artifact — title/kind header, a
2267
+ preview↔code toggle (rendered only once the `code` slot has content), version navigation with a
2268
+ "Restore this version" affordance (`lr-version-change`/`lr-restore`, versions are host state),
2269
+ `streaming`/`aria-busy` state, and built-in copy/download actions. Renders none of the artifact
2270
+ itself — content is slotted.
2271
+ - cf005b9: `lr-attachment-trigger` gains an `'audio'` capability, following the existing `camera` capability's
2272
+ request-only pattern exactly: activating it fires `lr-audio-request` (no embedded recorder), and the
2273
+ host opens its own capture UI — typically `<lr-push-to-talk>` in a `<lr-overlay>`/popover — then
2274
+ hands the resulting blob to its attachment tray. Purely additive: the default `capabilities` stays
2275
+ `['files']`, and every existing `files`/`image`/`camera` behavior is unchanged.
2276
+ - b85934b: Adds `<lr-audio-visualizer>`: a presentational, canvas-drawn voice-activity visualization (bars or
2277
+ waveform), driven by a `MediaStream` (lazily wired to a WebAudio analyser), a numeric `level`, or a
2278
+ `state` (`idle`/`listening`/`thinking`/`speaking`) alone for an ambient animation. Pairs with
2279
+ `lr-push-to-talk`'s `stream`/`lr-level` output. Zero dependencies — native Web Audio only,
2280
+ reduced-motion-aware.
2281
+ - 3310f16: Adds `<lr-av-player>`: an audio/video player built on a native media element with a cue transcript
2282
+ synced to playback, `time-range` anchor/highlight support, an optional dependency-free waveform
2283
+ (peaks-in, no in-component decoding), playback-rate control, and imperative transcript search.
2284
+ Self-registers into the document-viewer registry for the common audio/video MIME types. Owns
2285
+ recorded-media transcript sync — distinct from `lr-transcript-feed` (live voice-session captions)
2286
+ and from `lr-playback` (an index stepper, no media).
2287
+ - 0fe240b: Adds `<lr-branch-picker>`: a controlled "‹ 2 / 5 ›" navigator across regenerated/edited variants of
2288
+ one chat message, mirroring `lr-pagination`'s "never mutates its own state" contract. Fires
2289
+ `lr-branch-change` with the requested (always in-bounds) index; the host swaps the displayed branch
2290
+ content and applies the new index back. Designed to slot into `lr-message-actions`' default slot or
2291
+ directly into `lr-chat-message`'s `actions`/`badges` slots.
2292
+ - bc75a1f: Adds `<lr-browser-frame>`: a presentational "agent computer" viewport — a safe-URL-gated
2293
+ screenshot/frame stream `<img>` (or slotted live media), read-only address bar, visible (never
2294
+ color-only) connection status, kind-distinct action-ping overlays, and take-over/stop affordances
2295
+ (`lr-take-over`, `lr-stop`). No automation transport and no input relay — take-over is an event;
2296
+ the host swaps in its own interactive element.
2297
+ - e29f575: `lr-button` and `lr-input` gain `size="2xs"`, a sub-`xs` tier for dense, toolbar-embedded controls
2298
+ (e.g. a search input and text buttons inside a compact dialog header). Composes with `appearance`/
2299
+ `variant` the same way the existing five sizes already do.
2300
+ - e4762fd: `lr-button` gains `appearance="quiet"`: a bordered, transparent-until-hover tier for a toolbar-style
2301
+ icon+label action whose border/text read fixed `--lr-color-border`/`--lr-color-text-quiet` tokens
2302
+ regardless of `variant`, unlike `appearance="outlined"`'s variant-tinted text — for a call site that
2303
+ needs a genuinely muted resting state rather than a bold bordered button. New
2304
+ `--lr-button-quiet-border`/`--lr-button-quiet-text` custom properties back the two tokens.
2305
+ - 4ac983b: `lr-chat-message` gains `actionsOutsideBubble` (reflects to `actions-outside-bubble`): renders the
2306
+ `actions` slot's content as a sibling immediately after the message bubble instead of nested inside its
2307
+ footer's own padding/background box. Previously a consumer whose action row (e.g. a hover-reveal copy
2308
+ button) had to sit visually outside the bubble's chrome could not adopt this component at all, since
2309
+ `::part(footer)` styling alone cannot detach it from the bubble's box.
2310
+ - 65a1f8c: Adds `<lr-chat-viewport>`: the transcript scroll container for a chat/agent conversation surface —
2311
+ owns the stick-to-bottom `follow` state machine (`follow` property, `lr-follow-change` event,
2312
+ matching the same shared follow contract `<lr-activity-feed>` already implements) while an answer
2313
+ streams, a built-in "jump to latest" pill with a pluralized unread count, and an unread divider. Two
2314
+ content shapes are auto-detected: ordinary element children (slotted mode) or exactly one
2315
+ `lr-virtual-list` (virtual mode, built on that component's `scrollToIndex()` method). Renders no
2316
+ messages and computes no unread state itself — the host supplies `unreadStartIndex` and slots its
2317
+ own message elements or a virtual list.
2318
+ - bf601c8: Adds `<lr-checkpoint>`: an inline conversation restore point — a labeled marker between messages
2319
+ whose Restore affordance confirms inline (an accessible-name-carrying button swap, focus-managed,
2320
+ Escape/focus-out-aware) before firing a `lr-restore { checkpointId, label }` event. Persists and
2321
+ restores nothing itself — host state in, events out. `confirmRestore="false"` skips the inline
2322
+ confirm step entirely; `restorable="false"` renders a plain, non-interactive marker for read-only
2323
+ views or the currently-restored point.
2324
+ - 22c1006: Adds `<lr-chunk-inspector>`: a ranked retrieved-chunks "why this answer" panel — relevance score
2325
+ bars with tier-mapped tones, expandable chunk text (state keyed by chunk id, survives streaming
2326
+ reassignment), and `lr-chunk-open` for landing a chunk in `lr-document-viewer` with its anchor.
2327
+ Virtualizes automatically above `virtualizeAt` rows via the existing `lr-virtual-list`.
2328
+ - c274bd6: `lr-code-block` and `lr-code-block-core` gain `highlight-lines` (declarative `"3-5,7"`-style
2329
+ line emphasis), `interactive-lines` (turns the line-number gutter into a keyboard-navigable,
2330
+ clickable roving-tabindex group emitting `lr-line-click`), and `line-range` anchor-target support
2331
+ (`highlights`, `activeHighlightId`, `scrollToAnchor()`, event `lr-text-select`) — identical on
2332
+ both components since they share the new line-addressing logic. Previously there was no way to
2333
+ emphasize or deep-link to a specific line/range of lines in a rendered code block.
2334
+ - f71fcac: Adds `<lr-commit-card>`: a compact commit summary card — abbreviated/copyable hash, subject/body
2335
+ message split, author/time meta, a non-color-only aggregate `+N -M` diffstat, and a collapsible
2336
+ per-file change list (`lr-file-select` on activation) reusing `lr-file-tree`'s `GitStatus`
2337
+ vocabulary and shared `gitStatus*` labels.
2338
+ - 22c1006: Adds `<lr-community-card>`: a GraphRAG community-report card — label, summary excerpt, member
2339
+ count, member chips with a "+N" overflow chip, and a drill-in action (`lr-drill`) surfaced from
2340
+ the header, an explicit drill button, and the overflow chip alike. A `compact` mode renders just
2341
+ title + member count + drill button for dense listings (e.g. inside `lr-provenance-panel`).
2342
+ - 1432601: Add `lr-compare-panel`: side-by-side A/B output comparison with a winner vote (LMSYS-arena /
2343
+ LangSmith-pairwise style) — two slotted panes (`a`/`b`), an optional shared `prompt` header, a
2344
+ `role="group"` vote bar (better-A / better-B / tie / both-bad, the last two individually
2345
+ hideable), and optional proportional `syncScroll` between panes. No hotkeys (slotted content may
2346
+ contain inputs); casting a vote announces through an internal live region.
2347
+ - bc75a1f: Adds `<lr-confirm-bar>`: an inline, non-modal approve/deny block for one proposed action — the
2348
+ in-flow sibling of `lr-tool-approval-dialog` for confirmations that belong in the transcript instead
2349
+ of an overlay. Same `lr-approve`/`lr-deny` event shapes and the same heading/args-label/deny/approve
2350
+ localization keys as the dialog, so the two stay in lockstep. No focus trap, scroll lock, or
2351
+ Escape/backdrop handling; on activation, focus moves synchronously to the always-present decided-state
2352
+ text before the Deny/Approve buttons unmount, and an internal live region announces the outcome.
2353
+ - 23bfb7b: `lr-conversation-item` gains a `meta` slot (small, non-focusable structured fields below the
2354
+ title/excerpt — e.g. a day label, project name, cost) and an `excerpt` slot that wins over the
2355
+ existing `excerpt` property whenever it has assigned content, mirroring `lr-timeline-item`'s own
2356
+ `timestamp` slot-wins-over-property pattern. Previously a consumer needing a rich excerpt (e.g. a
2357
+ search-hit snippet with `<mark>` highlighting) or a multi-field meta line had to flatten that
2358
+ structure into the plain-text `excerpt` property or hand-roll the row entirely.
2359
+ - 2ad038b: `lr-dataset-viewer` now virtualizes through `lr-virtual-list` (a new `item-role="row"` mode,
2360
+ mapping to a proper `role="table"`/`role="row"`/`role="rowgroup"` accessibility tree) instead of a
2361
+ single synchronous `<table>`, lifting its row cap from 1,000 to the shared 10,000-row default every
2362
+ other tabular viewer already uses. It also gains `cell-range` anchor-target support (`highlights`,
2363
+ `activeHighlightId`, `scrollToAnchor()`, event `lr-highlight-activate`) and an imperative
2364
+ in-document search API (`search()`, `searchNext()`, `searchPrevious()`, `clearSearch()`, event
2365
+ `lr-search-change`), sharing the same raw-grid cell addressing as `lr-csv-viewer`, with the
2366
+ header row always included since this viewer always parses with PapaParse's `header: true`. The
2367
+ `lyra:dataset` document-viewer registration now declares `capabilities: { anchors: ['cell-range'],
2368
+ search: true, textSelect: false }`. `lr-virtual-list` itself gains the underlying
2369
+ `item-role`/`row-index-offset` properties this required, additive and defaulting to today's exact
2370
+ `listitem` behavior for every other consumer. Previously a 1,001+ row dataset file failed to load at
2371
+ all, and there was no way to highlight or search a cell.
2372
+ - 2ad038b: `lr-diff-view` gains `layout="split"` (two side-by-side columns derived from the same line-diff
2373
+ alignment as the default unified view — unbalanced replace hunks pad the shorter side with empty
2374
+ placeholder rows) and optional syntax highlighting via `language`/`languages` (same fine-grained
2375
+ shiki-core-only shape as `lr-code-block-core`, so the peer-free default stays truly peer-free).
2376
+ Previously diff-view only rendered a single interleaved unified view with no highlighting option.
2377
+ - dc168c7: `lr-docx-viewer` gains `getHeadingTree()` (a document-ordered heading outline stamped with
2378
+ GitHub-slugger-style ids, using the same slugging algorithm as `lr-markdown`), `fragment`/
2379
+ `text-quote` anchor-target support (`highlights`, `activeHighlightId`, `scrollToAnchor()`, events
2380
+ `lr-highlight-activate`/`lr-text-select`/`lr-anchor-result`), and an imperative in-document
2381
+ search API (`search()`, `searchNext()`, `searchPrevious()`, `clearSearch()`, event
2382
+ `lr-search-change`). Previously there was no way to deep-link into a section, highlight a quoted
2383
+ passage, or search inside a rendered Word document.
2384
+ - d3edf31: `lr-ebook-viewer` gains `getToc()` (a flat, nested table of contents from the EPUB's own
2385
+ navigation document), a `location` property (get/set the current CFI or spine href, with
2386
+ `lr-location-change` on user navigation), an imperative in-book search API (`search()`,
2387
+ `searchNext()`, `searchPrevious()`, `clearSearch()`, event `lr-search-change`), and `cfi`/
2388
+ `text-quote` anchor-target support (`highlights`, `activeHighlightId`, `scrollToAnchor()`, events
2389
+ `lr-highlight-activate`/`lr-text-select`). Previously there was no way to read an EPUB's table
2390
+ of contents, deep-link into a specific location, or search inside a rendered book.
2391
+ - 2ad038b: `lr-email-viewer` attachments become interactive: each row is now a real button emitting
2392
+ `lr-attachment-open { attachment: { filename, mimeType, content } }` with the attachment's decoded
2393
+ bytes attached (the component itself never opens/downloads anything — host-owned routing, e.g. into
2394
+ `lr-document-viewer`). A new `fold-quotes` property collapses trailing quoted-reply text/HTML
2395
+ (`>`-prefixed text runs, `gmail_quote`/`yahoo_quoted`/Outlook-style HTML blocks) behind a localized
2396
+ toggle. Previously attachments were inert metadata with no way to retrieve their content, and quoted
2397
+ reply chains always rendered in full.
2398
+ - ba094cb: Adds `<lr-emoji-picker>`: a searchable, keyboard-navigable, form-associated emoji picker
2399
+ (`value`/`lr-change`, matching this library's other form-control conventions). `groups` is fully
2400
+ consumer-suppliable — this component ships no emoji data of its own — with an optional convenience
2401
+ auto-loader for a default set via the `emoji-picker-element-data` peer when `groups` is left unset.
2402
+ Lets a consumer currently wrapping the third-party `emoji-picker-element` custom element (plus its
2403
+ locale-data package) as a direct dependency replace it with a first-party `lr-*` component instead.
2404
+ - 22c1006: Adds `<lr-entity-card>`: a dossier card for one knowledge-graph entity (`LyraEntity`) — type
2405
+ badge, description, key/value property rows, relationship-degree and community rows, and a
2406
+ built-in "focus in graph" action that emits `lr-entity-activate` for a host to route into
2407
+ `lr-graph`'s `focusNode()`.
2408
+ - 22c1006: Adds `<lr-entity-chip>`: an inline `@entity` mention for agent prose with a hover/focus preview
2409
+ popover, reusing `lr-citation-badge`'s interaction contract wholesale (200ms hover-leave grace,
2410
+ independent hover/focus hold-open state, Escape dismissal, Space opens/Enter activates). The
2411
+ knowledge-graph sibling of `lr-citation-badge` — renders its `label` text rather than a `[n]`
2412
+ index, and reflects `type` for host-level per-type theming.
2413
+ - 2ab49e6: Adds `<lr-env-list>`: a masked key/value list for environment variables and secrets
2414
+ (`<dl>`/`<dt>`/`<dd>` semantics), defaulting every entry to masked (a fixed eight-bullet run,
2415
+ length-independent so value length is never leaked) with per-row reveal (`lr-reveal-change`, state
2416
+ keyed by name and position, and reset for a row whose name shifts position) and copy (`lr-copy`,
2417
+ always copies the real value). `revealable=false` for screen-share-safe hosts. Masking is
2418
+ presentational, not a security boundary.
2419
+ - 892c9d3: Adds `<lr-file-tree>`: a file-explorer preset over `lr-tree` + `lr-file-icon` with path-keyed
2420
+ nodes, per-file git-status badges and `+N -M` diffstat, lazy directory loading (`setChildren()`,
2421
+ `lr-load-children`), `revealPath()`, and `lr-file-select`/`lr-file-open` events (matching the
2422
+ "Enter/click on an already-selected file opens it" keyboard parity rule).
2423
+ - 22c1006: Adds `<lr-flow-canvas>`: a dependency-free, pannable/zoomable DAG workflow canvas — HTML card
2424
+ nodes with typed connection handles, SVG Bézier edges with arrowheads and labels, a shared layered
2425
+ auto-layout for unpositioned nodes, and controlled selection/drag/connect gestures behind three
2426
+ independent opt-in flags (`nodes-draggable`, `connectable`, `droppable`). Readonly viewer by default;
2427
+ never mutates `nodes`/`edges` itself. Ships a `registerCompanion()` hook so `lr-flow-minimap`,
2428
+ `lr-flow-controls`, and `lr-flow-run-overlay` (following in subsequent releases) can attach
2429
+ without reaching into its shadow DOM.
2430
+ - 22c1006: Adds `<lr-flow-controls>`: the zoom in/out, fit, and interaction-lock button cluster for
2431
+ `lr-flow-canvas`, so every flow surface ships the same affordances without hosts rebuilding them.
2432
+ Zoom buttons disable at the resolved canvas's `minZoom`/`maxZoom` bounds; the lock toggle stays in
2433
+ sync with the canvas's `locked` attribute regardless of what changed it.
2434
+ - 22c1006: Adds `<lr-flow-minimap>`: a corner overview map for `lr-flow-canvas` — scaled node rectangles
2435
+ (status-tinted) plus a draggable, keyboard-operable viewport rectangle for orientation and fast
2436
+ navigation on canvases larger than the screen. Attaches via `registerCompanion()`, either slotted
2437
+ into one of the canvas's corner slots or externally via `for="canvas-id"`.
2438
+ - 22c1006: Adds `<lr-flow-node>`: the workflow node card — header/body/toolbar chrome, tool-lifecycle status
2439
+ tones with a visible (never color-only) status chip, a determinate progress bar, and named
2440
+ connection-handle elements. Used automatically by `lr-flow-canvas` as the default card for any
2441
+ node without a slotted override, and usable standalone for palette previews or docs.
2442
+ - 22c1006: Adds `<lr-flow-run-overlay>`: execution-state presentation for `lr-flow-canvas` — mirrors a
2443
+ `FlowRunDecorations` map into the resolved canvas (which owns the actual node/edge paint) and
2444
+ renders a compact "{done} of {total} steps complete" summary strip with per-status counts.
2445
+ Status transitions announce through a throttled live region. Pure pushed state — no execution,
2446
+ polling, or internal clock.
2447
+ - 2ad038b: Adds an internal `application/geo+json` document-viewer registry bridge (`<lr-geojson-view>`,
2448
+ `.geojson` filename matching included): fetches and validates a GeoJSON `Feature`/`FeatureCollection`/
2449
+ bare-geometry payload, computes a bounding-box fit, and renders it through `lr-map`'s new
2450
+ `dataLayers` property with a feature-count status line. Falls back to `lr-json-viewer` with a
2451
+ missing-library callout when the optional `maplibre-gl` peer isn't installed. Not a documented public
2452
+ tag this round — importing `geojson-view/geojson-view.js` opts a host into the bridge, matching how
2453
+ `lr-map`/`lr-graph`/the chart family already stay out of the root barrel import.
2454
+ - ca9258f: `lr-graph` gains `renderer: 'svg' | 'canvas'` (default `'svg'`, unchanged). `'canvas'` swaps the
2455
+ per-node/per-link SVG DOM for a single DPR-aware `<canvas>` (reusing `lr-heatmap`'s proven backing-
2456
+ store/resize/DPR-watch machinery), targeting roughly 5,000 nodes / 10,000 links versus SVG's ~500/
2457
+ ~1,500 ceiling. Hit-testing uses an offscreen color-picking canvas (exact hits for all three node
2458
+ shapes, stroked/dashed links, and hull blobs, one code path, zero new dependencies); pointer drag,
2459
+ click, double-click-to-expand, and hover tooltips all work via that same hit-test. Keyboard/screen-
2460
+ reader parity is preserved through an offscreen virtual-cursor button list driving the identical
2461
+ roving/announcement logic as SVG mode — the honest v1 trade-off is no `::part(node)`/`::part(link)`
2462
+ styling (pixels, not elements) and a drawn focus ring instead of a CSS one, both documented. Fully
2463
+ additive — the default `renderer: 'svg'` reproduces today's DOM exactly.
2464
+ - c6ab7c8: `lr-graph` gains `GraphNode.communityId` and a `communities` property, rendering one translucent
2465
+ convex-hull blob per entry (membership = union of `memberIds` and matching `communityId`) behind
2466
+ links/nodes. Hulls are keyboard/click-activatable (`lr-community-click`), join the roving focus
2467
+ ring after nodes and links, and are included in `fit()`'s bounding-box calculation. Fully additive
2468
+ — an empty `communities` array (the default) renders no hulls and leaves the roving ring/`fit()`
2469
+ behavior unchanged.
2470
+ - c996af0: `lr-graph` gains `showEdgeLabels` (default `false`) to draw each link's `label` as visible SVG
2471
+ text at the segment midpoint, and `edgeLabelMinZoom` (default `0.6`) to hide all edge labels below
2472
+ that zoom scale. A per-label length gate also hides a label whose measured text width exceeds 85%
2473
+ of its edge's current on-screen length. Labels are `aria-hidden` (the accessible name already
2474
+ carries `label` via the existing link announcement) and fully opt-in — a graph that never sets
2475
+ `showEdgeLabels` renders no edge-label DOM at all.
2476
+ - 7f7511a: `lr-graph` gains a double-activate expand gesture: double-clicking a node, or activating the same
2477
+ focused node twice via Enter/Space within 500ms, emits `lr-node-expand { id }`. A new
2478
+ `GraphNode.expandable` flag renders a "+" badge and adds "expandable" to the node's spoken text. A
2479
+ node newly linked to an already-positioned neighbor (e.g. appended after an expand) now spawns near
2480
+ that neighbor instead of a random position. Fully additive — no existing click/keyboard behavior
2481
+ changes, and a graph that never sets `expandable` never renders the badge (though the
2482
+ `lr-node-expand` event itself fires for any double-activated node, matching native
2483
+ dblclick semantics).
2484
+ - 5d77b48: `lr-graph` gains a programmatic camera (`focusNode(id, { zoom? })`, `fit({ padding? })`, both
2485
+ reduced-motion-aware rAF tweens that keep d3-zoom's own state consistent), a declarative
2486
+ `focusId` twin (centers once, renders a persistent `focus-halo` ring), and a controlled selection
2487
+ model (`selectionMode: 'none' | 'single' | 'multiple'`, `selectedNodeIds`/`selectedLinkIds`,
2488
+ `lr-selection-change`) mirroring `lr-heatmap.selectedCell`'s controlled contract — the
2489
+ component only ever emits intent, never assigns the selection props itself. Fully additive: default
2490
+ `selectionMode: 'none'` and unset `focusId` reproduce today's behavior exactly.
2491
+ - 844fe95: `lr-graph` gains `lr-node-enter`/`lr-node-leave`/`lr-link-enter`/`lr-link-leave` hover
2492
+ events (mirroring the existing `lr-node-click`/`lr-link-click` detail shapes) plus a `data-hovered`
2493
+ attribute toggled on the hovered node/link element for pure-CSS theming. Both are suppressed while a
2494
+ drag or pan gesture is in progress, so a drag crossing over other nodes/links doesn't spam
2495
+ enter/leave pairs. Previously a consumer computing an adjacency-based neighbor highlight on hover
2496
+ (e.g. dimming every unconnected node/link) had no way to observe which node/link was currently
2497
+ hovered from outside the component.
2498
+ - f8d6b9e: `lr-graph` gains `layout: 'force' | 'layered'` (default `'force'`, unchanged). `'layered'`
2499
+ computes a deterministic Sugiyama-lite layout instead of running d3-force — longest-path layering,
2500
+ barycenter crossing reduction, cycle-safe (back edges reversed internally, the caller's data is
2501
+ never mutated). The algorithm itself lives in a new shared, dependency-free
2502
+ `src/internal/layered-layout.ts`, a standalone util suitable for any future layered-diagram
2503
+ consumer. Node drag is disabled in layered mode; pan/zoom, keyboard, focus/fit, hulls, edge labels,
2504
+ and type filtering all work identically to force mode. Fully additive — the default `layout:
2505
+ 'force'` reproduces today's simulation-driven layout exactly.
2506
+ - 22c1006: Adds `<lr-graph-legend>`: a node-type legend for a paired `lr-graph`, rendering one swatch +
2507
+ label + count row per §3.4 node type and doubling as a visibility filter. Event-decoupled from any
2508
+ graph instance — a host forwards `graph.nodeTypes` in as `types` and forwards
2509
+ `lr-visibility-change`'s `hiddenTypes` back out to `graph.hiddenTypes`.
2510
+ - 942798e: `lr-graph` gains `GraphNode.type` and a new `nodeTypes` property declaring each type's legend
2511
+ label, fill color, and shape (`circle`/`square`/`diamond`). Fill resolution precedence is
2512
+ `node.color` > the type's own color > an ordered categorical fallback palette
2513
+ (`--lr-graph-cat-1`…`--lr-graph-cat-8`, new tokens) by the type's index in `nodeTypes` > the
2514
+ existing untyped default. Typed nodes also gain richer spoken text ("{label} ({type})"). Fully
2515
+ additive — a graph with no `type`/`nodeTypes` set renders identical circles, unchanged.
2516
+ - 32f7b12: `lr-graph` gains `hiddenTypes: string[]`, hiding every node whose `type` is listed (plus incident
2517
+ links) from rendering, the simulation, the keyboard roving ring, and the accessible data list/
2518
+ counts. Positions round-trip via a new remembered-position cache, so toggling a type off and back
2519
+ on restores each node where it was instead of re-randomizing. Fully additive — an empty
2520
+ `hiddenTypes` (the default) renders every node/link exactly as before.
2521
+ - e022166: Adds `<lr-handoff-divider>`: a labeled semantic separator marking control transfer between agents
2522
+ in a transcript (e.g. "Transferred to Research Agent"), with an optional `avatar` slot. Root is
2523
+ `role="separator"` named by the computed label; the label is announced once on first connect
2524
+ through an internal live region, since a handoff lands mid-stream and later property changes never
2525
+ re-announce.
2526
+ - 4cddc07: Adds `<lr-highlight-layer>`: a presentational overlay that paints highlight rectangles
2527
+ (percent-of-box coordinates) over positioned content — a pdf page, an image, any relatively-positioned
2528
+ frame. Roving-tabindex keyboard access (ArrowUp/Down/Left/Right honoring RTL, Home/End, Enter/Space),
2529
+ `aria-current` on the active rect, a one-shot `flash()` emphasis pulse with a reduced-motion static
2530
+ fallback, and token-mapped tones. Zero dependencies. `lr-pdf-viewer` adopts it next for per-page
2531
+ highlight painting.
2532
+ - 4c707de: Adds `<lr-image-viewer>`: a full pan/zoom raster-image viewer with labeled region highlights and
2533
+ opt-in region annotation (pointer-drag or keyboard), self-registering into the document-viewer
2534
+ registry for `image/png`, `image/jpeg`, `image/webp`, `image/gif`, `image/avif`, and `image/bmp`.
2535
+ Distinct from `<lr-svg-viewer>` (vector documents) and `<lr-image-comparer>` (before/after
2536
+ comparison) — this is the landing surface for `region`-anchored citations (bounding-box grounding).
2537
+ - 2ad038b: `lr-json-viewer` gains an imperative search API (`runSearch()`, `searchNext()`,
2538
+ `searchPrevious()`, `clearSearch()`, event `lr-search-change`) as a thin layer over its existing
2539
+ declarative `search` property -- the property, its highlighting, and its force-expand behavior are
2540
+ unchanged; the new methods add match-count resolution and a navigable cursor (`data-active` on the
2541
+ current match) on top. The count-resolving entry point is named `runSearch()` rather than `search()`
2542
+ (unlike this same quartet on other viewers) because `search` is already this component's own public
2543
+ string property -- a method can't share its name. Previously there was no way to count matches or
2544
+ step between them programmatically.
2545
+ - ac19eb0: `lr-lite-chart` gains a `legendText?: (label: string, datasetIndex: number) => string` hook,
2546
+ appending formatter-supplied text (e.g. a value or percentage share) after each series' label in the
2547
+ built-in legend row — mirrors the existing `pointText`/`tickFormat` opt-in-hook convention. Previously
2548
+ a consumer needing per-series legend text beyond the bare label had to hand-roll an entire replacement
2549
+ legend instead of using the built-in `legend` prop.
2550
+ - c721d97: `lr-map` gains a `dataLayers: GeoJsonDataLayer[]` property: each entry adds a GeoJSON source plus
2551
+ fill/line/circle layers (colored from `--lr-*` tokens by an optional `tone`), independent of the
2552
+ existing `choropleth` prop (which requires `field`/`stops` and can't display plain geometry). Defaults
2553
+ to an empty array — zero behavior change for existing `lr-map` users. This is the enabler for the
2554
+ upcoming GeoJSON-file document-viewer bridge, and is useful standalone for rendering arbitrary
2555
+ GeoJSON shapes (routes, zones, points of interest) without hand-building maplibre-gl layers.
2556
+ - 92955fc: `lr-markdown` gains `heading-anchors` (stamps computed GitHub-slugger-style ids on headings),
2557
+ `getHeadingTree()` (a document-ordered heading outline, computed regardless of `heading-anchors`),
2558
+ `fragment`/`text-quote` anchor-target support (`highlights`, `activeHighlightId`, `anchor`,
2559
+ `scrollToAnchor()`, events `lr-highlight-activate`/`lr-text-select`/`lr-anchor-result`), and
2560
+ `math` (renders `$...$`/`$$...$$` TeX as MathML via the optional `katex` peer, falling back to
2561
+ literal source text when the peer isn't installed). Previously there was no way to deep-link into a
2562
+ section, highlight a quoted passage, or render math in rendered Markdown content.
2563
+ - 3492739: `lr-markdown` gains real shiki syntax highlighting for fenced code blocks, reusing
2564
+ `<lr-code-block>`'s own optional `shiki` peer and grammar-loading machinery directly (not by
2565
+ embedding `<lr-code-block>` itself, which would have hit DOMPurify's default custom-element
2566
+ blocklist and re-mounted — losing state and re-triggering async loads — on every streaming chunk).
2567
+ On by default whenever the `shiki` peer is installed (set `highlightCode="false"` to opt out); new
2568
+ `languages`/`languagesOnly` properties mirror `<lr-code-block>`'s own fine-grained bundle-size
2569
+ controls. Highlighting is skipped entirely while `streaming` is `true` and applied once a stream
2570
+ settles, so there is no added per-chunk cost while content is still arriving.
2571
+ - e5df5af: Adds `<lr-message-actions>`: the per-message action toolbar for `lr-chat-message`'s `actions` slot
2572
+ — opt-in built-ins (`copy` / `regenerate` / `edit` / `feedback`, in `controls`-array order) that emit
2573
+ intent events (`lr-regenerate`, `lr-edit`, plus bubbled `lr-copy`/`lr-change`/`lr-submit`
2574
+ from the embedded copy button and thumbs-only feedback), and a default slot for custom controls (e.g.
2575
+ a slotted `lr-branch-picker`) that participate in the toolbar's ArrowLeft/ArrowRight/Home/End
2576
+ navigation. Optional `reveal-on-hover` hides the bar until the enclosing `lr-chat-message` is
2577
+ hovered or a control inside has focus.
2578
+ - 9544450: Add `lr-message-feedback`: thumbs up/down for one assistant message, with an optional inline
2579
+ detail step (multi-select reason chips + a free-text comment) that opens as a disclosure directly
2580
+ below the thumbs rather than a floating overlay. Fires `lr-change` on every rating toggle and
2581
+ `lr-submit` (`{ value, reasonIds, comment }`) from the panel's submit button; stores nothing
2582
+ itself — a host persists the rating and may reflect a previously-recorded one back via `value` +
2583
+ `disabled`. Re-activating the pressed thumb clears the rating unless its own detail panel is open,
2584
+ in which case that click re-opens the panel with any surviving draft instead.
2585
+ - 22c1006: Adds `<lr-mind-map>`: a radial expandable topic tree (NotebookLM-style Mind Maps) — zero-dependency
2586
+ SVG, closed-form arc-subdivision layout in its own `mind-map-layout.ts` module, single-tab-stop
2587
+ keyboard roving (mirroring `lr-word-cloud`), and `lr-topic-select`/`lr-topic-toggle` events.
2588
+ Multiple root topics hang off an implicit center hub; expansion state is keyed by topic id and
2589
+ survives streaming `topics` reassignment.
2590
+ - 2ad038b: Recorded decision: `.msg` (Outlook) files are not supported this round. `.msg` is OLE/CFB binary per
2591
+ MS-OXMSG; the available npm parser (`@kenjiuno/msgreader` plus its `decompressrtf` companion) is
2592
+ below this library's maintenance bar for an optional peer. `.msg` files continue to resolve to
2593
+ `<lr-document-preview>`'s generic download fallback, exactly like any other unregistered format —
2594
+ convert to `.eml` server-side to use `<lr-email-viewer>` instead. No API change; this changeset
2595
+ exists to document the decision, guarded by a permanent regression test.
2596
+ - 22c1006: Adds `<lr-neighbor-list>`: one entity's relationship rows (relation, direction, neighbor) with
2597
+ per-row navigate (`lr-entity-activate`) and expand-in-graph (`lr-node-expand`, matching
2598
+ `lr-graph`'s own event name/detail) affordances, optional relation grouping, and automatic
2599
+ `lr-virtual-list` virtualization above `virtualizeAt` rows.
2600
+ - 22c1006: Adds `<lr-node-palette>`: a searchable, categorized node library for workflow editors — drag an
2601
+ item onto a `droppable` `lr-flow-canvas`, or place it by keyboard (`lr-palette-place`/
2602
+ `lr-select`). Fully decoupled from the canvas itself, agreeing only on the exported
2603
+ `FLOW_PALETTE_MIME_TYPE` drag-payload constant.
2604
+ - a0e579a: Adds `<lr-notebook-viewer>`: a read-only Jupyter notebook (nbformat 4.x) renderer that parses
2605
+ `.ipynb` JSON natively and composes `lr-markdown`/`lr-code-block`/`lr-json-viewer` per cell,
2606
+ with `node-path`/`fragment` cell anchors and imperative search over cell sources and text outputs.
2607
+ Self-registers into the document-viewer registry for `application/x-ipynb+json`. Execution, kernels,
2608
+ and ipywidgets are out of scope; stream/error outputs render as plain preformatted text this round.
2609
+ - 15062d0: Adds `<lr-page-rail>`: a virtualized vertical thumbnail rail for page-addressed documents, with
2610
+ per-page highlight heat markers. Wired mode (`viewer`/`for`) tracks page/count from a
2611
+ `PageThumbnailSource`-shaped viewer's own `lr-load`/`lr-page-change` events and lazily renders
2612
+ thumbnails as rows materialize (`lr-pdf-viewer` satisfies this structurally); mediated mode
2613
+ (`page-count`/`page`) works as a fully functional pager without a wired viewer. Roving-tabindex
2614
+ keyboard access via `lr-virtual-list`, typed-digit page jump, `lr-page-select` event.
2615
+ - 22c1006: Adds `<lr-path-strip>`: a compact, horizontally scrollable node -> relation -> node chain
2616
+ rendering a GraphRAG reasoning path, with one roving tab stop across every element (nodes and
2617
+ relations alike), logical (RTL-mirroring) directed-edge arrows, and `lr-entity-activate`/
2618
+ `lr-relation-activate` events.
2619
+ - 75c17bd: `lr-pdf-viewer` becomes the reference `DocumentAnchorTarget` implementation: resolves `page`,
2620
+ `text-quote`, and `region` anchors (`scrollToAnchor()`), paints highlights per page via
2621
+ `lr-highlight-layer`, exposes `getPageText(page)` and `renderPageThumbnail(page, canvas, options?)`
2622
+ for rail/search/chunking consumers, and emits `lr-load { pageCount }`,
2623
+ `lr-highlight-activate`/`lr-text-select`/`lr-anchor-result`. The `application/pdf` document-
2624
+ viewer registration now declares its anchor/text-select capabilities and forwards `anchor`/
2625
+ `highlights`. All additive — existing `src`/`page`/`zoom`/`nextPage()`/`previousPage()`/`zoomIn()`/
2626
+ `zoomOut()` and their events are unchanged.
2627
+ - 1879c40: `lr-pdf-viewer` gains an imperative in-document search API (`search()`, `searchNext()`,
2628
+ `searchPrevious()`, `clearSearch()`, event `lr-search-change`), a public `goToPage(page):
2629
+ Promise<boolean>` method, and `getOutline(): Promise<PdfOutlineItem[]>` for reading a PDF's table of
2630
+ contents. Search matches paint as `<mark part="search-match">` (`search-match-active` for the
2631
+ current one) without touching any highlight state. The `application/pdf` document-viewer
2632
+ registration now declares `search: true` in its capabilities. Previously there was no way to search
2633
+ inside a rendered PDF, jump to a page programmatically, or read its outline.
2634
+ - 22c1006: Adds `<lr-provenance-panel>`: the grounding breakdown for one answer — a four-section disclosure
2635
+ panel (Entities / Relationships / Communities / Text chunks) composing `lr-entity-chip`,
2636
+ `lr-path-strip`, compact `lr-community-card`s, and a compact `lr-chunk-inspector`. Every child
2637
+ event bubbles straight through unmodified; its own `lr-toggle` event tracks per-section
2638
+ expand/collapse state, which survives streaming `provenance` reassignment.
2639
+ - 2d15c51: Adds `<lr-push-to-talk>`: a mic capture button owning the full `getUserMedia`/`MediaRecorder`
2640
+ lifecycle — permission request, hold or toggle recording, optional chunked streaming
2641
+ (`lr-record-chunk`) for streaming STT, an opt-in RMS level meter (`lr-level`), a `max-duration-ms`
2642
+ auto-stop guard, and `lr-record-start`/`lr-record-stop`/`lr-record-cancel`/`lr-record-error`
2643
+ events. No SDK dependency — native browser APIs only. Previously lyra-ui had no voice-capture
2644
+ component at all; every agentic voice UI had to hand-roll this lifecycle from scratch.
2645
+ - 3a2f6d2: Add `lr-rubric-form`: a configurable annotation rubric (LangSmith annotation-queue style) —
2646
+ score, category, and freeform-comment keys with a submit-and-next flow for working through an eval
2647
+ queue. Follows `lr-tool-param-form`'s exact `ElementInternals`-attached-directly, JSON-serialized
2648
+ form-value pattern; a `score` key renders `lr-segmented` (≤10 integer steps) or `lr-slider`,
2649
+ `category` renders `lr-select` or `lr-checkbox-group` (`multiple`), and `comment` renders
2650
+ `lr-textarea`.
2651
+ - c388b94: Add themeable static edge fades and native horizontal scrolling to overflowing `lr-segmented` and
2652
+ `lr-tabs` rows.
2653
+ - de5b8b7: Adds `<lr-sequence-strip>`: a compact, one-thin-cell-per-item strip visualizing a sequence of
2654
+ categorical states with an optional secondary per-cell marker (e.g. a CI build-step strip, a
2655
+ log-severity strip, or — the motivating case — a per-turn conversation-history strip). Pure CSS/flex,
2656
+ zero dependencies, `role="img"` with an auto-generated per-category "label: count" `aria-label`
2657
+ summary (matching `lr-sparkline`'s accessibility model), plus a pointer-hover tooltip showing each
2658
+ item's own label.
2659
+ - 22c1006: Adds `<lr-source-picker>`: a checkbox tree/list scoping which sources ground the next answer —
2660
+ tri-state folders, select-all, `lr-file-icon` type icons, and built-in search that keeps matching
2661
+ descendants' ancestors visible. Deliberately not `FormAssociated` (a scoping panel, not a form
2662
+ control, mirroring `lr-tool-select-dialog`'s stance) and renders its own `role="tree"` rather than
2663
+ composing `lr-tree`, since `TreeItem` has no tri-state checkbox model.
2664
+ - 685eb35: Add `lr-span-waterfall`: the horizontal-timeline projection of the same `LyraSpan[]`
2665
+ `lr-trace-tree` consumes — a time axis, one row per span in start order, and status-toned,
2666
+ keyboard-navigable bars (Langfuse timeline / Temporal event-history style). Declarative
2667
+ `viewStartMs`/`viewEndMs` window props (composable with `lr-time-range` as a brush) stand in for
2668
+ zoom/pan gestures this round. Both components emit the same `lr-span-select { id }` and accept
2669
+ the same `activeSpanId`, so a host syncs selection between them with two listeners and one property
2670
+ binding.
2671
+ - 2ad038b: `lr-spreadsheet-viewer` and `lr-csv-viewer` gain `cell-range` anchor-target support
2672
+ (`highlights`, `activeHighlightId`, `scrollToAnchor()`, event `lr-highlight-activate`) and an
2673
+ imperative in-document search API (`search()`, `searchNext()`, `searchPrevious()`, `clearSearch()`,
2674
+ event `lr-search-change`) — identical on both viewers, addressing cells by the same 1-based raw
2675
+ grid (header row included) an A1 reference already implies. Spreadsheet's search/anchor resolution
2676
+ additionally spans every sheet, switching `lr-tabs` as needed. Both registry entries now declare
2677
+ `capabilities: { anchors: ['cell-range'], search: true, textSelect: false }`. Previously there was
2678
+ no way to highlight or search a specific cell/range in a rendered spreadsheet or CSV file.
2679
+ - 761ab24: Adds `<lr-stack-trace>`: parses V8/JS-TS, Firefox/Safari, and Python stack traces (including
2680
+ chained-error groups) into a message plus collapsible, activatable frames (`lr-frame-select`),
2681
+ folding internal frames (`node_modules/`, `node:internal`, `site-packages/`, ...) behind a
2682
+ count-labeled toggle. Falls back to verbatim raw text when nothing parses.
2683
+ - b33bb35: Adds `<lr-suggestion-chips>`: starter prompts (empty thread) and follow-up suggestions (after a
2684
+ response) as a horizontally scrollable chip row (or a wrapping grid via `wrap`), each with an optional
2685
+ secondary detail line. Fires `lr-suggestion-select` (`{ id, label }`) on activation — never writes
2686
+ into a composer or sends anything itself. Keyed `repeat()` on `id` preserves focus across a mid-stream
2687
+ suggestions replacement.
2688
+ - 2ad038b: `lr-svg-viewer` and `lr-document-preview` (its image-format path) gain an opt-in `zoomable`
2689
+ property that wraps the rendered content in an internal `lr-zoomable-frame` for pan/zoom
2690
+ inspection, plus display-only `region` anchor-target support (`highlights`, `activeHighlightId`,
2691
+ `scrollToAnchor()`, event `lr-highlight-activate`) for percent-unit bounding-box highlights that
2692
+ scale with the zoom level. `zoomable` defaults to `false` on both, so an inline thumbnail (e.g. in a
2693
+ chat stream) doesn't unexpectedly grow a focusable zoom-chrome viewport. Previously neither viewer
2694
+ had any pan/zoom or region-highlighting capability.
2695
+ - 1e051a4: `lr-swatch-picker` options gain an optional `icon` field (`SwatchOption.icon`, mirroring
2696
+ `lr-segmented`'s `SegmentedItem.icon`): a consumer-supplied shape (e.g. a brand glyph) rendered in
2697
+ place of the plain filled circle, exposed as `::part(swatch-icon)`. A `currentColor`-based SVG picks up
2698
+ the option's `color` automatically through the swatch's `color` custom property, so consumers who
2699
+ previously hand-rolled a row of colored icon buttons (rather than plain color circles) can now use the
2700
+ picker directly.
2701
+
2702
+ The selected swatch also gains two new opt-in, off-by-default custom properties for a more emphatic
2703
+ selected state: `--lr-swatch-picker-selected-blur` (0 by default, a crisp ring; set a real length for
2704
+ a soft glow tinted by the swatch's own color -- works for both a plain color circle and an icon swatch,
2705
+ via a `box-shadow`/`drop-shadow` split so the glow follows the icon's actual silhouette rather than an
2706
+ invisible transparent box) and `--lr-swatch-picker-shine-duration` (0s by default, static; set a real
2707
+ duration for a rhythmic brighten-and-settle pulse, disabled under `prefers-reduced-motion: reduce`).
2708
+ Together they cover a "shining" gemstone-style accent-theme picker without changing the default look
2709
+ for any existing consumer.
2710
+
2711
+ - 55140c3: `lr-table` gains heat-tint mode: a per-column `heatValue(row)` accessor drives a `color-mix()`-based
2712
+ cell background computed from a shared min/max scale across the whole grid (auto-derived from the
2713
+ data, or overridden via the new `heatTintScale` property), matching `lr-heatmap`'s own
2714
+ `--lr-heatmap-scale-lo`/`-hi` ramp-token convention via new `--lr-table-heat-tint-lo`/`-hi` custom
2715
+ properties. Previously a consumer needing a value-driven cell background had to hand-compute a color
2716
+ string themselves via the existing `cellStyle` escape hatch.
2717
+ - 6f7c938: `lr-table` gains `rowTotal`/`grandTotal`: a trailing column showing each row's total (`rowTotal`)
2718
+ and, when at least one column also defines `footer`, a grand-total cell at its bottom-right
2719
+ intersection (`grandTotal`). Both share the existing `footer(rows)` hook's "consumer computes/renders,
2720
+ table only positions" contract rather than assuming addition. Previously a consumer needing row/grand
2721
+ totals alongside `lr-table`'s existing per-column `footer` had to render them outside the table
2722
+ entirely, breaking column alignment.
2723
+ - 4cae327: Adds `<lr-task-list>`: a live, collapsible tracker for an agent's plan, embedded in the
2724
+ transcript. Renders ordered steps with per-step lifecycle status (`pending`/`running`/`success`/
2725
+ `error`) and one level of nested sub-steps; status changes are announced through an internal
2726
+ throttled live region. A dynamic `detail-<id>` slot per item accepts rich content such as a
2727
+ `<lr-tool-call-chip>`. Unlike `<lr-stepper>` (a single-selection navigation control),
2728
+ `<lr-task-list>` is a read-only status report — several steps may be `running` at once, and
2729
+ there is no selection.
2730
+ - bf223ca: Adds `<lr-terminal>`: a read-only, virtualized ANSI console for streamed agent/tool output — SGR
2731
+ color rendering (16 named colors, 256-color, truecolor), stick-to-bottom `follow` with a
2732
+ `lr-follow-change` event, `write()`/`content` streaming, `\r`/`\b`/`\t` cursor handling so progress
2733
+ bars render correctly, in-buffer `search()`/`searchNext()`/`searchPrevious()`/`clearSearch()`,
2734
+ `line-range` highlight/anchor support (`scrollToAnchor()`, `lr-highlight-activate`), and built-in
2735
+ copy/download affordances. Not a PTY — no stdin/keystroke handling or cursor-addressed full-screen
2736
+ apps.
2737
+ - 52a90e5: Adds `<lr-test-results>`: a pass/fail suite summary with visible (never color-only) per-status
2738
+ counts, `aria-pressed` status filter toggles, and failure rows that auto-expand by default and can
2739
+ host a slotted `detail-{testId}` diff/code block. Row state (expansion, filter) survives a streaming
2740
+ `suites` reassignment mid-run, and a run's completion is announced through an internal live region.
2741
+ - 967e785: Adds `<lr-thread-list>`: the conversation sidebar — a grouped ("Pinned / Today / Yesterday / Previous
2742
+ 7 days / …"), searchable list of chat sessions built on `lr-conversation-item` and virtualized via
2743
+ `lr-virtual-list`. Data mode (`threads` array) renders rows with optional pin/archive/delete row
2744
+ actions, all controlled events (`lr-thread-pin`/`-archive`/`-delete`/`-rename`) carrying the
2745
+ _requested_ new state — no CRUD or persistence of its own. Slotted mode (host-supplied
2746
+ `lr-conversation-item`s) skips grouping/virtualization/row-actions entirely, for a host that wants
2747
+ full control over a short, unconstrained list.
2748
+ - 9448c10: Add `lr-trace-tree`: a collapsible span hierarchy for one agent/LLM trace (Langfuse/LangSmith
2749
+ run-tree style) — kind icon, name, status, an inline duration bar on the shared trace time scale,
2750
+ and optional tokens/cost columns. Consumes a flat `LyraSpan[]` array (hierarchy derived from
2751
+ `parentId`); expand state survives a streaming reassignment of `spans`. The shared `LyraSpan` type
2752
+ (`components/trace-tree/span.ts`) is also consumed by the upcoming `lr-span-waterfall`, so the
2753
+ two components can render the same trace as two synchronized projections.
2754
+ - bef6b0d: Adds `<lr-transcript-feed>`: a data-driven live-captions surface for an in-progress voice session —
2755
+ `entries` in (`{ id, speaker?, text, interim?, timestamp? }[]`), reconciled keyed by `id` so a same-id
2756
+ interim-to-final upgrade moves the row into the announcing `role="log"` region without a duplicate
2757
+ announcement. Ships the shared stick-to-bottom "follow" contract (`follow`/`lr-follow-change`, the
2758
+ same vocabulary `lr-terminal` uses). No dependency, no STT/diarization built in — bring your own
2759
+ transcription source and stream entries in.
2760
+ - ec5fe96: Adds the `DocumentAnchorTarget` mixin (`internal/anchor-target.ts`) and its `LyraAnchorTarget`
2761
+ interface: the shared implementation of the anchor-target contract every anchor-capable lyra-ui
2762
+ viewer adopts — `highlights`/`activeHighlightId`/`anchor` properties, `scrollToAnchor()` with a
2763
+ generation-guarded retry-until-loaded loop and screen-reader announcements, and
2764
+ `lr-highlight-activate`/`lr-text-select`/`lr-anchor-result` event plumbing including
2765
+ selection->anchor emission. Internal module; no adopter yet in this release (`lr-pdf-viewer` adopts
2766
+ it next). No behavior change for any existing component.
2767
+ - 44b6de7: Adds the shared `LyraAnchor`/`LyraHighlight` grounding-bridge type module
2768
+ (`@aceshooting/lyra-ui/components/document-viewer/anchors.js`): a W3C Web-Annotation-inspired
2769
+ discriminated union (`page`, `text-quote`, `fragment`, `line-range`, `cell-range`, `cfi`,
2770
+ `time-range`, `region`, `node-path`) that every anchor-capable viewer and every knowledge-grounded
2771
+ citation surface will address a passage through. Pure types plus one constant; nothing to register,
2772
+ no runtime behavior change for existing components.
2773
+ - c644abd: Widens `DocumentFile` with optional `anchor`/`highlights`/`alt` fields and
2774
+ `DocumentRendererDefinition` with an optional `capabilities` declaration; `lr-document-viewer` gains
2775
+ matching `anchor`/`highlights`/`alt` properties, forwards them to the resolved renderer, and emits
2776
+ `lr-anchor-result { found }` once per applied anchor. Every addition is optional and every existing
2777
+ registration/usage is unaffected — this removes the previous limitation where even a renderer's own
2778
+ props (like pdf's `page`) couldn't be reached through the router.
2779
+ - 5f92994: Adds `internal/text-highlights.ts`: a highlight paint manager for HTML-flow document viewers, using
2780
+ the CSS Custom Highlight API when available and falling back to `<mark>`-wrapping otherwise, with a
2781
+ uniform `acquireHighlightHandle()` API that never requires callers to branch on browser support
2782
+ themselves. Internal module with no public tag and no adopter yet in this release; ships ahead of the
2783
+ markdown/html-viewer/docx-viewer highlight support that will consume it. No behavior change for any
2784
+ existing component.
2785
+ - b067b83: Adds `internal/text-quote.ts`: dependency-free `text-quote` anchor resolution (quote/prefix/suffix ->
2786
+ DOM `Range`, and the reverse — a selection `Range` -> a `text-quote` anchor with captured context).
2787
+ Internal module with no public tag; used by the `DocumentAnchorTarget` mixin's default selection
2788
+ handling and by `lr-pdf-viewer`'s anchor/highlight resolution. No behavior change for any existing
2789
+ component.
2790
+ - bc75a1f: Adds `<lr-usage-badge>`: a compact, static resource strip for one message or run — tokens in/out,
2791
+ cost, latency — with a hover/focus tooltip breakdown (full grouped figures, plus a computed Total
2792
+ tokens row when both counts are set). Purely formatting: it computes no counts, rates, or prices,
2793
+ and every segment is independently optional. Reuses `<lr-tool-call-chip>`'s hover/focus/Escape
2794
+ tooltip contract. Distinct from `<lr-context-meter>` (occupancy of a fixed capacity) and
2795
+ `<lr-generation-status>` (a live ticking readout with a Stop button) — this is the static spend
2796
+ record shown after a message or run completes.
2797
+ - f3c744b: `lr-virtual-list` gains a public `scrollToIndex(index, { align, behavior })` method: scrolls a
2798
+ specific row into view (`align: 'start' | 'end' | 'auto'`, reduced-motion-aware `behavior`) without
2799
+ the `aria-current`/"active row" side effect of the existing `active-id` property. In
2800
+ `row-height="auto"` mode, a far-off target's estimate-based offset is corrected with a single re-scroll
2801
+ once the row's real height is measured. Previously there was no way to programmatically scroll to a
2802
+ specific row at all except by driving `active-id`, which also marks that row as the current selection —
2803
+ a streaming transcript's own stick-to-bottom auto-scroll has nothing to do with "selection."
2804
+ - e24ae10: Adds `<lr-voice-picker>`: a TTS voice selector mirroring `lr-model-select`'s closed-dropdown/
2805
+ free-text-combobox dual mode and form-association, with a `catalog` entry shape carrying
2806
+ `language`/`description`/`previewUrl`, and an event-first preview affordance (`lr-preview-request`,
2807
+ cancelable) that plays through one internal `<audio>` when a `previewUrl` is present and the host
2808
+ doesn't take over. No TTS SDK, no catalog fetching, no selection persistence — those stay host
2809
+ concerns.
2810
+ - 37a89cb: Adds `lr-widget-renderer`'s internal type registry (`registerWidgetType()`,
2811
+ `getDefaultWidgetTypeRegistry()`) and its security-critical, DOM-free allowlist resolver
2812
+ (`resolveTree()`): unknown widget types and disallowed/mistyped props are skipped, never rendered;
2813
+ `forcedProps` always win; a child's `slot` outside its parent's allowlist renders unslotted; depth
2814
+ (32) and node-count (5000) caps are enforced. No public API surface change on its own — groundwork
2815
+ for the `<lr-widget-renderer>` element, landing in the same release.
2816
+ - bcd3c2b: Adds `<lr-widget-renderer>`: renders an agent-streamed declarative JSON widget tree through an
2817
+ allowlisted `type → lyra tag` registry (`card`/`badge`/`button`/`stat`/`result-card`/`result-field`/
2818
+ `markdown`/`image` built in, plus `row`/`col`/`text` structural built-ins) — unknown types and
2819
+ disallowed/mistyped props are silently skipped, never rendered, with a deduped dev-mode warning; a
2820
+ single bubbling `lr-widget-action` event surfaces actions; streamed updates reconcile keyed by
2821
+ `id` (or structural path), so a mapped widget's own internal state survives a re-resolve.
2822
+ `registerWidgetType()` extends the default registry app-side; a per-instance `registry` property
2823
+ fully overrides it. No `innerHTML`/`unsafeHTML` path exists anywhere in the implementation.
2824
+ - dc168c7: Adds `<lr-xml-viewer>`: a `DOMParser`-based collapsible XML tree view mirroring
2825
+ `lr-json-viewer`'s UX (`collapsed-depth`, `copyable`, structural-path expand state that
2826
+ survives a same-shape `xml` reassignment), with an imperative `search()`/`searchNext()`/
2827
+ `searchPrevious()`/`clearSearch()` API and `node-path` anchors (element indices plus an optional
2828
+ trailing `'@attrName'` segment for attribute-level targeting). Self-registers into the
2829
+ document-viewer registry for `application/xml`/`text/xml` and `.xml`/`.xsd`/`.xsl`/`.xslt`/`.rss`/
2830
+ `.atom` files. No XPath/XSLT evaluation, no editing, no schema validation.
2831
+
2832
+ ### Patch Changes
2833
+
2834
+ - 7bbd069: Internal only: adds three new `src/internal/` modules (`slugger.ts`, `cell-range.ts`,
2835
+ `viewer-search.ts`) and five new localization keys (`viewerSearchMatchCount(Plural)`,
2836
+ `viewerSearchNoMatches`, `viewerSearchActiveMatch`, `viewerHighlightLabel`) used by upcoming
2837
+ per-viewer search/anchor/highlight support. No consumer-visible behavior change on its own.
2838
+ - da8bbf0: Requires `@aceshooting/lyra-flags` `^1.4.0` (up from `^1.3.0`) as the optional flag-asset peer.
2839
+ 1.4.0 is a docs/metadata-only release of the flags package (no runtime change), so this is a
2840
+ range refresh, not a behavioral requirement bump.
2841
+ - 967e785: Fixes `<lr-virtual-list>`: a `groups`-supplied group marker no longer carries `role="heading"`
2842
+ `aria-level="2"`. Those markers render inside the scroll container's `role="list"`, and ARIA's `list`
2843
+ role only permits `listitem` as a direct owned child — a `heading` sibling was a critical
2844
+ `aria-required-children` violation for any consumer combining `groups` with an accessibility check
2845
+ (surfaced by `<lr-thread-list>`'s date-grouped rows). The marker is still rendered as visible,
2846
+ non-interactive text; it's just no longer exposed as a heading landmark.
2847
+
2848
+ ## 3.7.0
2849
+
2850
+ ### Minor Changes
2851
+
2852
+ - 05c9f9c: Add `appearance="link"` to `<lr-button>`: a true inline-link tier that renders as zero-chrome underlined text — no padding, border, border-radius, or `min-block-size` floor — colored from the same `--lr-button-accent` token `appearance="plain"` uses (so `variant` still selects the link color) and inheriting the surrounding font-size/weight so it flows within a sentence rather than as a button-shaped control. Previously the smallest `<lr-button>` was still a padded, rounded, 24px-tall pill with a (transparent-but-present) border and no `text-decoration`, so an inline text link had to be hand-rolled; `appearance="link"` now covers that case directly. The notable design choice: the link rules are declared after the per-`size` rules so `font: inherit` and the zero padding/border/min-height win over whatever `size` is set, and the shared `[part='base']:focus-visible` outline is deliberately left intact.
2853
+ - 2ed831d: `<lr-file-icon>` gains a `size` property (bytes, formatted via the same convention as `<lr-attachment-chip>`) shown alongside its label, and exposes the raw MIME type as a `title` tooltip.
2854
+ - a5482d8: Add `<lr-swatch-picker>`, a single-select picker over a small, fixed set of color swatches — the row-of-round-accent-color-buttons pattern apps hand-roll, generalized into a first-party component. It carries the WAI-ARIA APG `radiogroup` contract (`role="radiogroup"`/`role="radio"`, roving tabindex, automatic activation on click or arrow-key move, cyclic Arrow/Home/End navigation), takes an `options: { value; color; label }[]` array plus a controlled `value`, and emits `lr-change` (`detail: { value }`) only when the selection actually changes. It is distinct from `<lr-color-picker>`'s freeform native color input: this picks exactly one of N designer-chosen named colors.
2855
+
2856
+ Notable design choice: the selection ring uses a dedicated `--lr-swatch-picker-selected-color` token (defaulting to `--lr-color-brand`) so it retheme independently of the focus ring, mirroring `<lr-heatmap>`'s `--lr-heatmap-selected-color`; each swatch's fill comes from its option's `color`, applied through a per-swatch custom property so a consumer's `::part(swatch)` background rule can still override it.
2857
+
2858
+ ### Patch Changes
2859
+
2860
+ - f3a606f: Fix `<lr-file-icon>`'s format badge overflowing its fixed size for multi-word localized labels (e.g. "Word document") — long badge text now truncates with an ellipsis instead of spilling outside the badge.
2861
+ - 64e6cb6: Document `<lr-file-icon>`'s new `size` property and `size` csspart in `llms-full.txt`, and add the explicit-MIME-vs-filename-extension precedence test called for by the original feature request's acceptance criteria.
2862
+ - 0975bcd: Fix `<lr-map>` throwing an unhandled error when the underlying maplibre-gl `Map` emits an `'error'` event (e.g. a tile/style source request failing) with no listener attached — maplibre-gl's `Evented` base rethrows in that case. The error is now caught and logged via `console.error` instead of surfacing as an uncaught exception.
2863
+
2864
+ ## 3.6.0
2865
+
2866
+ ### Minor Changes
2867
+
2868
+ - 30db265: Nine new components:
2869
+
2870
+ - `lr-animated-image` — a still/animated-GIF-style image that pauses on `prefers-reduced-motion`
2871
+ and exposes a play/pause toggle.
2872
+ - `lr-animation` — declarative Web Animations API wrapper for a slotted target, with named
2873
+ timing presets, `prefers-reduced-motion` handling, and `lr-start`/`lr-finish`/`lr-cancel`
2874
+ events.
2875
+ - `lr-avatar-group` — a stacked, overlapping set of avatars with a "+N" overflow indicator.
2876
+ - `lr-include` — fetches and renders external HTML/Markdown/plain-text content client-side, with
2877
+ URL validation and DOMPurify sanitization.
2878
+ - `lr-known-date` — a form-associated day/month/year input for approximate or partial dates
2879
+ (e.g. a birth date where only the year is known).
2880
+ - `lr-lightbox` — a full-screen, modal, click-to-enlarge image viewer with prev/next navigation
2881
+ across an ordered set of images, built on the same shared overlay infrastructure as
2882
+ `lr-dialog`/`lr-command-palette`.
2883
+ - `lr-qr-code` — renders a QR code from text/URL data, via the optional `qrcode` peer dependency
2884
+ (same optional-peer pattern as the chart/map bundles).
2885
+ - `lr-random-content` — displays a randomly (or sequentially) chosen subset of its slotted
2886
+ children, with optional autoplay.
2887
+ - `lr-timeline`/`lr-timeline-item` — a vertical event timeline with per-item status/icon
2888
+ markers.
2889
+ - `lr-tour` — a guided, multi-step product-tour overlay that highlights target elements in
2890
+ sequence.
2891
+
2892
+ ### Patch Changes
2893
+
2894
+ - e1aca7e: Shared-infrastructure hardening pass following a full-library audit:
2895
+
2896
+ - `lr-contact-viewer` and `lr-email-viewer` now expose a proper localized `aria-label` on their
2897
+ root surface (previously had no naming mechanism at all); `lr-calendar-viewer` gets the same
2898
+ fallback chain's final localized tier.
2899
+ - `lr-stat`'s trend announcement now interpolates the percentage into one localized template
2900
+ instead of concatenating separately-localized fragments (word order safe for non-English locales).
2901
+ - Fixed a real bug in `lr-model-settings-panel`'s `decimalPlaces` helper that returned `0` instead
2902
+ of the correct precision for exponential-notation step values (e.g. `1e-7`); it now shares the
2903
+ same exponential-aware implementation as `lr-slider`/`lr-time-range` via a new
2904
+ `src/internal/numbers.ts` export instead of a diverging local copy.
2905
+ - Deduplicated five other byte-identical/near-identical helpers that had drifted into 2-5 separate
2906
+ component files each (`prefersReducedMotion`, canvas-context memoization, swatch-color
2907
+ sanitization, slotted-content detection, and a title-attribute-stripping mixin) into single
2908
+ `src/internal/` implementations.
2909
+ - Removed an unused, never-adopted RTL helper (`rtlAwareSide`/`PhysicalSide`) from
2910
+ `src/internal/rtl.ts`.
2911
+ - Added missing accessibility test coverage for `lr-icon-button` and the standalone `lr-option`
2912
+ element (previously the only two custom elements in the library with no axe check).
2913
+
2914
+ ## 3.5.0
2915
+
2916
+ ### Minor Changes
2917
+
2918
+ - 681ed1f: Broad component hardening pass across ~50 components:
2919
+
2920
+ - `lr-command-palette` now uses the shared overlay infrastructure (`lr-dialog`'s
2921
+ focus-trap/Escape/backdrop/scroll-lock manager) instead of a bespoke implementation, adds
2922
+ `aria-activedescendant` tracking, and keeps the highlighted row scrolled into view.
2923
+ - `lr-table` forwards `spellcheck`/`autocapitalize`/`autocorrect` to its filter input and inline
2924
+ text-cell editor, matching the string-aware `spellcheck` converter already used by
2925
+ `lr-textarea`/`lr-model-select`.
2926
+ - `lr-token-input` and `lr-code-editor` fix `label`/`hint`/`error` slot-vs-attribute detection
2927
+ (a `[part]:empty` selector never matches since the part always contains a `<slot>`), and
2928
+ `lr-token-input` adopts the `effectiveDisabled`/`_fieldsetDisabled` pattern so a `<fieldset
2929
+ disabled>` ancestor no longer permanently overwrites its own `disabled` property.
2930
+ - `lr-calendar`: month grid gets proper `role="grid"`/`role="row"`/`role="gridcell"` semantics,
2931
+ per-day `aria-label`, a sanitized event-color style (rejects `url(...)` and anything else that
2932
+ isn't real CSS color syntax), and RTL-aware nav chevrons; `firstDayOfWeek` tolerates out-of-range
2933
+ input instead of producing `Invalid Date`.
2934
+ - `lr-icon` clones custom slotted SVG content into the component's own `<svg>` so slotted
2935
+ path/circle/group children paint reliably in Chromium.
2936
+ - `lr-document-preview` simplifies its abortable-fetch generation tracking onto the shared
2937
+ `beginAbortableLoad` helper.
2938
+ - `lr-app-rail-item`'s tooltip text now ignores text incidentally living in the decorative `icon`
2939
+ slot, mirroring `lr-chip`'s `labelText` getter.
2940
+ - Smaller accessibility/consistency fixes across app-rail, attachment-chip, breadcrumb, callout,
2941
+ chart/histogram, checkbox-group, data-grid, empty, format-\*, heatmap, html-viewer,
2942
+ image-comparer, intersection/mutation/resize-observer, map, model-select, pdf-viewer,
2943
+ phone-input, progress, radio/radio-group, responsive-panel, scroller, segmented, sparkline,
2944
+ split, stat, stepper, streaming-text, switch, tool-param-form, tool-select-dialog, widget, and
2945
+ zoomable-frame, plus a new standalone `breadcrumb-item.styles.ts` module and expanded test
2946
+ coverage throughout.
2947
+
2948
+ ## 3.4.0
2949
+
2950
+ ### Minor Changes
2951
+
2952
+ - d0ee919: Add command-palette, checkbox-group, token-input, icon/icon-button, code-editor, data-grid, and
2953
+ calendar components. Harden file-input with clipboard paste, native directory selection, and
2954
+ dropped-folder rejection reporting.
2955
+ - 1293f48: Hardening pass across ~70 components: document the button/spinner interaction custom-property APIs
2956
+ (`--lr-button-width`, hover-brightness, active-scale, spinner-duration) and add missing cssparts;
2957
+ `lr-breadcrumb` now reads its accessible-name override from the standard `aria-label` attribute
2958
+ (was `accessible-label`); phone-input preserves the caret through adapter reformats and ships a
2959
+ libphonenumber-js-backed adapter path with a clearer incomplete-number message; prune unused
2960
+ localization keys and size/line-height tokens; broaden test coverage across the library.
2961
+
2962
+ ## Unreleased
2963
+
2964
+ ### Minor Changes
2965
+
2966
+ - Added `<lr-command-palette>` with searchable command registration, groups, keyboard navigation,
2967
+ Escape dismissal, and a configurable `mod+k` shortcut.
2968
+ - Added `<lr-checkbox-group>` and `<lr-token-input>` as form-associated composite controls with
2969
+ array values, native reset/validity behavior, localized chrome, and accessible focus/editing APIs.
2970
+ - Added `<lr-icon>` and `<lr-icon-button>` as dependency-free SVG and icon-only action primitives.
2971
+ - Added `<lr-code-editor>` with line numbers, tab insertion, native textarea selection APIs, and
2972
+ editing-assistance passthrough.
2973
+ - Added `<lr-data-grid>` with sortable headers, roving cell focus, row selection events, loading/
2974
+ empty states, and responsive overflow.
2975
+ - Added `<lr-calendar>` with responsive month and agenda views, event markers, date navigation,
2976
+ RTL-aware keyboard navigation, and date/event selection events.
2977
+ - Hardened `<lr-file-input>` with clipboard paste support, optional native directory selection, and
2978
+ explicit dropped-folder rejection reporting.
2979
+ - Updated the component catalog, consumer API reference, custom-elements manifest, stories, and
2980
+ accessibility/behavior coverage for the new public surface.
2981
+
2982
+ ## 3.3.0
2983
+
2984
+ ### Minor Changes
2985
+
2986
+ - 7e7cc44: Harden every remote-resource viewer against oversized, cancelled, and failed loads, and close a set of localization gaps.
2987
+
2988
+ **Resource limits.** A new internal resource loader caps any remote resource a viewer fetches at 25 MB before handing it to a parser, enforced by streaming the response so the cap holds even when the server omits `Content-Length`. Parsed tabular data is additionally capped at 10,000 rows and 1,000 columns before it is retained or rendered. Exceeding either limit now surfaces the localized `documentPreviewResourceTooLarge` message instead of attempting the parse. This is a behavior change for consumers previewing documents above those thresholds — they will now see a size error where the viewer previously tried (and typically hung or crashed) on them.
2989
+
2990
+ **Cancellable loads.** `LyraElement` gained internal `beginAbortableLoad()` and `scheduleAfterUpdate()` helpers. In-flight fetches are now aborted when the element disconnects or its `src` changes again, and loads are coalesced to one per update rather than firing from `willUpdate`. This fixes stale responses racing a newer `src` and work continuing after an element is removed from the DOM. A `src` assigned while an element is detached is held and replayed when it reconnects, rather than being dropped.
2991
+
2992
+ **Error messages no longer leak internals.** Viewers previously rendered raw `error.message` text (fetch/parser internals, URLs) directly into the UI on failure. They now render the localized `documentPreviewFailedToLoad` message, with the underlying error still available to consumers via the `lr-render-error` event.
2993
+
2994
+ Affected viewers: `lr-archive-viewer`, `lr-calendar-viewer`, `lr-contact-viewer`, `lr-csv-viewer`, `lr-dataset-viewer`, `lr-docx-viewer`, `lr-document-preview`, `lr-ebook-viewer`, `lr-email-viewer`, `lr-html-viewer`, `lr-pdf-viewer`, `lr-pptx-viewer`, `lr-spreadsheet-viewer`, `lr-svg-viewer`.
2995
+
2996
+ **Localization fixes.**
2997
+
2998
+ - Form-associated components rendered the required-field validation message as a hardcoded English string (`Please fill out this field.`). It now resolves through the `fieldRequired` message key, so `registerLyraLocale()` and per-element `strings` overrides apply. Note that this also changes the default English text to `This field is required.` — if you assert on `validationMessage`, update the expected string.
2999
+ - Removed a duplicate `hidePassword` member from the `LyraMessageKey` union. The key itself is unchanged and still used by `lr-input`; only the redundant second declaration is gone.
3000
+
3001
+ **Component coverage contract.** A new `check-component-coverage.mjs` gate runs as part of `contract-policy` (and therefore `lint`), requiring every public tag in the manifest to be exercised by a story and a behavior test, and every component family to carry an accessibility assertion. Stories and tests were added across the library to satisfy it, and `test:coverage` now runs the full test suite rather than five hardcoded files. No public API change.
3002
+
3003
+ ## 3.2.0
3004
+
3005
+ ### Minor Changes
3006
+
3007
+ - 62c6b05: `lr-attachment-chip` gains a preview action: a new `previewSrc` property (used when `file` is
3008
+ unset; a real `File` takes precedence via a temporary blob URL) and `previewable` boolean (default
3009
+ `true`) show a new `preview-button` part whenever a file or preview source is available, emitting
3010
+ `lr-preview` (`detail: { id, name, mimeType, src }`) to open `<lr-document-viewer>` with the
3011
+ same effective MIME type. `lr-document-viewer` gains a matching `download-link` slot and
3012
+ `lr-download` event for a safe native download action. Both properties/events are additive and
3013
+ default off/no-op, so existing usages are unaffected.
3014
+
3015
+ ## 3.1.0
3016
+
3017
+ ### Minor Changes
3018
+
3019
+ - de80dc5: Adds `<lr-archive-viewer>` for listing names and human-readable sizes inside `.zip` archives via
3020
+ the optional `jszip` peer. It registers standard ZIP MIME types and a `.zip` filename fallback with
3021
+ `<lr-document-viewer>`; other archive formats remain on the generic download fallback.
3022
+ - de80dc5: Adds the optional `line-numbers` display to `<lr-code-block>` and `<lr-code-block-core>`.
3023
+ - 53c7c13: Add sanitized SVG and HTML viewers, plus PapaParse-backed dataset and vCard contact viewers to the document renderer registry.
3024
+ - c6dd26c: Adds `<lr-document-viewer>`, a dialog-hosted, format-dispatching document viewer, plus a
3025
+ `registerDocumentRenderer()` registry for plugging in per-format renderers. Files without a
3026
+ registered renderer fall back to the existing `<lr-document-preview>` component.
3027
+ - d992ee7: Adds `<lr-docx-viewer>`, rendering `.docx` Word documents as sanitized semantic HTML through the
3028
+ optional `mammoth` and `dompurify` peers. It registers the official WordprocessingML MIME type and
3029
+ falls back to matching `.docx` filenames.
3030
+ - de80dc5: Adds `<lr-ebook-viewer>` using the optional `epubjs` peer and registers EPUB files with the
3031
+ document-viewer registry.
3032
+ - 49f7b87: Adds `<lr-email-viewer>` for sanitized `.eml` messages via the optional `postal-mime` and
3033
+ `dompurify` peers, plus `<lr-calendar-viewer>` for `.ics` event lists via optional `ical.js`.
3034
+ Both viewers register their standard MIME types and filename-extension fallbacks with
3035
+ `<lr-document-viewer>`.
3036
+ - de80dc5: Adds `getFileTypeMetadata()`, `registerFileTypeMetadata()`, and `<lr-file-icon>` for localized,
3037
+ tokenized MIME/filename format presentation.
3038
+ - 68bb5e3: Adds `<lr-pdf-viewer>`, a PDF renderer built on optional `pdfjs-dist`, with pagination, zoom, selectable text, and virtualized page rendering.
3039
+ - de80dc5: Adds `<lr-pptx-viewer>` using the optional `@aiden0z/pptx-renderer` peer for best-effort client-side
3040
+ PPTX rendering with a persistent fidelity notice.
3041
+ - 0b6f412: Add SheetJS-backed spreadsheet and PapaParse-backed CSV document viewers with virtualized rows.
3042
+
3043
+ ## 3.0.0
3044
+
3045
+ ### Major Changes
3046
+
3047
+ - a712749: **Breaking:** the outer, externally-overridable tier of the design-token chain no longer lives in
3048
+ the previous external theme-input namespace — it moved to lyra's own `--lr-theme-*` namespace
3049
+ (for example, the brand fill input now uses `--lr-theme-color-brand-fill-loud`). Any consumer
3050
+ retheming components through the old external custom properties must rename those
3051
+ properties to `--lr-theme-*`; the two-tier override mechanism itself (set one property at any
3052
+ ancestor to retheme every component) is unchanged. This removes lyra-ui's remaining live runtime
3053
+ CSS coupling to Web Awesome.
3054
+
3055
+ ### Minor Changes
3056
+
3057
+ - 66c8819: Adds an independent `--lr-theme-*` shared token layer, aligns `<lr-button>`'s medium size with
3058
+ the standard Lyra font scale, exposes its host-width and size contracts, and adds opt-in native
3059
+ per-cell semantics to `<lr-heatmap>` through `accessible-cells`.
3060
+
3061
+ ### Patch Changes
3062
+
3063
+ - 11e6a03: `lr-details`/`lr-accordion-item` no longer render the localized "Details" fallback text alongside rich content slotted into `summary` when the plain-string `summary` prop is left unset. The fallback previously always rendered whenever `summary` was empty, regardless of whether a `slot="summary"` child was present — visible only when a consumer needed markup (an icon, multiple spans) in the summary rather than a plain string.
3064
+ - 581f5f3: `installHappyDomFormAssociatedShims()` no longer throws a `ReferenceError` when `HTMLElement` isn't a global at all — e.g. a plain Node Vitest environment sharing one `setupFiles` entry with happy-dom/jsdom test files. It previously read `HTMLElement.prototype` unconditionally, contradicting its own documented "safe to call unconditionally from a shared setup file used across multiple test environments" contract.
3065
+ - b5de65c: `lr-popover`/`lr-dropdown`/`lr-tooltip`'s `[part="popup"]` is now `position: fixed` from the start instead of only once the popup is first opened and JS positions it. Previously, while closed, the popup stayed `position: static` sized to its full slotted content, inflating the component's own inline-block host box to match -- an invisible-but-still-hit-testable area that could sit on top of unrelated page content and intercept pointer events until the trigger was first clicked.
3066
+
3067
+ ## 2.13.0
3068
+
3069
+ ### Minor Changes
3070
+
3071
+ - 80cb577: `lr-table` gains opt-in row selection (`selectionMode: 'single' | 'multiple'`, `selectedKeys`,
3072
+ `lr-selection-change`), a built-in filter field (`filterable`, `filterText`, `filter`,
3073
+ `lr-filter-change`), controlled pagination through `<lr-pagination>` (`pageSize`, `page`,
3074
+ `totalItems`, `paginationMode`, `lr-page-change`), a `loading` state with an indeterminate
3075
+ spinner, per-column double-click inline editing (`TableColumn.editable`/`editValue`/`editType`,
3076
+ `lr-cell-edit`), and row grouping (`groupBy`, `groupLabel`). All new properties default to
3077
+ today's exact behavior when left unset.
3078
+ - 5628327: `lr-input` and `lr-textarea` now also emit native-style `input`/`change` events (composed,
3079
+ matching the native element's own timing) alongside the existing `lr-input`/`lr-change`
3080
+ aliases, so consumers migrating from a native `<input>`/`<textarea>` don't need to rename their
3081
+ listeners. Both components also forward `spellcheck`, `autocapitalize`, `autocorrect`,
3082
+ `inputmode`, and `enterkeyhint` to their internal native control.
3083
+ - d009cd8: Adds a new "Web Awesome parity primitives" family: `lr-badge`/`lr-tag`, `lr-callout`,
3084
+ `lr-divider`, `lr-breadcrumb`/`lr-breadcrumb-item`, `lr-details`/`lr-accordion`/
3085
+ `lr-accordion-item`, `lr-button-group`, `lr-carousel`/`lr-carousel-item`,
3086
+ `lr-color-picker`, `lr-drawer`, `lr-popover`/`lr-tooltip`/`lr-dropdown`/
3087
+ `lr-dropdown-item`, `lr-radio`/`lr-radio-group`, `lr-rating`, `lr-spinner`,
3088
+ `lr-progress-bar`/`lr-progress-ring`, `lr-format-number`/`lr-format-date`/
3089
+ `lr-format-bytes`/`lr-relative-time`, `lr-image-comparer`, `lr-zoomable-frame`,
3090
+ `lr-scroller`, and headless `lr-intersection-observer`/`lr-mutation-observer`/
3091
+ `lr-resize-observer` wrappers. `lr-number-input` and `lr-time-input` join `lr-input` as
3092
+ sibling native-input-type primitives.
3093
+
3094
+ These close out the remaining free-tier Web Awesome components with no prior lyra-ui equivalent —
3095
+ 133 tags total, up from 97.
3096
+
3097
+ ### Patch Changes
3098
+
3099
+ - 5766257: `installHappyDomFormAssociatedShims()`'s stub `ElementInternals` now implements `setValidity()` as a no-op. `AnchoredValidityController` (used by every form-associated component) calls `internals.setValidity()` on every update, not just at construction, so a consumer's happy-dom test suite installing the shim would throw the moment any shimmed component's value changed after mount.
3100
+
3101
+ ## 2.12.0
3102
+
3103
+ ### Minor Changes
3104
+
3105
+ - 42036af: `lr-table` gains expandable rows: a table-level `expandedContent?: (row) => unknown` renders a
3106
+ full-width panel beneath any row whose key is in the new consumer-owned `expandedKeys: Set<string |
3107
+ number>` property, toggled via a built-in leading chevron cell and the new `lr-row-expand-toggle`
3108
+ event (`detail: { row, key }`). An optional `canExpand?: (row) => boolean` gates which rows get an
3109
+ interactive toggle at all. All three properties are additive and default to a no-op, so existing
3110
+ tables are unaffected.
3111
+
3112
+ - d612939: Make card headers wrap with their actions in narrow allocations, expose citation previews through
3113
+ a stable tooltip relationship, and localize the complete citation status announcement.
3114
+
3115
+ Add reactive `accessibleLabel` overrides to both code-block variants and media cards so host
3116
+ `aria-label` values reach the actionable or semantic element inside shadow DOM. Media-card's
3117
+ unnamed actions now use complete, per-kind localized messages.
3118
+
3119
+ Keep markdown within logical narrow allocations and make its `streaming` state hold `aria-busy`
3120
+ until the final content update.
3121
+
3122
+ - 159f3c9: `lr-file-input` now forwards host accessible names to its dropzone and file input, exposes an
3123
+ imperative focus target, reports explicit enabled/disabled ARIA state, and announces accepted and
3124
+ rejected file counts with correct singular and plural messages.
3125
+
3126
+ `lr-export-button` now forwards host accessible names to its trigger, exposes native focus and
3127
+ blur methods, and keeps long format menus within the positioned overlay's available space.
3128
+
3129
+ `lr-document-preview` now supports explicit image alternative text (including `alt=""` for
3130
+ decorative previews), aborts superseded text fetches, and documents its sizing, font, and spinner
3131
+ motion custom properties.
3132
+
3133
+ - 3da4f80: `lr-button` ships a default `:hover`/`:active` pointer-interaction treatment on `[part='base']`
3134
+ (`filter: brightness(--lr-button-hover-brightness)` on hover, `transform: scale(--lr-button-active-scale)`
3135
+ on active, both disabled under `prefers-reduced-motion`) -- previously it had zero hover/active CSS,
3136
+ so a mechanical `wa-button` -> `lr-button` rename silently dropped all pointer-interaction feedback.
3137
+
3138
+ `lr-button` is now form-associated (`static formAssociated = true` + `attachInternals()`), so it
3139
+ participates in an ancestor `<form>.elements` the same way `wa-button` does -- a sibling text field's
3140
+ own Enter-to-submit lookup (which scans `form.elements` for a `type === 'submit'` control) now finds
3141
+ it, instead of silently failing to submit the form.
3142
+
3143
+ `lr-button` gains an `appearance="accent"` value -- a loud, high-contrast filled tier equivalent to
3144
+ `wa-button`'s own runtime-default appearance, including for `variant="neutral"` (`'filled'` reads the
3145
+ ambient surface color there, matching `wa-button`'s `appearance="filled"`; `'accent'` reads a solid
3146
+ neutral fill, matching `wa-button`'s own unset-appearance default). New `--lr-button-accent-fill`/
3147
+ `-accent-on-fill` custom properties back it.
3148
+
3149
+ `lr-heatmap` gains a `monthLabelText?: (jsMonth: number, year: number) => string | undefined`
3150
+ property, the month-axis analogue of the existing `weekdayLabelText` -- lets a consumer's calendar-mode
3151
+ month labels track the same locale signal (e.g. an app's own i18n store) as every other localizable
3152
+ string on the component, instead of always following `toLocaleString(undefined, ...)`'s browser/OS-
3153
+ language default. Unset (the default) reproduces today's exact locale-derived output.
3154
+
3155
+ - 8a1777b: `lr-skeleton` adds an `announce` switch so grouped or decorative placeholders can avoid
3156
+ duplicating live-region announcements. Pulse and sheen effects now use the shared
3157
+ `--lr-transition-ambient` motion token and remain disabled by the reduced-motion branch.
3158
+ - 8e8a77f: `lr-tool-result-dialog` now forwards host `aria-label` to the internal dialog, exports its
3159
+ typed event map, localizes complete duration messages, omits non-finite durations, exposes its
3160
+ running-spin timing, and wraps footer actions in narrow layouts.
3161
+
3162
+ ### Patch Changes
3163
+
3164
+ - 6ba4d1f: Localize generation metrics, graph position announcements, attachment upload context, and duration templates. Mirror JSON viewer disclosure chevrons in RTL and give map content a named semantic group with correct host-label precedence.
3165
+ - b67a25e: Forward host accessible names to the semantic canvas or SVG in the chart, histogram, box-plot,
3166
+ and lite-chart families. Localize numeric summaries, mirror chart axes in RTL, refresh derived
3167
+ histogram data, improve BoxPlot theming and reduced-motion behavior, and support narrow allocations
3168
+ with long content across charts and context meters.
3169
+ - 5dd8066: `lr-chat-message` now formats its default timestamp with the component's effective locale,
3170
+ uses the shared ambient-motion token for streaming feedback, and wraps crowded footer controls
3171
+ in narrow allocations.
3172
+ - e95f942: Adds a complete interpolated localization message for citation status announcements so
3173
+ translations can reorder the citation index and status naturally.
3174
+ - 303e701: `lr-heatmap` now localizes its built-in value label and formats legend, accessible-range, cell,
3175
+ and calendar-date values with the component's effective locale. Explicit `value-label` text remains
3176
+ verbatim.
3177
+ - 87eb96a: `lr-heatmap` now mirrors its low-to-high legend ramp in right-to-left layouts, including
3178
+ consumer-provided multi-stop palettes.
3179
+ - 134dba0: Adds a complete interpolated localization message for lite-chart mark announcements so
3180
+ translations can reorder series, label, value, and position naturally.
3181
+ - 0260f9b: Harden `lr-app-rail`, `lr-attachment-chip`, `lr-avatar`, and `lr-chip-group`: respect the
3182
+ configured element prefix, preserve localized attachment-message word order, support image `File`
3183
+ objects in thumbnail-only mode, make spinner timing themeable, retry replacement avatar images,
3184
+ forward avatar accessible-name overrides, and collapse slot-forwarded overflow chips correctly.
3185
+ - 9033a43: Forward host naming and native textarea editing APIs through `lr-chat-composer`, complete
3186
+ `lr-phone-input` selection and range-editing methods, and expose observable focus/blur contracts
3187
+ for pagination, playback, and select controls.
3188
+ - acbbf00: Logical safe-area tokens now mirror the underlying physical browser insets in right-to-left
3189
+ layouts, keeping dialogs, toasts, widgets, and tool overlays clear of notches on the correct side.
3190
+ - 1f93e0c: `lr-sparkline` now applies its generated or consumer-provided accessible name to the internal
3191
+ SVG that owns the image role. Generated value summaries also respect the component's effective
3192
+ locale and per-instance message overrides.
3193
+ - 18003e2: `lr-tool-call-chip` now interpolates duration values through localized message templates and
3194
+ exposes coherent motion controls for its running spin and pending pulse. Its event map is also
3195
+ exported for typed listeners.
3196
+ - 140f9ea: Align `lr-checkbox` with the native checkbox keyboard, focus, reset, ARIA-state, and `input`/`change` event contracts while retaining `lr-change` as a compatibility alias.
3197
+ - d099ea7: Complete the combobox's native editing surface and clearable compatibility, align conversation-item event and story semantics, add accessible disabled and timing controls to copy-button, and localize and theme flag presentation.
3198
+
3199
+ ## 2.11.0
3200
+
3201
+ ### Minor Changes
3202
+
3203
+ - c0648ec: `lr-input` gains a `size: 'xs' | 's' | 'm' | 'l' | 'xl' = 'm'` property (reflected), the same scale
3204
+ `lr-select`/`lr-combobox` already use — `--lr-input-padding-block`/`-padding-inline`/
3205
+ `-font-size` swap per size, the same pattern as `lr-select`'s own size tokens. Unset (the default,
3206
+ `'m'`) reproduces today's exact sizing.
3207
+
3208
+ ## 2.10.0
3209
+
3210
+ ### Minor Changes
3211
+
3212
+ - f506542: `lr-heatmap` gains a `selectedCell` property (`{ row, col }` in matrix mode, `{ date }` in
3213
+ calendar mode) — a controlled, consumer-owned marker (mirroring `lr-lite-chart`'s
3214
+ `selectedIndex`) that draws a persistent canvas ring independent of keyboard focus, appends a
3215
+ "Selected: ..." description to the host's own `aria-label` so it stays discoverable after focus
3216
+ moves elsewhere, and appends a "(selected)" suffix to the keyboard live-region announcement. Unset
3217
+ (the default, `null`) reproduces today's exact output.
3218
+ - 6f6d758: Add `lr-button`, a generic action-button primitive (`variant`/`appearance`/`size`/`loading`/`disabled`/`type`, default + `start`/`end` slots) -- the `lr-*` equivalent of a plain `wa-button`.
3219
+ - 5eda04d: Add `lr-input`, a single-line plain-text input primitive (`type="text"`/`"password"`/`"email"`/`"number"`, label/hint/error chrome, form-associated validation, a built-in password-visibility toggle) -- the `lr-*` equivalent of a plain `wa-input`.
3220
+ - 7c95e95: `lr-tool-result-view` gains a real `fallback="text"` mode (previously accepted as an attribute
3221
+ value but silently treated identically to `"json"`): a string `result` renders as preformatted text
3222
+ instead of being forced through `<lr-json-viewer>`'s tree view, falling back to the `"json"`
3223
+ behavior when `result` isn't a string. A new `copyable` property adds a copy-to-clipboard affordance
3224
+ to either fallback kind. Additive — unset, both fallback kinds and every existing consumer render
3225
+ byte-identical to before.
3226
+
3227
+ ### Patch Changes
3228
+
3229
+ - 83fe6ba: Fix `lr-heatmap`'s `llms-full.txt` section, which was missing four real, already-shipped members
3230
+ (`cellInteractive`, `weekdayLabelText`, `colorSteps`, `refreshTheme`), and add a matching
3231
+ `focus()`/`blur()` mention to `lr-button`'s own section. Add a `pnpm run llms-freshness` lint gate
3232
+ (wired into `contract-policy`, so it runs in `lint`/CI/`publish.sh`) that fails the build if any
3233
+ custom element's public property isn't mentioned anywhere in its own `llms-full.txt` section, so
3234
+ this can't silently drift again. A small baseline of ~20 pre-existing drift items on unrelated
3235
+ components (chart family, dialog, menu, split, tree-node, widget, etc.), discovered while building
3236
+ this check, is exempted for now via a documented allowlist in the script — out of scope for this
3237
+ change, left for a follow-up cleanup.
3238
+
3239
+ ## 2.9.0
3240
+
3241
+ ### Minor Changes
3242
+
3243
+ - b4a6f5b: `lr-heatmap`'s color ramp now preserves a translucent `rgba()`/`hsla()`/hex-with-alpha color instead of silently resolving it to fully opaque. `resolveRgb()`/`hexToRgb()` return an `[r, g, b, a]` quadruple (previously `[r, g, b]`), and the ramp emits `rgba(...)` whenever an endpoint is translucent — unchanged `rgb(...)` output for opaque colors, so an existing consumer using only opaque `--lr-heatmap-scale-lo`/`-hi` values sees no difference. Lets a consumer key a ramp endpoint off a themed semi-transparent surface token (e.g. a "quiet baseline" tint) and get the intended translucent cell color instead of a stark opaque one.
3244
+
3245
+ ## 2.8.0
3246
+
3247
+ ### Minor Changes
3248
+
3249
+ - 0331bbf: `lr-table` gains a public, reflected `showAllColumns` property/`show-all-columns` attribute for its reveal-hidden-columns state, plus a `lr-columns-revealed` event fired when `[part='reveal-columns-button']` toggles it. Consumers can now read the current reveal state back (to persist it) and set an initial one (to restore a previously-persisted preference), mirroring the read-back/set-forward contract `sortKey`/`sortDir` already support. The button still toggles the state itself by default, so existing usage is unaffected.
3250
+
3251
+ ## 2.7.0
3252
+
3253
+ ### Minor Changes
3254
+
3255
+ - af61856: `lr-app-rail`'s navigation landmark (and its `role="dialog"` while the mobile overlay is open) now honors a host-level `aria-label` attribute, taking precedence over the `label` property and its localized `"Navigation"` default, mirroring `<lr-date-input>`'s `accessibleLabel` pattern. Previously a host-level `aria-label` on `<lr-app-rail>` had no effect on the accessible name computed inside its shadow DOM.
3256
+ - 4ee4e76: `lr-chat-composer` forwards `spellcheck`/`autocapitalize`/`autocorrect` onto its internal `<textarea>` and re-dispatches bubbling, composed `blur`/`focus` events so a host-level listener can observe focus changes across the shadow boundary.
3257
+ - 06e5fda: `lr-chip` gains a `--lr-chip-pressed-bg` custom property (falls back to `--lr-chip-bg`) so the pressed/selected background can be set independent of the resting background. A toggleable-but-unpressed chip now announces `aria-pressed="false"` instead of omitting the attribute entirely, matching the ARIA Authoring Practices convention for toggle buttons.
3258
+ - a158b6b: `lr-combobox` gains a `size` property (`'xs'|'s'|'m'|'l'|'xl'`, default `'m'`) mirroring `lr-select`'s existing scale, including matched sizing for the "+N" overflow tag so it stays visually consistent with the trigger at every size. Async `ComboboxSourceRow` results can now carry a decorative `icon`, trailing `badge`, richer `accessibleLabel`, and opaque `data`; the read-only `selectedRows` getter retains the structured rows and payloads for the current selection. The new visuals are exposed through `option-icon` and `option-badge` CSS parts.
3259
+ - 480d9e2: `lr-conversation-item` forwards `spellcheck`/`autocapitalize`/`autocorrect` onto its in-place rename `<input>` and re-dispatches bubbling, composed `blur`/`focus` events so a host-level listener can observe focus changes across the shadow boundary while a rename is in progress.
3260
+ - 74dcaa7: `lr-date-input` forwards `spellcheck`/`autocapitalize`/`autocorrect` onto its internal `<input>` and re-dispatches bubbling, composed `blur`/`focus` events so a host-level listener can observe focus changes across the shadow boundary.
3261
+ - 22f206c: `lr-dialog` now lets a host-level `aria-label` attribute win over its computed accessible name (a slotted heading, `heading`, or `label`), matching `<lr-date-input>`'s `accessibleLabel` pattern. Previously a consumer setting `aria-label` directly on `<lr-dialog>` was silently ignored in favor of the bespoke `label`/`heading` props. Additive — left unset, today's existing three-tier fallback is unchanged.
3262
+ - 80b22ba: `lr-empty`'s `compact` mode gains a `--lr-empty-compact-align` custom property (defaulting to today's exact `flex-start`/`start` pair) so a consumer can combine `compact`'s denser padding with a centered heading/description layout by setting it to `center`.
3263
+ - 0f21c57: `lr-export-button` accepts custom format descriptors with consumer-supplied labels, descriptions, and extension metadata. Custom formats emit `lr-export` for application handling without bundling an encoder, while a new controlled `loading` state exposes busy semantics and prevents duplicate activation during async exports.
3264
+ - 3ac5e4d: `lr-gauge` gains a full-circle `type="ring"` presentation and a `--lr-gauge-fill` custom property for setting the fill stroke per instance across radial, ring, and linear gauges.
3265
+ - f6b2aa5: `lr-graph` nodes gain independent accessible labels and SVG tooltip descriptions. Links gain stable ids, spoken-name/tooltip relationship-label fallbacks (not visible edge text), tooltip descriptions, directed arrowheads, per-link colors, and dash patterns; `lr-link-click` now includes the optional link id and the marker is exposed through the `arrowhead` CSS part. A host `aria-label` is forwarded to the internal semantic SVG.
3266
+ - efc1182: `lr-map` now forwards a host-level `aria-label` attribute onto `[part="base"]`'s accessible name as a fallback when `label` is left unset, matching `lr-slider`/`lr-checkbox`/`lr-switch` — previously a host `aria-label` was silently dropped in favor of the localized `'map'` default.
3267
+ - 085d173: `lr-mention-popover` now honors a host-level `aria-label` attribute as the accessible name for its internal `role="listbox"` popup, taking priority over the `label` property and its localized default. Previously the popup's name came only from `label`/`localize()`, so a plain `aria-label` set on `<lr-mention-popover>` itself was silently ignored — matches the same fallback already used by `lr-combobox`/`lr-table`.
3268
+ - 3b59e94: `lr-menu`'s `role="menu"` popup now honors a host-level `aria-label` attribute over both the `label` prop and its localized default, matching `lr-select`/`lr-model-select`'s established `this.getAttribute('aria-label') || <computed default>` precedence. Additive — `aria-label` is unset by default, so every existing consumer (whether relying on the default `"Menu"` text or an explicit `label` prop) renders byte-identical to before.
3269
+ - 653173d: `lr-model-select` gains an opt-in `hint`/`error-text` form-control chrome (matching named slots and `hint`/`error` CSS parts, mirroring `lr-select`, with `aria-describedby` wired to the rendered ids), plus `spellcheck`/`autocapitalize`/`autocorrect` passthrough and bubbling `blur`/`focus` events on the free-text mode's internal `<input>`. All additive — a bare `<lr-model-select>` with none of these set renders byte-identical to before.
3270
+ - 992b0ba: Add `lr-pagination`, a controlled, localized page-navigation component with previous/next controls, a validated numeric page jump, range summaries, applied-page announcements, loading/empty handling, RTL-aware icons, five sizes, and container-responsive stacking. Enrich `TreeItem` rows with optional `icon`, `description`, and `accessibleLabel` fields plus matching structured CSS parts while preserving the existing tree keyboard model.
3271
+ - dfb2f5e: Add `lr-phone-input`, a form-associated country/telephone field that keeps canonical form values in E.164 while preserving partial editable input. Numbering metadata stays opt-in through an injected adapter or the consumer-loaded `loadLibphonenumberAdapter()` helper; `libphonenumber-js` is an optional peer and international E.164 input works without a formatter.
3272
+ - d88377a: `lr-switch` gains an opt-in `hint`/`error-text` form-control chrome (props + matching named `hint`/`error` slots + CSS parts), mirroring `lr-select`'s pattern for those two pieces, with `aria-describedby` wired to whichever are rendered. Left unset, neither renders and the control is unchanged. The default slot stays the control's visible, clickable label (same as `lr-checkbox`) — no separate top-of-field `label` prop was added.
3273
+ - c8709cd: `lr-textarea` gains optional label/hint/error chrome, accessible-name forwarding, bounded auto-resize, editing-assistance attributes, public native-input and selection/caret APIs, synchronized `setRangeText()`, and bubbling composed focus/blur events. Existing visual and behavioral defaults remain unchanged when the new options are unused.
3274
+ - fca0ffb: `lr-tool-approval-dialog`'s raw-JSON args `<textarea>` now also hardcodes `autocapitalize="off"` and `autocorrect="off"` alongside its existing `spellcheck="false"`, so a mobile browser (notably iOS Safari, which defaults textarea `autocapitalize` to `'sentences'`) can no longer auto-capitalize or auto-correct JSON key/value text while a user edits tool-call arguments, silently corrupting the JSON.
3275
+ - 5b9b056: `lr-tree` now forwards a host-level `aria-label` attribute onto the internal `role="tree"` element's accessible name as a fallback when `label` is left unset, matching `lr-slider`/`lr-select` — previously a host `aria-label` was silently dropped since `role="tree"` lives on an internal element, not the host.
3276
+ - 12595bd: `lr-typing-indicator`'s dots-variant stagger delays are now themeable via `--lr-typing-dot-stagger-1`/`-2` (defaulting to today's exact `600ms`/`1200ms`), so a consumer retiming `--lr-transition-ambient` can keep the stagger proportional.
3277
+
3278
+ ## 2.6.0
3279
+
3280
+ ### Minor Changes
3281
+
3282
+ - 78d4b58: `lr-chat-message` gains an `attachments-position` prop (`'before' | 'after'`, default `'after'`) so the `attachments` slot can render above the message body instead of below it, keeping DOM/visual/reading order in sync.
3283
+ - a072af9: `lr-chip` gains a `--lr-chip-pressed-border` custom property so a consumer can set the pressed/selected border color independent of `--lr-chip-accent` (which also drives the label text color). Falls back to `--lr-chip-accent`, so existing consumers are unaffected.
3284
+ - b56bdb2: `lr-empty` gains a `--lr-empty-compact-padding` custom property to override `compact`'s fixed uniform padding (e.g. with an asymmetric shorthand like `8px 2px`). Falls back to `var(--lr-space-xs)`, today's exact value.
3285
+ - e029ac2: `lr-heatmap` calendar mode gains a `weekdayLabelText?: (jsWeekday: number) => string | undefined` hook to override the weekday-axis label text (e.g. for a consumer with its own locale/translation state independent of the browser's runtime locale).
3286
+ - 6d5f9c4: Add `lr-textarea`, a bare multiline plain-text input primitive (value/rows/resize/placeholder, form-associated validation) — the `lr-*` equivalent of a plain `wa-textarea`.
3287
+ - bbe8007: `lr-segmented`'s `SegmentedItem` gains an optional `icon` field, rendered before the item's label.
3288
+ - e98013a: `lr-table`'s `TableColumn` gains a `headerCell` render hook (mirroring `cell`/`footer`) and `width`/`minWidth` fields. Any column defining `width` switches the table to `table-layout: fixed` so widths are authoritative.
3289
+ - 993809a: `lr-widget` gains a `backdrop-inset` prop to decouple the fullscreen backdrop's inset from the panel's own `fullscreen-inset`. Falls back to `fullscreen-inset`, so existing consumers are unaffected.
3290
+
3291
+ ### Patch Changes
3292
+
3293
+ - 1c78bd2: Fix `lr-poll-status`, `lr-typing-indicator`, and `lr-stream-status`'s ambient "still alive" pulse/bounce animations, which reused `--lr-transition-base` (180ms — reserved for discrete UI micro-interactions) and rendered as a fast flicker instead of a calm breathing loop. Adds a dedicated `--lr-transition-ambient` token (1.8s) for infinite looping indicators.
3294
+ - e029ac2: Fix `lr-heatmap`'s `cellColor` hook silently rendering solid black when it returns a CSS custom property or other non-literal color (e.g. `color-mix(...)`) — the value is now resolved via a cached, hidden probe element before being assigned to the canvas `fillStyle`.
3295
+ - 600544f: Fix `lr-skeleton` rendering as an invisible 0×0 box everywhere: `[part='base']` was a bare `<span>` (UA default `display: inline`), so its own `inline-size`/`block-size` were CSS no-ops per spec. Adds `display: block`.
3296
+
3297
+ ## 2.5.0
3298
+
3299
+ ### Minor Changes
3300
+
3301
+ - 84cefde: `lr-attachment-trigger`'s single-capability trigger `aria-label`s ("Attach files"/"Attach an
3302
+ image"/"Use camera"), its multi-capability menu's "Add attachment" label/aria-label, and its menu
3303
+ item labels ("Upload files"/"Upload a photo"/"Take a photo") now route through `this.localize()`,
3304
+ overridable via `.strings`/`registerLyraLocale()`. Default English output is unchanged when no
3305
+ override is set.
3306
+ - 6bf30ea: `lr-avatar` now accepts default-slotted icon/glyph content (e.g. an inline SVG), shown in place of
3307
+ the image/initials and taking priority over both `src` and `initials` — useful for a chat UI
3308
+ distinguishing an "AI" avatar from a "user" avatar by role glyph rather than a photo or initials. Set
3309
+ `alt` alongside the icon for an accessible name, since the glyph itself is treated as decorative.
3310
+ - 87890ea: `lr-checkbox`'s built-in required-field validation message ("Please check this box if you want
3311
+ to continue.") now routes through `this.localize()`, overridable via `.strings`/
3312
+ `registerLyraLocale()`. Default English output is unchanged when no override is set.
3313
+ - b720eda: Fixed `lr-chip`'s opt-in `selected` toggle/pressed mode so it stays interactive after the first
3314
+ click. `[part='base']`'s `role="button"`, `tabindex`, `aria-pressed`, and click/keydown handlers
3315
+ used to be gated on the _current_ value of `selected`, so a chip that started `selected` and was
3316
+ clicked (flipping it to `false`) lost its focusable/clickable semantics on the next render — there
3317
+ was no way to click it back on. `selected` becoming `true` at any point now latches the chip into
3318
+ toggle mode for good, so it stays clickable in both directions. A chip that must be interactive
3319
+ from the outset while starting **unselected** (e.g. an initially-inactive filter chip) can opt in
3320
+ explicitly with the new `toggleable` property, since `selected`'s own default (`false`) can't be
3321
+ told apart from "never opted in" on its own.
3322
+ - cbfec47: `lr-citation-badge`'s visible status words folded into its computed accessible name ("High
3323
+ confidence"/"Medium confidence"/"Low confidence"/"Verified"/"Unverified") now route through
3324
+ `this.localize()`, overridable via `.strings`/`registerLyraLocale()`. Default English output is
3325
+ unchanged when no override is set.
3326
+ - dba57e9: `lr-context-meter`'s accessible summary ("{used} of {total} used" / "{used} used") now routes
3327
+ through `this.localize()`, overridable via `.strings`/`registerLyraLocale()`. Default English
3328
+ output is unchanged when no override is set.
3329
+ - 7379a41: `lr-conversation-item`'s "Untitled conversation" fallback title now routes through
3330
+ `this.localize()`, overridable via `.strings`/`registerLyraLocale()`. Default English output is
3331
+ unchanged when no override is set.
3332
+ - acdaa37: `lr-dock-panel`'s resize-handle and collapse-toggle `aria-label`s ("Resize panel",
3333
+ "Collapse panel"/"Expand panel") now route through `this.localize()`, overridable via
3334
+ `.strings`/`registerLyraLocale()`. Default English output is unchanged when no override is set.
3335
+ - eca2ea4: `lr-document-preview`'s hardcoded English strings — the image-preview `alt` fallback
3336
+ ("Document preview"), the unsafe-URL error ("Document URL is not allowed."), the non-`Error`
3337
+ fetch-failure message ("Failed to load document."), and the empty-`error-message` fallback
3338
+ ("Something went wrong.") — now route through `this.localize()`, overridable via
3339
+ `.strings`/`registerLyraLocale()`. Its in-flight text-fetch spinner label ("Loading document…")
3340
+ is now also wired through the existing `loadingDocument` message key. Default English output is
3341
+ unchanged when no override is set.
3342
+ - a3c4ebf: `lr-export-button`'s trigger button text (default "Export", also reused for the format menu's
3343
+ `aria-label`) now routes through `this.localize()` when `label` is left at its built-in default,
3344
+ overridable via `.strings`/`registerLyraLocale()` — matching `lr-attachment-chip`'s
3345
+ `removeLabel`/`retryLabel` convention. Setting the `label` attribute/property explicitly still
3346
+ overrides it directly. Default English output is unchanged when no override is set.
3347
+ - df8341b: `lr-generation-status`'s stop-button `aria-label` ("Stop generating") now routes through
3348
+ `this.localize()` (sharing the existing `stopGenerating` key used elsewhere in the library), and
3349
+ the tokens segment's singular/plural noun ("token"/"tokens") is now localizable too, matching
3350
+ `lr-json-viewer`'s/`lr-word-cloud`'s existing count-noun pattern. Overridable via
3351
+ `.strings`/`registerLyraLocale()`. Default English output is unchanged when no override is set.
3352
+ - 20ae3e7: `lr-graph`'s visually-hidden data-list `aria-label` ("Graph data") now routes through
3353
+ `this.localize()`, overridable via `.strings`/`registerLyraLocale()`. Default English output is
3354
+ unchanged when no override is set.
3355
+ - 8c29581: `lr-segmented` gains a `label` property giving its `role="radiogroup"` root an accessible name.
3356
+ When unset, a plain `aria-label` attribute on the host element is honored as a fallback, matching
3357
+ `lr-slider`'s existing `label`/`aria-label` convention. Previously the radiogroup had no way to
3358
+ receive an accessible name at all.
3359
+ - 259c0c6: Completed a full-library i18n/RTL/styling standardization pass across the remaining component
3360
+ families not yet covered by earlier rounds — `chart` (and `box-plot`/`histogram`/`lite-chart`),
3361
+ `avatar`, `code-block`, `combobox`, `date-picker`, `dialog`, `document-preview`, `export-button`,
3362
+ `file-input`, `graph`, `heatmap`, `map`, `time-range`, `tool-call-chip`, `tool-param-form`,
3363
+ `tool-result-dialog`, `tree`, `widget`, and several smaller components. Highlights:
3364
+
3365
+ - Routed remaining hardcoded English strings (accessible descriptions, aria-labels, empty-state
3366
+ text) through `this.localize()`.
3367
+ - Fixed RTL gaps: `date-picker`'s previous/next chevrons now mirror under `dir="rtl"` (rotating
3368
+ the wrapping `part`, not the icon), matching the grid's own arrow-key swap.
3369
+ - `lr-avatar`: fixed a dangling `--lr-color-surface-alt` token reference, corrected its `size`
3370
+ JSDoc, and extended the accessible-name role/`aria-label` to the initials-fallback path (not
3371
+ just the icon-slot path) whenever `alt` is set.
3372
+ - `lr-export-button` now fires `lr-show`/`lr-hide` on its format menu, matching the same
3373
+ convention already used by `lr-menu`/`lr-select`/`lr-combobox`.
3374
+ - Fixed a `this.localize(key, literalFallback)` pattern that unconditionally short-circuited
3375
+ `registerLyraLocale()` lookups for the affected keys (the fallback is now omitted wherever
3376
+ `DEFAULT_STRINGS` already carries the same default).
3377
+
3378
+ AGENTS.md gained a new "Internationalization (i18n), RTL, and theming" section documenting the
3379
+ resulting standard, and both READMEs now summarize it for consumers.
3380
+
3381
+ - 79e4390: Fixed gaps found during a full re-verification pass over previously-completed work:
3382
+
3383
+ - `lr-menu`'s type-ahead navigation now excludes `hidden`/`aria-hidden` items (it already
3384
+ excluded `disabled` ones), matching the Arrow/Home/End roving-focus navigation it sits next to.
3385
+ - The root barrel (`src/lyra.ts`) now re-exports 13 component event-map types that were previously
3386
+ unreachable from the package root even though their owning classes were exported: `LyraChip`,
3387
+ `LyraChipGroup`, `LyraCitationBadge`, `LyraCopyButton`, `LyraDiffView`, `LyraFileInput`,
3388
+ `LyraHeatmap`, `LyraLiteChart`, `LyraMediaCard`, `LyraSelect`, `LyraSourceCard`, `LyraSplit`, and
3389
+ `LyraTimeRange`'s `*EventMap` types are now all importable from `@aceshooting/lyra-ui`.
3390
+
3391
+ - 59d4477: `lr-media-card`'s hardcoded English fallback strings — the file-chip "Untitled file" name, the
3392
+ `image`/`video` alt-text fallbacks ("Image attachment"/"Video attachment"), and the accessible
3393
+ "Open …" label (both the named and generic-kind forms) — now route through `this.localize()`,
3394
+ overridable via `.strings`/`registerLyraLocale()`. Default English output is unchanged when no
3395
+ override is set.
3396
+ - ea774a8: `lr-mention-popover`'s default listbox accessible name ("Suggestions") now routes through
3397
+ `this.localize()`, overridable via `.strings`/`registerLyraLocale()` — matching the already-shared
3398
+ `noMatches` key its empty-state row uses. An explicit `label`/`empty-text` value still wins
3399
+ verbatim. Default English output is unchanged when no override is set.
3400
+ - cd10606: `<lr-menu>` gains an opt-in `closeOnEscapeAnywhere` property. Escape has always closed the menu
3401
+ and refocused the trigger when it originates from a real `<lr-menu-item>`, but slotted non-item
3402
+ content (e.g. a form control slotted alongside the items) previously got full default keyboard
3403
+ behavior with no way to close the menu on Escape. Setting `closeOnEscapeAnywhere` extends that
3404
+ same Escape-closes-and-refocuses behavior to keydowns from anywhere in the list, including slotted
3405
+ non-item content. Defaults to `false`, so existing consumers are unaffected.
3406
+ - 7d63af9: `lr-menu`'s `role="menu"` popup default accessible name ("Menu") now routes through
3407
+ `this.localize()`, overridable via `.strings`/`registerLyraLocale()`. An explicit `label` value
3408
+ still wins verbatim. Default English output is unchanged when no override is set.
3409
+ - f232381: `lr-model-settings-panel`'s hardcoded English strings — the visible "Temperature" caption
3410
+ (also reused as the nested `lr-slider`'s accessible name) and the internal `lr-model-select`'s
3411
+ "Select a model…" placeholder — now route through `this.localize()`, overridable via
3412
+ `.strings`/`registerLyraLocale()`. Default English output is unchanged when no override is set.
3413
+ - 1686322: `lr-playback`'s play/pause button and position-slider `aria-label`s ("Play"/"Pause",
3414
+ "Playback position") now route through `this.localize()`, overridable via
3415
+ `.strings`/`registerLyraLocale()`. Default English output is unchanged when no override is set.
3416
+ - 0cacb4d: `lr-poll-status`'s pause/resume button aria-label, due-state countdown text ("Refreshing…"), and its
3417
+ three live-region announcements ("Paused."/"Resumed."/"Refreshing now.") now route through
3418
+ `this.localize()`, overridable via `.strings`/`registerLyraLocale()`. It also now shows a distinct
3419
+ "Paused" countdown state while `paused`, instead of freezing on whatever value it last displayed.
3420
+ Default English output is unchanged when no override is set.
3421
+ - 870523f: `lr-widget` gains two new named slots, `collapse-icon` and `fullscreen-icon`, overriding the
3422
+ built-in chevron/expand-or-close glyphs on the collapse and fullscreen toggle buttons entirely
3423
+ (platform slot-fallback-content mechanism: whatever is assigned wins, otherwise the default glyph
3424
+ renders unchanged). `WidgetView`'s `label` is now optional and a new `ariaLabel` field lets a view
3425
+ toggle be icon-only while still exposing an accessible name — previously a toggle with no `label`
3426
+ had no accessible name at all.
3427
+ - c2bc232: Re-audited every component against the library's i18n/RTL/theming standard and fixed the
3428
+ remaining gaps found:
3429
+
3430
+ - Removed several `this.localize(key, literalFallback)` call sites (`toolApprovalHeading`,
3431
+ `playback`'s play/pause/position labels, `model-settings-panel`'s temperature/model labels,
3432
+ `media-card`'s five accessible-name strings, `kbd`'s shortcut-token labels, `chat-composer`'s
3433
+ composer label) where the literal fallback silently defeated `registerLyraLocale()` translation
3434
+ for that call site.
3435
+ - Routed remaining hardcoded strings through `this.localize()`: `date-picker`'s next-month label
3436
+ and `date-input`'s validation messages, `toast-item`'s/`chip`'s/`combobox`'s remove/close
3437
+ labels (now interpolated via a `{placeholder}` instead of string concatenation), `heatmap`'s
3438
+ matrix/calendar aria-labels and "no data"/row/col fallbacks, `chart`/`box-plot`'s description
3439
+ and data-table text, `lite-chart`'s mark-position announcement, `document-preview`'s empty-state
3440
+ nouns, `json-viewer`'s copy/expand/collapse/count labels, `stat`'s trend announcement,
3441
+ `dialog`'s `confirm()` cancel button, `typing-indicator`'s default label, `tool-param-form`'s
3442
+ edge-case validation message, and `tool-result-dialog`/`tool-call-chip`'s duration seconds unit.
3443
+ - Fixed RTL gaps: `app-rail-item`'s icon tooltip now flips side under `dir="rtl"` via
3444
+ `rtlAwarePlacement()`, `chat-message`'s and `source-list`'s collapse/disclosure chevrons now
3445
+ mirror under RTL, and `lite-chart`'s roving-tabindex point navigation now swaps
3446
+ ArrowLeft/ArrowRight under RTL.
3447
+
3448
+ Also compressed the shared string registry (`internal/localization.ts`): removed 21 `kbd*` base
3449
+ keys (`kbdEnter`, `kbdEscape`, `kbdTab`, etc.) that were fully superseded by their `*Word`/`*Visual`
3450
+ counterparts and had no remaining call sites anywhere in the library, reducing the packed consumer
3451
+ bundle size.
3452
+
3453
+ - aeef118: `lr-select`'s required-field validation message ("Please select an option.") and its
3454
+ trigger's fallback accessible name ("Select", used only when no `aria-label`, `label`, or
3455
+ `placeholder` is set) now route through `this.localize()`, overridable via
3456
+ `.strings`/`registerLyraLocale()`. Default English output is unchanged when no override is set.
3457
+ - 4fb27a2: `lr-skeleton`'s default accessible name ("Loading…") now routes through `this.localize()`
3458
+ (reusing the shared `loading` key), overridable via `.strings`/`registerLyraLocale()`. An
3459
+ explicit `label` still wins verbatim. Default English output is unchanged when no override is set.
3460
+ - f7b9f0e: `lr-source-list`'s fallback header text ("Sources", used only when neither `label` nor
3461
+ `label-plural` is set) now routes through `this.localize()`, overridable via
3462
+ `.strings`/`registerLyraLocale()`. Default English output is unchanged when no override is set.
3463
+ - f2ea145: `lr-stepper`'s `StepItem` gains an optional `title` field, rendered as a native `title` tooltip on
3464
+ that step's button — useful for explaining why a `disabled` step is locked (e.g. "Complete Basics
3465
+ first"). Steps that omit it render no `title` attribute at all, unchanged from today.
3466
+ - 9e5864a: `lr-stream-status`'s built-in stalled-message default ("Taking longer than usual…") and its
3467
+ three live-region announcements ("Connection stalled."/"Connection restored."/"No longer
3468
+ stalled.") now route through `this.localize()`, overridable via `.strings`/`registerLyraLocale()`.
3469
+ Default English output is unchanged when no override is set.
3470
+ - 9174500: `lr-switch`'s built-in required-field validation message ("Please turn this on.") now routes
3471
+ through `this.localize()`, overridable via `.strings`/`registerLyraLocale()`. Default English
3472
+ output is unchanged when no override is set.
3473
+ - 60084ba: `lr-thinking-panel`'s default header label ("Thinking") and its duration-display text ("Thought
3474
+ for …"/"Thinking…") now route through `this.localize()`, overridable via
3475
+ `.strings`/`registerLyraLocale()`. An explicit `label` still wins verbatim. Default English
3476
+ output is unchanged when no override is set.
3477
+ - b113bda: `lr-tool-approval-dialog`'s heading text, generic tool-name fallback, args-editor accessible
3478
+ name, invalid-JSON fallback error, and its Deny/Edit/Approve button labels now route through
3479
+ `this.localize()`, overridable via `.strings`/`registerLyraLocale()`. Default English output is
3480
+ unchanged when no override is set.
3481
+ - 3b1f930: `lr-tool-call-chip`'s visible status labels (Pending/Running/Success/Error/Denied, shared with
3482
+ `lr-tool-result-dialog`'s identical vocabulary) and its unnamed-tool fallback ("Tool call") now
3483
+ route through `this.localize()`, overridable via `.strings`/`registerLyraLocale()`. Default English
3484
+ output is unchanged when no override is set.
3485
+ - bbaea80: `lr-tool-param-form`'s validation messages (required field, wrong type for a string/number/
3486
+ integer/boolean, enum mismatch, const mismatch, unsupported field type, malformed schema shape,
3487
+ non-serializable value) now route through `this.localize()`, overridable via
3488
+ `.strings`/`registerLyraLocale()`. Default English output is unchanged when no override is set.
3489
+ - bda19ac: `lr-tool-select-dialog`'s dialog title, search placeholder, "use default tools" switch label
3490
+ and hint, category count/"Other" fallback, tools-enabled summary, no-matches message, and the
3491
+ no-tools-available empty state now route through `this.localize()`, overridable via
3492
+ `.strings`/`registerLyraLocale()`. Default English output is unchanged when no override is set.
3493
+ - 220bd73: `lr-widget`'s collapse/expand, exit-fullscreen/expand-to-fullscreen, and view-toggle-group
3494
+ aria-labels, plus its fullscreen dialog's fallback accessible name, now route through
3495
+ `this.localize()`, overridable via `.strings`/`registerLyraLocale()`. The collapse/expand labels
3496
+ reuse `lr-dock-panel`'s existing `dockPanelCollapse`/`dockPanelExpand` keys. Default English
3497
+ output is unchanged when no override is set.
3498
+
3499
+ ### Patch Changes
3500
+
3501
+ - 00ce49f: Fix `lr-date-picker`'s day-grid keyboard navigation to swap ArrowLeft/ArrowRight under `dir="rtl"`, matching the grid's own visual mirroring (the day cells use unset `direction`, so the browser already lays them out right-to-left). ArrowUp/ArrowDown (by week) are unaffected.
3502
+ - 37e1a2f: `lr-table`'s header-cell ArrowLeft/ArrowRight roving-tabindex navigation now derives its RTL
3503
+ check through the shared `isRtl()` helper instead of a duplicated inline `getComputedStyle`
3504
+ check, and gains test coverage confirming ArrowRight/ArrowLeft already swap correctly under
3505
+ `dir="rtl"` (a native `<table>` mirrors column visual order under RTL on its own) while
3506
+ ArrowUp/ArrowDown row navigation is unaffected. No behavior change.
3507
+ - 2fd3786: Fix calendar-heatmap weekday-axis labels to respect firstDayOfWeek instead of always labeling grid rows 1/3/5.
3508
+
3509
+ ## 2.4.0
3510
+
3511
+ ### Minor Changes
3512
+
3513
+ - 171bdbd: `lr-attachment-chip`'s file-size unit abbreviations ("B"/"KB"/"MB"/"GB"/"TB") now route through
3514
+ `this.localize()` when rendered, overridable via `.strings`/`registerLyraLocale()`. The exported
3515
+ `formatFileSize()` pure function gains an optional `unitLabel` resolver parameter, defaulting to the
3516
+ plain English abbreviation — every existing single-argument call is unaffected.
3517
+ - 5f043ba: `lr-chart`'s data-table "Category" column header, per-row "Point N" fallback label, and "Reset
3518
+ zoom" button text now route through `this.localize()`, overridable via `.strings`/
3519
+ `registerLyraLocale()`. Default English text is unchanged.
3520
+ - 5e90140: `lr-chat-composer`'s action button labels ("Send message"/"Stop generating") now route through
3521
+ `this.localize()`, overridable via `.strings`/`registerLyraLocale()`. Also adds `stoppable: boolean =
3522
+ true` — when set to `false`, the button never renders as a Stop/cancel control while busy; it stays a
3523
+ disabled Send button instead, for backends with no cancellation endpoint. Default behavior is
3524
+ unchanged.
3525
+ - 558e76c: `lr-chat-message`'s visible status text ("Sending…"/"Responding…"/"Failed to send") and its two
3526
+ live-region status-change announcements ("Message failed to send."/"Message complete.") now route
3527
+ through `this.localize()`, overridable via `.strings`/`registerLyraLocale()`. Default English text is
3528
+ unchanged.
3529
+ - 238c8d7: `lr-chip-group`'s collapsed overflow-indicator's visible "+N" text now routes through
3530
+ `this.localize('showMoreCollapsed', ...)`, matching the aria-label it sits beside, which was already
3531
+ localized. Default English output ("+N") is unchanged.
3532
+ - 0d9018f: `lr-code-block`'s collapse-toggle, copy-button, and code-region aria-labels now route entirely
3533
+ through `this.localize()` instead of concatenating a localized verb with a hardcoded English suffix
3534
+ ("code"/"to clipboard"/"Code"). Default English output is unchanged.
3535
+ - a249bd6: `lr-diff-view`'s copy-button aria-label now routes entirely through `this.localize('copyDiff', ...)`
3536
+ instead of concatenating the localized "copy" verb with a hardcoded " diff" suffix. Default English
3537
+ output ("Copy diff") is unchanged.
3538
+ - 58c6e59: `lr-file-input`'s drag-preview live-region announcements ("Release to add the file." / "This file
3539
+ type is not accepted.") now route through `this.localize()`, overridable via `.strings`/
3540
+ `registerLyraLocale()`. Default English text is unchanged. The post-drop `acceptedMessage`/
3541
+ `rejectedMessage` properties and the visible `label` property are unaffected (already
3542
+ consumer-overridable).
3543
+ - b3e3bb6: `lr-json-viewer`'s root-node toggle/copy fallback words ("array"/"object"/"value", used only when a
3544
+ node has no key label) now route through `this.localize()`, overridable via `.strings`/
3545
+ `registerLyraLocale()`. Default English text is unchanged.
3546
+ - b322e75: `lr-model-select`'s synthetic stale-value row badge ("not in catalog") now routes through
3547
+ `this.localize('notInCatalog')`, so it can be overridden via `.strings`/`registerLyraLocale()` like
3548
+ the component's other built-in message (`noMatches`). Default English text is unchanged.
3549
+ - e54eeee: `lr-source-card`'s "Untitled source" fallback and its " — p. N" page-suffix format now route
3550
+ through `this.localize()`, overridable via `.strings`/`registerLyraLocale()`. Default English output
3551
+ is unchanged.
3552
+ - 0576643: `lr-split` now redistributes the track space freed when a `panelConstraints` pixel bound clamps a
3553
+ panel's percentage basis down (e.g. a `maxPx` cap on a wide viewport) to sibling panels that have no
3554
+ pixel constraint of their own, instead of leaving that space unused. No behavior change for splits
3555
+ without `panelConstraints`, or where no panel is actually clamped this render.
3556
+ - 97756af: `lr-table`'s `columns[].sticky` option now accepts `'start' | 'end'` in addition to the legacy
3557
+ `boolean` (`true` continues to mean `'start'`, unchanged). An `'end'`-sticky column pins to the
3558
+ inline-end edge instead — useful for a trailing actions column that would otherwise be pushed off
3559
+ a narrow viewport — via the same `inset-inline-*` logical-property approach, so RTL is unaffected.
3560
+ - ffee803: `lr-tool-result-dialog`'s tool-name fallback ("Tool call"), visible status label
3561
+ ("Pending"/"Running"/"Success"/"Error"/"Denied"), and maximize/restore button aria-label now route
3562
+ through `this.localize()`, overridable via `.strings`/`registerLyraLocale()`. Default English output
3563
+ is unchanged.
3564
+ - f9f57f9: `lr-word-cloud`'s default aria-label's pluralized "word"/"words" noun now routes through
3565
+ `this.localize()` too, so a registered translation of the `wordCloud` template's `{word}` slot is no
3566
+ longer stuck in English. Default output is unchanged.
3567
+
3568
+ ## 2.3.0
3569
+
3570
+ ### Minor Changes
3571
+
3572
+ - a1b2f8e: `lr-app-rail` gains `dragging` (reflected boolean, true for the duration of a pointer-driven
3573
+ resize -- not a keyboard step -- so its own `[part='base']` transition suppresses during the drag
3574
+ instead of visibly "chasing" the pointer) and `hideToggle` (suppresses the built-in mobile hamburger
3575
+ button for a consumer that owns its own external toggle wired to `open`).
3576
+ - e9075b8: `lr-app-rail-item` gains an opt-in `tooltip` property: a hover/focus flyout showing the item's
3577
+ label text while `icon-only` hides it from view, using the library's existing Floating-UI-backed
3578
+ `place()` positioner -- an explicit, documented alternative to hand-rolling a `::part()`+`::after`
3579
+ tooltip composition.
3580
+ - 8160548: `lr-attachment-chip`'s `compact` variant now also shrinks font-size and gap (via new
3581
+ `--lr-attachment-chip-compact-font-size`/`-compact-gap` custom properties), not just
3582
+ border/radius/padding/thumbnail-size. Also adds `thumbnailOnly`, which -- combined with `compact`
3583
+ on an image-mime chip -- hides the filename/size text entirely for a pure thumbnail density with
3584
+ no consumer-side CSS.
3585
+ - 099fa8a: Add `lr-avatar`: a small, fixed-size identity marker (image, or an initials fallback) for a
3586
+ user-menu trigger or similar identity affordance -- `size`/`shape`/`tone` variants mirror
3587
+ `lr-chip`'s existing tone vocabulary for consistency.
3588
+ - bf9d442: Add `lr-card`: a generic bordered content container (`appearance` variants mirroring `wa-card`,
3589
+ `header`/`media`/`footer`/`actions` slots) for the "small bordered surface with padding" idiom
3590
+ common across hero highlights and clickable grid tiles -- a real `lyra-ui` parity counterpart to
3591
+ `wa-card`, which this library otherwise mirrors 1:1.
3592
+ - f9ecffd: `lr-chip` gains an opt-in `selected`/pressed interactive mode: `[part='base']` becomes
3593
+ keyboard-activatable and reflects `aria-pressed`, toggling on click/Enter/Space and emitting
3594
+ `lr-chip-select`. Not combinable with `removable` (avoids a nested-interactive a11y violation);
3595
+ today's passive-label-pill usage is unaffected since `selected` defaults to `false`.
3596
+ - db24359: Add `lr-code-block-core`: a build-lean variant of `lr-code-block` for a consumer whose
3597
+ `languages` map already covers every language it renders. Unlike `languagesOnly` (a runtime flag
3598
+ on `lr-code-block` itself, which a bundler can't prove always-true and so can't tree-shake),
3599
+ `lr-code-block-core` is a genuinely separate module that never references shiki's full
3600
+ ~200-language default entry point at all -- importing it instead of `code-block.js` gives a real
3601
+ compile-time exclusion of that table from the build output.
3602
+ - 83ba36c: `lr-dialog` gains `--lr-dialog-width`, unset by default -- when set, the panel actually
3603
+ stretches to that width instead of only shrink-wrapping its content capped at
3604
+ `--lr-dialog-max-width`, which was a real gotcha for anyone porting from `wa-dialog`'s
3605
+ assertive `--width` token.
3606
+ - a1d7030: Add `lr-diff-view`: a real two-string line diff (LCS-aligned), rendered as interleaved
3607
+ unified-diff output -- unlike diff-flavored syntax highlighting over an already-formatted string,
3608
+ this computes the alignment itself, so a one-line change inside a longer block renders as one
3609
+ red/green pair near the change instead of every old line then every new line.
3610
+ - b56abda: `lr-empty`'s `heading`/`description` gain the same slot-override-attribute treatment
3611
+ `lr-stat`'s `caption`/`sub` already have -- a consumer can now pass rich mid-sentence content
3612
+ (e.g. an inline `<code>` reference) while the plain-string attribute stays the default.
3613
+ - 4324a73: `lr-graph` now renders a link whose `target` isn't a real node as a short dashed stub off the
3614
+ source's position, instead of silently dropping it -- for a wiki-style `[[link]]`/broken-reference
3615
+ visualization where "this edge exists but its endpoint doesn't" is a meaningful state, not noise.
3616
+ A dangling `source` is still dropped (no position to draw a stub from).
3617
+ - 1e71d71: Rewrite `lr-heatmap`'s two weekday-axis-label tests to assert against independently fixed dates
3618
+ instead of re-deriving the implementation's own formula, which could never fail regardless of
3619
+ correctness -- the underlying `weekdayLabels()`/`firstDayOfWeek` anchoring was already correct.
3620
+ Also add `cellColor`, an optional per-cell color override function (mirroring the existing
3621
+ `cellText`/`cellInteractive` shape) that bypasses the color ramp entirely for an exact value.
3622
+ - 2e74ea0: Fix `lr-lite-chart`'s `minBarHeight` z-order bug for stacked bars: a floored near-zero segment
3623
+ was being overdrawn by the segment stacked on top of it, since each segment's position was derived
3624
+ independently from cumulative value rather than from where the previous (possibly-floored) segment
3625
+ actually ended on screen. Also add `selectedIndex: number[]`, reflecting `data-selected` onto every
3626
+ bar at a given category index across all datasets, for highlighting a whole selected column.
3627
+ - 00f3b37: `lr-markdown` gains `escapeHtml`, an opt-in property overriding `marked`'s `html` renderer hook
3628
+ to emit escaped text instead of parsed/sanitized markup -- for a consumer rendering arbitrary
3629
+ already-written content (transcripts, logs) where a stray angle bracket should render as visible
3630
+ text rather than a real DOM element, without giving up GFM tables/lists/etc.
3631
+ - d3fbf36: Add `lr-poll-status`: a "next scheduled refresh" countdown with a built-in pause control -- a
3632
+ ticking M:SS display, a "Refreshing…" due state, and an internal live region announcing phase
3633
+ transitions, mirroring `lr-stream-status`'s own composition for a different concern (a scheduled
3634
+ interval, not transport/connection health).
3635
+ - b5464bd: Add `lr-segmented`: a single-select button row with the WAI-ARIA APG `radiogroup` contract
3636
+ (role="radio", roving tabindex, automatic-activation Arrow/Home/End navigation) built in --
3637
+ "choose exactly one of N labeled options" is ubiquitous settings/filter-panel UI that otherwise
3638
+ gets hand-rolled without keyboard/ARIA semantics every time.
3639
+ - 551f272: `lr-select` gains `--lr-select-trigger-height`, unset (auto) by default -- when a consumer sets
3640
+ it, the trigger resolves to exactly that height (both floor and cap) instead of only being
3641
+ floored by `--lr-select-trigger-min-height`, for pixel-matching a sibling form field in the same
3642
+ row without a blunt `::part(trigger){block-size:...}` override.
3643
+ - 1fddbdc: Add `lr-stepper`: ordered multi-step wizard navigation (label + index, current/completed/
3644
+ locked/error state, click-to-jump, horizontal/vertical orientation). Fully data-driven and
3645
+ controlled -- like `lr-table`, it never mutates its own `steps` data, firing a cancelable
3646
+ `lr-step-select` event and leaving state updates to the host, so gating a jump behind an
3647
+ external validity check (e.g. "does the target step's data exist yet") is a normal listener, not a
3648
+ workaround.
3649
+ - 60dbf18: `lr-table` gains two per-column hooks: `footer(rows)`, rendered in a real sticky-bottom
3650
+ `<tfoot>` (only when at least one column defines it) -- e.g. a totals row; and `cellStyle(row)`,
3651
+ applied via `styleMap` directly to the generated `<td>` -- e.g. a computed heat-tint background --
3652
+ which coexists safely with the existing sticky-column offset styling.
3653
+ - 6ce5b87: Add a new `./testing` subpath exporting `installHappyDomFormAssociatedShims()` -- an opt-in,
3654
+ environment-guarded polyfill for `HTMLElement.prototype.attachInternals`, for a downstream
3655
+ consumer's own Vitest+happy-dom test suite (happy-dom has no `ElementInternals` implementation,
3656
+ and every form-associated `lr-*` component calls `attachInternals()` unconditionally in its
3657
+ constructor). Not used by this package's own tests, which already run against real browsers.
3658
+ - 25254f2: `lr-widget` gains a leading `icon` slot, rich `label`/`sublabel` slot overrides (mirroring
3659
+ `lr-stat`'s `caption`/`sub` pattern), and a `views` property driving a built-in header toggle
3660
+ group plus one named slot per entry -- for a chart/table (or similar) toggle inside the same card
3661
+ chrome, so a consumer no longer has to hand-roll that shell around a bare default slot.
3662
+
3663
+ ### Patch Changes
3664
+
3665
+ - 062f036: Fix `lr-attachment-trigger`'s internal hidden `<input type="file">` actually rendering as a
3666
+ visible, focusable-adjacent element in normal document flow — it now has `display: none` by
3667
+ default (and a new `hidden-input` CSS part, for the rare integration that needs to override that).
3668
+ - 9094b39: Fix `lr-chart` losing a user's legend-toggled hidden-dataset state on every data-driven redraw --
3669
+ `draw()` now snapshots each dataset's `isDatasetVisible()` state before reassigning `chart.data` and
3670
+ restores it via `setDatasetVisibility()` afterward, since Chart.js's own dataset-object identity
3671
+ changes on every reactive update from a live-polling consumer.
3672
+ - a413c8c: Fix `lr-chip-group`'s "+N"/"Show less" overflow toggle hardcoding English strings instead of using
3673
+ the library's own existing `localize()`/`strings` override mechanism, which every other component
3674
+ with translatable text already uses (including the identical `showMore`/`showLess` keys, already
3675
+ consumed by `lr-source-card`).
3676
+ - 4010bc4: `lr-menu`'s `onListKeyDown` now ignores a keydown whose target isn't a real `<lr-menu-item>`,
3677
+ matching the same `instanceof LyraMenuItem` guard `onItemSelect`/`onListFocusIn` already use --
3678
+ previously it unconditionally intercepted Arrow/Home/End/Enter/Space/Escape/Tab from any keydown
3679
+ bubbling through `[part="list"]`, including from non-item slotted content (e.g. a custom-range
3680
+ date input), hijacking keystrokes meant for it. Note: Escape/Tab now also only close the menu when
3681
+ the event originates from a real item -- a slotted non-item control gets fully default keyboard
3682
+ behavior instead.
3683
+ - a5a055f: Fix `lr-split`'s fixed-percent panels not reserving space for the auto-inserted divider between
3684
+ them, causing a deterministic `(panelCount - 1) * dividerWidth` container overflow in the default
3685
+ (uncollapsed) state. Panels now get a nonzero `flex-shrink` so they absorb the dividers' own width
3686
+ instead of the row overflowing.
3687
+ - 18003f0: Fix `lr-stat`'s `[part='base']` not stretching to fill its host in a CSS Grid -- a stat tile with
3688
+ a longer `sub`/breakdown-rows line rendered visibly taller than its row-mates. `block-size: 100%` on
3689
+ `[part='base']` now matches the convention `lr-word-cloud`/`lr-context-meter` already use.
3690
+ - 55c384e: Fix `lr-tabs`'s `tablist` part showing a phantom vertical scrollbar on a tablist with no
3691
+ vertically-overflowing content — `overflow-x: auto` alone can leave the y axis's computed overflow
3692
+ at `auto` too per the CSS overflow spec, which sub-pixel rounding can trip; `overflow-y: hidden` is
3693
+ now explicit, since the tablist is never meant to scroll vertically.
3694
+
3695
+ ## 2.2.0
3696
+
3697
+ ### Minor Changes
3698
+
3699
+ - ff41aba: `lr-app-rail`: add a `resizable` opt-in (drag + keyboard-steppable `[part="resizer"]` handle,
3700
+ `railWidthPx`/`minRailWidthPx`/`maxRailWidthPx`, `lr-rail-resize` event) for the `'full'` state's
3701
+ width; add `preferredMode` to manually prefer `'full'`/`'icon-only'` while the mobile breakpoint
3702
+ keeps tracking automatically; and fix the mobile toggle button's `aria-label` to use a proper
3703
+ `openNavigation` message key (consistent with the existing `closeNavigation` key) instead of
3704
+ concatenating a hardcoded `" navigation"` suffix onto a partially-localized string.
3705
+ - 3b1a404: `lr-app-rail-item`: add an `active` property that reflects `aria-current="page"` onto the
3706
+ internal link/button, mirroring `lr-conversation-item`'s existing `active` pattern.
3707
+ - 3b7a98b: `lr-attachment-chip`: fix the uploading progressbar/spinner's `aria-label` to actually use
3708
+ `uploadingLabel` (previously hardcoded, unlike the adjacent visible status text); add an
3709
+ `untitledLabel` override for the empty-name fallback; add a `compact` density variant.
3710
+ - 49be9e4: `lr-attachment-trigger`: add a `triggerTitle` property forwarded to the internal trigger
3711
+ button(s)' native `title` (a sighted-mouse-user hover tooltip, distinct from `triggerLabel`'s
3712
+ `aria-label` role); reduce the internal `.trigger-button:hover` rule's specificity via `:where()`
3713
+ so a consumer's `::part(trigger):hover` override wins without needing `!important`.
3714
+ - 4d04843: `lr-code-block`: add a `languagesOnly` opt-in that skips the default `loadShikiHighlighter()`
3715
+ call entirely, so a consumer whose `languages` map already covers every language it renders has no
3716
+ bundler-reachable path to shiki's full per-language dynamic-import table.
3717
+ - 2968d7b: Add `lr-copy-button`: a standalone icon-only copy-to-clipboard button for a plain text `value`,
3718
+ with no positioning opinion of its own — for a consumer needing just the copy/checkmark-swap
3719
+ affordance without adopting `lr-code-block`'s or `lr-json-viewer`'s full content model.
3720
+ - 49be9e4: `lr-dialog`: add `noLightDismiss` to opt out of backdrop-click dismissal, and make `close()`
3721
+ actually respect a `lr-dialog-close` listener's `preventDefault()` (the event is now genuinely
3722
+ `cancelable: true`) for every dismissal path — Escape, backdrop, the built-in close button, and a
3723
+ consumer's own `close()` call.
3724
+ - 6958595: `lr-heatmap`: add a `cellInteractive` predicate to opt individual cells out of hit-testing and
3725
+ keyboard roving focus, and a `colorSteps` discrete-array ramp as an alternative to the 2-endpoint
3726
+ `--lr-heatmap-scale-lo`/`-hi` linear interpolation (governs both `mode`s and both `scale`
3727
+ values). Also adds test coverage confirming `firstDayOfWeek`'s calendar-mode weekday-axis labels
3728
+ are correct for a non-Sunday-first week (the underlying computation was already correct; only the
3729
+ test combining the two was missing).
3730
+ - 2c6fc82: `lr-lite-chart`: add a `minBarHeight`/`min-bar-height` pixel floor for near-zero stacked
3731
+ segments, fix `scale="sqrt"` proportionality for stacked bars (previously compressed each
3732
+ segment's absolute cumulative stack position independently instead of the bar's total height
3733
+ split linearly by segment share), and add a `chartLabel`/`chart-label` override for the chart's
3734
+ auto-derived `aria-label`.
3735
+ - e29b2f9: `lr-markdown`: add `part="paragraph"`, `part="list"` (both `<ul>` and `<ol>`), and
3736
+ `part="inline-code"` (bare inline codespans only, not a fenced code block's `<code>`, which
3737
+ already has its own `part="code-block"` wrapper) so a consumer's `::part()` CSS can reach plain
3738
+ text elements that previously had no themeable hook.
3739
+ - 3b7a98b: `lr-split`: add a `dividerLabel` function property overriding the auto-inserted divider's
3740
+ hardcoded English `aria-label` template.
3741
+
3742
+ ## 2.1.0
3743
+
3744
+ ### Minor Changes
3745
+
3746
+ - 82a3419: `<lr-attachment-chip>`: added four label-override properties for i18n/locale — `removeLabel`/`retryLabel` (`remove-label`/`retry-label` attributes, the verb prefixed to the remove/retry buttons' `aria-label` ahead of the interpolated filename) and `uploadingLabel`/`uploadFailedLabel` (`uploading-label`/`upload-failed-label` attributes, the verb/phrase used in the visible uploading/error status text, keeping the live percentage interpolation intact for `uploadingLabel`). All four default to today's exact hardcoded English text (`'Remove'`, `'Retry'`, `'Uploading'`, `'Upload failed'`), so leaving them unset changes nothing for existing consumers.
3747
+ - 82a3419: `<lr-attachment-trigger>`: added a `triggerLabel` property (`trigger-label` attribute) that overrides the single-capability trigger button's `aria-label`, which previously came unconditionally from the built-in `CAPABILITY_META` table (e.g. `'Attach files'`, `'Attach an image'`, `'Use camera'`). Lets a host localize the accessible name without forking the component. Unset (the default) preserves today's exact `CAPABILITY_META`-derived label for every capability.
3748
+ - 82a3419: Add `<lr-code-block>` `languages`, a map of language id to an already-imported shiki grammar module (e.g. `import bash from 'shiki/langs/bash.mjs'`). When `language` matches a key in `languages`, highlighting for it is seeded from exactly that pre-supplied grammar via a fine-grained `createHighlighterCore()` highlighter (`code-loader.ts`'s new `loadShikiHighlighterCore()`), bypassing the default `loadShikiHighlighter()` singleton and its dynamic per-language `loadLanguage()` import entirely for that language — no loading skeleton either, since this path never waits on that singleton. shiki's main entry point (what the default path imports) bundles a dynamic `import()` per bundled language (~200 of them), since a bundler can't statically narrow which of those a `loadLanguage(lang: string)` call might request at runtime; `shiki/core`'s fine-grained API has no such table, so a consumer who pins its full, known language set this way gets a build output scoped to just those languages instead of shiki's entire bundled set. A `language` value absent from `languages` (or left unset, or when `languages` itself is unset) still falls back to the ordinary dynamic-import path unchanged — this is a partial, additive opt-in, not a replacement for it.
3749
+ - 82a3419: Fixed 'confirm()''s own usage example to import from the granular subpath
3750
+ ('@aceshooting/lyra-ui/components/dialog/confirm.js') instead of the root barrel
3751
+ ('@aceshooting/lyra-ui') — following the root-barrel example as written previously pulled in the
3752
+ library's entire ~80-component side-effect-import chain into a consumer's eager bundle
3753
+ (confirmed via a real build: +79 KB gzip regression, fixed by switching to the subpath import).
3754
+ No code changed, documentation only.
3755
+ - 82a3419: Add `heading`/`closable` convenience chrome and a `--lr-dialog-max-width` token to `<lr-dialog>`. `<lr-dialog>` previously required a consumer to hand-build any visible title bar (by slotting a real heading element) and any close affordance (via a footer button wired to `close()`) — `heading` now renders a visible header row with that text when no heading element is slotted (still deferring to a slotted heading, unchanged, when present), and `closable` renders a built-in close (X) button in that same header row, wired through the exact same `close()` path Escape/backdrop-dismiss already use, with reason `'close-button'`. `[part="panel"]`'s previously-hardcoded `max-inline-size: min(32rem, 100%)` is now `min(var(--lr-dialog-max-width, 32rem), 100%)`, mirroring `<lr-media-card>`'s `--lr-media-card-max-height` — the default stays exactly `32rem` when unset. All three are additive/opt-in; existing consumers see no behavior change.
3756
+ - 82a3419: `<lr-heatmap>`'s calendar mode gained four additive extensions. `firstDayOfWeek` (0-6, Sunday-first default, same numbering as `CalendarCellPos.weekday`) anchors the week grid at a different weekday instead of always Sunday, threaded into `buildCalendarGrid()`'s new `firstDayOfWeek` parameter; matrix mode ignores it. `rowY` overrides the y-origin computed for each weekday row, the vertical analogue of the existing `columnX`, consulted consistently by drawing, hit-testing, and the keyboard focus ring via a new private `rowYFor()` helper mirroring `columnXFor()`'s exact dispatch-with-computed-fallback shape. The previously matrix-mode-only `cellSize`/`fitToWidth` properties now also size calendar mode's grid, replacing its hardcoded 11px cell constant when explicitly set (unset, calendar mode keeps that original 11px default). The previously matrix-mode-only `scale` property now also governs calendar mode's bucketing: `scale="sqrt"` compresses via the same square-root magnitude compression matrix mode uses instead of always calling `quartileBucket()`, so one heavy day doesn't wash out a skewed dataset; the default `"linear"` preserves today's exact quartile-only calendar behavior. All four are opt-in and no-ops when left unset/default.
3757
+ - 82a3419: `<lr-lite-chart>` gained seven additive properties. `pointText` overrides the per-bar/per-point `<title>`/`aria-label` tooltip text (mirrors `lr-heatmap`'s `cellText` hook), falling back to today's exact raw-value template when unset. `roundedBars` draws bars as a rounded-top-corner path instead of a square-cornered rect (default `false` keeps the plain rect). `skipZero` omits a bar entirely — no mark, no `tabindex`, no tooltip — for a value that is exactly `0`, instead of today's zero-height-but-focusable bar (default `false` unchanged). `padLeft`/`barGapRatio` override the internal `PAD_LEFT`/`BAR_GROUP_GAP` layout constants (36px / 0.2 respectively) when set. `scale` (`'linear' | 'sqrt'`, `type="bar"` only) switches the bar-height mapping from the default linear `niceDomain` fraction to a `Math.sqrt(value / domainMax)` compression mirroring `lr-heatmap`'s matrix-mode `sqrt` scale, so a skewed dataset's smaller bars aren't washed out by one dominant value; `type="line"` ignores `scale` entirely. `hideAxis` suppresses `renderGrid()`'s gridlines and y-axis tick labels altogether (x-axis category labels are unaffected). All seven are opt-in and no-ops when left unset/`false`.
3758
+ - 82a3419: `<lr-markdown>` gains four additive properties. Every rendered `<img>` now carries a `part="img"` (with a matching `[part='img'] { max-width: 100% }` base style), alongside the existing `content`/`heading`/`code-block`/`link`/`table`/`blockquote` parts — previously images went through marked's default renderer with no styling hook at all. `heading-offset` (default `0`) shifts every rendered heading's depth before emitting `<h${depth}>`, clamped to `<h1>`–`<h6>`, letting a consumer nest rendered markdown under an existing heading level without losing document outline. `link-target` (default `'_blank'`, unchanged) can now be set to `null`/`''` to omit `target`/`rel="noopener noreferrer"` entirely and open links in the same tab, instead of always forcing a new tab. `eager-load` (default `false`) skips `connectedCallback()`'s async `marked`/`dompurify` `import()` and renders synchronously whenever the shared module cache (`markdown-loader.ts`) is already warm — e.g. a second `<lr-markdown>` on the same page, or a consumer that primes `loadMarkdownDeps()` at startup — avoiding the brief plain-text fallback paint that otherwise happens on every connect, even when both peers load without error. All four are opt-in; unset, output is byte-identical to before.
3759
+ - 82a3419: `<lr-menu-item>` gained a `type` property (`'normal' | 'checkbox'`, default `'normal'`) and a `checked` boolean, mirroring `wa-dropdown-item`'s identical `type="checkbox"` pattern for building things like a "Word wrap" or "Show minimap" toggle inside a `<lr-menu>`. A `type="checkbox"` item renders `role="menuitemcheckbox"` (instead of `role="menuitem"`) with `aria-checked` reflecting `checked` and a checkmark glyph shown once checked; activating it (click, or Enter/Space via a parent `<lr-menu>`'s roving-focus handling) toggles `checked` and fires a new `lr-menu-item-change` event (`detail: { value, checked }`) in addition to — not instead of — the existing `lr-menu-item-select`, so a parent menu still closes and re-fires its consolidated `lr-menu-select` exactly as before. `type="normal"` (the default, and every existing `<lr-menu-item>` in the wild) is completely unaffected: same role, same rendering, same events as prior releases.
3760
+ - 82a3419: `<lr-model-select>`: added a `label` property that renders a visible `part="form-control-label"` title above the trigger/combobox, paired with it via `for`/`id`, mirroring `<lr-select>`'s own `label` exactly. Once non-empty it also takes over as the accessible-name source, with an explicit host `aria-label` still winning over it (same precedence as `lr-select`). Unset (the default), the control keeps today's exact `aria-label || placeholder || 'Model'` fallback chain unchanged.
3761
+ - 82a3419: `<lr-select>`'s single-enabled-option auto-commit trigger (added 1.3.0) is now gated behind a new `autoCommitSingleOption` property, default `false`. Previously this behavior was unconditional as soon as exactly one `<lr-option>` was enabled, silently swapping the trigger's ARIA role and keyboard model on any consumer whose option list happened to narrow to one entry at runtime. Existing consumers now get the pre-1.3.0 combobox trigger unless they explicitly opt in with `auto-commit-single-option`.
3762
+ - 82a3419: `<lr-split>`'s `collapseState` is now a public accessor with force/auto semantics mirroring `<lr-app-rail>`'s `mode`: it was previously derived only from the `ResizeObserver`-measured container width, but assigning a concrete `'wide'`/`'rail'`/`'floating'` value now pins it there (ignoring further measurement) until released back to automatic tracking by assigning the write-only `'auto'` sentinel, which immediately re-derives it from the current width. `lr-split-collapse-change` fires on both a forced assignment and a release-to-auto, exactly as it already did for a breakpoint crossing, and only when the effective state actually changes. The `'floating'` tier also gains a new `open` property (default `false`): previously this state always rendered its pane as an always-visible overlay card the moment the container narrowed past `float-breakpoint`; it's now a hidden-by-default drawer — the pane renders nothing (hidden, out of the accessibility tree) until a consumer sets `open`, at which point it renders with a `[part="backdrop"]` scrim, traps focus, and closes (`open = false`) on Escape or a backdrop click, mirroring `<lr-app-rail>`'s mobile overlay. `collapseState` still reflects to a `collapse-state` attribute for CSS targeting. `open` defaulting to `false` is a deliberate behavior change for the `'floating'` tier specifically (it was previously always visible); every other collapse behavior, and `collapse="none"` (the default), is unaffected.
3763
+ - 82a3419: `<lr-tabs>` can now render a leading icon inside a generated tab button without changing its accessible name. Give a panel's tab an extra direct-child sibling of `<lr-tabs>` carrying `slot="<id>-icon"` (any markup — an inline SVG, an emoji span, a custom icon element) and it renders ahead of the label inside that tab's button, wrapped in a new `part="tab-icon"` `aria-hidden="true"` span so it's always excluded from the button's accessible name (which stays exactly the `label` attribute's text, as before). A tab with no matching `<id>-icon` sibling renders no icon wrapper at all, so every existing text-only `<lr-tabs>` is byte-for-byte unaffected. A named slot (rather than an `icon="<name>"` attribute keyed into this library's internal `icons.ts`) was chosen because that internal set is a small closed vocabulary of chrome glyphs for this library's own components, not a public icon registry — a slot lets a consumer supply an arbitrary, domain-specific icon instead.
3764
+
3765
+ ## 2.0.0
3766
+
3767
+ ### Major Changes
3768
+
3769
+ - 8b5f729: **Breaking:** the root `@aceshooting/lyra-ui` entry point no longer re-exports or
3770
+ side-effect-registers the optional-peer-dependent component families — `<lr-chart>`
3771
+ and its typed subclasses, `<lr-box-plot>`, `<lr-histogram>`, `<lr-map>`, and
3772
+ `<lr-graph>`. Import each of these directly from its own subpath instead (the README
3773
+ already recommends granular subpath imports as the primary pattern):
3774
+
3775
+ ```js
3776
+ import "@aceshooting/lyra-ui/components/chart/chart.js";
3777
+ import "@aceshooting/lyra-ui/components/map/map.js";
3778
+ ```
3779
+
3780
+ Why: the root barrel previously re-exported every component's public API from one
3781
+ `lyra.ts` file, so TypeScript had to resolve `chart.js`/`maplibre-gl`/`d3-force`'s type
3782
+ declarations even for a consumer who only imports an unrelated component (e.g.
3783
+ `LyraEmpty`) from the package root — a hard compile error for anyone who hadn't
3784
+ installed every optional peer. Splitting these families out of the root barrel means
3785
+ importing `@aceshooting/lyra-ui` (or any of its remaining members) never requires an
3786
+ optional peer's types to be resolvable.
3787
+
3788
+ Every other component (including `<lr-lite-chart>`, which has zero peer
3789
+ dependencies) is unaffected — the root barrel still re-exports/registers everything
3790
+ else exactly as before.
3791
+
3792
+ ### Minor Changes
3793
+
3794
+ - 144ad8f: Add a `compact` flag tier and expose three fidelity tiers via `variant`.
3795
+
3796
+ `@aceshooting/lyra-flags`: the ~65 emblem flags now ship a tiny WebP raster at
3797
+ `flags/compact/<code>.webp` (~1–3 KB) alongside the standard vector and the pristine `detailed`
3798
+ original. `flagUrl(code, { variant: 'compact' | 'standard' | 'detailed' })` selects a tier,
3799
+ code-split per flag _and_ per tier so a bundled app ships only the tiers it actually uses. The
3800
+ `standard` tier was also re-derived from the pristine originals so every flag is now under 80 KB
3801
+ (no fidelity loss perceptible at card/row scale).
3802
+
3803
+ `@aceshooting/lyra-ui`: `<lr-flag>` gains a `variant="compact" | "standard" | "detailed"`
3804
+ property — a tiny raster for icon-scale use (menu items, language selectors), the default
3805
+ icon-optimized vector for card/row sizes, or the pristine full-detail vector for hero display.
3806
+ The `detailed` boolean is deprecated but kept working as an alias for `variant="detailed"`.
3807
+
3808
+ - 2a7390d: Fix `lr-heatmap` calendar mode's month/weekday axis labels to follow the runtime locale instead of hardcoded English, and add a `columnX` override so a calendar's week columns can be pixel-aligned with an external coordinate function.
3809
+ - 43864d6: Add `lr-lite-chart` `layout="scroll"` (fixed-width, horizontally-scrollable bars via `barWidth`), `maxLabels` axis-label decimation, and a `barX` coordinate override for pixel-aligning bars with a sibling `lr-heatmap`.
3810
+ - 043b7b0: Move `LyraSelectSize` above `<lr-select>`'s class JSDoc block so `custom-elements.json` correctly documents `lr-select` as a custom element.
3811
+ - 7bbe3d2: Add `lr-split` opt-in responsive collapse (`collapse="start"|"end"`, `rail-width`, `rail-breakpoint`, `float-breakpoint`): below `rail-breakpoint` the chosen pane clamps to a fixed rail width, below `float-breakpoint` it becomes an absolutely-positioned floating overlay, both signaled via a `data-collapse-state` attribute/dataset marker and the new `lr-split-collapse-change` event.
3812
+ - f14165f: `<lr-stat>` breakdown rows (`StatRow`) gain an optional `exactValue` field, mirroring the headline value's tooltip: setting it renders a `title` tooltip and makes that row's `[part='row-value']` keyboard-focusable, independently per row.
3813
+ - d62725d: `lr-table`'s `[part='reveal-columns-button']` now renders only when a `priority` column is actually hidden by the `@container` breakpoints (or `showAllColumns` force-visible mode is active), instead of whenever any column merely declares a `priority`; the new `columnsHidden` reactive property and `lr-columns-hidden-change` event expose the same real-time state to consumers.
3814
+
3815
+ ### Patch Changes
3816
+
3817
+ - Updated dependencies [144ad8f]
3818
+ - @aceshooting/lyra-flags@1.3.0
3819
+
3820
+ ## 1.3.0
3821
+
3822
+ ### Minor Changes
3823
+
3824
+ - 6358479: Added a "Conversation & Agent UI" family: chat/tool-call/agent-config building blocks for
3825
+ streaming AI interfaces, plus the general-purpose primitives (dialog, tabs, checkbox, switch,
3826
+ menu, chip, JSON viewer, live region, markdown, code block) they're built from. No breaking
3827
+ changes to any existing component.
3828
+
3829
+ New tags: `lr-dialog`/`confirm()`, `lr-tabs`, `lr-checkbox`, `lr-switch`,
3830
+ `lr-json-viewer`, `lr-live-region` (+ `internal/announcer.ts`'s throttled `Announcer`),
3831
+ `lr-markdown` (needs the optional peers `marked`/`dompurify`), `lr-chat-message`,
3832
+ `lr-typing-indicator`, `lr-tool-call-chip`, `lr-tool-result-view` (+ its
3833
+ `registerToolRenderer()` renderer registry), `lr-tool-result-dialog`, `lr-chat-composer`
3834
+ (form-associated), `lr-attachment-chip`, `lr-stream-status`, `lr-virtual-list`,
3835
+ `lr-conversation-item`, `lr-model-select`, `lr-slider` (form-associated),
3836
+ `lr-tool-select-dialog`, `lr-citation-badge`, `lr-source-list`/`lr-source-card`,
3837
+ `lr-app-rail`, `lr-responsive-panel`, `lr-mention-popover`, `lr-streaming-text`,
3838
+ `lr-thinking-panel`, `lr-generation-status`, `lr-code-block` (needs the optional peer
3839
+ `shiki`), `lr-tool-approval-dialog`, `lr-tool-param-form`, `lr-menu`/`lr-menu-item`,
3840
+ `lr-chip`/`lr-chip-group`, `lr-model-settings-panel`, `lr-context-meter`,
3841
+ `lr-dock-panel`, `lr-document-preview`, `lr-media-card`, `lr-attachment-trigger`,
3842
+ `lr-kbd`, `lr-result-card`/`lr-result-field`.
3843
+
3844
+ Also extends `internal/rtl.ts` with `rtlAwareSide()`/`rtlAwarePlacement()` (mirrors a physical
3845
+ `left`/`right` value, or the `left`/`right` component of a Floating UI `Placement`, under RTL) —
3846
+ used by `lr-menu`'s `placement` property so an explicit `placement="left-start"` still anchors
3847
+ to the trailing edge instead of the physical left when the page is RTL.
3848
+
3849
+ - 6358479: `<lr-select>`: when exactly one `<lr-option>` is enabled, the trigger now auto-commits that
3850
+ option on click or Arrow Up/Down instead of opening a single-row listbox — no chevron, no popup,
3851
+ `role="button"` instead of `role="combobox"`. Avoids an unnecessary extra click for "only one
3852
+ choice available" states (e.g. a filtered picker that's converged to a single match). Multi-option
3853
+ selects are unaffected; `value`/validity defaults are unchanged. Not gated behind a new prop — this
3854
+ is the new default trigger behavior for any select with a single enabled option.
3855
+
3856
+ ## 1.2.0
3857
+
3858
+ ### Minor Changes
3859
+
3860
+ - 6e832d5: `<lr-chart>`: added `IntersectionObserver`-gated lazy redraw and content-signature memoization — a
3861
+ chart skips calling into Chart.js while scrolled off-screen (redrawing once when it re-enters the
3862
+ viewport) or when none of its content-affecting properties (`type`, `labels`, `datasets`, `legend`,
3863
+ `area`, `xLabel`, `yLabel`, `y2Label`, `beginAtZero`, `horizontal`, `stacked`, `config`) have actually
3864
+ changed since the last draw. `refreshTheme()` is unaffected and always redraws.
3865
+ - 9d36af5: `<lr-combobox>`: the input's accessible name now checks a host-level `aria-label` attribute before
3866
+ falling back to `label`/`placeholder`/`"Combobox"` — previously a plain `aria-label` on
3867
+ `<lr-combobox>` was silently ignored. Matches the same fix in `<lr-select>`.
3868
+ - 0b3ea6c: `<lr-flag>`: added a `detailed` boolean property that requests the pristine, full-detail source SVG
3869
+ for the minority of flags whose default rendering was recently optimized for icon scale (e.g. `es`,
3870
+ `pt`, `sv` — see the `@aceshooting/lyra-flags` changeset). A safe no-op for every other flag. Useful
3871
+ for a flag rendered larger than icon scale (e.g. a hero display) where the extra illustrative detail
3872
+ is actually visible.
3873
+ - 2027e3f: `<lr-flag>`: the default accessible name (`alt`, used when `label` is unset) is now a human-readable
3874
+ region name via `Intl.DisplayNames` (e.g. `language="en"` → `"United Kingdom"`) instead of the bare
3875
+ uppercase country code (`"GB"`, previously read letter-by-letter by most screen readers).
3876
+ - 49569ed: `<lr-heatmap>`: fixed `role="img"` conflicting with the canvas's own focusable, keyboard-interactive
3877
+ descendant (arrow-key roving focus, Enter/Space activation) — now `role="group"`, matching
3878
+ `lr-lite-chart`/`lr-word-cloud`'s existing pattern. Added `cellText?: (pos, value) => string`, a
3879
+ formatter hook for the per-cell hover tooltip and keyboard live-region announcement (both draw from the
3880
+ built-in English template by default; this is additive, not breaking). Also fixed calendar mode's date
3881
+ label formatting, which hardcoded the literal `'en'` locale instead of the runtime locale.
3882
+ - ef74f4a: `<lr-lite-chart>`: added `tickFormat?: (value: number) => string` to customize y-axis tick label
3883
+ formatting (e.g. currency, duration) instead of the built-in nice-number formatter. Also added
3884
+ `IntersectionObserver`-gated lazy rendering and content-signature memoization — a chart skips
3885
+ recomputing its grid/marks while scrolled off-screen or when none of its content-affecting properties
3886
+ (`type`, `labels`, `datasets`, `legend`, `xLabel`, `yLabel`, `beginAtZero`, `stacked`, plot size) have
3887
+ actually changed since the last render.
3888
+ - 22cf001: `<lr-select>`: added a `size` property (`xs`/`s`/`m`/`l`/`xl`, default `m`, same scale as
3889
+ `lr-toast-item`'s `size`) for compact toolbar placements that don't fit the default trigger height.
3890
+ Also, the trigger's accessible name now checks a host-level `aria-label` attribute before falling back
3891
+ to `label`/`placeholder`/`"Select"` — previously a plain `aria-label` on `<lr-select>` was silently
3892
+ ignored.
3893
+ - 4bf80aa: `<lr-stat>`: added `exact-value` (shown as a hover/focus tooltip on the headline value, e.g.
3894
+ `value="$1.2K" exact-value="$1,204.37"`), a `sub` property/slot (a secondary line distinct from
3895
+ `caption`, e.g. a comparison-period label), a `prose` boolean (renders `value` as smaller/lighter text
3896
+ with `unit` hidden, for a loading/status message in place of a numeric value), and a `compact` boolean
3897
+ (tighter padding for constrained spaces — same convention as `lr-empty`'s and `lr-widget`'s
3898
+ `compact`).
3899
+ - c8206f8: `<lr-widget>`: added `fullscreen-inset` (a raw CSS `inset` shorthand, e.g. `"0 0 0 240px"`, applied to
3900
+ the fullscreen panel and backdrop instead of the default `var(--lr-space-l)` on every side — for apps
3901
+ with a persistent sidebar/toolbar that should stay visible during fullscreen) and a `compact` boolean
3902
+ (tighter header/body padding), matching `lr-empty`'s existing `compact` convention.
3903
+ - a768a20: `<lr-word-cloud>`: fixed the rendered `<svg>` not respecting a host-assigned height —
3904
+ `[part='base']` had no `block-size` rule, so the internal `svg { block-size: 100% }` resolved against
3905
+ an indefinite containing-block height and fell back to the spiral layout's own intrinsic size instead,
3906
+ overflowing past the host's box. `[part='base']` now constrains to `block-size: 100%`, matching the
3907
+ component's own documented `<lr-word-cloud style="height: 20rem">` usage pattern.
3908
+
3909
+ ### Patch Changes
3910
+
3911
+ - Updated dependencies [da766cb]
3912
+ - @aceshooting/lyra-flags@1.2.0
3913
+
3914
+ ## 1.1.0
3915
+
3916
+ ### Minor Changes
3917
+
3918
+ - c033ec0: `@aceshooting/lyra-flags`: `flagUrl(code)` is now genuinely code-split per flag — each code is
3919
+ its own dynamically-`import()`ed chunk, so using it (directly, or via `<lr-flag
3920
+ country=...>`/`<lr-flag language=...>`) only ever fetches the flags actually requested at
3921
+ runtime, not all 249. This makes `flagUrl()` `async` (**breaking**: `Promise<string | undefined>`
3922
+ instead of `string`). `FLAG_URLS` (the old synchronous, eager, all-249-at-once map) is no longer
3923
+ exported from the package root — the equivalent for a consumer that genuinely wants every flag up
3924
+ front (e.g. a flag-picker listing every country) is the new `flagUrls()` (`async`, resolves the
3925
+ full map). `FLAG_LOADERS` (the new lazy per-code map `flagUrl()` is built on) is exported directly
3926
+ for consumers that want the per-code laziness without going through `flagUrl()`.
3927
+
3928
+ `@aceshooting/lyra-ui`: `<lr-flag>` transparently picks up the lazy-loading fix — no changes
3929
+ needed at call sites using `country`/`language`. Also adds a new `src` property: a pre-resolved
3930
+ flag image URL that takes precedence over `country`/`language` and skips the peer-package lookup
3931
+ (and its loading-skeleton round trip) entirely, for consumers who already have a flag's URL at
3932
+ build time (e.g. via `import frUrl from '@aceshooting/lyra-flags/flags/fr.svg?url'`).
3933
+
3934
+ - c033ec0: Added `<lr-lite-chart>` — a dependency-free bar/line chart (plain SVG/DOM rendering, zero peer
3935
+ dependencies) for projects whose architecture forbids a charting dependency outright. Covers
3936
+ grouped/stacked bars, multi-series lines, per-point click (`lr-point-click`, same detail shape as
3937
+ `lr-chart`'s), and hover tooltips via native SVG `<title>`. Not a full `lr-chart` replacement —
3938
+ no zoom/pan, no pie/doughnut/radar/scatter/bubble types, no horizontal/dual-y-axis, no raw-config
3939
+ passthrough. Reuses `lr-chart`'s `--lr-chart-*` theme token names for free cross-component
3940
+ theming.
3941
+ - c033ec0: Added `<lr-word-cloud>` — a dependency-free SVG word/tag cloud, laid out via an outward
3942
+ Archimedean-spiral placement search (heaviest word first). Supports `linear`/`sqrt` weight-to-font
3943
+ scaling, optional `mixed` (rotated) orientation, per-word or per-`group` coloring with a themeable
3944
+ `--lr-word-cloud-color-1..8` palette, and roving-tabindex keyboard navigation matching
3945
+ `lr-heatmap`'s pattern (a single tab stop, arrow keys, Home/End, a live-region announcement).
3946
+
3947
+ Also a hardening pass across the rest of the library — real bugs fixed, not just polish:
3948
+
3949
+ - `lr-skeleton`: `width`/`height` properties had zero visual effect (the custom property was set
3950
+ on the wrong shadow-DOM node); now actually resizes the placeholder.
3951
+ - `lr-combobox`: setting `open` directly (bypassing `show()`) never wired up click-outside or
3952
+ fired `lr-show`/`lr-hide`; picking a row or clearing while using `source` left stale async
3953
+ results displayed; a `<lr-option selected>` appended after the first slotchange was ignored;
3954
+ two nameless `multiple` comboboxes in the same form merged their submitted values; a pending
3955
+ debounced `source` fetch could fire after the element was removed.
3956
+ - `lr-chart`: bubble-chart series got a categorical (not numeric) x-axis, collapsing every point
3957
+ onto one tick; `resetZoom()` double-emitted `lr-zoom`, briefly reporting the stale pre-reset
3958
+ `zoomed` state to `{ once: true }` listeners.
3959
+ - `lr-date-picker` / `lr-date-input`: the already-exported `clampDate()` was never actually
3960
+ wired in, so `goToDate()`/`goToToday()` could navigate to (and focus) an out-of-range date;
3961
+ locale/weekday-format/first-day-of-week wiring gained test coverage; outside-month placeholder
3962
+ cells are now `aria-hidden` only in rows that also have a real visible day.
3963
+ - `lr-tree`: mouse-driven expand/collapse/select could desync the roving-tabindex `activeId` from
3964
+ real DOM focus; arrow-key expand/collapse is now RTL-aware, matching `lr-split`/`lr-time-range`.
3965
+ - `lr-widget`: the fullscreen focus trap didn't pierce into a slotted custom element's own shadow
3966
+ root, letting focus escape to a hidden nested control.
3967
+ - `lr-toast-item`: the close button used the native `disabled` attribute, which force-blurs a
3968
+ focused element with nothing to restore it — switched to `aria-disabled`.
3969
+ - `lr-empty`: gained a live-region announcement when entering the empty state, matching
3970
+ `lr-skeleton`'s existing `role="status"` convention.
3971
+ - Accessibility, documentation, and test-coverage fixes across most other components; `llms.txt`,
3972
+ `llms-full.txt`, and both READMEs corrected for drift against the current API surface.
3973
+
3974
+ No breaking changes.
3975
+
3976
+ ### Patch Changes
3977
+
3978
+ - Updated dependencies [c033ec0]
3979
+ - @aceshooting/lyra-flags@1.1.0
3980
+
3981
+ ## 1.0.1
3982
+
3983
+ ### Patch Changes
3984
+
3985
+ - 436b1ce: Fix `scripts/publish.sh` to commit `CHANGELOG.md` and `custom-elements.json` with each release commit (previously only `package.json`/the lockfile were staged, leaving those generated files uncommitted after every release). Remove the redundant `.github/workflows/publish.yml` CI job, which always failed by re-publishing a version `publish.sh` had already shipped.
3986
+
3987
+ ## 1.0.0
3988
+
3989
+ ### Major Changes
3990
+
3991
+ - 99fb0e0: Added several new components
3992
+
3993
+ ### Patch Changes
3994
+
3995
+ - Updated dependencies [99fb0e0]
3996
+ - @aceshooting/lyra-flags@1.0.0
3997
+
3998
+ All notable changes to `@aceshooting/lyra-ui` are documented in this file.
3999
+
4000
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
4001
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
4002
+
4003
+ Release notes on GitHub (`gh release create --generate-notes`) are generated from commit
4004
+ history and may be more granular than this file; this file is the curated, human-readable
4005
+ summary.
4006
+
4007
+ ## [Unreleased]
4008
+
4009
+ No unreleased changes yet.
4010
+
4011
+ ## [0.1.3] baseline
4012
+
4013
+ Current published baseline at the time this changelog was introduced. Historical versions
4014
+ prior to 0.1.3 were not backfilled into this file — see git tags (`git tag -l`) and GitHub
4015
+ Releases for the full release history.
4016
+
4017
+ - Free, clean-room Lit 3 web-component library — an open-source companion to Web Awesome.
4018
+ - Tiered component set (layout/atoms, forms, overlays, data-viz/dashboard, temporal/graph,
4019
+ map/file/flag families) — see `packages/lyra-ui/llms.txt` and `llms-full.txt` for the full
4020
+ API reference.
4021
+ - `@aceshooting/lyra-flags` optional companion package for `<lr-flag>` artwork.
4022
+
4023
+ [Unreleased]: https://github.com/aceshooting/lyra-ui/compare/0.1.3...HEAD
4024
+ [0.1.3]: https://github.com/aceshooting/lyra-ui/releases/tag/0.1.3