@aceshooting/lyra-ui 21.0.0 → 21.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 (272) hide show
  1. package/CHANGELOG.md +56 -0
  2. package/README.md +6 -3
  3. package/custom-elements.json +1 -1
  4. package/dist/ai/runtime.js +1 -1
  5. package/dist/ai/types.d.ts +13 -5
  6. package/dist/cli/lyra-rename-ledger.mjs +1 -0
  7. package/dist/cli/migrate-wa.mjs +33 -13
  8. package/dist/cli/migration-contract.json +1 -1
  9. package/dist/components/agent-tools/agent-trace/agent-trace.class.d.ts +5 -3
  10. package/dist/components/agent-tools/agent-trace/agent-trace.class.js +3 -2
  11. package/dist/components/agent-tools/tool-call-block/tool-call-block.class.d.ts +15 -3
  12. package/dist/components/agent-tools/tool-call-block/tool-call-block.class.js +3 -3
  13. package/dist/components/agent-tools/tool-call-chip/tool-call-chip.class.d.ts +24 -8
  14. package/dist/components/agent-tools/tool-call-chip/tool-call-chip.class.js +3 -3
  15. package/dist/components/agent-tools/tool-param-form/tool-param-form.class.js +4 -0
  16. package/dist/components/agent-tools/tool-result-dialog/tool-result-dialog.class.d.ts +9 -5
  17. package/dist/components/agent-tools/tool-result-dialog/tool-result-dialog.class.js +2 -2
  18. package/dist/components/agent-tools/tool-result-dialog/tool-result-dialog.styles.js +1 -1
  19. package/dist/components/agent-tools/tool-status.js +2 -2
  20. package/dist/components/agent-tools/tool-timeline/tool-timeline.class.d.ts +8 -0
  21. package/dist/components/agent-tools/tool-timeline/tool-timeline.class.js +3 -2
  22. package/dist/components/agent-tools/tool-timeline/tool-timeline.styles.js +1 -1
  23. package/dist/components/agent-tools/trace-tree/span.d.ts +2 -2
  24. package/dist/components/charts/chart/box-plot.class.d.ts +3 -1
  25. package/dist/components/charts/chart/box-plot.class.js +9 -9
  26. package/dist/components/charts/chart/chart-bidi.d.ts +109 -0
  27. package/dist/components/charts/chart/chart-bidi.js +1 -0
  28. package/dist/components/charts/chart/chart.class.d.ts +17 -2
  29. package/dist/components/charts/chart/chart.class.js +10 -8
  30. package/dist/components/charts/chart/histogram.class.js +1 -1
  31. package/dist/components/charts/chart/lite-chart.class.d.ts +24 -5
  32. package/dist/components/charts/chart/lite-chart.class.js +9 -9
  33. package/dist/components/charts/chart/lite-chart.styles.js +1 -1
  34. package/dist/components/conversation/code-block/shiki-dark-theme.d.ts +2 -2
  35. package/dist/components/conversation/code-block/shiki-dark-theme.js +1 -1
  36. package/dist/components/conversation/conversation-item/conversation-item.class.d.ts +18 -2
  37. package/dist/components/conversation/conversation-item/conversation-item.class.js +3 -3
  38. package/dist/components/conversation/conversation-item/conversation-item.styles.js +1 -1
  39. package/dist/components/conversation/markdown/markdown-base.class.js +1 -1
  40. package/dist/components/conversation/markdown/markdown-core.class.d.ts +3 -1
  41. package/dist/components/conversation/markdown/markdown.class.d.ts +3 -1
  42. package/dist/components/conversation/message-actions/message-actions.class.d.ts +7 -2
  43. package/dist/components/conversation/message-actions/message-actions.class.js +2 -2
  44. package/dist/components/conversation/message-parts/message-parts.class.d.ts +6 -2
  45. package/dist/components/conversation/message-parts/message-parts.class.js +5 -3
  46. package/dist/components/conversation/selection-toolbar/selection-toolbar.class.d.ts +3 -2
  47. package/dist/components/conversation/selection-toolbar/selection-toolbar.class.js +1 -1
  48. package/dist/components/conversation/streaming-text/streaming-text-base.class.d.ts +1 -5
  49. package/dist/components/conversation/streaming-text/streaming-text-base.class.js +2 -2
  50. package/dist/components/conversation/streaming-text/streaming-text-core.class.d.ts +7 -1
  51. package/dist/components/conversation/streaming-text/streaming-text-core.class.js +3 -4
  52. package/dist/components/conversation/streaming-text/streaming-text.class.d.ts +7 -1
  53. package/dist/components/conversation/streaming-text/streaming-text.class.js +3 -4
  54. package/dist/components/conversation/thread-list/thread-list.class.d.ts +13 -2
  55. package/dist/components/conversation/thread-list/thread-list.class.js +3 -3
  56. package/dist/components/data/data-grid/data-grid.class.js +1 -1
  57. package/dist/components/data/document-library/document-library.class.js +2 -0
  58. package/dist/components/data/flow-canvas/flow-canvas.class.js +1 -1
  59. package/dist/components/data/flow-minimap/flow-minimap.class.js +1 -1
  60. package/dist/components/data/flow-node/flow-node.class.d.ts +6 -2
  61. package/dist/components/data/flow-node/flow-node.class.js +6 -2
  62. package/dist/components/data/flow-node/flow-node.styles.js +1 -1
  63. package/dist/components/data/gauge/gauge.styles.js +1 -1
  64. package/dist/components/data/heatmap/heatmap.class.d.ts +3 -0
  65. package/dist/components/data/heatmap/heatmap.class.js +2 -2
  66. package/dist/components/data/heatmap/heatmap.styles.js +1 -1
  67. package/dist/components/data/sparkline/sparkline.class.d.ts +5 -3
  68. package/dist/components/data/stat/stat.class.d.ts +4 -3
  69. package/dist/components/data/table/table.class.d.ts +32 -5
  70. package/dist/components/data/table/table.class.js +3 -2
  71. package/dist/components/forms/button/button.class.d.ts +7 -1
  72. package/dist/components/forms/button/button.styles.js +1 -1
  73. package/dist/components/forms/date-picker/date-input.styles.js +1 -1
  74. package/dist/components/forms/input/input.styles.js +1 -1
  75. package/dist/components/forms/rubric-form/rubric-form.class.js +1 -0
  76. package/dist/components/layout/app-rail/app-rail.class.d.ts +50 -11
  77. package/dist/components/layout/app-rail/app-rail.class.js +2 -2
  78. package/dist/components/layout/command-palette/command-palette.class.js +1 -1
  79. package/dist/components/layout/menu/menu.class.d.ts +6 -5
  80. package/dist/components/layout/split-panel/split-panel.class.d.ts +2 -1
  81. package/dist/components/media/flag/language-map.d.ts +8 -0
  82. package/dist/components/media/flag/language-map.js +1 -1
  83. package/dist/components/media/map/map-loader.d.ts +7 -1
  84. package/dist/components/media/map/map.class.d.ts +111 -5
  85. package/dist/components/media/map/map.class.js +3 -3
  86. package/dist/components/media/media-card/media-card.class.d.ts +18 -5
  87. package/dist/components/media/media-card/media-card.class.js +1 -1
  88. package/dist/components/overlays/overlay/popover.class.d.ts +20 -0
  89. package/dist/components/overlays/overlay/popover.class.js +2 -2
  90. package/dist/components/retrieval/graph/graph.class.d.ts +3 -3
  91. package/dist/components/retrieval/graph/graph.class.js +1 -1
  92. package/dist/components/retrieval/knowledge-graph-explorer/knowledge-graph-explorer.class.d.ts +5 -3
  93. package/dist/components/retrieval/knowledge-graph-explorer/knowledge-graph-explorer.class.js +3 -2
  94. package/dist/components/retrieval/mind-map/mind-map.class.d.ts +3 -3
  95. package/dist/components/retrieval/mind-map/mind-map.class.js +1 -1
  96. package/dist/components/retrieval/retrieval-results/retrieval-results.class.d.ts +4 -1
  97. package/dist/components/retrieval/retrieval-results/retrieval-results.class.js +5 -1
  98. package/dist/components/retrieval/source-picker/source-picker.class.d.ts +4 -1
  99. package/dist/components/retrieval/source-picker/source-picker.class.js +5 -1
  100. package/dist/components/utility/icon/icon.class.d.ts +9 -3
  101. package/dist/components/utility/icon/icon.class.js +1 -1
  102. package/dist/components/utility/mutation-observer/mutation-observer.class.d.ts +14 -8
  103. package/dist/components/utility/mutation-observer/mutation-observer.class.js +1 -1
  104. package/dist/components/viewers/document-viewer/document-viewer.class.d.ts +6 -1
  105. package/dist/components/viewers/document-viewer/document-viewer.class.js +7 -1
  106. package/dist/components/viewers/document-viewer/registry.d.ts +12 -3
  107. package/dist/components/viewers/geojson-view/geojson-view.class.d.ts +13 -5
  108. package/dist/components/viewers/geojson-view/geojson-view.class.js +1 -1
  109. package/dist/components/viewers/geojson-view/geojson-viewer.class.d.ts +3 -2
  110. package/dist/custom-elements-jsx.d.ts +1 -1
  111. package/dist/events.d.ts +644 -1242
  112. package/dist/internal/anchored-overlay-runtime.d.ts +2 -2
  113. package/dist/internal/cell-range.d.ts +0 -6
  114. package/dist/internal/cell-range.js +1 -1
  115. package/dist/internal/css-token-length.d.ts +7 -0
  116. package/dist/internal/css-token-length.js +1 -0
  117. package/dist/internal/default-strings.generated.d.ts +1 -1
  118. package/dist/internal/default-strings.generated.js +1 -1
  119. package/dist/internal/deferred-focus-return.d.ts +7 -4
  120. package/dist/internal/deferred-focus-return.js +1 -1
  121. package/dist/internal/dev-mode-attribute-warning.d.ts +35 -0
  122. package/dist/internal/dev-mode-attribute-warning.js +1 -1
  123. package/dist/internal/localization-runtime.js +1 -1
  124. package/dist/internal/localization-types.d.ts +1 -1
  125. package/dist/internal/localization.js +2 -2
  126. package/dist/internal/package-metadata.d.ts +1 -1
  127. package/dist/internal/package-metadata.js +1 -1
  128. package/dist/internal/papaparse-loader.d.ts +1 -1
  129. package/dist/internal/papaparse-loader.js +1 -1
  130. package/dist/internal/positioner.d.ts +10 -0
  131. package/dist/internal/positioner.js +1 -1
  132. package/dist/internal/shared-unions.d.ts +2 -1
  133. package/dist/internal/slotted-overlay-controller.d.ts +20 -0
  134. package/dist/internal/slotted-overlay-controller.js +1 -0
  135. package/dist/internal/text-quote.d.ts +1 -1
  136. package/dist/internal/text-quote.js +1 -1
  137. package/dist/internal/theme-observation.d.ts +4 -0
  138. package/dist/internal/theme-observation.js +1 -0
  139. package/dist/internal/theme-watcher.js +1 -1
  140. package/dist/localization.d.ts +6 -1
  141. package/dist/localization.js +1 -1
  142. package/dist/lyra.d.ts +1 -1
  143. package/dist/lyra.js +1 -1
  144. package/dist/svelte.d.ts +1 -1
  145. package/dist/testing/lyra-tag-event-map.js +1 -1
  146. package/dist/translations/ar/agent-tools.js +1 -1
  147. package/dist/translations/cs/agent-tools.js +1 -1
  148. package/dist/translations/da/agent-tools.js +1 -1
  149. package/dist/translations/de/agent-tools.js +1 -1
  150. package/dist/translations/de-CH/agent-tools.js +1 -1
  151. package/dist/translations/es/agent-tools.js +1 -1
  152. package/dist/translations/fa/agent-tools.js +1 -1
  153. package/dist/translations/fi/agent-tools.js +1 -1
  154. package/dist/translations/fr/agent-tools.js +1 -1
  155. package/dist/translations/he/agent-tools.js +1 -1
  156. package/dist/translations/hi/agent-tools.js +1 -1
  157. package/dist/translations/hr/agent-tools.js +1 -1
  158. package/dist/translations/hu/agent-tools.js +1 -1
  159. package/dist/translations/id/agent-tools.js +1 -1
  160. package/dist/translations/it/agent-tools.js +1 -1
  161. package/dist/translations/ja/agent-tools.js +1 -1
  162. package/dist/translations/kk/agent-tools.js +1 -1
  163. package/dist/translations/ko/agent-tools.js +1 -1
  164. package/dist/translations/nb/agent-tools.js +1 -1
  165. package/dist/translations/nl/agent-tools.js +1 -1
  166. package/dist/translations/nn/agent-tools.js +1 -1
  167. package/dist/translations/pl/agent-tools.js +1 -1
  168. package/dist/translations/pt-BR/agent-tools.js +1 -1
  169. package/dist/translations/pt-PT/agent-tools.js +1 -1
  170. package/dist/translations/pt-PT/charts.js +1 -1
  171. package/dist/translations/pt-PT/conversation.js +1 -1
  172. package/dist/translations/pt-PT/data.js +1 -1
  173. package/dist/translations/pt-PT/forms.js +1 -1
  174. package/dist/translations/pt-PT/layout.js +1 -1
  175. package/dist/translations/pt-PT/media.js +1 -1
  176. package/dist/translations/pt-PT/retrieval.js +1 -1
  177. package/dist/translations/pt-PT/shared.js +1 -1
  178. package/dist/translations/pt-PT/utility.js +1 -1
  179. package/dist/translations/pt-PT/viewers.js +2 -2
  180. package/dist/translations/ro/agent-tools.js +1 -1
  181. package/dist/translations/ru/agent-tools.js +1 -1
  182. package/dist/translations/sl/agent-tools.js +1 -1
  183. package/dist/translations/sv/agent-tools.js +1 -1
  184. package/dist/translations/tr/agent-tools.js +1 -1
  185. package/dist/translations/uk/agent-tools.js +1 -1
  186. package/dist/translations/zh-CN/agent-tools.js +1 -1
  187. package/dist/translations/zh-TW/agent-tools.js +1 -1
  188. package/dist/utilities/index.d.ts +1 -1
  189. package/dist/utilities/index.js +1 -1
  190. package/dist/utilities/localization.d.ts +28 -10
  191. package/dist/vue.d.ts +1 -1
  192. package/llms/components/lr-accordion-item.md +2 -344
  193. package/llms/components/lr-accordion.md +2 -344
  194. package/llms/components/lr-app-rail-group.md +2 -721
  195. package/llms/components/lr-app-rail-item.md +2 -721
  196. package/llms/components/lr-app-rail.md +29 -4
  197. package/llms/components/lr-bar-chart.md +2 -87
  198. package/llms/components/lr-box-plot.md +1 -1
  199. package/llms/components/lr-breadcrumb-item.md +2 -67
  200. package/llms/components/lr-bubble-chart.md +2 -87
  201. package/llms/components/lr-button.md +7 -0
  202. package/llms/components/lr-chart.md +4 -5
  203. package/llms/components/lr-chip-group.md +2 -272
  204. package/llms/components/lr-conversation-item.md +20 -2
  205. package/llms/components/lr-date-input.md +2 -457
  206. package/llms/components/lr-date-picker.md +6 -2
  207. package/llms/components/lr-document-library.md +3 -3
  208. package/llms/components/lr-document-viewer.md +14 -5
  209. package/llms/components/lr-doughnut-chart.md +2 -87
  210. package/llms/components/lr-dropdown-item.md +2 -306
  211. package/llms/components/lr-dropdown.md +6 -0
  212. package/llms/components/lr-flag.md +9 -1
  213. package/llms/components/lr-flow-node.md +4 -1
  214. package/llms/components/lr-geojson-view.md +3 -90
  215. package/llms/components/lr-geojson-viewer.md +13 -5
  216. package/llms/components/lr-icon-button.md +4 -1
  217. package/llms/components/lr-icon.md +14 -6
  218. package/llms/components/lr-input.md +9 -2
  219. package/llms/components/lr-lite-chart.md +17 -9
  220. package/llms/components/lr-map.md +87 -2
  221. package/llms/components/lr-markdown-core.md +5 -4
  222. package/llms/components/lr-markdown.md +4 -2
  223. package/llms/components/lr-media-card.md +10 -5
  224. package/llms/components/lr-menu-item.md +2 -306
  225. package/llms/components/lr-menu.md +9 -6
  226. package/llms/components/lr-menubar-item.md +2 -125
  227. package/llms/components/lr-message-actions.md +4 -1
  228. package/llms/components/lr-message-parts.md +14 -5
  229. package/llms/components/lr-mutation-observer.md +12 -6
  230. package/llms/components/lr-navigation-menu-item.md +2 -237
  231. package/llms/components/lr-number-input.md +4 -0
  232. package/llms/components/lr-option.md +2 -712
  233. package/llms/components/lr-pie-chart.md +2 -87
  234. package/llms/components/lr-polar-area-chart.md +2 -87
  235. package/llms/components/lr-popover.md +10 -0
  236. package/llms/components/lr-prompt-input.md +5 -1
  237. package/llms/components/lr-radar-chart.md +2 -87
  238. package/llms/components/lr-reorder-item.md +2 -157
  239. package/llms/components/lr-result-field.md +2 -117
  240. package/llms/components/lr-retrieval-results.md +3 -1
  241. package/llms/components/lr-rubric-form.md +3 -2
  242. package/llms/components/lr-scatter-chart.md +2 -87
  243. package/llms/components/lr-selection-toolbar.md +4 -2
  244. package/llms/components/lr-source-card.md +2 -186
  245. package/llms/components/lr-source-picker.md +3 -1
  246. package/llms/components/lr-sparkline.md +9 -4
  247. package/llms/components/lr-split-panel.md +5 -3
  248. package/llms/components/lr-stat.md +4 -3
  249. package/llms/components/lr-streaming-text-core.md +7 -5
  250. package/llms/components/lr-streaming-text.md +9 -6
  251. package/llms/components/lr-swatch-picker.md +130 -0
  252. package/llms/components/lr-tag.md +2 -177
  253. package/llms/components/lr-thread-list.md +27 -4
  254. package/llms/components/lr-timeline-item.md +2 -120
  255. package/llms/components/lr-toast-item.md +2 -223
  256. package/llms/components/lr-tool-call-block.md +12 -3
  257. package/llms/components/lr-tool-call-chip.md +12 -6
  258. package/llms/components/lr-tool-param-form.md +3 -2
  259. package/llms/components/lr-tool-result-dialog.md +7 -3
  260. package/llms/components/lr-tool-result-view.md +4 -3
  261. package/llms/components/lr-tool-timeline.md +12 -5
  262. package/llms/components/lr-tree-item.md +2 -354
  263. package/llms/index.md +22 -4
  264. package/llms/migration.md +75 -1
  265. package/llms/peers.md +1 -1
  266. package/llms/shared.md +86 -39
  267. package/llms-full.txt +739 -163
  268. package/package.json +6 -6
  269. package/registrations.json +1 -1
  270. package/vscode-css-data.json +1 -1
  271. package/vscode-html-data.json +1 -1
  272. package/web-types.json +1 -1
@@ -33,7 +33,16 @@ modes use the same expression semantics at initial render and after a theme chan
33
33
  **Properties:**
34
34
 
35
35
  - `center: [number, number] = [0, 0]`
36
- - `zoom: number = 2`
36
+ - `zoom: number = 2` — `center` and `zoom` are the declarative camera. Assigning either moves the
37
+ map without emitting anything. When the camera settles after a user gesture or `fitBounds()`, the
38
+ element writes that camera into both and reports it through `lr-map-view-change`, so its next
39
+ update never resets it, and a later, different assignment still moves the map. Assigning a value
40
+ the map already shows moves nothing, so echoing a reported camera back, however late, never stops
41
+ an animation or gesture. An assignment that does interrupt one (a fit still animating, a
42
+ gesture's inertia) applies the whole declared camera, `center` and `zoom` alike, so the axis you
43
+ did not assign is not left wherever the interrupted movement stopped; with nothing in flight,
44
+ only the assigned axis moves. Because both track the settled camera, a map rebuilt after a
45
+ disconnect/reconnect opens at the last settled camera rather than the originally declared one.
37
46
  - `renderWorldCopies?: boolean` (attribute: false) — forwarded to MapLibre when its map is
38
47
  constructed. Leave it unset to preserve MapLibre's own current default; set `false` before
39
48
  construction to stop repeating the world horizontally. This is a construction-time option, so a
@@ -448,6 +457,73 @@ shared `maplibre-gl` import without constructing a map or allocating a WebGL con
448
457
  `false` when the peer is unavailable, allowing an application to choose a fallback before connecting
449
458
  an element.
450
459
 
460
+ `fitBounds(bounds: LyraMapBounds, options?: LyraMapFitBoundsOptions): boolean` frames a box
461
+ `[[west, south], [east, north]]` in the viewport: the way to show every current marker, or a
462
+ selected region, whenever the data set changes. Use it instead of calling the peer's own
463
+ `fitBounds()` through `map`, which the element neither knows about nor reports. Once the camera
464
+ settles, the element writes it into `center`/`zoom` and emits `lr-map-view-change` with
465
+ `source: 'fit'`, so declarative state stays in sync and the element never resets the fitted camera.
466
+
467
+ - `options.padding` — screen pixels kept clear around the box: one number for every side, or a
468
+ `LyraMapPadding { top?, right?, bottom?, left? }`. The sides are the viewport's physical sides in
469
+ both text directions, because the map's projected space is physical. A negative or non-finite
470
+ side counts as `0`. Defaults to `0`.
471
+ - `options.maxZoom` — the highest zoom the fit may reach, so one marker or a tight cluster does not
472
+ zoom to the street. Clamped into `[0, 22]`; a non-finite value sets no ceiling.
473
+ - `options.animate` — defaults to `true`. The camera never animates under
474
+ `prefers-reduced-motion: reduce`.
475
+ - Latitudes lie in `[-90, 90]`, with `south <= north`, and longitudes in `[-180, 180]`. A box
476
+ crossing the antimeridian takes either of MapLibre's forms: `west > east`, or `east` unwrapped
477
+ past 180, up to one full turn east of `west` (`[[170, -10], [190, 10]]`, the form MapLibre's
478
+ `LngLatBounds` produces). A single point is a valid zero-size box; pair it with `maxZoom`.
479
+ Anything else (non-finite or non-number values, out-of-range coordinates, an inverted latitude
480
+ span, the wrong shape) returns `false` without moving or queueing anything, with a
481
+ development-mode warning.
482
+ - Callable before the map exists, whether the peer is still loading or an off-screen map has not
483
+ been constructed yet. The most recent request is queued and applied without animation right
484
+ after construction, unless `center` or `zoom` has been given a different value since the call.
485
+ Re-assigning the value already held (a framework re-render building an equal array, say) keeps
486
+ the queued fit.
487
+ - A `center`/`zoom` assignment made while a fit is still animating wins: the interrupted fit is
488
+ neither written back nor reported, and the camera lands on the whole declared `center`/`zoom`.
489
+ - Returns `true` once the fit is running or queued, and `false` when the loaded peer cannot fit a
490
+ box. When the padded box cannot fit the map's current size (padding wider or taller than the
491
+ map), MapLibre leaves the camera where it is and logs its own warning: the call still returns
492
+ `true`, and no `lr-map-view-change` fires.
493
+
494
+ There is deliberately no declarative `bounds` property. `center` and `zoom` already describe the
495
+ camera; a third camera input would need a precedence rule against them, and a framework that
496
+ rebuilds its arrays on every render would refit on every render, pulling the camera away from a user
497
+ who has just panned. A one-shot command whose result lands in `center`/`zoom` keeps one camera input.
498
+
499
+ ```ts
500
+ import type {
501
+ LyraMap,
502
+ LyraMapBounds,
503
+ LyraMapMarker,
504
+ LyraMapViewChangeDetail,
505
+ } from '@aceshooting/lyra-ui/components/media/map/map.class.js';
506
+
507
+ let camera: LyraMapViewChangeDetail | undefined;
508
+ const mapEl = document.querySelector('lr-map') as LyraMap;
509
+ mapEl.addEventListener('lr-map-view-change', (event) => {
510
+ // Keep the host's own camera state in step: { center, zoom, source }.
511
+ camera = event.detail;
512
+ });
513
+
514
+ function showMarkers(markers: LyraMapMarker[]): void {
515
+ mapEl.markers = markers;
516
+ if (markers.length === 0) return;
517
+ const lngs = markers.map((marker) => marker.lngLat[0]);
518
+ const lats = markers.map((marker) => marker.lngLat[1]);
519
+ const box: LyraMapBounds = [
520
+ [Math.min(...lngs), Math.min(...lats)],
521
+ [Math.max(...lngs), Math.max(...lats)],
522
+ ];
523
+ mapEl.fitBounds(box, { padding: 48, maxZoom: 14 });
524
+ }
525
+ ```
526
+
451
527
  **Events:** `lr-map-load` (fired once, after the underlying map's own `'load'`),
452
528
  `lr-map-legend-toggle` (**cancelable**; frozen `LyraMapLegendToggleDetail { value, visible,
453
529
  hiddenCategories }` — the activated row's category key, its proposed visibility, and the complete
@@ -480,7 +556,16 @@ separately because it is a synthetic aggregate rather than one of your features:
480
556
  is MapLibre's `point_count`/`point_count_abbreviated`/`cluster_id` properties, which is what a
481
557
  zoom-to-cluster handler reads. The count label is deliberately not hit-tested (it sits exactly on
482
558
  the circle already queried and would only make the label the topmost hit), and a `kind: 'heatmap'`
483
- layer is never queried at all — MapLibre returns no features for a rendered density surface
559
+ layer is never queried at all — MapLibre returns no features for a rendered density surface.
560
+ Also `lr-map-view-change` (non-cancelable; frozen `LyraMapViewChangeDetail { center, zoom, source }`,
561
+ `source` being `LyraMapViewChangeSource = 'user' | 'fit'`), fired once each time the camera settles
562
+ after a user gesture (drag, wheel, touch, keyboard, Shift+drag box zoom, or a standard peer
563
+ navigation button) or a `fitBounds()` call. `center` is `[longitude, latitude]` with the longitude
564
+ wrapped into `[-180, 180]`. The element has already written the camera into `center` and `zoom`
565
+ when it fires, so a host that mirrors camera state assigns the detail back, at any later time,
566
+ without moving the map. Assigning `center`/`zoom` reconciles without emitting it, so a controlled
567
+ host cannot loop, and camera moves made directly through `map` are not reported — which is why
568
+ `'user'` and `'fit'` are the only sources.
484
569
 
485
570
  The outer marker-activation detail is frozen, while an opaque marker `unsafeHtml` value remains the
486
571
  original supplied value at the MapLibre popup and marker-activation boundary. Treat it as trusted
@@ -7,7 +7,7 @@
7
7
  - **Family** `components/conversation/` — see `llms/index.md` for its siblings
8
8
  - **Status** `stable` since `4.0.0` — see the maturity and deprecation policy in `llms/shared.md`
9
9
  - **Release history** [CHANGELOG.md](../../CHANGELOG.md); family-wide breaking-change summaries: [llms-full.txt](../../llms-full.txt)
10
- - **Deprecations** none
10
+ - **Deprecated property** `codeBlockChrome` / `code-block-chrome` since `21.1.0`; use property `code-block-header`; removal not before `23.0.0` — code-block-chrome is a second spelling of code-block-header with identical behavior: either one enables the code-block header. One name per concept across the Markdown elements and the components that compose them removes a choice with no difference. It keeps enabling the header through the 22.x line, and setting it logs a one-time development warning.
11
11
  - **Optional peers** `dompurify`, `katex`, `marked`, `shiki` — see `llms/peers.md`
12
12
  - **Themeable via** 24 parts, 19 custom properties — see this component's own `@csspart`/`@cssprop` list below
13
13
  - **Library-wide behavior** (events, form association, `locale`/`strings`, tokens, TS types): `llms/shared.md`
@@ -53,8 +53,9 @@ instance's isolated peer-neutral configurable parser; `htmlMode: 'sanitize' | 'e
53
53
  `link-target`), `internalLinkPrefix: string = ''` (attribute `internal-link-prefix`),
54
54
  `headingOffset: number = 0` (attribute `heading-offset`), `streaming: boolean = false` (reflected),
55
55
  `streamingRender: MarkdownStreamingRender = 'plain'` (attribute `streaming-render`, not reflected),
56
- `codeBlockHeader: boolean = false` (attribute `code-block-header`) with its compatibility alias
57
- `codeBlockChrome: boolean = false` (attribute `code-block-chrome`),
56
+ `codeBlockHeader: boolean = false` (attribute `code-block-header`) with its deprecated
57
+ compatibility alias `codeBlockChrome: boolean = false` (attribute `code-block-chrome`; removal not
58
+ before 23.0.0),
58
59
  `highlightCode: boolean = true` (attribute
59
60
  `highlight-code`), `languages: Record<string, ShikiLanguageSource> = {}` (attribute: false) —
60
61
  required, unlike `<lr-markdown>`'s optional `languages?:`; empty (the default) means every fenced
@@ -144,7 +145,7 @@ The Markdown part set also includes `task-list`, `task-item`, `task-item-checked
144
145
  `task-checkbox`, `table-wrapper`, `code-block-frame`, `code-block-copy-success`,
145
146
  `code-block-copy-error` and `streaming-tail`. `codeBlockHeader: boolean = false`
146
147
  (attribute `code-block-header`) enables the code-block header; `codeBlockChrome` (attribute
147
- `code-block-chrome`) is its compatibility alias. Successful and
148
+ `code-block-chrome`) is its deprecated compatibility alias (removal not before 23.0.0). Successful and
148
149
  failed writes pass through as `lr-copy` and `lr-copy-error`, carrying the immutable clipboard
149
150
  outcome, bubbling and composed.
150
151
 
@@ -7,7 +7,7 @@
7
7
  - **Family** `components/conversation/` — see `llms/index.md` for its siblings
8
8
  - **Status** `stable` since `4.0.0` — see the maturity and deprecation policy in `llms/shared.md`
9
9
  - **Release history** [CHANGELOG.md](../../CHANGELOG.md); family-wide breaking-change summaries: [llms-full.txt](../../llms-full.txt)
10
- - **Deprecations** none
10
+ - **Deprecated property** `codeBlockChrome` / `code-block-chrome` since `21.1.0`; use property `code-block-header`; removal not before `23.0.0` — code-block-chrome is a second spelling of code-block-header with identical behavior: either one enables the code-block header. One name per concept across the Markdown elements and the components that compose them removes a choice with no difference. It keeps enabling the header through the 22.x line, and setting it logs a one-time development warning.
11
11
  - **Optional peers** `dompurify`, `katex`, `marked`, `shiki` — see `llms/peers.md`
12
12
  - **Themeable via** 24 parts, 19 custom properties — see this component's own `@csspart`/`@cssprop` list below
13
13
  - **Library-wide behavior** (events, form association, `locale`/`strings`, tokens, TS types): `llms/shared.md`
@@ -130,7 +130,9 @@ uses for its own `[part="body"]`.
130
130
  indented. It copies source text without the renderer's terminal newline, preserving leading tabs
131
131
  whenever they match the displayed code after expansion. Custom code renderers and pre-escaped
132
132
  code bypass it. `codeBlockChrome: boolean = false` (attribute `code-block-chrome`) is a
133
- compatibility spelling; either property enables the header. Plain streaming defers headers until
133
+ deprecated compatibility spelling (removal not before 23.0.0; setting it logs a one-time
134
+ development warning): either property enables the header, so use `code-block-header`. Plain
135
+ streaming defers headers until
134
136
  settle; progressive streaming adds them to committed blocks. The button has a localized accessible
135
137
  name and native pointer title, with no custom tooltip on keyboard focus. In sanitize mode enabling
136
138
  the header also removes authored style elements and their CSS text to prevent visual copy
@@ -7,7 +7,7 @@
7
7
  - **Family** `components/media/` — see `llms/index.md` for its siblings
8
8
  - **Status** `stable` since `4.0.0` — see the maturity and deprecation policy in `llms/shared.md`
9
9
  - **Release history** [CHANGELOG.md](../../CHANGELOG.md); family-wide breaking-change summaries: [llms-full.txt](../../llms-full.txt)
10
- - **Deprecations** none
10
+ - **Deprecated event** `lr-before-media-download` since `21.1.0`; use event `addEventListener('lr-media-download-request', ...)`; removal not before `23.0.0` — Renamed to the library's dominant *-request veto-event convention. Both names fire from the same activation of a safe file anchor with an equal { src, filename } detail during the compatibility window, the canonical name first, and either may veto the native download/open. A veto through the alias logs a one-time development warning.
11
11
  - **Optional peers** none
12
12
  - **Themeable via** 5 parts, 4 custom properties — see this component's own `@csspart`/`@cssprop` list below
13
13
  - **Library-wide behavior** (events, form association, `locale`/`strings`, tokens, TS types): `llms/shared.md`
@@ -61,7 +61,8 @@ and later MIME values restore detection.
61
61
  button and the `kind="video"` `open-button` render `disabled`; a safe file chip's anchor loses
62
62
  its `href` and `download`, so it genuinely cannot fetch, and gains an explicit `role="link"` so
63
63
  its accessible name and `aria-current` stay valid on an element that no longer has an implicit
64
- role. `lr-media-open` and `lr-before-media-download` stop firing from every path, `click()`
64
+ role. `lr-media-open`, `lr-media-download-request` and its deprecated `lr-before-media-download`
65
+ alias stop firing from every path, `click()`
65
66
  included, the action leaves the tab order, and it paints at `--lr-opacity-disabled` with a
66
67
  `not-allowed` cursor. Deliberately does NOT reach into the `kind="video"` player: `<video
67
68
  controls>` is media content with its own native transport, not this card's action. An
@@ -93,9 +94,13 @@ not exports from the component entry.
93
94
  **Events:** `lr-media-open` (`detail: LyraMediaCardOpenDetail { src: string; filename: string }`,
94
95
  noncancelable) notifies
95
96
  after image-card or video open-button activation; those kinds have no component-owned navigation,
96
- so a host decides what "open" means. `lr-before-media-download` carries the same detail and is
97
+ so a host decides what "open" means. `lr-media-download-request` carries the same detail and is
97
98
  cancelable only for a safe file anchor immediately before its native download/open default; calling
98
- `preventDefault()` there suppresses that exact default. `detail.src` is whichever internally
99
+ `preventDefault()` there suppresses that exact default. `lr-before-media-download` is its deprecated
100
+ alias (removal not before 23.0.0): it still fires right after the canonical event from the same
101
+ activation, with an equal but separate `detail`, and either event's `preventDefault()` vetoes the
102
+ download/open. A veto through the alias logs a one-time development warning, so move listeners to
103
+ `lr-media-download-request`. `detail.src` is whichever internally
99
104
  validated safe-URL sink actually rendered, not necessarily the raw `src` property verbatim — a
100
105
  whitespace-padded value is trimmed, so it matches the rendered sink.
101
106
  The former generic `lr-open` event is removed in v9: notification and veto phases now have distinct,
@@ -151,7 +156,7 @@ sizing), `--lr-focus-ring-*`, `--lr-transition-fast`.
151
156
  .addEventListener("lr-media-open", (e) => openLightbox(e.detail.src));
152
157
  document
153
158
  .getElementById("file-card")
154
- .addEventListener("lr-before-media-download", (e) => shouldUseNativeDownload || e.preventDefault());
159
+ .addEventListener("lr-media-download-request", (e) => shouldUseNativeDownload || e.preventDefault());
155
160
  </script>
156
161
  ```
157
162
 
@@ -9,310 +9,6 @@
9
9
  - **Release history** [CHANGELOG.md](../../CHANGELOG.md); family-wide breaking-change summaries: [llms-full.txt](../../llms-full.txt)
10
10
  - **Deprecations** none
11
11
  - **Optional peers** none
12
- - **Themeable via** 12 parts, 13 custom properties — see this component's own `@csspart`/`@cssprop` list below
13
- - **Documented with** `lr-menu`, `lr-dropdown-item` (same section below)
12
+ - **Themeable via** 12 parts, 13 custom properties — see `lr-menu.md`
13
+ - **Documented with** `lr-menu`: see [lr-menu.md](./lr-menu.md).
14
14
  - **Library-wide behavior** (events, form association, `locale`/`strings`, tokens, TS types): `llms/shared.md`
15
-
16
- ---
17
-
18
- ## `lr-menu` / `lr-menu-item`
19
-
20
- The inline semantic menu mapped from Shoelace's `sl-menu`, plus its action-row element. A root
21
- `<lr-menu>` is always visible and owns the named `role="menu"` list, real roving DOM focus,
22
- wrapping keyboard navigation, type-ahead, and one canonical selection event. It deliberately has no
23
- trigger, positioned popup, root open state, placement API, or overlay lifecycle.
24
-
25
- Removing or disabling the remembered active item repairs the roving stop without taking focus from
26
- outside controls or the menu's header/footer. If the changed item held actual focus, focus moves to
27
- a valid survivor or through the existing owner dismissal path when none remain.
28
-
29
- For a menu button or other anchored overlay, compose the semantic controller inside
30
- `<lr-dropdown>`:
31
-
32
- ```html
33
- <lr-dropdown label="Row actions">
34
- <button slot="trigger" aria-label="Row actions">⋮</button>
35
- <lr-menu>
36
- <lr-menu-item value="edit">Edit</lr-menu-item>
37
- <lr-menu-item value="delete" variant="danger">Delete</lr-menu-item>
38
- </lr-menu>
39
- </lr-dropdown>
40
- ```
41
-
42
- The dropdown shell owns trigger relationships, positioning, opening/closing, outside dismissal,
43
- focus return, and lifecycle events. The contained menu remains the sole semantic owner: its
44
- `header`/default/`footer` regions and named `role="menu"` list are preserved, while the outer popup
45
- is neutral. This is also the composition used for direct `<lr-dropdown-item>` children.
46
-
47
- ### `lr-menu`
48
-
49
- **Properties:**
50
-
51
- - `label?: string` — accessible name for the `role="menu"` list. A host `aria-label`
52
- attribute is authoritative, including `aria-label=""`; any supplied `label` follows (including `"Menu"` or
53
- `""`),
54
- then a containing dropdown's supplied fallback, then the localized menu label. Omission,
55
- not comparison with an English sentinel, is what selects localization.
56
- - `dropdownOpen: boolean = false` (attribute: false) — the containing dropdown's controlled open
57
- state, used to synchronize the menu interaction engine while it is rendered inside a popup.
58
-
59
- **Events:**
60
-
61
- - `lr-select` — cancelable, with `detail: { item }`. It originates exactly once at the menu that
62
- owns the activated item, then bubbles unchanged through ancestor menus and a containing dropdown.
63
- Preventing it anywhere keeps the current menu/submenu chain open. There are no
64
- `lr-menu-select`, `lr-menu-item-select`, or nested-selection aliases.
65
-
66
- **Slots:** default (`<lr-menu-item>`/`<lr-dropdown-item>` plus semantic separators), `header`, and
67
- `footer`. Header and footer are composed controls or explanatory regions outside the
68
- `role="menu"` list, so filters, counts, or footer actions do not violate the menu required-child
69
- contract. Arbitrary non-item content in the default slot still renders, but is not enrolled as a
70
- menu item.
71
-
72
- **CSS parts:** `header`, `list`, and `footer`. Root `trigger` and `popup` parts do not exist;
73
- style those on `<lr-dropdown>` when using the overlay composition.
74
-
75
- **Themeable custom properties:** the standalone menu surface and a submenu's own surface paint from
76
- the **shared overlay-surface family** (16.0.0) — `--lr-overlay-surface` (default
77
- `var(--lr-color-surface-overlay)`), `--lr-overlay-border` (default `var(--lr-color-border-subtle)`),
78
- `--lr-overlay-radius` (default `var(--lr-radius)`) and, on the submenu only,
79
- `--lr-overlay-shadow-anchored` (default `var(--lr-shadow-m)`). None is declared on `:host`, so one
80
- declaration on `:root` (or on any ancestor, to scope it) retints this menu together with every other
81
- floating surface. A menu contained by `<lr-dropdown>` paints no surface of its own, so the family has
82
- no effect there — the dropdown's popup carries it. The header/footer dividing rules and a slotted
83
- `<hr>` deliberately stay outside the family on the decorative `--lr-color-border-subtle`: they
84
- separate content rather than draw the surface's edge. Otherwise shared spacing and motion tokens.
85
- Row chrome is controlled through the menu-item properties listed below.
86
-
87
- Width is a pair, applied to the standalone surface and to a submenu's own surface alike:
88
- `--lr-menu-max-inline-size` (default `var(--lr-size-20rem)`) and `--lr-menu-min-inline-size`
89
- (default `var(--lr-size-10rem)`). They move together — the floor wins over the ceiling, so capping
90
- alone cannot take a menu below 10rem. Neither is declared on `:host`, so an ancestor theme wrapper's
91
- value reaches the menu. The ceiling takes a length or a percentage; `100%` and `none` both uncap it
92
- to the container, and any other value outside `<length-percentage>` is treated as `none` rather than
93
- dropping the cap's safety terms. Those terms — the shared `--lr-popover-viewport-clamp` and the
94
- container allocation — are applied outside the name, so no value of the hook can make a menu wider
95
- than its container or the viewport. (That guarantee is enforced by a registered custom property, so
96
- an out-of-syntax value falls back cleanly instead of invalidating the whole declaration; an engine
97
- without `CSS.registerProperty` degrades to "use `100%`, not `none`".) A menu contained by
98
- `<lr-dropdown>` sizes from its dropdown and is unaffected by both names.
99
-
100
- **`--lr-positioning-strategy`** (16.0.0) — the private submenu surface reads this same cascading
101
- `absolute`/`fixed` override documented on `<lr-popover>` when it is (re)positioned, falling back to
102
- its own `fixed` default when nothing is set. There is no per-instance `positioning-strategy`
103
- property on `<lr-menu>`; set the custom property on `:root`, a theme, or one clipping ancestor to
104
- change every unset submenu beneath it. A menu contained by `<lr-dropdown>` is positioned by the
105
- dropdown instead and is unaffected.
106
-
107
- **Methods:** no menu-specific public overlay methods. Use `<lr-dropdown>`'s `show()`/`hide()` and
108
- `open` state for an overlay. Menu-item submenu methods remain public because they drive a row's
109
- nested disclosure.
110
-
111
- **Keyboard and focus:** exactly one navigable row has `tabindex="0"`. ArrowDown/ArrowUp wrap;
112
- Home/End move to the first/last navigable row; Enter/Space activate; printable input performs
113
- locale-aware type-ahead. Rows that are disabled, loading, hidden, `aria-hidden`, inert, or inside an
114
- inert subtree are skipped. Navigation is repaired live when those states or light-DOM membership
115
- change. A root inline menu does not consume Escape or turn Tab into overlay dismissal; a containing
116
- dropdown owns those root-level behaviors.
117
-
118
- ### `lr-menu-item`
119
-
120
- A focusable action row owned by `<lr-menu>`. The host itself carries `role="menuitem"` (or
121
- `menuitemcheckbox`/`menuitemradio`) and roving `tabindex`; `[part="base"]` is only the visual row.
122
-
123
- **Properties:**
124
-
125
- - `value: string = ''` — identifier available as `event.detail.item.value` on `lr-select`
126
- - `size: '2xs' | 'xs' | 's' | 'm' | 'l' | 'xl' | 'small' | 'medium' | 'large' = 'm'`
127
- - `disabled: boolean = false`
128
- - `variant: 'default' | 'danger' = 'default'`
129
- - `type: 'normal' | 'checkbox' | 'radio' = 'normal'`
130
- - `checked: boolean = false` — meaningful only for `type="checkbox"`/`type="radio"`
131
- - `group?: string` — narrows a `type="radio"` item's exclusive-choice scope to only the other
132
- radio items sharing this same string. Unset, the scope is every `type="radio"` item the same
133
- owning `<lr-menu>` owns directly — a nested submenu's radio items belong to that submenu's own
134
- `<lr-menu>` instead, so they're never in scope regardless of `group`. Meaningless for
135
- `type="normal"`/`"checkbox"`
136
- - `loading: boolean = false`
137
- - `href?: string` — when set to a safe link URL (`http:`/`https:`/`blob:`/`mailto:`/relative; see
138
- `safeLinkHref`, or `safeDownloadHref` when `download` is set, which drops `mailto:`),
139
- `[part="base"]` renders as a real `<a href=…>` instead of a `<span>`, and activation (click, or
140
- the owning menu's Enter/Space handling, which forwards through `click()` for a link item so the
141
- anchor's own native default action runs) navigates there in addition to firing the usual
142
- `select()`/`lr-select` contract. An unsafe/unparseable value falls back to the plain `<span>`,
143
- matching `lr-button`'s identical fallback
144
- - `target?: string` — native anchor `target`, used only while `href` resolves to a link. Setting it
145
- (e.g. `'_blank'`) always force-adds `noopener noreferrer` to the rendered anchor's `rel`,
146
- matching `lr-button`'s identical pattern
147
- - `rel?: string` — independently settable author relationship tokens, no default. Author tokens are
148
- merged rather than replaced: `opener` is always stripped, and whenever `target` is set the
149
- non-removable `noopener noreferrer` floor is added, so a same-tab link (no `target`) keeps
150
- exactly the author's tokens while a link opening a new context can never lose the guard
151
- - `download?: string` — native anchor `download` attribute, used only while `href` resolves to a
152
- link. Presence narrows the safe-URL allowlist to `safeDownloadHref`'s, which drops `mailto:` — a
153
- mail handoff names no retrievable bytes, so it cannot be a download target
154
- - `hasSubmenu: boolean` (read-only)
155
- - `submenuOpen: boolean = false` — transient live state; assigning it drives an existing submenu
156
- without moving focus and disconnect resets it
157
-
158
- **Methods:**
159
-
160
- - `click(): void` forwards programmatic activation through the visual-row path
161
- - `select(): void` activates through the current owning menu; it is inert while disabled/loading
162
- - `openSubmenu(focus: 'first' | 'last' | 'none' = 'first'): Promise<void>`
163
- - `closeSubmenu(): Promise<void>`
164
- - `getTextLabel(): string` returns the accessibility-visible label used by type-ahead
165
-
166
- The computed name is derived from the row's own visible label and does not depend on whether the
167
- menu is currently displayed, so a row inside a closed dropdown — whose popup is `visibility:
168
- hidden` — is named the same as an open one, and `getTextLabel()` drives type-ahead either way.
169
- A row with no label text carries **no** `aria-label` attribute rather than an empty one, so the
170
- browser falls back to the row's own content; an `aria-label` or `aria-labelledby` you set yourself,
171
- including an explicitly empty value, still wins.
172
-
173
- A checkbox activation first emits cancelable `lr-menu-item-change` with the proposed
174
- `detail: { value, checked }`. Preventing that event retains the current checked state; the owning
175
- menu's canonical `lr-select` still follows. A submenu parent is a disclosure instead of an action:
176
- activation opens its submenu and emits neither checkbox-change nor selection.
177
-
178
- A `type="radio"` item works the same way, with exclusive-choice semantics layered on top:
179
- activating an already-checked radio is a no-op on `checked` — no `lr-menu-item-change`, no state
180
- change, matching native `<input type="radio">` — but still falls through to the owning menu's
181
- usual selection. Activating an unchecked radio fires `lr-menu-item-change` with
182
- `checked: true`; once not prevented, this item becomes `checked` and every other `type="radio"`
183
- item the same owning `<lr-menu>` owns directly whose `group` matches is unchecked directly
184
- (without an `lr-menu-item-change` of its own).
185
-
186
- **Events:**
187
-
188
- - `lr-menu-item-change` — cancelable checkbox/radio-state proposal; never fired when activating an
189
- already-checked radio
190
- - `lr-menu-item-state-change` — internal navigation repair signal with
191
- `detail: { disabled, hidden, inert }`; the owning menu consumes and contains it, so it does not
192
- escape a menu or a composite wrapper as an apparent public event
193
-
194
- Item activation itself is private owner plumbing, not a public child event. Listen for `lr-select`
195
- on the owning menu.
196
-
197
- **Slots:** default label, `icon`, `prefix`, `details`, `suffix`, and `submenu`. Display slots are
198
- inert visual content; their accessibility-visible default-slot text names the focusable host. The
199
- submenu slot accepts either one nested `<lr-menu>` or direct mapped items. Long `details` and
200
- `suffix` content shrinks and ellipsizes within the allocated row in both directions rather than
201
- expanding the popup.
202
-
203
- **CSS parts:** `base`, `icon`, `prefix`, `label`, `details`, `suffix`, `checkmark`,
204
- `checked-icon`, `spinner`, `spinner__base`, `submenu-icon`, and `submenu`.
205
-
206
- **Themeable custom properties:** `--lr-menu-item-gap`, `--lr-menu-item-radius`,
207
- `--lr-menu-item-danger-color`, `--lr-menu-item-danger-hover-bg`,
208
- `--lr-menu-item-danger-active-bg`, `--lr-menu-item-checked-bg` (default `transparent`),
209
- `--lr-menu-item-checked-color` (default `inherit`), `--lr-menu-item-checked-font-weight` (default
210
- `inherit`), and `--submenu-offset`, plus shared size/focus/color/spacing tokens. The checked hooks
211
- apply to a `type="checkbox" checked` or `type="radio" checked` row's `[part="base"]`, matching the
212
- checked/selected-state hooks `<lr-option>`, `<lr-select>`, `<lr-combobox>`, and `<lr-tree-item>`
213
- already expose; unset, a checked row paints identically to an unchecked one.
214
-
215
- Four more row-chrome hooks land in 16.0.0, each an inline fallback so unset rendering is
216
- byte-identical: `--lr-menu-item-hover-bg` (default `var(--lr-color-brand-quiet)`) is the enabled
217
- row's fill under the pointer, and the pressed state mixes from that same value, so a retuned hover
218
- fill keeps its pressed step instead of snapping back to the brand default; `--lr-menu-item-active-bg`
219
- (default `color-mix(in oklab, var(--lr-menu-item-hover-bg, var(--lr-color-brand-quiet)),
220
- var(--lr-color-mix-partner) var(--lr-color-mix-active))`) overrides that pressed fill directly,
221
- matching `--lr-option-active-bg`'s equivalent hook — unset, the pressed row keeps mixing from
222
- `--lr-menu-item-hover-bg` exactly as before this hook existed; `--lr-menu-item-icon-color` (default
223
- `inherit`) recolours `[part="icon"]` without touching the label beside it, so it still follows the
224
- row while the row is disabled or `variant="danger"` unless you say otherwise; and
225
- `--lr-menu-item-min-height` (default `max(var(--lr-form-control-height), var(--lr-size-24px))`)
226
- sets the row's minimum block size for a denser or roomier menu, replacing a `::part(base)` rule per
227
- item. A value below the 24px floor is your call, exactly as it is when overriding the shared ladder
228
- itself.
229
-
230
- Any element assigned to `details` counts as content, including a shadow-rendered
231
- `<lr-kbd slot="details" keys="mod+t">` chip or an icon. An intentionally empty placeholder element
232
- also shows the part and reserves one `--lr-menu-item-gap`; whitespace-only text and empty forwarding
233
- slots keep the part hidden. This also applies to `lr-dropdown-item`.
234
-
235
- ### Nested submenus
236
-
237
- Both supported authoring shapes use the `submenu` slot:
238
-
239
- ```html
240
- <lr-menu label="Share actions">
241
- <lr-menu-item value="share">
242
- Share
243
- <lr-menu slot="submenu" label="Share options">
244
- <lr-menu-item value="email">Email</lr-menu-item>
245
- <lr-menu-item value="link">Copy link</lr-menu-item>
246
- </lr-menu>
247
- </lr-menu-item>
248
- </lr-menu>
249
- ```
250
-
251
- ```html
252
- <lr-dropdown-item>
253
- Share
254
- <lr-dropdown-item slot="submenu" value="email">Email</lr-dropdown-item>
255
- <lr-dropdown-item slot="submenu" value="link">Copy link</lr-dropdown-item>
256
- </lr-dropdown-item>
257
- ```
258
-
259
- The submenu presentation is private to the parent row, not a second root-menu API. A submenu parent
260
- has `aria-haspopup="menu"`, explicit `aria-expanded="true|false"`, the transient
261
- `submenu-open` state, and a logical-direction chevron. Its submenu is named from the parent's
262
- accessible label unless the submenu supplies its own `aria-label` or non-default `label`.
263
-
264
- The into-branch and back-out arrow keys swap under RTL. Enter/Space and the into key open and focus
265
- the first child; the back-out key and Escape close only the innermost branch and return focus to its
266
- parent row. Pointer hover uses an intent delay, outside pointer dismissal closes the branch, and at
267
- most one branch per level is open. Selection bubbles as the same single `lr-select`; a non-vetoed
268
- selection closes the full nested chain.
269
-
270
- ### `lr-dropdown-item`
271
-
272
- The Web Awesome-compatible name for the same item implementation. It shares all menu-item
273
- properties, slots, parts, methods, checkbox/radio/state events, roving focus, and canonical parent
274
- `lr-select` behavior. Its host also exposes native, non-bubbling, composed `focus` and `blur`
275
- events.
276
-
277
- **Attributes:** `href`, `target`, `rel`, and `download` — the same link-rendering properties
278
- documented above for `<lr-menu-item>`, settable directly in markup
279
- (`<lr-dropdown-item href="/settings" target="_blank">`). The `rel` guard is identical: author
280
- tokens merge rather than get replaced, `opener` is always stripped, and setting `target` force-adds
281
- the non-removable `noopener noreferrer` floor, so a same-tab link keeps exactly the author's tokens
282
- while a link opening a new context can never lose the guard.
283
-
284
- **Events:** native, non-bubbling, composed, non-cancelable `focus` and `blur` (`FocusEvent`) when
285
- the focusable host gains or loses focus, plus the shared menu-item events above.
286
-
287
- **Themeable custom properties:** every `<lr-menu-item>` hook above, including 16.0.0's
288
- `--lr-menu-item-hover-bg`, `--lr-menu-item-active-bg`, `--lr-menu-item-icon-color` and
289
- `--lr-menu-item-min-height`.
290
- `--lr-overlay-surface`, `--lr-overlay-border` and `--lr-overlay-radius` are listed on this tag
291
- because it shares a stylesheet directory with `<lr-menu>`, whose surface reads them; a dropdown item
292
- is a row **inside** that surface and paints no surface of its own, so setting them here is a no-op —
293
- set them on the menu or on any ancestor instead. The row's own corner stays `--lr-menu-item-radius`.
294
-
295
- `submenuOpen` reflects to canonical `submenu-open`. HTML normalizes Web Awesome's documented
296
- mixed-case spelling to `submenuopen`, so that lowercase token is a permanent compatibility alias.
297
- Adding either spelling opens the submenu and synchronizes the other; removing either closes it and
298
- removes both. Internal close paths — `closeSubmenu()`, Escape, outside dismissal, selection,
299
- replacement, and disconnect — clear both spellings, preventing a persistent alias from reopening a
300
- dismissed branch. An authored initial open request remains pending until submenu content connects.
301
-
302
- ### 9.0 migration
303
-
304
- Root overlay behavior moved from `<lr-menu>` to `<lr-dropdown>`. Migrate mechanically:
305
-
306
- - Move a former menu `trigger` slot and menu `open`, `placement`, `anchor`, or
307
- `close-on-escape-anywhere` policy to an enclosing `<lr-dropdown>`.
308
- - Replace `menu.show()`/`menu.hide()` and menu `lr-show`/`lr-hide` listeners with the equivalent
309
- dropdown APIs/events.
310
- - Replace `lr-menu-select` (`detail.value`) and `lr-menu-item-select` listeners with one
311
- `lr-select` listener on the menu or dropdown and read `event.detail.item`.
312
- - Replace menu `::part(trigger)`/`::part(popup)` rules with dropdown part styling. Menu
313
- `header`/`list`/`footer` parts remain on the semantic controller.
314
-
315
- Standalone mapped `<sl-menu>` markup needs no wrapper: the mechanical `sl-` → `lr-` tag rename
316
- continues to produce an inline menu.
317
-
318
- ---
@@ -7,7 +7,7 @@
7
7
  - **Family** `components/layout/` — see `llms/index.md` for its siblings
8
8
  - **Status** `stable` since `4.0.0` — see the maturity and deprecation policy in `llms/shared.md`
9
9
  - **Release history** [CHANGELOG.md](../../CHANGELOG.md); family-wide breaking-change summaries: [llms-full.txt](../../llms-full.txt)
10
- - **Deprecations** none
10
+ - **Deprecated slot-content** default-slot content other than `<hr>`, `<lr-divider>`, `<lr-dropdown-item>`, `<lr-menu-item>`, `<lr-menu-label>` since `21.1.0`; use slot `slot="header" (or slot="footer")`; removal not before `23.0.0` — Content other than items, labels and separators renders inside role="menu" without a menu-item role and is skipped by roving focus; the header and footer slots render the same content outside the list with its native keyboard behavior. Content that lr-dropdown forwards into its own menu is not covered: it mirrors sl-dropdown's free-form default slot.
11
11
  - **Optional peers** none
12
12
  - **Themeable via** 3 parts, 7 custom properties — see this component's own `@csspart`/`@cssprop` list below
13
13
  - **Documented with** `lr-menu-item`, `lr-dropdown-item` (same section below)
@@ -63,11 +63,14 @@ is neutral. This is also the composition used for direct `<lr-dropdown-item>` ch
63
63
  Preventing it anywhere keeps the current menu/submenu chain open. There are no
64
64
  `lr-menu-select`, `lr-menu-item-select`, or nested-selection aliases.
65
65
 
66
- **Slots:** default (`<lr-menu-item>`/`<lr-dropdown-item>` plus semantic separators), `header`, and
67
- `footer`. Header and footer are composed controls or explanatory regions outside the
68
- `role="menu"` list, so filters, counts, or footer actions do not violate the menu required-child
69
- contract. Arbitrary non-item content in the default slot still renders, but is not enrolled as a
70
- menu item.
66
+ **Slots:** default (`<lr-menu-item>`/`<lr-dropdown-item>` rows, `<lr-menu-label>` captions, and
67
+ `<hr>`/`<lr-divider>` separators), `header`, and `footer`. Header and footer are composed controls
68
+ or explanatory regions outside the `role="menu"` list, so filters, counts, or footer actions do not
69
+ violate the menu required-child contract. Any other default-slot content is deprecated (removal not
70
+ before 23.0.0): it still renders, but inside `role="menu"` without a menu-item role and skipped by
71
+ keyboard navigation, so move it to `slot="header"` or `slot="footer"`. Content that `lr-dropdown`
72
+ forwards into its own menu is not covered: its default slot mirrors `sl-dropdown`'s free-form
73
+ content.
71
74
 
72
75
  **CSS parts:** `header`, `list`, and `footer`. Root `trigger` and `popup` parts do not exist;
73
76
  style those on `<lr-dropdown>` when using the overlay composition.