@k2b/ui 0.49.0 → 0.51.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 (461) hide show
  1. package/dist/base.css +70 -1
  2. package/dist/browser/actions/Button.js.map +1 -1
  3. package/dist/browser/actions/CommandList.js +861 -0
  4. package/dist/browser/actions/CommandList.js.map +1 -0
  5. package/dist/browser/actions/CommandMenu.js +237 -0
  6. package/dist/browser/actions/CommandMenu.js.map +1 -0
  7. package/dist/browser/actions/ContextMenu.js +3 -0
  8. package/dist/browser/actions/ContextMenu.js.map +1 -1
  9. package/dist/browser/actions/Dropdown.js +43 -10
  10. package/dist/browser/actions/Dropdown.js.map +1 -1
  11. package/dist/browser/actions/command-dock.js +47 -0
  12. package/dist/browser/actions/command-dock.js.map +1 -0
  13. package/dist/browser/actions/command-items.js +84 -0
  14. package/dist/browser/actions/command-items.js.map +1 -0
  15. package/dist/browser/actions/command-messages.js +42 -0
  16. package/dist/browser/actions/command-messages.js.map +1 -0
  17. package/dist/browser/actions/index.js +1 -0
  18. package/dist/browser/actions/index.js.map +1 -1
  19. package/dist/browser/charts/core/area.js +188 -0
  20. package/dist/browser/charts/core/area.js.map +1 -0
  21. package/dist/browser/charts/core/calendar.js +186 -0
  22. package/dist/browser/charts/core/calendar.js.map +1 -0
  23. package/dist/browser/charts/core/chart-map-data.js +9 -0
  24. package/dist/browser/charts/core/chart-map-data.js.map +1 -0
  25. package/dist/browser/charts/core/chart-messages.js +17 -0
  26. package/dist/browser/charts/core/chart-messages.js.map +1 -0
  27. package/dist/browser/charts/core/hbar-layout.js +118 -0
  28. package/dist/browser/charts/core/hbar-layout.js.map +1 -0
  29. package/dist/browser/charts/core/hbar.js +39 -0
  30. package/dist/browser/charts/core/hbar.js.map +1 -0
  31. package/dist/browser/charts/core/index.js +17 -0
  32. package/dist/browser/charts/core/index.js.map +1 -0
  33. package/dist/browser/charts/core/inspection.js +9 -0
  34. package/dist/browser/charts/core/inspection.js.map +1 -0
  35. package/dist/browser/charts/core/map.js +116 -0
  36. package/dist/browser/charts/core/map.js.map +1 -0
  37. package/dist/browser/charts/core/registry.js +35 -0
  38. package/dist/browser/charts/core/registry.js.map +1 -0
  39. package/dist/browser/charts/core/render-size.js +13 -0
  40. package/dist/browser/charts/core/render-size.js.map +1 -0
  41. package/dist/browser/charts/core/render.js +113 -0
  42. package/dist/browser/charts/core/render.js.map +1 -0
  43. package/dist/browser/charts/core/snapshot.js +65 -0
  44. package/dist/browser/charts/core/snapshot.js.map +1 -0
  45. package/dist/browser/charts/core/svg-renderers.js +2406 -0
  46. package/dist/browser/charts/core/svg-renderers.js.map +1 -0
  47. package/dist/browser/charts/core/svg.js +21 -0
  48. package/dist/browser/charts/core/svg.js.map +1 -0
  49. package/dist/browser/charts/core/termination.test-fixture.js +162 -0
  50. package/dist/browser/charts/core/termination.test-fixture.js.map +1 -0
  51. package/dist/browser/charts/core/text.js +13 -0
  52. package/dist/browser/charts/core/text.js.map +1 -0
  53. package/dist/browser/charts/core/types.js +6 -0
  54. package/dist/browser/charts/core/types.js.map +1 -0
  55. package/dist/browser/charts/core/waterfall.js +162 -0
  56. package/dist/browser/charts/core/waterfall.js.map +1 -0
  57. package/dist/browser/charts/description.js +2 -0
  58. package/dist/browser/charts/description.js.map +1 -0
  59. package/dist/browser/charts.js +4 -2
  60. package/dist/browser/charts.js.map +1 -1
  61. package/dist/browser/content/BalanceSummary.js +106 -0
  62. package/dist/browser/content/BalanceSummary.js.map +1 -0
  63. package/dist/browser/content/Chart.js +21 -616
  64. package/dist/browser/content/Chart.js.map +1 -1
  65. package/dist/browser/content/ChartExplorer.js +366 -122
  66. package/dist/browser/content/ChartExplorer.js.map +1 -1
  67. package/dist/browser/content/ChartRoot.js +632 -0
  68. package/dist/browser/content/ChartRoot.js.map +1 -0
  69. package/dist/browser/content/ChartSnapshotView.js +16 -9
  70. package/dist/browser/content/ChartSnapshotView.js.map +1 -1
  71. package/dist/browser/content/ChartSparkline.js +24 -0
  72. package/dist/browser/content/ChartSparkline.js.map +1 -0
  73. package/dist/browser/content/DataTable.js +676 -293
  74. package/dist/browser/content/DataTable.js.map +1 -1
  75. package/dist/browser/content/DataTableTools.js +119 -0
  76. package/dist/browser/content/DataTableTools.js.map +1 -0
  77. package/dist/browser/content/FileView.js +111 -61
  78. package/dist/browser/content/FileView.js.map +1 -1
  79. package/dist/browser/content/FlowAmount.js +82 -0
  80. package/dist/browser/content/FlowAmount.js.map +1 -0
  81. package/dist/browser/content/Lightbox.js +8 -8
  82. package/dist/browser/content/Lightbox.js.map +1 -1
  83. package/dist/browser/content/MapView.js +30 -28
  84. package/dist/browser/content/MapView.js.map +1 -1
  85. package/dist/browser/content/PdfPreview.js +84 -52
  86. package/dist/browser/content/PdfPreview.js.map +1 -1
  87. package/dist/browser/content/PdfViewer.js +588 -0
  88. package/dist/browser/content/PdfViewer.js.map +1 -0
  89. package/dist/browser/content/balance-summary-messages.js +26 -0
  90. package/dist/browser/content/balance-summary-messages.js.map +1 -0
  91. package/dist/browser/content/chart-bar.js +251 -21
  92. package/dist/browser/content/chart-bar.js.map +1 -1
  93. package/dist/browser/content/chart-calendar.js +43 -0
  94. package/dist/browser/content/chart-calendar.js.map +1 -0
  95. package/dist/browser/content/chart-inspection-core.js +178 -50
  96. package/dist/browser/content/chart-inspection-core.js.map +1 -1
  97. package/dist/browser/content/chart-inspection.js.map +1 -1
  98. package/dist/browser/content/chart-line-gaps.js +2 -2
  99. package/dist/browser/content/chart-line-gaps.js.map +1 -1
  100. package/dist/browser/content/chart-map-viewport.js.map +1 -1
  101. package/dist/browser/content/chart-message-catalog.js +174 -0
  102. package/dist/browser/content/chart-message-catalog.js.map +1 -0
  103. package/dist/browser/content/chart-messages.js +2 -138
  104. package/dist/browser/content/chart-messages.js.map +1 -1
  105. package/dist/browser/content/chart-snapshot.js +1 -62
  106. package/dist/browser/content/chart-snapshot.js.map +1 -1
  107. package/dist/browser/content/chart-state-timeline.js +1 -1
  108. package/dist/browser/content/chart-state-timeline.js.map +1 -1
  109. package/dist/browser/content/chart-svg.js +4 -2
  110. package/dist/browser/content/chart-svg.js.map +1 -1
  111. package/dist/browser/content/chart-time-axis.js +139 -0
  112. package/dist/browser/content/chart-time-axis.js.map +1 -0
  113. package/dist/browser/content/data-table-columns.js +160 -0
  114. package/dist/browser/content/data-table-columns.js.map +1 -0
  115. package/dist/browser/content/data-table-messages.js +38 -2
  116. package/dist/browser/content/data-table-messages.js.map +1 -1
  117. package/dist/browser/content/flow-amount-messages.js +26 -0
  118. package/dist/browser/content/flow-amount-messages.js.map +1 -0
  119. package/dist/browser/content/index.js +5 -0
  120. package/dist/browser/content/index.js.map +1 -1
  121. package/dist/browser/content/pdf-document.js +29 -0
  122. package/dist/browser/content/pdf-document.js.map +1 -0
  123. package/dist/browser/content/pdf-limits.js +31 -0
  124. package/dist/browser/content/pdf-limits.js.map +1 -0
  125. package/dist/browser/content/pdf-messages.js +34 -2
  126. package/dist/browser/content/pdf-messages.js.map +1 -1
  127. package/dist/browser/content/pdf-viewer-engine.js +57 -0
  128. package/dist/browser/content/pdf-viewer-worker.js +28 -0
  129. package/dist/browser/inputs/ChoiceInputs.js +94 -51
  130. package/dist/browser/inputs/ChoiceInputs.js.map +1 -1
  131. package/dist/browser/inputs/ChoiceSlider.js +75 -58
  132. package/dist/browser/inputs/ChoiceSlider.js.map +1 -1
  133. package/dist/browser/inputs/DatePicker.js +118 -102
  134. package/dist/browser/inputs/DatePicker.js.map +1 -1
  135. package/dist/browser/inputs/PeriodPicker.js +874 -0
  136. package/dist/browser/inputs/PeriodPicker.js.map +1 -0
  137. package/dist/browser/inputs/SelectChip.js +50 -17
  138. package/dist/browser/inputs/SelectChip.js.map +1 -1
  139. package/dist/browser/inputs/date-picker.js +13 -0
  140. package/dist/browser/inputs/date-picker.js.map +1 -1
  141. package/dist/browser/inputs/index.js +4 -1
  142. package/dist/browser/inputs/index.js.map +1 -1
  143. package/dist/browser/inputs/input-messages.js +8 -2
  144. package/dist/browser/inputs/input-messages.js.map +1 -1
  145. package/dist/browser/inputs/markdown/MarkdownEditor.js +14 -10
  146. package/dist/browser/inputs/markdown/MarkdownEditor.js.map +1 -1
  147. package/dist/browser/inputs/markdown/SlashCommands.js +402 -0
  148. package/dist/browser/inputs/markdown/SlashCommands.js.map +1 -0
  149. package/dist/browser/inputs/period-picker-messages.js +71 -0
  150. package/dist/browser/inputs/period-picker-messages.js.map +1 -0
  151. package/dist/browser/inputs/period.js +263 -0
  152. package/dist/browser/inputs/period.js.map +1 -0
  153. package/dist/browser/intl/Format.js +31 -8
  154. package/dist/browser/intl/Format.js.map +1 -1
  155. package/dist/browser/layout/AppWorkspace.js +7 -1
  156. package/dist/browser/layout/AppWorkspace.js.map +1 -1
  157. package/dist/browser/layout/DetailPanel.js +147 -120
  158. package/dist/browser/layout/DetailPanel.js.map +1 -1
  159. package/dist/browser/layout/Discussion.js +101 -108
  160. package/dist/browser/layout/Discussion.js.map +1 -1
  161. package/dist/browser/layout/index.js.map +1 -1
  162. package/dist/browser/surfaces/BudgetList.js +281 -0
  163. package/dist/browser/surfaces/BudgetList.js.map +1 -0
  164. package/dist/browser/surfaces/DescriptionList.js +5 -2
  165. package/dist/browser/surfaces/DescriptionList.js.map +1 -1
  166. package/dist/browser/surfaces/ProgressBar.js +134 -21
  167. package/dist/browser/surfaces/ProgressBar.js.map +1 -1
  168. package/dist/browser/surfaces/StatCell.js +327 -146
  169. package/dist/browser/surfaces/StatCell.js.map +1 -1
  170. package/dist/browser/surfaces/StatGrid.js +75 -57
  171. package/dist/browser/surfaces/StatGrid.js.map +1 -1
  172. package/dist/browser/surfaces/budget-messages.js +64 -0
  173. package/dist/browser/surfaces/budget-messages.js.map +1 -0
  174. package/dist/browser/surfaces/delta-badge.js +79 -0
  175. package/dist/browser/surfaces/delta-badge.js.map +1 -0
  176. package/dist/browser/surfaces/index.js +2 -1
  177. package/dist/browser/surfaces/index.js.map +1 -1
  178. package/dist/browser/surfaces/person-color.js +2 -2
  179. package/dist/browser/surfaces/person-color.js.map +1 -1
  180. package/dist/browser/surfaces/stat-cell-messages.js +41 -0
  181. package/dist/browser/surfaces/stat-cell-messages.js.map +1 -0
  182. package/dist/browser/widgets/Dashboard.js +137 -0
  183. package/dist/browser/widgets/Dashboard.js.map +1 -0
  184. package/dist/browser/widgets/DashboardFrame.js +310 -0
  185. package/dist/browser/widgets/DashboardFrame.js.map +1 -0
  186. package/dist/browser/widgets/index.js +2 -0
  187. package/dist/browser/widgets/index.js.map +1 -1
  188. package/dist/licenses/pdfjs-dist.txt +177 -0
  189. package/dist/ssr/actions/Button.js.map +1 -1
  190. package/dist/ssr/actions/CommandList.js +638 -0
  191. package/dist/ssr/actions/CommandList.js.map +1 -0
  192. package/dist/ssr/actions/CommandMenu.js +197 -0
  193. package/dist/ssr/actions/CommandMenu.js.map +1 -0
  194. package/dist/ssr/actions/ContextMenu.js +3 -0
  195. package/dist/ssr/actions/ContextMenu.js.map +1 -1
  196. package/dist/ssr/actions/Dropdown.js +43 -10
  197. package/dist/ssr/actions/Dropdown.js.map +1 -1
  198. package/dist/ssr/actions/command-dock.js +47 -0
  199. package/dist/ssr/actions/command-dock.js.map +1 -0
  200. package/dist/ssr/actions/command-items.js +84 -0
  201. package/dist/ssr/actions/command-items.js.map +1 -0
  202. package/dist/ssr/actions/command-messages.js +42 -0
  203. package/dist/ssr/actions/command-messages.js.map +1 -0
  204. package/dist/ssr/actions/index.js +1 -0
  205. package/dist/ssr/actions/index.js.map +1 -1
  206. package/dist/ssr/charts/core/area.js +188 -0
  207. package/dist/ssr/charts/core/area.js.map +1 -0
  208. package/dist/ssr/charts/core/calendar.js +186 -0
  209. package/dist/ssr/charts/core/calendar.js.map +1 -0
  210. package/dist/ssr/charts/core/chart-map-data.js +9 -0
  211. package/dist/ssr/charts/core/chart-map-data.js.map +1 -0
  212. package/dist/ssr/charts/core/chart-messages.js +17 -0
  213. package/dist/ssr/charts/core/chart-messages.js.map +1 -0
  214. package/dist/ssr/charts/core/hbar-layout.js +118 -0
  215. package/dist/ssr/charts/core/hbar-layout.js.map +1 -0
  216. package/dist/ssr/charts/core/hbar.js +39 -0
  217. package/dist/ssr/charts/core/hbar.js.map +1 -0
  218. package/dist/ssr/charts/core/index.js +17 -0
  219. package/dist/ssr/charts/core/index.js.map +1 -0
  220. package/dist/ssr/charts/core/inspection.js +9 -0
  221. package/dist/ssr/charts/core/inspection.js.map +1 -0
  222. package/dist/ssr/charts/core/map.js +116 -0
  223. package/dist/ssr/charts/core/map.js.map +1 -0
  224. package/dist/ssr/charts/core/registry.js +35 -0
  225. package/dist/ssr/charts/core/registry.js.map +1 -0
  226. package/dist/ssr/charts/core/render-size.js +13 -0
  227. package/dist/ssr/charts/core/render-size.js.map +1 -0
  228. package/dist/ssr/charts/core/render.js +113 -0
  229. package/dist/ssr/charts/core/render.js.map +1 -0
  230. package/dist/ssr/charts/core/snapshot.js +65 -0
  231. package/dist/ssr/charts/core/snapshot.js.map +1 -0
  232. package/dist/ssr/charts/core/svg-renderers.js +2406 -0
  233. package/dist/ssr/charts/core/svg-renderers.js.map +1 -0
  234. package/dist/ssr/charts/core/svg.js +21 -0
  235. package/dist/ssr/charts/core/svg.js.map +1 -0
  236. package/dist/ssr/charts/core/termination.test-fixture.js +162 -0
  237. package/dist/ssr/charts/core/termination.test-fixture.js.map +1 -0
  238. package/dist/ssr/charts/core/text.js +13 -0
  239. package/dist/ssr/charts/core/text.js.map +1 -0
  240. package/dist/ssr/charts/core/types.js +6 -0
  241. package/dist/ssr/charts/core/types.js.map +1 -0
  242. package/dist/ssr/charts/core/waterfall.js +162 -0
  243. package/dist/ssr/charts/core/waterfall.js.map +1 -0
  244. package/dist/ssr/charts/description.js +2 -0
  245. package/dist/ssr/charts/description.js.map +1 -0
  246. package/dist/ssr/charts.js +4 -2
  247. package/dist/ssr/charts.js.map +1 -1
  248. package/dist/ssr/content/BalanceSummary.js +75 -0
  249. package/dist/ssr/content/BalanceSummary.js.map +1 -0
  250. package/dist/ssr/content/Chart.js +21 -483
  251. package/dist/ssr/content/Chart.js.map +1 -1
  252. package/dist/ssr/content/ChartExplorer.js +190 -46
  253. package/dist/ssr/content/ChartExplorer.js.map +1 -1
  254. package/dist/ssr/content/ChartRoot.js +475 -0
  255. package/dist/ssr/content/ChartRoot.js.map +1 -0
  256. package/dist/ssr/content/ChartSnapshotView.js +5 -1
  257. package/dist/ssr/content/ChartSnapshotView.js.map +1 -1
  258. package/dist/ssr/content/ChartSparkline.js +24 -0
  259. package/dist/ssr/content/ChartSparkline.js.map +1 -0
  260. package/dist/ssr/content/DataTable.js +287 -78
  261. package/dist/ssr/content/DataTable.js.map +1 -1
  262. package/dist/ssr/content/DataTableTools.js +106 -0
  263. package/dist/ssr/content/DataTableTools.js.map +1 -0
  264. package/dist/ssr/content/FileView.js +56 -7
  265. package/dist/ssr/content/FileView.js.map +1 -1
  266. package/dist/ssr/content/FlowAmount.js +58 -0
  267. package/dist/ssr/content/FlowAmount.js.map +1 -0
  268. package/dist/ssr/content/Lightbox.js +8 -8
  269. package/dist/ssr/content/Lightbox.js.map +1 -1
  270. package/dist/ssr/content/MapView.js +9 -9
  271. package/dist/ssr/content/MapView.js.map +1 -1
  272. package/dist/ssr/content/PdfPreview.js +49 -20
  273. package/dist/ssr/content/PdfPreview.js.map +1 -1
  274. package/dist/ssr/content/PdfViewer.js +484 -0
  275. package/dist/ssr/content/PdfViewer.js.map +1 -0
  276. package/dist/ssr/content/balance-summary-messages.js +26 -0
  277. package/dist/ssr/content/balance-summary-messages.js.map +1 -0
  278. package/dist/ssr/content/chart-bar.js +251 -21
  279. package/dist/ssr/content/chart-bar.js.map +1 -1
  280. package/dist/ssr/content/chart-calendar.js +43 -0
  281. package/dist/ssr/content/chart-calendar.js.map +1 -0
  282. package/dist/ssr/content/chart-inspection-core.js +178 -50
  283. package/dist/ssr/content/chart-inspection-core.js.map +1 -1
  284. package/dist/ssr/content/chart-inspection.js.map +1 -1
  285. package/dist/ssr/content/chart-line-gaps.js +2 -2
  286. package/dist/ssr/content/chart-line-gaps.js.map +1 -1
  287. package/dist/ssr/content/chart-map-viewport.js.map +1 -1
  288. package/dist/ssr/content/chart-message-catalog.js +174 -0
  289. package/dist/ssr/content/chart-message-catalog.js.map +1 -0
  290. package/dist/ssr/content/chart-messages.js +2 -138
  291. package/dist/ssr/content/chart-messages.js.map +1 -1
  292. package/dist/ssr/content/chart-snapshot.js +1 -62
  293. package/dist/ssr/content/chart-snapshot.js.map +1 -1
  294. package/dist/ssr/content/chart-state-timeline.js +1 -1
  295. package/dist/ssr/content/chart-state-timeline.js.map +1 -1
  296. package/dist/ssr/content/chart-svg.js +4 -2
  297. package/dist/ssr/content/chart-svg.js.map +1 -1
  298. package/dist/ssr/content/chart-time-axis.js +139 -0
  299. package/dist/ssr/content/chart-time-axis.js.map +1 -0
  300. package/dist/ssr/content/data-table-columns.js +160 -0
  301. package/dist/ssr/content/data-table-columns.js.map +1 -0
  302. package/dist/ssr/content/data-table-messages.js +38 -2
  303. package/dist/ssr/content/data-table-messages.js.map +1 -1
  304. package/dist/ssr/content/flow-amount-messages.js +26 -0
  305. package/dist/ssr/content/flow-amount-messages.js.map +1 -0
  306. package/dist/ssr/content/index.js +5 -0
  307. package/dist/ssr/content/index.js.map +1 -1
  308. package/dist/ssr/content/pdf-document.js +29 -0
  309. package/dist/ssr/content/pdf-document.js.map +1 -0
  310. package/dist/ssr/content/pdf-limits.js +31 -0
  311. package/dist/ssr/content/pdf-limits.js.map +1 -0
  312. package/dist/ssr/content/pdf-messages.js +34 -2
  313. package/dist/ssr/content/pdf-messages.js.map +1 -1
  314. package/dist/ssr/inputs/ChoiceInputs.js +49 -12
  315. package/dist/ssr/inputs/ChoiceInputs.js.map +1 -1
  316. package/dist/ssr/inputs/ChoiceSlider.js +17 -12
  317. package/dist/ssr/inputs/ChoiceSlider.js.map +1 -1
  318. package/dist/ssr/inputs/DatePicker.js +19 -13
  319. package/dist/ssr/inputs/DatePicker.js.map +1 -1
  320. package/dist/ssr/inputs/PeriodPicker.js +598 -0
  321. package/dist/ssr/inputs/PeriodPicker.js.map +1 -0
  322. package/dist/ssr/inputs/SelectChip.js +26 -9
  323. package/dist/ssr/inputs/SelectChip.js.map +1 -1
  324. package/dist/ssr/inputs/date-picker.js +13 -0
  325. package/dist/ssr/inputs/date-picker.js.map +1 -1
  326. package/dist/ssr/inputs/index.js +4 -1
  327. package/dist/ssr/inputs/index.js.map +1 -1
  328. package/dist/ssr/inputs/input-messages.js +8 -2
  329. package/dist/ssr/inputs/input-messages.js.map +1 -1
  330. package/dist/ssr/inputs/markdown/MarkdownEditor.js +3 -2
  331. package/dist/ssr/inputs/markdown/MarkdownEditor.js.map +1 -1
  332. package/dist/ssr/inputs/markdown/SlashCommands.js +339 -0
  333. package/dist/ssr/inputs/markdown/SlashCommands.js.map +1 -0
  334. package/dist/ssr/inputs/period-picker-messages.js +71 -0
  335. package/dist/ssr/inputs/period-picker-messages.js.map +1 -0
  336. package/dist/ssr/inputs/period.js +263 -0
  337. package/dist/ssr/inputs/period.js.map +1 -0
  338. package/dist/ssr/intl/Format.js +22 -2
  339. package/dist/ssr/intl/Format.js.map +1 -1
  340. package/dist/ssr/layout/AppWorkspace.js +7 -1
  341. package/dist/ssr/layout/AppWorkspace.js.map +1 -1
  342. package/dist/ssr/layout/DetailPanel.js +27 -4
  343. package/dist/ssr/layout/DetailPanel.js.map +1 -1
  344. package/dist/ssr/layout/Discussion.js +16 -2
  345. package/dist/ssr/layout/Discussion.js.map +1 -1
  346. package/dist/ssr/layout/index.js.map +1 -1
  347. package/dist/ssr/surfaces/BudgetList.js +170 -0
  348. package/dist/ssr/surfaces/BudgetList.js.map +1 -0
  349. package/dist/ssr/surfaces/DescriptionList.js +1 -1
  350. package/dist/ssr/surfaces/DescriptionList.js.map +1 -1
  351. package/dist/ssr/surfaces/ProgressBar.js +96 -5
  352. package/dist/ssr/surfaces/ProgressBar.js.map +1 -1
  353. package/dist/ssr/surfaces/StatCell.js +157 -52
  354. package/dist/ssr/surfaces/StatCell.js.map +1 -1
  355. package/dist/ssr/surfaces/StatGrid.js +24 -35
  356. package/dist/ssr/surfaces/StatGrid.js.map +1 -1
  357. package/dist/ssr/surfaces/budget-messages.js +64 -0
  358. package/dist/ssr/surfaces/budget-messages.js.map +1 -0
  359. package/dist/ssr/surfaces/delta-badge.js +55 -0
  360. package/dist/ssr/surfaces/delta-badge.js.map +1 -0
  361. package/dist/ssr/surfaces/index.js +2 -1
  362. package/dist/ssr/surfaces/index.js.map +1 -1
  363. package/dist/ssr/surfaces/person-color.js +2 -2
  364. package/dist/ssr/surfaces/person-color.js.map +1 -1
  365. package/dist/ssr/surfaces/stat-cell-messages.js +41 -0
  366. package/dist/ssr/surfaces/stat-cell-messages.js.map +1 -0
  367. package/dist/ssr/widgets/Dashboard.js +84 -0
  368. package/dist/ssr/widgets/Dashboard.js.map +1 -0
  369. package/dist/ssr/widgets/DashboardFrame.js +200 -0
  370. package/dist/ssr/widgets/DashboardFrame.js.map +1 -0
  371. package/dist/ssr/widgets/index.js +2 -0
  372. package/dist/ssr/widgets/index.js.map +1 -1
  373. package/dist/styles.css +1 -1
  374. package/dist/types/actions/Button.d.ts +1 -1
  375. package/dist/types/actions/CommandList.d.ts +120 -0
  376. package/dist/types/actions/CommandMenu.d.ts +39 -0
  377. package/dist/types/actions/Dropdown.d.ts +17 -0
  378. package/dist/types/actions/command-dock.d.ts +8 -0
  379. package/dist/types/actions/command-items.d.ts +134 -0
  380. package/dist/types/actions/command-messages.d.ts +19 -0
  381. package/dist/types/actions/index.d.ts +3 -0
  382. package/dist/types/charts/core/area.d.ts +62 -0
  383. package/dist/types/charts/core/calendar.d.ts +57 -0
  384. package/dist/types/charts/core/chart-map-data.d.ts +3 -0
  385. package/dist/types/charts/core/chart-messages.d.ts +5 -0
  386. package/dist/types/charts/core/hbar-layout.d.ts +74 -0
  387. package/dist/types/charts/core/hbar.d.ts +13 -0
  388. package/dist/types/charts/core/index.d.ts +16 -0
  389. package/dist/types/charts/core/inspection.d.ts +16 -0
  390. package/dist/types/charts/core/map.d.ts +3 -0
  391. package/dist/types/charts/core/registry.d.ts +33 -0
  392. package/dist/types/charts/core/render-size.d.ts +7 -0
  393. package/dist/types/charts/core/render.d.ts +37 -0
  394. package/dist/types/charts/core/snapshot.d.ts +27 -0
  395. package/dist/types/charts/core/svg-renderers.d.ts +722 -0
  396. package/dist/types/charts/core/svg.d.ts +20 -0
  397. package/dist/types/charts/core/termination.test-fixture.d.ts +1 -0
  398. package/dist/types/charts/core/text.d.ts +5 -0
  399. package/dist/types/charts/core/types.d.ts +20 -0
  400. package/dist/types/charts/core/waterfall.d.ts +68 -0
  401. package/dist/types/charts/description.d.ts +226 -0
  402. package/dist/types/charts.d.ts +5 -2
  403. package/dist/types/content/BalanceSummary.d.ts +29 -0
  404. package/dist/types/content/Chart.d.ts +19 -117
  405. package/dist/types/content/ChartExplorer.d.ts +43 -2
  406. package/dist/types/content/ChartRoot.d.ts +92 -0
  407. package/dist/types/content/ChartSnapshotView.d.ts +1 -0
  408. package/dist/types/content/ChartSparkline.d.ts +5 -0
  409. package/dist/types/content/DataTable.d.ts +28 -0
  410. package/dist/types/content/DataTableTools.d.ts +44 -0
  411. package/dist/types/content/FlowAmount.d.ts +28 -0
  412. package/dist/types/content/PdfViewer.d.ts +32 -0
  413. package/dist/types/content/balance-summary-messages.d.ts +11 -0
  414. package/dist/types/content/chart-bar.d.ts +95 -2
  415. package/dist/types/content/chart-calendar.d.ts +4 -0
  416. package/dist/types/content/chart-inspection-core.d.ts +21 -16
  417. package/dist/types/content/chart-inspection.d.ts +5 -1
  418. package/dist/types/content/chart-map-viewport.d.ts +1 -1
  419. package/dist/types/content/chart-message-catalog.d.ts +84 -0
  420. package/dist/types/content/chart-messages.d.ts +2 -33
  421. package/dist/types/content/chart-snapshot.d.ts +1 -26
  422. package/dist/types/content/chart-svg.d.ts +1 -1
  423. package/dist/types/content/chart-time-axis.d.ts +26 -0
  424. package/dist/types/content/data-table-columns.d.ts +72 -0
  425. package/dist/types/content/data-table-messages.d.ts +18 -0
  426. package/dist/types/content/flow-amount-messages.d.ts +11 -0
  427. package/dist/types/content/index.d.ts +12 -2
  428. package/dist/types/content/pdf-document.d.ts +5 -0
  429. package/dist/types/content/pdf-engine.d.ts +9 -0
  430. package/dist/types/content/pdf-limits.d.ts +43 -0
  431. package/dist/types/content/pdf-messages.d.ts +16 -0
  432. package/dist/types/inputs/ChoiceInputs.d.ts +4 -0
  433. package/dist/types/inputs/ChoiceSlider.d.ts +12 -0
  434. package/dist/types/inputs/DatePicker.d.ts +22 -0
  435. package/dist/types/inputs/PeriodPicker.d.ts +24 -0
  436. package/dist/types/inputs/SelectChip.d.ts +2 -0
  437. package/dist/types/inputs/date-picker.d.ts +6 -0
  438. package/dist/types/inputs/index.d.ts +8 -2
  439. package/dist/types/inputs/input-messages.d.ts +3 -0
  440. package/dist/types/inputs/markdown/MarkdownEditor.d.ts +5 -0
  441. package/dist/types/inputs/markdown/SlashCommands.d.ts +20 -0
  442. package/dist/types/inputs/period-picker-messages.d.ts +34 -0
  443. package/dist/types/inputs/period.d.ts +134 -0
  444. package/dist/types/intl/Format.d.ts +5 -0
  445. package/dist/types/layout/AppWorkspace.d.ts +5 -0
  446. package/dist/types/layout/DetailPanel.d.ts +12 -0
  447. package/dist/types/layout/index.d.ts +1 -1
  448. package/dist/types/surfaces/BudgetList.d.ts +42 -0
  449. package/dist/types/surfaces/DescriptionList.d.ts +5 -0
  450. package/dist/types/surfaces/ProgressBar.d.ts +38 -2
  451. package/dist/types/surfaces/StatCell.d.ts +40 -2
  452. package/dist/types/surfaces/StatGrid.d.ts +3 -1
  453. package/dist/types/surfaces/budget-messages.d.ts +30 -0
  454. package/dist/types/surfaces/delta-badge.d.ts +10 -0
  455. package/dist/types/surfaces/index.d.ts +4 -3
  456. package/dist/types/surfaces/person-color.d.ts +2 -2
  457. package/dist/types/surfaces/stat-cell-messages.d.ts +19 -0
  458. package/dist/types/widgets/Dashboard.d.ts +42 -0
  459. package/dist/types/widgets/DashboardFrame.d.ts +58 -0
  460. package/dist/types/widgets/index.d.ts +2 -0
  461. package/package.json +8 -1
@@ -0,0 +1 @@
1
+ {"version":3,"names":[],"sources":["actions/CommandList.tsx"],"sourcesContent":["import { type Accessor, createEffect, createMemo, createSignal, For, type JSX, onCleanup, Show, untrack } from \"solid-js\";\nimport { useUiMessages } from \"../intl/messages\";\nimport {\n type CommandContext,\n type CommandGroup,\n type CommandItem,\n type CommandSource,\n commandKey,\n filterCommandItems,\n groupCommandItems,\n} from \"./command-items\";\nimport { useCommandMessages } from \"./command-messages\";\n\n/** The state of one open command list: its steps, the shown entries, and the marked one. */\nexport type CommandNavigator = ReturnType<typeof createCommandNavigator>;\n\n/** The context without what the list adds itself: the query, the path, the signal, and the reports. */\nexport type CommandPlace = Omit<CommandContext, \"query\" | \"path\" | \"signal\" | \"success\" | \"error\">;\n\n/** A list whose entries come from a promise: pending, or failed with the message of its rejection. */\nexport type CommandListLoad = { state: \"ready\" } | { state: \"loading\" } | { state: \"failed\"; message?: string };\n\n/** A command that returned a promise, busy while it runs. */\nexport type CommandStatus = { key: string; label: string; state: \"running\" };\n\n/**\n * What a finished command reported, shown in the list's place: a confirmation, an error (with a way to try again when\n * the command threw or rejected), or the command running again after a retry.\n */\nexport type CommandOutcome =\n | { state: \"success\"; message: string }\n | { state: \"error\"; message?: string; retry?: () => void }\n | { state: \"running\"; message: string };\n\n/** A confirmation or an error stays at least this long, even when the person types on at once. */\nexport const COMMAND_OUTCOME_MIN_MS = 1200;\n/** A confirmation goes by itself after this long; an error stays until the person types, retries, or presses Escape. */\nexport const COMMAND_OUTCOME_SUCCESS_MS = 4000;\n\nconst ignoreReport = () => {};\n\n/**\n * Keeps the steps, the marked entry, and the running command of a command list. The host owns the query and the\n * effects: `onText` places an entry's text; for an entry with `onSelect`, `beforeRun` lets the host remove its query,\n * `context` describes the text the command acts on, and `afterRun` closes the list once the command finished.\n * `onStep` runs after a further list opened or closed, with the new depth, so the host clears its query.\n */\nexport const createCommandNavigator = (options: {\n items: Accessor<CommandSource>;\n query: Accessor<string>;\n onText: (item: CommandItem) => void;\n /** The part of the context the host knows: the text and where the list is in it. */\n context: () => CommandPlace;\n /** Whether the list is open; a closed list asks no source. */\n active: () => boolean;\n beforeRun?: () => void;\n /** Runs once a command finished, before its outcome shows; `outcome` tells the host to keep its place for it. */\n afterRun: (outcome: boolean) => void;\n onStep?: (depth: number) => void;\n}) => {\n const [status, setStatus] = createSignal<CommandStatus>();\n const [outcome, setOutcome] = createSignal<CommandOutcome>();\n let shownAt = 0;\n let outcomeTimer: ReturnType<typeof setTimeout> | undefined;\n const clearOutcome = () => {\n clearTimeout(outcomeTimer);\n outcomeTimer = undefined;\n setOutcome(undefined);\n };\n const showOutcome = (next: CommandOutcome) => {\n clearTimeout(outcomeTimer);\n outcomeTimer = undefined;\n setOutcome(next);\n shownAt = Date.now();\n if (next.state === \"success\") outcomeTimer = setTimeout(clearOutcome, COMMAND_OUTCOME_SUCCESS_MS);\n };\n let running: AbortController | undefined;\n // A list that goes away forgets its run, as `reset` does: a late result reports nothing and starts no timer.\n onCleanup(() => {\n clearTimeout(outcomeTimer);\n running = undefined;\n });\n const run = (item: CommandItem, path: readonly CommandItem[], again = false) => {\n const controller = new AbortController();\n running = controller;\n const key = commandKey(item);\n setStatus(undefined);\n if (!again) options.beforeRun?.();\n // What the command reported before it finished; a stopped command's report never shows.\n let report: CommandOutcome | undefined;\n const reporting = () => running === controller && !controller.signal.aborted;\n const settle = (failure?: { error: unknown }) => {\n if (!reporting()) return;\n running = undefined;\n setStatus(undefined);\n const next: CommandOutcome | undefined = failure\n ? {\n state: \"error\",\n message: failure.error instanceof Error && failure.error.message ? failure.error.message : undefined,\n retry: () => runAgain(item, path),\n }\n : report;\n // The outcome takes its place before the host closes the list, so the container and its live regions stay and\n // their text changes, which is what a screen reader announces.\n if (next) showOutcome(next);\n else clearOutcome();\n options.afterRun(next !== undefined);\n };\n let result: unknown;\n try {\n const base = options.context();\n result = item.onSelect?.({\n ...base,\n // A command the person stopped writes nothing more.\n insert: (text: string) => {\n if (!controller.signal.aborted) base.insert(text);\n },\n success: (message: string) => {\n report = { state: \"success\", message };\n },\n error: (message: string) => {\n report = { state: \"error\", message };\n },\n query: options.query(),\n path,\n signal: controller.signal,\n });\n } catch (error) {\n settle({ error });\n return;\n }\n if (!(result instanceof Promise)) return settle();\n // A first run shows on its row; a retry runs where its error was.\n if (again) showOutcome({ state: \"running\", message: item.label });\n else setStatus({ key, label: item.label, state: \"running\" });\n result.then(\n () => settle(),\n (error: unknown) => settle({ error }),\n );\n };\n // The error stays until the retry's own state replaces it, so a host never sees the outcome go in between.\n const runAgain = (item: CommandItem, path: readonly CommandItem[]) => run(item, path, true);\n const [steps, setSteps] = createSignal<readonly CommandItem[]>([]);\n const step = () => steps().at(-1);\n // A source that returns a promise: each request has a token, and only the latest one's result reaches the list. A new\n // request aborts the previous one's signal, so stale results are discarded where they are made.\n const [retries, setRetries] = createSignal(0);\n const [settled, setSettled] = createSignal<{ token: object; items?: readonly CommandItem[]; error?: unknown }>();\n let pending: AbortController | undefined;\n type Request = { items?: readonly CommandItem[]; error?: unknown; token?: object };\n // Where the list is, compared by value: only a new place, query, or path asks a source again, not every selection event.\n const place = createMemo(() => options.context(), undefined, {\n equals: (a, b) =>\n a.text === b.text &&\n a.before === b.before &&\n a.atStart === b.atStart &&\n a.lineStart === b.lineStart &&\n a.selection.start === b.selection.start &&\n a.selection.end === b.selection.end,\n });\n const request = createMemo<Request>(() => {\n retries();\n pending?.abort();\n pending = undefined;\n if (!options.active()) return { items: [] };\n const source = step()?.next?.items ?? options.items();\n if (typeof source !== \"function\") return { items: filterCommandItems(source, options.query()) };\n const controller = new AbortController();\n const context: CommandContext = {\n ...place(),\n query: options.query(),\n path: steps(),\n signal: controller.signal,\n success: ignoreReport,\n error: ignoreReport,\n };\n let result: readonly CommandItem[] | Promise<readonly CommandItem[]>;\n try {\n result = untrack(() => source(context));\n } catch (error) {\n return { error };\n }\n if (!(result instanceof Promise)) return { items: filterCommandItems(result, context.query) };\n pending = controller;\n const token = {};\n result.then(\n (items) => {\n if (pending === controller) setSettled({ token, items: filterCommandItems(items, context.query) });\n },\n (error: unknown) => {\n if (pending === controller && !controller.signal.aborted) setSettled({ token, error });\n },\n );\n return { token };\n });\n /** Pending, failed, or ready; while a new query loads, the step's previous entries stay in place. */\n const load = createMemo<CommandListLoad>(() => {\n const current = request();\n const result = current.token ? (settled()?.token === current.token ? settled() : undefined) : current;\n if (!result) return { state: \"loading\" };\n if (result.error !== undefined) {\n const message = result.error instanceof Error && result.error.message ? result.error.message : undefined;\n return { state: \"failed\", message };\n }\n return { state: \"ready\" };\n });\n // Only entries of the same step stay while a query loads: a further list never shows the list it came from.\n const shown = createMemo<{ step: CommandItem | undefined; items: readonly CommandItem[] }>(\n (previous) => {\n const current = request();\n const at = step();\n if (!current.token) return { step: at, items: current.items ?? [] };\n const result = settled();\n if (result?.token === current.token) return { step: at, items: result.items ?? [] };\n return { step: at, items: previous.step === at ? previous.items : [] };\n },\n { step: undefined, items: [] },\n );\n const entries = () => shown().items;\n const groups = createMemo<CommandGroup[]>(() => groupCommandItems(entries()));\n const ordered = createMemo(() => groups().flatMap((group) => group.entries.map((entry) => entry.item)));\n // The marked entry is remembered for the query and step it was marked in; a new query marks the first entry again.\n const [wanted, setWanted] = createSignal<{ key: string; query: string; step: CommandItem | undefined }>();\n const active = createMemo(() => {\n const list = ordered();\n const mark = wanted();\n if (mark && mark.query === options.query() && mark.step === step()) {\n const index = list.findIndex((item) => commandKey(item) === mark.key);\n if (index >= 0) return index;\n }\n const enabled = list.findIndex((item) => !item.disabled);\n return enabled >= 0 ? enabled : 0;\n });\n const setActive = (index: number) => {\n const list = ordered();\n const item = list[(index + list.length) % Math.max(1, list.length)];\n if (item && !item.disabled) setWanted({ key: commandKey(item), query: options.query(), step: step() });\n };\n /** The next entry that can be chosen from `from` in `direction`, wrapping; unavailable entries are passed over. */\n const nextEnabled = (from: number, direction: 1 | -1) => {\n const list = ordered();\n for (let step = 1; step <= list.length; step++) {\n const index = (((from + direction * step) % list.length) + list.length) % list.length;\n if (!list[index]?.disabled) return index;\n }\n return from;\n };\n /** Chooses the marked entry or the one at `index`. An unavailable entry, or any while a command runs, does nothing. */\n const choose = (index = active()) => {\n const item = ordered()[index];\n if (!item || item.disabled || status()?.state === \"running\") return;\n if (item.next) changeStep([...steps(), item]);\n else if (item.text !== undefined) options.onText(item);\n else run(item, steps());\n };\n const changeStep = (next: readonly CommandItem[]) => {\n setSteps(next);\n setWanted(undefined);\n options.onStep?.(next.length);\n };\n // Enter while entries load waits for that query's entries and takes the first that can be chosen; a new query or no\n // match chooses nothing.\n const [awaiting, setAwaiting] = createSignal<string>();\n createEffect(() => {\n const query = awaiting();\n if (query === undefined) return;\n if (query !== options.query()) return setAwaiting(undefined);\n const state = load().state;\n if (state === \"loading\") return;\n setAwaiting(undefined);\n if (state !== \"ready\") return;\n const index = ordered().findIndex((item) => !item.disabled);\n if (index >= 0) untrack(() => choose(index));\n });\n\n return {\n query: options.query,\n step,\n groups,\n entries: ordered,\n active,\n setActive,\n /** Marks the next or previous entry, wrapping; unavailable entries are passed over, as in a searchable menu. */\n move: (delta: 1 | -1) => setActive(nextEnabled(active(), delta)),\n edge: (which: \"first\" | \"last\") => setActive(which === \"first\" ? nextEnabled(-1, 1) : nextEnabled(ordered().length, -1)),\n status,\n load,\n /** Asks a source whose promise failed again. */\n retry: () => setRetries((value) => value + 1),\n /** Whether a command's promise is pending; the list then waits for it. */\n busy: () => status()?.state === \"running\",\n choose: (index?: number) => choose(index),\n /** Enter while entries load: chooses the first entry of this query once it arrives. */\n chooseWhenLoaded: () => setAwaiting(options.query()),\n /** Whether a choice waits for entries on their way. */\n awaitingChoice: () => awaiting() !== undefined,\n /** Stops a running command: its signal aborts, and its result no longer reaches the list. */\n abort: () => {\n running?.abort();\n running = undefined;\n setStatus(undefined);\n if (outcome()?.state === \"running\") clearOutcome();\n },\n /** What the last command reported, shown in the list's place until it clears. */\n outcome,\n /** The person typed on: the outcome clears, but not before it showed for `COMMAND_OUTCOME_MIN_MS`. */\n typedOn: () => {\n const current = outcome();\n if (!current || current.state === \"running\") return;\n const left = COMMAND_OUTCOME_MIN_MS - (Date.now() - shownAt);\n if (left <= 0) return clearOutcome();\n clearTimeout(outcomeTimer);\n outcomeTimer = setTimeout(clearOutcome, left);\n },\n /** Clears the outcome at once, for Escape or a new list; a retry still running is stopped. */\n clearOutcome: () => {\n if (outcome()?.state === \"running\") {\n running?.abort();\n running = undefined;\n }\n clearOutcome();\n },\n /** Leaves the second list; `false` when the first list shows. */\n back: () => {\n if (steps().length === 0) return false;\n changeStep(steps().slice(0, -1));\n return true;\n },\n /**\n * Forgets steps, mark, and status. A running command goes on, but its result no longer reaches the list, so a\n * retry's running line goes too; a reported outcome stays until it clears.\n */\n reset: () => {\n if (outcome()?.state === \"running\") clearOutcome();\n running = undefined;\n pending?.abort();\n pending = undefined;\n setSteps([]);\n setWanted(undefined);\n setStatus(undefined);\n },\n };\n};\n\nexport const commandOptionId = (listId: string, index: number) => `${listId}-${index}`;\n\n/**\n * The rows of a command list as a list box, with the menu's own rows and headings. The focus stays in the host's\n * field, which points at the marked row as its active descendant; the rows only answer the pointer.\n */\nexport function CommandList(props: {\n navigator: CommandNavigator;\n id: string;\n /** Names the first list; a second list is named by its step. */\n label: string;\n /** Shows the step's label beside the back control, for a host without its own search field. */\n stepHint?: boolean;\n /** Says how many entries match, after the query changed. */\n query: Accessor<string>;\n /** Content between the back control and the list, such as a search field. */\n header?: JSX.Element;\n /** Runs after Retry or Close on an outcome, so the host puts the focus back where the person writes. */\n onOutcomeAction?: () => void;\n}): JSX.Element {\n const messages = useUiMessages();\n const commandMessages = useCommandMessages();\n const nav = props.navigator;\n const matches = () => nav.entries().filter((item) => !item.disabled).length;\n // The focus stays in the field, so the marked row scrolls into view itself.\n createEffect(() => {\n if (nav.entries().length === 0) return;\n document.getElementById(commandOptionId(props.id, nav.active()))?.scrollIntoView?.({ block: \"nearest\" });\n });\n const statusOf = (item: CommandItem) => {\n const current = nav.status();\n return current?.key === commandKey(item) ? current : undefined;\n };\n const runningLabel = () => {\n const current = nav.status();\n return current?.state === \"running\" ? commandMessages().running({ label: current.label }) : \"\";\n };\n const loadFailure = () => {\n const current = nav.load();\n return current.state === \"failed\" ? (current.message ?? commandMessages().loadFailed) : \"\";\n };\n /** The outcome as one line of text: the report, or for an error without one, that it did not work. */\n const outcomeText = (outcome: CommandOutcome) =>\n outcome.state === \"running\"\n ? commandMessages().running({ label: outcome.message })\n : (outcome.message ?? (outcome.state === \"error\" ? commandMessages().failed : commandMessages().done));\n const outcomeError = () => {\n const current = nav.outcome();\n return current?.state === \"error\" ? outcomeText(current) : \"\";\n };\n const status = () => {\n const current = nav.outcome();\n if (current) return current.state === \"error\" ? \"\" : outcomeText(current);\n if (runningLabel()) return runningLabel();\n const step = nav.step()?.next;\n const count = props.query().trim() || step ? messages().searchMatches({ count: matches() }) : \"\";\n return step && count ? `${step.label}, ${count}` : count;\n };\n\n return (\n <>\n {/* After a command reported, a status line of the same width takes the list's place until it clears. */}\n <Show when={!nav.outcome()} fallback={<CommandOutcomeLine navigator={nav} text={outcomeText} onAction={props.onOutcomeAction} />}>\n <Show when={nav.step()}>\n {(item) => (\n <div class=\"k2b-command-list__step\">\n <button\n type=\"button\"\n class=\"k2b-command-list__back\"\n tabIndex={-1}\n aria-label={commandMessages().back({ label: item().label })}\n onMouseDown={(event) => event.preventDefault()}\n onClick={() => nav.back()}\n >\n <i class=\"ti ti-chevron-left\" aria-hidden=\"true\" />\n <span>{item().label}</span>\n </button>\n <Show when={props.stepHint}>\n <span class=\"k2b-command-list__step-hint\">{item().next?.label}</span>\n </Show>\n </div>\n )}\n </Show>\n {props.header}\n <div\n id={props.id}\n role=\"listbox\"\n aria-label={nav.step()?.next?.label ?? props.label}\n aria-busy={nav.load().state === \"loading\" ? \"true\" : undefined}\n class=\"k2b-command-list\"\n // A press on a row leaves the focus in the host's field.\n onMouseDown={(event) => event.preventDefault()}\n >\n <For each={nav.groups()}>\n {(group) => {\n const headingId = `${props.id}-group-${group.entries[0]?.index ?? 0}`;\n return (\n <div class=\"k2b-dropdown__section\" role=\"group\" aria-labelledby={group.label ? headingId : undefined}>\n <Show when={group.label}>\n <div id={headingId} class=\"k2b-dropdown__label\">\n {group.label}\n </div>\n </Show>\n <For each={group.entries}>\n {(entry) => (\n // biome-ignore lint/a11y/useKeyWithClickEvents: the host's field handles the keys through aria-activedescendant.\n <div\n id={commandOptionId(props.id, entry.index)}\n role=\"option\"\n class=\"k2b-dropdown__item\"\n aria-selected={entry.index === nav.active()}\n aria-disabled={entry.item.disabled ? \"true\" : undefined}\n aria-busy={statusOf(entry.item)?.state === \"running\" ? \"true\" : undefined}\n data-active={entry.index === nav.active() && !entry.item.disabled ? \"\" : undefined}\n onPointerMove={() => {\n if (entry.index !== nav.active()) nav.setActive(entry.index);\n }}\n onClick={() => nav.choose(entry.index)}\n >\n <Show\n when={statusOf(entry.item)?.state !== \"running\"}\n fallback={<i class=\"ti ti-loader-2 k2b-spin k2b-command-list__busy\" aria-hidden=\"true\" />}\n >\n <Show when={entry.item.leading} fallback={<CommandVisual item={entry.item} />}>\n {(leading) => (\n <span class=\"k2b-command-list__leading\" aria-hidden=\"true\">\n {leading()()}\n </span>\n )}\n </Show>\n </Show>\n {/* One line: the label, then quietly the reason it is unavailable, or what it does. */}\n <span class=\"k2b-dropdown__copy k2b-command-list__text\">\n <span>{entry.item.label}</span>\n <Show when={entry.item.disabled ?? entry.item.description}>\n {(text) => <small class=\"k2b-command-list__description\">{text()}</small>}\n </Show>\n </span>\n <Show when={entry.item.hint}>\n {(hint) => (\n <span class=\"k2b-command-list__hint\" aria-hidden=\"true\">\n {hint()}\n </span>\n )}\n </Show>\n <Show when={entry.item.next}>\n <i class=\"ti ti-chevron-right k2b-command-list__next\" aria-hidden=\"true\" />\n </Show>\n </div>\n )}\n </For>\n </div>\n );\n }}\n </For>\n <Show when={nav.entries().length === 0 && nav.load().state === \"ready\"}>\n <p class=\"k2b-dropdown__empty\">{messages().noResults}</p>\n </Show>\n {/* Entries on their way keep the previous ones in place; the state takes one row at the end. */}\n <Show when={nav.load().state === \"loading\"}>\n <p class=\"k2b-command-list__state\">\n <i class=\"ti ti-loader-2 k2b-spin\" aria-hidden=\"true\" />\n <span>{nav.awaitingChoice() ? commandMessages().loadingChoice : commandMessages().loading}</span>\n </p>\n </Show>\n <Show when={nav.load().state === \"failed\" ? (nav.load() as { message?: string }) : undefined}>\n {(failed) => (\n <p class=\"k2b-command-list__state\" data-error=\"\">\n <i class=\"ti ti-alert-circle\" aria-hidden=\"true\" />\n <span>{failed().message ?? commandMessages().loadFailed}</span>\n <button type=\"button\" tabIndex={-1} onMouseDown={(event) => event.preventDefault()} onClick={() => nav.retry()}>\n {messages().retry}\n </button>\n </p>\n )}\n </Show>\n </div>\n </Show>\n {/* Announced once, when the text changes: a confirmation politely, an error at once. */}\n <span class=\"k2b-sr-only\" role=\"status\">\n {status()}\n </span>\n <span class=\"k2b-sr-only\" role=\"alert\">\n {outcomeError() || loadFailure()}\n </span>\n </>\n );\n}\n\n/**\n * A command's outcome in the list's place, one line: a confirmation in the status green, an error in the status red\n * with Retry when the command threw or rejected, or a retry running. The live regions of the list announce its text,\n * so the text is hidden here; its buttons are ordinary buttons, since the list it replaced is gone.\n */\nfunction CommandOutcomeLine(props: {\n navigator: CommandNavigator;\n text: (outcome: CommandOutcome) => string;\n onAction?: () => void;\n}): JSX.Element {\n const messages = useUiMessages();\n const outcome = () => props.navigator.outcome();\n return (\n <Show when={outcome()}>\n {(current) => (\n // biome-ignore lint/a11y/noStaticElementInteractions: it holds the focus only when a menu without a target has nowhere else to keep it.\n <div\n class=\"k2b-command-outcome\"\n data-state={current().state}\n tabIndex={-1}\n onKeyDown={(event) => {\n if (event.key === \"Tab\") {\n // Tab moves between Retry and Close inside the line; only leaving it reaches the menu, which closes.\n const buttons = Array.from(event.currentTarget.querySelectorAll(\"button\"));\n const next = buttons.indexOf(document.activeElement as HTMLButtonElement) + (event.shiftKey ? -1 : 1);\n if (next >= 0 && next < buttons.length) event.stopPropagation();\n return;\n }\n // Keys on the outcome itself are the person moving on, as typing in the text is.\n if (event.target === event.currentTarget && ![\"Escape\", \"Shift\"].includes(event.key)) props.navigator.typedOn();\n }}\n >\n <i\n aria-hidden=\"true\"\n class={\n current().state === \"success\"\n ? \"ti ti-circle-check\"\n : current().state === \"error\"\n ? \"ti ti-alert-circle\"\n : \"ti ti-loader-2 k2b-spin\"\n }\n />\n <span class=\"k2b-command-outcome__text\" title={props.text(current())} aria-hidden=\"true\">\n {props.text(current())}\n </span>\n <Show when={current().state === \"error\" ? (current() as { retry?: () => void }).retry : undefined}>\n {(retry) => (\n <button\n type=\"button\"\n onMouseDown={(event) => event.preventDefault()}\n onClick={() => {\n retry()();\n props.onAction?.();\n }}\n >\n {messages().retry}\n </button>\n )}\n </Show>\n <Show when={current().state === \"error\"}>\n <button\n type=\"button\"\n class=\"k2b-command-outcome__close\"\n aria-label={messages().close}\n onMouseDown={(event) => event.preventDefault()}\n onClick={() => {\n props.navigator.clearOutcome();\n props.onAction?.();\n }}\n >\n <i class=\"ti ti-x\" aria-hidden=\"true\" />\n </button>\n </Show>\n </div>\n )}\n </Show>\n );\n}\n\n/** An entry's image, one per theme when it has two, at icon size; or its icon. */\nfunction CommandVisual(props: { item: CommandItem }): JSX.Element {\n const image = () => props.item.image;\n return (\n <Show when={image()} fallback={<Show when={props.item.icon}>{(icon) => <i class={icon()} aria-hidden=\"true\" />}</Show>}>\n {(source) => (\n <span class=\"k2b-command-list__image\" aria-hidden=\"true\">\n <Show\n when={typeof source() === \"object\" ? (source() as { light: string; dark: string }) : undefined}\n fallback={<img src={source() as string} alt=\"\" width=\"16\" height=\"16\" decoding=\"async\" />}\n >\n {(pair) => (\n <>\n <img class=\"k2b-command-list__image-light\" src={pair().light} alt=\"\" width=\"16\" height=\"16\" decoding=\"async\" />\n <img class=\"k2b-command-list__image-dark\" src={pair().dark} alt=\"\" width=\"16\" height=\"16\" decoding=\"async\" />\n </>\n )}\n </Show>\n </span>\n )}\n </Show>\n );\n}\n\n/**\n * The keys of a command list in its host's field: Up, Down, Home, and End mark; Enter and Tab choose; Escape and\n * Backspace on an empty query leave a second list. Returns whether the key was used; Escape in the first list is left\n * to the host, which closes.\n */\nexport const commandListKey = (nav: CommandNavigator, event: KeyboardEvent, query: string): boolean => {\n if (event.isComposing || event.metaKey || event.ctrlKey || event.altKey) return false;\n switch (event.key) {\n case \"ArrowDown\":\n case \"ArrowUp\":\n if (nav.entries().length === 0) return false;\n nav.move(event.key === \"ArrowDown\" ? 1 : -1);\n return true;\n case \"Home\":\n case \"End\":\n if (event.shiftKey || nav.entries().length === 0) return false;\n nav.edge(event.key === \"Home\" ? \"first\" : \"last\");\n return true;\n case \"Enter\":\n case \"Tab\":\n // Enter while entries load takes the first entry of exactly this query once it arrives, never a stale one.\n if (event.key === \"Enter\" && !event.shiftKey && nav.load().state === \"loading\") {\n nav.chooseWhenLoaded();\n return true;\n }\n // Enter asks a list that could not load again.\n if (event.key === \"Enter\" && !event.shiftKey && nav.load().state === \"failed\" && nav.entries().length === 0) {\n nav.retry();\n return true;\n }\n if (event.shiftKey || nav.entries().length === 0) return false;\n nav.choose();\n return true;\n case \"Escape\":\n // A running command is stopped by the host, before any back.\n if (nav.busy()) return false;\n return nav.back();\n case \"Backspace\":\n return query === \"\" && nav.back();\n default:\n return false;\n }\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,SAAwB,YAAY,EAAE,UAAU,EAAE,YAAY,EAAE,GAAG,EAAY,SAAS,EAAE,IAAI,EAAE,OAAO,QAAQ,UAAU;AACzH,SAAS,aAAa,QAAQ,kBAAkB;AAChD,SAKE,UAAU,EACV,kBAAkB,EAClB,iBAAiB,QACZ,iBAAiB;AACxB,SAAS,kBAAkB,QAAQ,oBAAoB;;AAEvD;;AAGA;;AAGA;;AAGA;;AAGA;AACA;AACA;AACA;;AAMA;AACA,OAAO,MAAM,sBAAsB,GAAG,IAAI;AAC1C;AACA,OAAO,MAAM,0BAA0B,GAAG,IAAI;AAE9C,MAAM,YAAY,GAAG,MAAM,CAAC,CAAC;;AAE7B;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,MAAM,sBAAsB,GAAI,OAYtC,IAAK;EACJ,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,YAAY,CAAgB,CAAC;EACzD,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,YAAY,CAAiB,CAAC;EAC5D,IAAI,OAAO,GAAG,CAAC;EACf,IAAI,YAAuD;EAC3D,MAAM,YAAY,GAAG,MAAM;IACzB,YAAY,CAAC,YAAY,CAAC;IAC1B,YAAY,GAAG,SAAS;IACxB,UAAU,CAAC,SAAS,CAAC;EACvB,CAAC;EACD,MAAM,WAAW,GAAI,IAAoB,IAAK;IAC5C,YAAY,CAAC,YAAY,CAAC;IAC1B,YAAY,GAAG,SAAS;IACxB,UAAU,CAAC,IAAI,CAAC;IAChB,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC;IACpB,IAAI,IAAI,CAAC,KAAK,KAAK,SAAS,EAAE,YAAY,GAAG,UAAU,CAAC,YAAY,EAAE,0BAA0B,CAAC;EACnG,CAAC;EACD,IAAI,OAAoC;EACxC;EACA,SAAS,CAAC,MAAM;IACd,YAAY,CAAC,YAAY,CAAC;IAC1B,OAAO,GAAG,SAAS;EACrB,CAAC,CAAC;EACF,MAAM,GAAG,GAAG,CAAC,IAAiB,EAAE,IAA4B,EAAE,KAAK,GAAG,KAAK,KAAK;IAC9E,MAAM,UAAU,GAAG,IAAI,eAAe,CAAC,CAAC;IACxC,OAAO,GAAG,UAAU;IACpB,MAAM,GAAG,GAAG,UAAU,CAAC,IAAI,CAAC;IAC5B,SAAS,CAAC,SAAS,CAAC;IACpB,IAAI,CAAC,KAAK,EAAE,OAAO,CAAC,SAAS,GAAG,CAAC;IACjC;IACA,IAAI,MAAkC;IACtC,MAAM,SAAS,GAAG,MAAM,OAAO,KAAK,UAAU,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,OAAO;IAC5E,MAAM,MAAM,GAAI,OAA4B,IAAK;MAC/C,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE;MAClB,OAAO,GAAG,SAAS;MACnB,SAAS,CAAC,SAAS,CAAC;MACpB,MAAM,IAAgC,GAAG,OAAO,GAC5C;QACE,KAAK,EAAE,OAAO;QACd,OAAO,EAAE,OAAO,CAAC,KAAK,YAAY,KAAK,IAAI,OAAO,CAAC,KAAK,CAAC,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,OAAO,GAAG,SAAS;QACpG,KAAK,EAAE,MAAM,QAAQ,CAAC,IAAI,EAAE,IAAI;MAClC,CAAC,GACD,MAAM;MACV;MACA;MACA,IAAI,IAAI,EAAE,WAAW,CAAC,IAAI,CAAC,CAAC,KACvB,YAAY,CAAC,CAAC;MACnB,OAAO,CAAC,QAAQ,CAAC,IAAI,KAAK,SAAS,CAAC;IACtC,CAAC;IACD,IAAI,MAAe;IACnB,IAAI;MACF,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;MAC9B,MAAM,GAAG,IAAI,CAAC,QAAQ,GAAG;QACvB,GAAG,IAAI;QACP;QACA,MAAM,EAAG,IAAY,IAAK;UACxB,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,OAAO,EAAE,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC;QACnD,CAAC;QACD,OAAO,EAAG,OAAe,IAAK;UAC5B,MAAM,GAAG;YAAE,KAAK,EAAE,SAAS;YAAE;UAAQ,CAAC;QACxC,CAAC;QACD,KAAK,EAAG,OAAe,IAAK;UAC1B,MAAM,GAAG;YAAE,KAAK,EAAE,OAAO;YAAE;UAAQ,CAAC;QACtC,CAAC;QACD,KAAK,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC;QACtB,IAAI;QACJ,MAAM,EAAE,UAAU,CAAC;MACrB,CAAC,CAAC;IACJ,CAAC,CAAC,OAAO,KAAK,EAAE;MACd,MAAM,CAAC;QAAE;MAAM,CAAC,CAAC;MACjB;IACF;IACA,IAAI,EAAE,MAAM,YAAY,OAAO,CAAC,EAAE,OAAO,MAAM,CAAC,CAAC;IACjD;IACA,IAAI,KAAK,EAAE,WAAW,CAAC;MAAE,KAAK,EAAE,SAAS;MAAE,OAAO,EAAE,IAAI,CAAC;IAAM,CAAC,CAAC,CAAC,KAC7D,SAAS,CAAC;MAAE,GAAG;MAAE,KAAK,EAAE,IAAI,CAAC,KAAK;MAAE,KAAK,EAAE;IAAU,CAAC,CAAC;IAC5D,MAAM,CAAC,IAAI,CACT,MAAM,MAAM,CAAC,CAAC,EACb,KAAc,IAAK,MAAM,CAAC;MAAE;IAAM,CAAC,CACtC,CAAC;EACH,CAAC;EACD;EACA,MAAM,QAAQ,GAAG,CAAC,IAAiB,EAAE,IAA4B,KAAK,GAAG,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC;EAC3F,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,YAAY,CAAyB,EAAE,CAAC;EAClE,MAAM,IAAI,GAAG,MAAM,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;EACjC;EACA;EACA,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,YAAY,CAAC,CAAC,CAAC;EAC7C,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,YAAY,CAAqE,CAAC;EAChH,IAAI,OAAoC;EAExC;EACA,MAAM,KAAK,GAAG,UAAU,CAAC,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC,EAAE,SAAS,EAAE;IAC3D,MAAM,EAAE,CAAC,CAAC,EAAE,CAAC,KACX,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,IAAI,IACjB,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,MAAM,IACrB,CAAC,CAAC,OAAO,KAAK,CAAC,CAAC,OAAO,IACvB,CAAC,CAAC,SAAS,KAAK,CAAC,CAAC,SAAS,IAC3B,CAAC,CAAC,SAAS,CAAC,KAAK,KAAK,CAAC,CAAC,SAAS,CAAC,KAAK,IACvC,CAAC,CAAC,SAAS,CAAC,GAAG,KAAK,CAAC,CAAC,SAAS,CAAC;EACpC,CAAC,CAAC;EACF,MAAM,OAAO,GAAG,UAAU,CAAU,MAAM;IACxC,OAAO,CAAC,CAAC;IACT,OAAO,EAAE,KAAK,CAAC,CAAC;IAChB,OAAO,GAAG,SAAS;IACnB,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,OAAO;MAAE,KAAK,EAAE;IAAG,CAAC;IAC3C,MAAM,MAAM,GAAG,IAAI,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,IAAI,OAAO,CAAC,KAAK,CAAC,CAAC;IACrD,IAAI,OAAO,MAAM,KAAK,UAAU,EAAE,OAAO;MAAE,KAAK,EAAE,kBAAkB,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC;IAAE,CAAC;IAC/F,MAAM,UAAU,GAAG,IAAI,eAAe,CAAC,CAAC;IACxC,MAAM,OAAuB,GAAG;MAC9B,GAAG,KAAK,CAAC,CAAC;MACV,KAAK,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC;MACtB,IAAI,EAAE,KAAK,CAAC,CAAC;MACb,MAAM,EAAE,UAAU,CAAC,MAAM;MACzB,OAAO,EAAE,YAAY;MACrB,KAAK,EAAE;IACT,CAAC;IACD,IAAI,MAAgE;IACpE,IAAI;MACF,MAAM,GAAG,OAAO,CAAC,MAAM,MAAM,CAAC,OAAO,CAAC,CAAC;IACzC,CAAC,CAAC,OAAO,KAAK,EAAE;MACd,OAAO;QAAE;MAAM,CAAC;IAClB;IACA,IAAI,EAAE,MAAM,YAAY,OAAO,CAAC,EAAE,OAAO;MAAE,KAAK,EAAE,kBAAkB,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK;IAAE,CAAC;IAC7F,OAAO,GAAG,UAAU;IACpB,MAAM,KAAK,GAAG,CAAC,CAAC;IAChB,MAAM,CAAC,IAAI,CACR,KAAK,IAAK;MACT,IAAI,OAAO,KAAK,UAAU,EAAE,UAAU,CAAC;QAAE,KAAK;QAAE,KAAK,EAAE,kBAAkB,CAAC,KAAK,EAAE,OAAO,CAAC,KAAK;MAAE,CAAC,CAAC;IACpG,CAAC,EACA,KAAc,IAAK;MAClB,IAAI,OAAO,KAAK,UAAU,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC;QAAE,KAAK;QAAE;MAAM,CAAC,CAAC;IACxF,CACF,CAAC;IACD,OAAO;MAAE;IAAM,CAAC;EAClB,CAAC,CAAC;EACF;EACA,MAAM,IAAI,GAAG,UAAU,CAAkB,MAAM;IAC7C,MAAM,OAAO,GAAG,OAAO,CAAC,CAAC;IACzB,MAAM,MAAM,GAAG,OAAO,CAAC,KAAK,GAAI,OAAO,CAAC,CAAC,EAAE,KAAK,KAAK,OAAO,CAAC,KAAK,GAAG,OAAO,CAAC,CAAC,GAAG,SAAS,GAAI,OAAO;IACrG,IAAI,CAAC,MAAM,EAAE,OAAO;MAAE,KAAK,EAAE;IAAU,CAAC;IACxC,IAAI,MAAM,CAAC,KAAK,KAAK,SAAS,EAAE;MAC9B,MAAM,OAAO,GAAG,MAAM,CAAC,KAAK,YAAY,KAAK,IAAI,MAAM,CAAC,KAAK,CAAC,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,OAAO,GAAG,SAAS;MACxG,OAAO;QAAE,KAAK,EAAE,QAAQ;QAAE;MAAQ,CAAC;IACrC;IACA,OAAO;MAAE,KAAK,EAAE;IAAQ,CAAC;EAC3B,CAAC,CAAC;EACF;EACA,MAAM,KAAK,GAAG,UAAU,CACrB,QAAQ,IAAK;IACZ,MAAM,OAAO,GAAG,OAAO,CAAC,CAAC;IACzB,MAAM,EAAE,GAAG,IAAI,CAAC,CAAC;IACjB,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,OAAO;MAAE,IAAI,EAAE,EAAE;MAAE,KAAK,EAAE,OAAO,CAAC,KAAK,IAAI;IAAG,CAAC;IACnE,MAAM,MAAM,GAAG,OAAO,CAAC,CAAC;IACxB,IAAI,MAAM,EAAE,KAAK,KAAK,OAAO,CAAC,KAAK,EAAE,OAAO;MAAE,IAAI,EAAE,EAAE;MAAE,KAAK,EAAE,MAAM,CAAC,KAAK,IAAI;IAAG,CAAC;IACnF,OAAO;MAAE,IAAI,EAAE,EAAE;MAAE,KAAK,EAAE,QAAQ,CAAC,IAAI,KAAK,EAAE,GAAG,QAAQ,CAAC,KAAK,GAAG;IAAG,CAAC;EACxE,CAAC,EACD;IAAE,IAAI,EAAE,SAAS;IAAE,KAAK,EAAE;EAAG,CAC/B,CAAC;EACD,MAAM,OAAO,GAAG,MAAM,KAAK,CAAC,CAAC,CAAC,KAAK;EACnC,MAAM,MAAM,GAAG,UAAU,CAAiB,MAAM,iBAAiB,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;EAC7E,MAAM,OAAO,GAAG,UAAU,CAAC,MAAM,MAAM,CAAC,CAAC,CAAC,OAAO,CAAE,KAAK,IAAK,KAAK,CAAC,OAAO,CAAC,GAAG,CAAE,KAAK,IAAK,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;EACvG;EACA,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,YAAY,CAAgE,CAAC;EACzG,MAAM,MAAM,GAAG,UAAU,CAAC,MAAM;IAC9B,MAAM,IAAI,GAAG,OAAO,CAAC,CAAC;IACtB,MAAM,IAAI,GAAG,MAAM,CAAC,CAAC;IACrB,IAAI,IAAI,IAAI,IAAI,CAAC,KAAK,KAAK,OAAO,CAAC,KAAK,CAAC,CAAC,IAAI,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC,EAAE;MAClE,MAAM,KAAK,GAAG,IAAI,CAAC,SAAS,CAAE,IAAI,IAAK,UAAU,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC,GAAG,CAAC;MACrE,IAAI,KAAK,IAAI,CAAC,EAAE,OAAO,KAAK;IAC9B;IACA,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAE,IAAI,IAAK,CAAC,IAAI,CAAC,QAAQ,CAAC;IACxD,OAAO,OAAO,IAAI,CAAC,GAAG,OAAO,GAAG,CAAC;EACnC,CAAC,CAAC;EACF,MAAM,SAAS,GAAI,KAAa,IAAK;IACnC,MAAM,IAAI,GAAG,OAAO,CAAC,CAAC;IACtB,MAAM,IAAI,GAAG,IAAI,CAAC,CAAC,KAAK,GAAG,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;IACnE,IAAI,IAAI,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,SAAS,CAAC;MAAE,GAAG,EAAE,UAAU,CAAC,IAAI,CAAC;MAAE,KAAK,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC;MAAE,IAAI,EAAE,IAAI,CAAC;IAAE,CAAC,CAAC;EACxG,CAAC;EACD;EACA,MAAM,WAAW,GAAG,CAAC,IAAY,EAAE,SAAiB,KAAK;IACvD,MAAM,IAAI,GAAG,OAAO,CAAC,CAAC;IACtB,KAAK,IAAI,IAAI,GAAG,CAAC,EAAE,IAAI,IAAI,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,EAAE;MAC9C,MAAM,KAAK,GAAG,CAAE,CAAC,IAAI,GAAG,SAAS,GAAG,IAAI,IAAI,IAAI,CAAC,MAAM,GAAI,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,MAAM;MACrF,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,QAAQ,EAAE,OAAO,KAAK;IAC1C;IACA,OAAO,IAAI;EACb,CAAC;EACD;EACA,MAAM,MAAM,GAAG,CAAC,KAAK,GAAG,MAAM,CAAC,CAAC,KAAK;IACnC,MAAM,IAAI,GAAG,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC;IAC7B,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,QAAQ,IAAI,MAAM,CAAC,CAAC,EAAE,KAAK,KAAK,SAAS,EAAE;IAC7D,IAAI,IAAI,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,KACzC,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS,EAAE,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,KAClD,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC;EACzB,CAAC;EACD,MAAM,UAAU,GAAI,IAA4B,IAAK;IACnD,QAAQ,CAAC,IAAI,CAAC;IACd,SAAS,CAAC,SAAS,CAAC;IACpB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;EAC/B,CAAC;EACD;EACA;EACA,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,GAAG,YAAY,CAAS,CAAC;EACtD,YAAY,CAAC,MAAM;IACjB,MAAM,KAAK,GAAG,QAAQ,CAAC,CAAC;IACxB,IAAI,KAAK,KAAK,SAAS,EAAE;IACzB,IAAI,KAAK,KAAK,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,OAAO,WAAW,CAAC,SAAS,CAAC;IAC5D,MAAM,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC,KAAK;IAC1B,IAAI,KAAK,KAAK,SAAS,EAAE;IACzB,WAAW,CAAC,SAAS,CAAC;IACtB,IAAI,KAAK,KAAK,OAAO,EAAE;IACvB,MAAM,KAAK,GAAG,OAAO,CAAC,CAAC,CAAC,SAAS,CAAE,IAAI,IAAK,CAAC,IAAI,CAAC,QAAQ,CAAC;IAC3D,IAAI,KAAK,IAAI,CAAC,EAAE,OAAO,CAAC,MAAM,MAAM,CAAC,KAAK,CAAC,CAAC;EAC9C,CAAC,CAAC;EAEF,OAAO;IACL,KAAK,EAAE,OAAO,CAAC,KAAK;IACpB,IAAI;IACJ,MAAM;IACN,OAAO,EAAE,OAAO;IAChB,MAAM;IACN,SAAS;IACT;IACA,IAAI,EAAG,KAAa,IAAK,SAAS,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;IAChE,IAAI,EAAG,KAAuB,IAAK,SAAS,CAAC,KAAK,KAAK,OAAO,GAAG,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC;IACxH,MAAM;IACN,IAAI;IACJ;IACA,KAAK,EAAE,MAAM,UAAU,CAAE,KAAK,IAAK,KAAK,GAAG,CAAC,CAAC;IAC7C;IACA,IAAI,EAAE,MAAM,MAAM,CAAC,CAAC,EAAE,KAAK,KAAK,SAAS;IACzC,MAAM,EAAG,KAAc,IAAK,MAAM,CAAC,KAAK,CAAC;IACzC;IACA,gBAAgB,EAAE,MAAM,WAAW,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC;IACpD;IACA,cAAc,EAAE,MAAM,QAAQ,CAAC,CAAC,KAAK,SAAS;IAC9C;IACA,KAAK,EAAE,MAAM;MACX,OAAO,EAAE,KAAK,CAAC,CAAC;MAChB,OAAO,GAAG,SAAS;MACnB,SAAS,CAAC,SAAS,CAAC;MACpB,IAAI,OAAO,CAAC,CAAC,EAAE,KAAK,KAAK,SAAS,EAAE,YAAY,CAAC,CAAC;IACpD,CAAC;IACD;IACA,OAAO;IACP;IACA,OAAO,EAAE,MAAM;MACb,MAAM,OAAO,GAAG,OAAO,CAAC,CAAC;MACzB,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,KAAK,KAAK,SAAS,EAAE;MAC7C,MAAM,IAAI,GAAG,sBAAsB,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,OAAO,CAAC;MAC5D,IAAI,IAAI,IAAI,CAAC,EAAE,OAAO,YAAY,CAAC,CAAC;MACpC,YAAY,CAAC,YAAY,CAAC;MAC1B,YAAY,GAAG,UAAU,CAAC,YAAY,EAAE,IAAI,CAAC;IAC/C,CAAC;IACD;IACA,YAAY,EAAE,MAAM;MAClB,IAAI,OAAO,CAAC,CAAC,EAAE,KAAK,KAAK,SAAS,EAAE;QAClC,OAAO,EAAE,KAAK,CAAC,CAAC;QAChB,OAAO,GAAG,SAAS;MACrB;MACA,YAAY,CAAC,CAAC;IAChB,CAAC;IACD;IACA,IAAI,EAAE,MAAM;MACV,IAAI,KAAK,CAAC,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE,OAAO,KAAK;MACtC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;MAChC,OAAO,IAAI;IACb,CAAC;IACD;AACJ;AACA;AACA;IACI,KAAK,EAAE,MAAM;MACX,IAAI,OAAO,CAAC,CAAC,EAAE,KAAK,KAAK,SAAS,EAAE,YAAY,CAAC,CAAC;MAClD,OAAO,GAAG,SAAS;MACnB,OAAO,EAAE,KAAK,CAAC,CAAC;MAChB,OAAO,GAAG,SAAS;MACnB,QAAQ,CAAC,EAAE,CAAC;MACZ,SAAS,CAAC,SAAS,CAAC;MACpB,SAAS,CAAC,SAAS,CAAC;IACtB;EACF,CAAC;AACH,CAAC;AAED,OAAO,MAAM,eAAe,GAAG,CAAC,MAAc,EAAE,KAAa,KAAK,GAAG,MAAM,IAAI,KAAK,EAAE;;AAEtF;AACA;AACA;AACA;AACA,OAAO,SAAS,WAAW,CAAC,KAa3B,EAAe;EACd,MAAM,QAAQ,GAAG,aAAa,CAAC,CAAC;EAChC,MAAM,eAAe,GAAG,kBAAkB,CAAC,CAAC;EAC5C,MAAM,GAAG,GAAG,KAAK,CAAC,SAAS;EAC3B,MAAM,OAAO,GAAG,MAAM,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAE,IAAI,IAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,MAAM;EAC3E;EACA,YAAY,CAAC,MAAM;IACjB,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE;IAChC,QAAQ,CAAC,cAAc,CAAC,eAAe,CAAC,KAAK,CAAC,EAAE,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,cAAc,GAAG;MAAE,KAAK,EAAE;IAAU,CAAC,CAAC;EAC1G,CAAC,CAAC;EACF,MAAM,QAAQ,GAAI,IAAiB,IAAK;IACtC,MAAM,OAAO,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC;IAC5B,OAAO,OAAO,EAAE,GAAG,KAAK,UAAU,CAAC,IAAI,CAAC,GAAG,OAAO,GAAG,SAAS;EAChE,CAAC;EACD,MAAM,YAAY,GAAG,MAAM;IACzB,MAAM,OAAO,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC;IAC5B,OAAO,OAAO,EAAE,KAAK,KAAK,SAAS,GAAG,eAAe,CAAC,CAAC,CAAC,OAAO,CAAC;MAAE,KAAK,EAAE,OAAO,CAAC;IAAM,CAAC,CAAC,GAAG,EAAE;EAChG,CAAC;EACD,MAAM,WAAW,GAAG,MAAM;IACxB,MAAM,OAAO,GAAG,GAAG,CAAC,IAAI,CAAC,CAAC;IAC1B,OAAO,OAAO,CAAC,KAAK,KAAK,QAAQ,GAAI,OAAO,CAAC,OAAO,IAAI,eAAe,CAAC,CAAC,CAAC,UAAU,GAAI,EAAE;EAC5F,CAAC;EACD;EACA,MAAM,WAAW,GAAI,OAAuB,IAC1C,OAAO,CAAC,KAAK,KAAK,SAAS,GACvB,eAAe,CAAC,CAAC,CAAC,OAAO,CAAC;IAAE,KAAK,EAAE,OAAO,CAAC;EAAQ,CAAC,CAAC,GACpD,OAAO,CAAC,OAAO,KAAK,OAAO,CAAC,KAAK,KAAK,OAAO,GAAG,eAAe,CAAC,CAAC,CAAC,MAAM,GAAG,eAAe,CAAC,CAAC,CAAC,IAAI,CAAE;EAC1G,MAAM,YAAY,GAAG,MAAM;IACzB,MAAM,OAAO,GAAG,GAAG,CAAC,OAAO,CAAC,CAAC;IAC7B,OAAO,OAAO,EAAE,KAAK,KAAK,OAAO,GAAG,WAAW,CAAC,OAAO,CAAC,GAAG,EAAE;EAC/D,CAAC;EACD,MAAM,MAAM,GAAG,MAAM;IACnB,MAAM,OAAO,GAAG,GAAG,CAAC,OAAO,CAAC,CAAC;IAC7B,IAAI,OAAO,EAAE,OAAO,OAAO,CAAC,KAAK,KAAK,OAAO,GAAG,EAAE,GAAG,WAAW,CAAC,OAAO,CAAC;IACzE,IAAI,YAAY,CAAC,CAAC,EAAE,OAAO,YAAY,CAAC,CAAC;IACzC,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,CAAC,CAAC,EAAE,IAAI;IAC7B,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,IAAI,GAAG,QAAQ,CAAC,CAAC,CAAC,aAAa,CAAC;MAAE,KAAK,EAAE,OAAO,CAAC;IAAE,CAAC,CAAC,GAAG,EAAE;IAChG,OAAO,IAAI,IAAI,KAAK,GAAG,GAAG,IAAI,CAAC,KAAK,KAAK,KAAK,EAAE,GAAG,KAAK;EAC1D,CAAC;EAED,0BAGK,IAAI;IAAA,IAAC,IAAI;MAAA,OAAE,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IAAA;IAAA,IAAE,QAAQ;MAAA,yBAAG,kBAAkB;QAAC,SAAS,EAAE,GAAG;QAAE,IAAI,EAAE,WAAW;QAAA,IAAE,QAAQ;UAAA,OAAE,KAAK,CAAC,eAAe;QAAA;MAAA;IAAA;IAAA;MAAA,0BACzH,IAAI;QAAA,IAAC,IAAI;UAAA,OAAE,GAAG,CAAC,IAAI,CAAC,CAAC;QAAA;QAAA,UAClB,IAAI,yDAMY,eAAe,CAAC,CAAC,CAAC,IAAI,CAAC;UAAE,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC;QAAM,CAAC,CAAC,0BAKpD,IAAI,CAAC,CAAC,CAAC,KAAK,8BAEpB,IAAI;UAAA,IAAC,IAAI;YAAA,OAAE,KAAK,CAAC,QAAQ;UAAA;UAAA;YAAA,+BACmB,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK;UAAA;QAAA;MAGlE,IAEF,KAAK,CAAC,MAAM,+CAEP,KAAK,CAAC,EAAE,uDAEA,GAAG,CAAC,IAAI,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,IAAI,KAAK,CAAC,KAAK,8CACvC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,KAAK,SAAS,GAAG,MAAM,YAAG,SAAS,4CAK7D,GAAG;QAAA,IAAC,IAAI;UAAA,OAAE,GAAG,CAAC,MAAM,CAAC,CAAC;QAAA;QAAA,UACnB,KAAK,IAAK;UACV,MAAM,SAAS,GAAG,GAAG,KAAK,CAAC,EAAE,UAAU,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,KAAK,IAAI,CAAC,EAAE;UACrE,wDACmE,KAAK,CAAC,KAAK,YAAG,SAAS,mBAAG,SAAS,4CACjG,IAAI;YAAA,IAAC,IAAI;cAAA,OAAE,KAAK,CAAC,KAAK;YAAA;YAAA;cAAA,oDACZ,SAAS,0BACf,KAAK,CAAC,KAAK;YAAA;UAAA,gCAGf,GAAG;YAAA,IAAC,IAAI;cAAA,OAAE,KAAK,CAAC,OAAO;YAAA;YAAA,UACpB,KAAK,IACL;YAAA,6CAEM,eAAe,CAAC,KAAK,CAAC,EAAE,EAAE,KAAK,CAAC,KAAK,CAAC,iDAG3B,cAAK,CAAC,KAAK,qBAAK,GAAG,CAAC,MAAM,CAAC,CAAC,kDAC5B,KAAK,CAAC,IAAI,CAAC,QAAQ,GAAG,MAAM,YAAG,SAAS,8CAC5C,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,KAAK,KAAK,SAAS,GAAG,MAAM,YAAG,SAAS,gDAC5D,KAAK,CAAC,KAAK,KAAK,GAAG,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,GAAG,EAAE,YAAG,SAAS,4CAMjF,IAAI;cAAA,IACH,IAAI;gBAAA,OAAE,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,KAAK,KAAK,SAAS;cAAA;cAAA,IAC/C,QAAQ;gBAAA;cAAA;cAAA;gBAAA,yBAEP,IAAI;kBAAA,IAAC,IAAI;oBAAA,OAAE,KAAK,CAAC,IAAI,CAAC,OAAO;kBAAA;kBAAA,IAAE,QAAQ;oBAAA,yBAAG,aAAa;sBAAA,IAAC,IAAI;wBAAA,OAAE,KAAK,CAAC,IAAI;sBAAA;oBAAA;kBAAA;kBAAA,UACrE,OAAO,6BAEJ,OAAO,CAAC,CAAC,CAAC,CAAC;gBAEf;cAAA;YAAA,cAKI,KAAK,CAAC,IAAI,CAAC,KAAK,8BACtB,IAAI;cAAA,IAAC,IAAI;gBAAA,OAAE,KAAK,CAAC,IAAI,CAAC,QAAQ,IAAI,KAAK,CAAC,IAAI,CAAC,WAAW;cAAA;cAAA,UACrD,IAAI,6BAAmD,IAAI,CAAC,CAAC;YAAS,gCAG3E,IAAI;cAAA,IAAC,IAAI;gBAAA,OAAE,KAAK,CAAC,IAAI,CAAC,IAAI;cAAA;cAAA,UACvB,IAAI,6BAED,IAAI,CAAC,CAAC;YAEV,gCAEF,IAAI;cAAA,IAAC,IAAI;gBAAA,OAAE,KAAK,CAAC,IAAI,CAAC,IAAI;cAAA;cAAA;gBAAA;cAAA;YAAA;UAI9B;QAIT;MAAC,gCAEF,IAAI;QAAA,IAAC,IAAI;UAAA,OAAE,gBAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,KAAK,CAAC,OAAI,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,KAAK,OAAO;QAAA;QAAA;UAAA,8BACpC,QAAQ,CAAC,CAAC,CAAC,SAAS;QAAA;MAAA,gCAGrD,IAAI;QAAA,IAAC,IAAI;UAAA,OAAE,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,KAAK,SAAS;QAAA;QAAA;UAAA,sBAG/B,GAAG,CAAC,cAAc,CAAC,CAAC,YAAG,eAAe,CAAC,CAAC,CAAC,aAAa,aAAG,eAAe,CAAC,CAAC,CAAC,OAAO;QAAA;MAAA,gCAG5F,IAAI;QAAA,IAAC,IAAI;UAAA,OAAE,gBAAG,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,KAAK,QAAQ,MAAI,GAAG,CAAC,IAAI,CAAC,CAAC,GAA4B,SAAS;QAAA;QAAA,UACxF,MAAM,6BAGG,MAAM,CAAC,CAAC,CAAC,OAAO,IAAI,eAAe,CAAC,CAAC,CAAC,UAAU,YAEpD,QAAQ,CAAC,CAAC,CAAC,KAAK;MAGtB;IAAA;EAAA,4BAMJ,MAAM,CAAC,CAAC,4BAGR,YAAY,CAAC,CAAC,IAAI,WAAW,CAAC,CAAC;AAIxC;;AAEA;AACA;AACA;AACA;AACA;AACA,SAAS,kBAAkB,CAAC,KAI3B,EAAe;EACd,MAAM,QAAQ,GAAG,aAAa,CAAC,CAAC;EAChC,MAAM,OAAO,GAAG,MAAM,KAAK,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;EAC/C,yBACG,IAAI;IAAA,IAAC,IAAI;MAAA,OAAE,OAAO,CAAC,CAAC;IAAA;IAAA,UACjB,OAAO,IACP;IAAA,sDAGc,OAAO,CAAC,CAAC,CAAC,KAAK,yCAiBvB,OAAO,CAAC,CAAC,CAAC,KAAK,KAAK,SAAS,GACzB,oBAAoB,GACpB,OAAO,CAAC,CAAC,CAAC,KAAK,KAAK,OAAO,GACzB,oBAAoB,GACpB,yBAAyB,2CAGY,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,0BACjE,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,8BAEvB,IAAI;MAAA,IAAC,IAAI;QAAA,OAAE,oBAAO,CAAC,CAAC,CAAC,KAAK,KAAK,OAAO,MAAI,OAAO,CAAC,CAAC,CAA4B,KAAK,GAAG,SAAS;MAAA;MAAA,UAC7F,KAAK,6BASF,QAAQ,CAAC,CAAC,CAAC,KAAK;IAEpB,gCAEF,IAAI;MAAA,IAAC,IAAI;QAAA,OAAE,OAAO,CAAC,CAAC,CAAC,KAAK,KAAK,OAAO;MAAA;MAAA;QAAA,6DAIvB,QAAQ,CAAC,CAAC,CAAC,KAAK;MAAA;IAAA;EAWnC;AAGP;;AAEA;AACA,SAAS,aAAa,CAAC,KAA4B,EAAe;EAChE,MAAM,KAAK,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,KAAK;EACpC,yBACG,IAAI;IAAA,IAAC,IAAI;MAAA,OAAE,KAAK,CAAC,CAAC;IAAA;IAAA,IAAE,QAAQ;MAAA,yBAAG,IAAI;QAAA,IAAC,IAAI;UAAA,OAAE,KAAK,CAAC,IAAI,CAAC,IAAI;QAAA;QAAA,UAAI,IAAI,qDAAe,IAAI,CAAC,CAAC;MAAuB;IAAA;IAAA,UAC1G,MAAM,+CAEH,IAAI;MAAA,IACH,IAAI;QAAA,OAAE,oBAAO,MAAM,CAAC,CAAC,KAAK,QAAQ,MAAI,MAAM,CAAC,CAAC,GAAuC,SAAS;MAAA;MAAA,IAC9F,QAAQ;QAAA,sDAAY,MAAM,CAAC,CAAC;MAAA;MAAA,UAE1B,IAAI,oDAE8C,IAAI,CAAC,CAAC,CAAC,KAAK,iEACb,IAAI,CAAC,CAAC,CAAC,IAAI;IAE7D;EAGN;AAGP;;AAEA;AACA;AACA;AACA;AACA;AACA,OAAO,MAAM,cAAc,GAAG,CAAC,GAAqB,EAAE,KAAoB,EAAE,KAAa,KAAc;EACrG,IAAI,KAAK,CAAC,WAAW,IAAI,KAAK,CAAC,OAAO,IAAI,KAAK,CAAC,OAAO,IAAI,KAAK,CAAC,MAAM,EAAE,OAAO,KAAK;EACrF,QAAQ,KAAK,CAAC,GAAG;IACf,KAAK,WAAW;IAChB,KAAK,SAAS;MACZ,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE,OAAO,KAAK;MAC5C,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,KAAK,WAAW,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;MAC5C,OAAO,IAAI;IACb,KAAK,MAAM;IACX,KAAK,KAAK;MACR,IAAI,KAAK,CAAC,QAAQ,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE,OAAO,KAAK;MAC9D,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,KAAK,MAAM,GAAG,OAAO,GAAG,MAAM,CAAC;MACjD,OAAO,IAAI;IACb,KAAK,OAAO;IACZ,KAAK,KAAK;MACR;MACA,IAAI,KAAK,CAAC,GAAG,KAAK,OAAO,IAAI,CAAC,KAAK,CAAC,QAAQ,IAAI,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,KAAK,SAAS,EAAE;QAC9E,GAAG,CAAC,gBAAgB,CAAC,CAAC;QACtB,OAAO,IAAI;MACb;MACA;MACA,IAAI,KAAK,CAAC,GAAG,KAAK,OAAO,IAAI,CAAC,KAAK,CAAC,QAAQ,IAAI,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,KAAK,QAAQ,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE;QAC3G,GAAG,CAAC,KAAK,CAAC,CAAC;QACX,OAAO,IAAI;MACb;MACA,IAAI,KAAK,CAAC,QAAQ,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE,OAAO,KAAK;MAC9D,GAAG,CAAC,MAAM,CAAC,CAAC;MACZ,OAAO,IAAI;IACb,KAAK,QAAQ;MACX;MACA,IAAI,GAAG,CAAC,IAAI,CAAC,CAAC,EAAE,OAAO,KAAK;MAC5B,OAAO,GAAG,CAAC,IAAI,CAAC,CAAC;IACnB,KAAK,WAAW;MACd,OAAO,KAAK,KAAK,EAAE,IAAI,GAAG,CAAC,IAAI,CAAC,CAAC;IACnC;MACE,OAAO,KAAK;EAChB;AACF,CAAC","ignoreList":[]}
@@ -0,0 +1,197 @@
1
+ import { memo as _$memo } from "solid-js/web";
2
+ import { createComponent as _$createComponent } from "solid-js/web";
3
+ import { ssr as _$ssr } from "solid-js/web";
4
+ import { ssrAttribute as _$ssrAttribute } from "solid-js/web";
5
+ import { escape as _$escape } from "solid-js/web";
6
+ var _tmpl$ = ["<label class=\"k2b-dropdown__search\"><i class=\"ti ti-search\" aria-hidden=\"true\"></i><input type=\"search\" role=\"combobox\"", " aria-expanded=\"true\"", " aria-autocomplete=\"list\"", " autocomplete=\"off\" spellcheck=\"false\" enterkeyhint=\"go\"", "></label>"];
7
+ import { createEffect, createSignal, createUniqueId, on, onCleanup } from "solid-js";
8
+ import { replaceTextareaRange } from "../inputs/editor-dom";
9
+ import { CommandList, commandListKey, commandOptionId, createCommandNavigator } from "./CommandList";
10
+ import { dockCommandList, followComposer } from "./command-dock";
11
+ import { commandPlace } from "./command-items";
12
+ import { Dropdown, DropdownShell } from "./Dropdown";
13
+ /**
14
+ * A searchable command list beside a trigger or an anchor, with the slash menu's entries and rows: groups, icons,
15
+ * unavailable entries with their reason, and second lists. Focus stays in the search field; Up, Down, Home, and End
16
+ * mark, Enter and Tab choose, Escape or Backspace in an empty field go back, and Escape in the first list closes.
17
+ */
18
+ function CommandMenuRoot(props) {
19
+ const body = shell => {
20
+ const listId = `k2b-command-menu-${createUniqueId().replace(/[^a-zA-Z0-9_-]/g, "-")}`;
21
+ const [query, setQuery] = createSignal("");
22
+ let input;
23
+ /** The open menu, kept while an outcome replaces the search field that finds it. */
24
+ let menu = null;
25
+ /** Where the focus was when an outcome took the list's place: inside the menu, or in the target. */
26
+ let focusInMenu = false;
27
+ const nav = createCommandNavigator({
28
+ items: () => props.items,
29
+ query,
30
+ onText: item => {
31
+ // Read before closing: closing resets the list.
32
+ const text = item.text ?? "";
33
+ const target = props.target;
34
+ shell.close(!target);
35
+ insert(text);
36
+ },
37
+ context: () => {
38
+ const target = props.target;
39
+ const value = target?.value ?? "";
40
+ const start = target?.selectionStart ?? 0;
41
+ return {
42
+ ...commandPlace(value, start, start),
43
+ selection: {
44
+ start,
45
+ end: target?.selectionEnd ?? start
46
+ },
47
+ insert: text => insert(text)
48
+ };
49
+ },
50
+ active: shell.open,
51
+ // The focus goes back to the trigger only from inside the menu: an entry that wrote into the target, or moved
52
+ // the focus elsewhere itself, leaves it there. An outcome keeps the menu open in the list's place: the person
53
+ // writes on in the target, or, without one, the focus rests on the outcome until it clears.
54
+ afterRun: outcome => {
55
+ // An outcome replaces the search field before this runs, which leaves the focus on the page's body.
56
+ const focused = document.activeElement;
57
+ const inside = !focused || focused === document.body || Boolean(menu?.contains(focused));
58
+ if (!outcome) return shell.close(inside);
59
+ focusInMenu = inside && !props.target;
60
+ if (inside && props.target) props.target.focus({
61
+ preventScroll: true
62
+ });else if (focusInMenu) queueMicrotask(() => menu?.querySelector(".k2b-command-outcome")?.focus({
63
+ preventScroll: true
64
+ }));
65
+ },
66
+ onStep: () => setQuery("")
67
+ });
68
+ /** Writes into the target at its caret, as typing would, or hands the text to `onInsert`. */
69
+ const insert = text => {
70
+ const target = props.target;
71
+ if (!target) return props.onInsert?.(text);
72
+ replaceTextareaRange(target, target.selectionStart ?? 0, target.selectionEnd ?? 0, text);
73
+ };
74
+ // An outcome that cleared closes the menu; the focus returns to the trigger only from inside it.
75
+ createEffect(on(nav.outcome, (outcome, previous) => {
76
+ if (menu) {
77
+ if (outcome) menu.dataset.outcome = outcome.state;else delete menu.dataset.outcome;
78
+ }
79
+ if (!outcome && previous && shell.open()) shell.close(Boolean(menu?.contains(document.activeElement)) || focusInMenu);
80
+ }, {
81
+ defer: true
82
+ }));
83
+ // Typing on in the target clears an outcome once it showed long enough; keys on the outcome itself do too. When
84
+ // the typing opened another list for the target, such as its slash commands, the outcome gives way at once.
85
+ createEffect(() => {
86
+ const target = props.target;
87
+ if (!target || !nav.outcome()) return;
88
+ const typed = () => {
89
+ nav.typedOn();
90
+ queueMicrotask(() => {
91
+ const controls = target.getAttribute("aria-controls");
92
+ if (controls && controls !== listId) nav.clearOutcome();
93
+ });
94
+ };
95
+ target.addEventListener("input", typed);
96
+ onCleanup(() => target.removeEventListener("input", typed));
97
+ });
98
+ createEffect(on(shell.open, open => {
99
+ menu = input.closest(".k2b-dropdown__menu") ?? menu;
100
+ const docked = menu;
101
+ const dock = props.dock;
102
+ if (open && dock && docked) {
103
+ // A phone's keyboard moves the visible viewport, which the menu follows like the slash list.
104
+ const follow = () => {
105
+ if (docked.matches(":popover-open")) dockCommandList(docked, dock);
106
+ };
107
+ follow();
108
+ const stop = followComposer(dock, follow);
109
+ const closed = () => {
110
+ if (!docked.matches(":popover-open")) {
111
+ stop();
112
+ docked.removeEventListener("toggle", closed);
113
+ }
114
+ };
115
+ docked.addEventListener("toggle", closed);
116
+ return;
117
+ }
118
+ if (open) {
119
+ // The width it opened with stays its least, so filtering never narrows it.
120
+ queueMicrotask(() => {
121
+ if (menu?.matches(":popover-open")) menu.style.minWidth = `min(${menu.getBoundingClientRect().width}px, 100vw - 2rem)`;
122
+ });
123
+ return;
124
+ }
125
+ if (menu) menu.style.minWidth = "";
126
+ // Closing the menu, with Escape or a press outside, stops a running command and clears its outcome.
127
+ nav.abort();
128
+ nav.clearOutcome();
129
+ nav.reset();
130
+ setQuery("");
131
+ focusInMenu = false;
132
+ }));
133
+ shell.api({
134
+ focus: mark => {
135
+ input.focus({
136
+ preventScroll: true
137
+ });
138
+ if (mark === "last") nav.edge("last");
139
+ }
140
+ });
141
+ const search = _$ssr(_tmpl$, _$ssrAttribute("aria-label", _$escape(nav.step()?.next?.label ?? props.search, true), false), _$ssrAttribute("aria-controls", _$escape(listId, true), false), _$ssrAttribute("aria-activedescendant", nav.entries()[nav.active()] && !nav.entries()[nav.active()].disabled ? _$escape(commandOptionId(listId, nav.active()), true) : _$escape(undefined, true), false), _$ssrAttribute("placeholder", _$escape(nav.step()?.next?.label ?? props.search, true), false) + _$ssrAttribute("value", _$escape(query(), true), false) + _$ssrAttribute("readonly", _$escape(nav.busy(), true), false));
142
+ return _$createComponent(CommandList, {
143
+ navigator: nav,
144
+ id: listId,
145
+ get label() {
146
+ return props.label;
147
+ },
148
+ query: query,
149
+ header: search,
150
+ onOutcomeAction: () => {
151
+ if (props.target) props.target.focus({
152
+ preventScroll: true
153
+ });else menu?.querySelector(".k2b-command-outcome")?.focus({
154
+ preventScroll: true
155
+ });
156
+ }
157
+ });
158
+ };
159
+ return _$createComponent(DropdownShell, {
160
+ items: [],
161
+ body: body,
162
+ get label() {
163
+ return props.label;
164
+ },
165
+ menuClass: "k2b-command-menu",
166
+ get placeMenu() {
167
+ return props.dock ? menu => dockCommandList(menu, props.dock) : undefined;
168
+ },
169
+ get position() {
170
+ return props.position;
171
+ },
172
+ get align() {
173
+ return props.align;
174
+ },
175
+ get openAt() {
176
+ return props.openAt;
177
+ },
178
+ get attach() {
179
+ return props.attach;
180
+ },
181
+ get onOpenChange() {
182
+ return props.onOpenChange;
183
+ },
184
+ get disabled() {
185
+ return props.disabled;
186
+ },
187
+ get ["class"]() {
188
+ return props.class;
189
+ },
190
+ get children() {
191
+ return props.children;
192
+ }
193
+ });
194
+ }
195
+ export const CommandMenu = CommandMenuRoot;
196
+ CommandMenu.Trigger = Dropdown.Trigger;
197
+ //# sourceMappingURL=CommandMenu.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":[],"sources":["actions/CommandMenu.tsx"],"sourcesContent":["import { createEffect, createSignal, createUniqueId, type JSX, on, onCleanup } from \"solid-js\";\nimport { replaceTextareaRange } from \"../inputs/editor-dom\";\nimport { CommandList, commandListKey, commandOptionId, createCommandNavigator } from \"./CommandList\";\nimport { dockCommandList, followComposer } from \"./command-dock\";\nimport { type CommandSource, commandPlace } from \"./command-items\";\nimport {\n Dropdown,\n type DropdownAnchor,\n type DropdownBody,\n type DropdownPosition,\n type DropdownReturnFocus,\n DropdownShell,\n} from \"./Dropdown\";\n\nexport type CommandMenuProps = {\n /** The same entries as `MarkdownEditor`'s `commands`, so the slash menu, a \"+\" button, and a chip offer one list. */\n items: CommandSource;\n /** Names the menu and its first list, such as \"Add to message\". */\n label: string;\n /** Names the search field and is its hint, such as \"Search commands\". A second list shows its own label there. */\n search: string;\n /**\n * The field the commands act on, such as the composer's textarea beside a \"+\" button. Its text and selection are the\n * `context` of an `onSelect`, and `context.insert` and entries with `text` write into it as typing would.\n */\n target?: HTMLTextAreaElement | HTMLInputElement;\n /**\n * The composer box the menu docks to, as the slash list does: as wide as the box, just above it, or below it when\n * there is more room there. Without it, the menu opens beside its trigger.\n */\n dock?: HTMLElement;\n /** Receives inserted text when there is no `target`, such as a snippet the host places itself. */\n onInsert?: (text: string) => void;\n /** The `CommandMenu.Trigger`; leave it out for a menu opened through `openAt` or `attach`. */\n children?: JSX.Element;\n position?: DropdownPosition;\n align?: \"start\" | \"end\";\n /** Receives `open`, which shows the menu beside `anchor` without its trigger; focus returns to `returnFocus`. */\n openAt?: (open: (anchor: DropdownAnchor, returnFocus?: DropdownReturnFocus) => void) => void;\n /** Adopts an element rendered elsewhere, such as a server-rendered chip, as the trigger. */\n attach?: () => HTMLElement | null | undefined;\n onOpenChange?: (open: boolean) => void;\n disabled?: boolean;\n class?: string;\n};\n\n/**\n * A searchable command list beside a trigger or an anchor, with the slash menu's entries and rows: groups, icons,\n * unavailable entries with their reason, and second lists. Focus stays in the search field; Up, Down, Home, and End\n * mark, Enter and Tab choose, Escape or Backspace in an empty field go back, and Escape in the first list closes.\n */\nfunction CommandMenuRoot(props: CommandMenuProps): JSX.Element {\n const body: DropdownBody = (shell) => {\n const listId = `k2b-command-menu-${createUniqueId().replace(/[^a-zA-Z0-9_-]/g, \"-\")}`;\n const [query, setQuery] = createSignal(\"\");\n let input!: HTMLInputElement;\n /** The open menu, kept while an outcome replaces the search field that finds it. */\n let menu: HTMLElement | null = null;\n /** Where the focus was when an outcome took the list's place: inside the menu, or in the target. */\n let focusInMenu = false;\n const nav = createCommandNavigator({\n items: () => props.items,\n query,\n onText: (item) => {\n // Read before closing: closing resets the list.\n const text = item.text ?? \"\";\n const target = props.target;\n shell.close(!target);\n insert(text);\n },\n context: () => {\n const target = props.target;\n const value = target?.value ?? \"\";\n const start = target?.selectionStart ?? 0;\n return {\n ...commandPlace(value, start, start),\n selection: { start, end: target?.selectionEnd ?? start },\n insert: (text: string) => insert(text),\n };\n },\n active: shell.open,\n // The focus goes back to the trigger only from inside the menu: an entry that wrote into the target, or moved\n // the focus elsewhere itself, leaves it there. An outcome keeps the menu open in the list's place: the person\n // writes on in the target, or, without one, the focus rests on the outcome until it clears.\n afterRun: (outcome) => {\n // An outcome replaces the search field before this runs, which leaves the focus on the page's body.\n const focused = document.activeElement;\n const inside = !focused || focused === document.body || Boolean(menu?.contains(focused));\n if (!outcome) return shell.close(inside);\n focusInMenu = inside && !props.target;\n if (inside && props.target) props.target.focus({ preventScroll: true });\n else if (focusInMenu)\n queueMicrotask(() => menu?.querySelector<HTMLElement>(\".k2b-command-outcome\")?.focus({ preventScroll: true }));\n },\n onStep: () => setQuery(\"\"),\n });\n /** Writes into the target at its caret, as typing would, or hands the text to `onInsert`. */\n const insert = (text: string) => {\n const target = props.target;\n if (!target) return props.onInsert?.(text);\n replaceTextareaRange(target as HTMLTextAreaElement, target.selectionStart ?? 0, target.selectionEnd ?? 0, text);\n };\n // An outcome that cleared closes the menu; the focus returns to the trigger only from inside it.\n createEffect(\n on(\n nav.outcome,\n (outcome, previous) => {\n if (menu) {\n if (outcome) menu.dataset.outcome = outcome.state;\n else delete menu.dataset.outcome;\n }\n if (!outcome && previous && shell.open()) shell.close(Boolean(menu?.contains(document.activeElement)) || focusInMenu);\n },\n { defer: true },\n ),\n );\n // Typing on in the target clears an outcome once it showed long enough; keys on the outcome itself do too. When\n // the typing opened another list for the target, such as its slash commands, the outcome gives way at once.\n createEffect(() => {\n const target = props.target;\n if (!target || !nav.outcome()) return;\n const typed = () => {\n nav.typedOn();\n queueMicrotask(() => {\n const controls = target.getAttribute(\"aria-controls\");\n if (controls && controls !== listId) nav.clearOutcome();\n });\n };\n target.addEventListener(\"input\", typed);\n onCleanup(() => target.removeEventListener(\"input\", typed));\n });\n createEffect(\n on(shell.open, (open) => {\n menu = input.closest<HTMLElement>(\".k2b-dropdown__menu\") ?? menu;\n const docked = menu;\n const dock = props.dock;\n if (open && dock && docked) {\n // A phone's keyboard moves the visible viewport, which the menu follows like the slash list.\n const follow = () => {\n if (docked.matches(\":popover-open\")) dockCommandList(docked, dock);\n };\n follow();\n const stop = followComposer(dock, follow);\n const closed = () => {\n if (!docked.matches(\":popover-open\")) {\n stop();\n docked.removeEventListener(\"toggle\", closed);\n }\n };\n docked.addEventListener(\"toggle\", closed);\n return;\n }\n if (open) {\n // The width it opened with stays its least, so filtering never narrows it.\n queueMicrotask(() => {\n if (menu?.matches(\":popover-open\")) menu.style.minWidth = `min(${menu.getBoundingClientRect().width}px, 100vw - 2rem)`;\n });\n return;\n }\n if (menu) menu.style.minWidth = \"\";\n // Closing the menu, with Escape or a press outside, stops a running command and clears its outcome.\n nav.abort();\n nav.clearOutcome();\n nav.reset();\n setQuery(\"\");\n focusInMenu = false;\n }),\n );\n shell.api({\n focus: (mark) => {\n input.focus({ preventScroll: true });\n if (mark === \"last\") nav.edge(\"last\");\n },\n });\n const search = (\n <label class=\"k2b-dropdown__search\">\n <i class=\"ti ti-search\" aria-hidden=\"true\" />\n <input\n ref={input}\n type=\"search\"\n role=\"combobox\"\n aria-label={nav.step()?.next?.label ?? props.search}\n aria-expanded=\"true\"\n aria-controls={listId}\n aria-autocomplete=\"list\"\n aria-activedescendant={\n nav.entries()[nav.active()] && !nav.entries()[nav.active()]!.disabled ? commandOptionId(listId, nav.active()) : undefined\n }\n autocomplete=\"off\"\n spellcheck={false}\n enterkeyhint=\"go\"\n placeholder={nav.step()?.next?.label ?? props.search}\n value={query()}\n // While a command runs, the list waits for it; the query keeps the running entry in view.\n readOnly={nav.busy()}\n onInput={(event) => setQuery(event.currentTarget.value)}\n onKeyDown={(event) => {\n if (!commandListKey(nav, event, query())) return;\n // Escape that left a second list, and Tab that chose, stay inside the menu.\n event.preventDefault();\n event.stopPropagation();\n }}\n />\n </label>\n );\n return (\n <CommandList\n navigator={nav}\n id={listId}\n label={props.label}\n query={query}\n header={search}\n // After Retry or Close the focus stays where the person works: the target, or the outcome itself.\n onOutcomeAction={() => {\n if (props.target) props.target.focus({ preventScroll: true });\n else menu?.querySelector<HTMLElement>(\".k2b-command-outcome\")?.focus({ preventScroll: true });\n }}\n />\n );\n };\n\n return (\n <DropdownShell\n items={[]}\n body={body}\n label={props.label}\n menuClass=\"k2b-command-menu\"\n placeMenu={props.dock ? (menu) => dockCommandList(menu, props.dock!) : undefined}\n position={props.position}\n align={props.align}\n openAt={props.openAt}\n attach={props.attach}\n onOpenChange={props.onOpenChange}\n disabled={props.disabled}\n class={props.class}\n >\n {props.children}\n </DropdownShell>\n );\n}\n\ntype CommandMenuComponent = ((props: CommandMenuProps) => JSX.Element) & {\n Trigger: typeof Dropdown.Trigger;\n};\n\nexport const CommandMenu = CommandMenuRoot as CommandMenuComponent;\nCommandMenu.Trigger = Dropdown.Trigger;\n"],"mappings":"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","ignoreList":[]}
@@ -103,6 +103,9 @@ export function ContextMenuBase(props) {
103
103
  const close = () => {
104
104
  detachOpenListeners();
105
105
  if (!isOpen()) return;
106
+ // An activated entry closes the menu before its action runs: focus goes back to where the menu opened from, as
107
+ // Escape returns it, so the keyboard never lands on the page body.
108
+ if (menu?.contains(document.activeElement)) returnFocus(opener?.isConnected ? opener : host, hostRing);
106
109
  setPosition();
107
110
  if (closeActiveContextMenu === close) closeActiveContextMenu = undefined;
108
111
  props.onClose?.();
@@ -1 +1 @@
1
- {"version":3,"names":[],"sources":["actions/ContextMenu.tsx"],"sourcesContent":["import { createMemo, createSignal, createUniqueId, type JSX, onCleanup, onMount, Show } from \"solid-js\";\nimport { Portal } from \"solid-js/web\";\nimport { returnFocus, ringOnReturn } from \"../internal/focus-return\";\nimport { useUiMessages } from \"../intl/messages\";\nimport { type DropdownItem, DropdownItems, type DropdownPosition, dropdownPosition } from \"./Dropdown\";\nimport { focusRowSegment } from \"./menu-rows\";\n\nexport type ContextMenuProps = {\n items: readonly DropdownItem[];\n children: JSX.Element;\n class?: string | ((isOpen: boolean) => string);\n /** Tab order of the context-menu host. Descendant-focused composite widgets use -1. */\n tabIndex?: number;\n disabled?: boolean;\n onClose?: () => void;\n onOpen?: () => void;\n id?: string;\n label?: string;\n /**\n * Links, form fields, editable text, and selected text inside the host keep the browser's own menu, with its Copy,\n * Paste, and Open link. Use it where the host wraps readable content rather than one row.\n */\n keepNativeMenu?: boolean;\n};\n\nconst NATIVE_MENU_TARGETS = \"a[href], input, textarea, select, [contenteditable]:not([contenteditable='false'])\";\n\nlet closeActiveContextMenu: (() => void) | undefined;\n\nconst focusableItems = (menu: HTMLElement | undefined): HTMLElement[] =>\n menu\n ? Array.from(\n menu.querySelectorAll<HTMLElement>(\n [\n \"[role='menuitem']:not([aria-disabled='true'])\",\n \"[role='menuitemcheckbox']:not([aria-disabled='true'])\",\n \"[role='menuitemradio']:not([aria-disabled='true'])\",\n ].join(\", \"),\n ),\n )\n : [];\n\n/** Right-click menu with keyboard invocation, one-open-at-a-time behavior, and viewport clamping. */\nexport function ContextMenu(props: ContextMenuProps): JSX.Element {\n return ContextMenuBase(props);\n}\n\n/**\n * Package-internal, not exported from the package index: `openAt` lets GestureMenu open the menu at a held finger, and\n * `title` names what was pressed above the entries, since the finger covers it.\n */\nexport function ContextMenuBase(\n props: ContextMenuProps & {\n openAt?: (open: (x: number, y: number) => void) => void;\n title?: string;\n closeWith?: (close: () => void) => void;\n },\n): JSX.Element {\n const messages = useUiMessages();\n const generatedId = `k2b-context-${createUniqueId()}`;\n const menuId = `${generatedId}-menu`;\n const [position, setPosition] = createSignal<{ x: number; y: number }>();\n let host: HTMLDivElement | undefined;\n let menu: HTMLDivElement | undefined;\n let listenersAttached = false;\n let hostRing = true;\n /** The element inside the host that had focus as the menu opened, such as a row or a day of a composite widget. */\n let opener: HTMLElement | undefined;\n let anchor = { x: 0, y: 0 };\n let viewport = { width: 0, height: 0 };\n let resizeObserver: ResizeObserver | undefined;\n\n const isOpen = () => position() !== undefined;\n const keepsNativeMenu = (target: EventTarget | null): boolean => {\n if (!props.keepNativeMenu || !(target instanceof Node)) return false;\n const element = target instanceof Element ? target : target.parentElement;\n const native = element?.closest(NATIVE_MENU_TARGETS);\n if (native && host?.contains(native)) return true;\n const selection = window.getSelection();\n return Boolean(selection && !selection.isCollapsed && selection.toString().trim() && selection.containsNode(target, true));\n };\n const hostClass = createMemo(() => (typeof props.class === \"function\" ? props.class(isOpen()) : props.class));\n const items = createMemo<readonly DropdownItem[]>(() => props.items);\n\n const dismiss = (event: PointerEvent) => {\n if (menu?.contains(event.target as Node)) return;\n close();\n };\n const closeOnScroll = (event: Event) => {\n const target = event.target;\n if (target instanceof Node && menu?.contains(target)) return;\n close();\n };\n // A resize event may leave the viewport's size unchanged; headless Chromium\n // was seen to fire one on a fresh page. The clamped menu is still in place.\n const closeOnResize = () => {\n if (window.innerWidth === viewport.width && window.innerHeight === viewport.height) return;\n close();\n };\n const attachOpenListeners = () => {\n if (listenersAttached) return;\n listenersAttached = true;\n document.addEventListener(\"pointerdown\", dismiss);\n document.addEventListener(\"keydown\", keyDown);\n window.addEventListener(\"resize\", closeOnResize);\n window.addEventListener(\"scroll\", closeOnScroll, true);\n };\n const detachOpenListeners = () => {\n if (!listenersAttached) return;\n listenersAttached = false;\n document.removeEventListener(\"pointerdown\", dismiss);\n document.removeEventListener(\"keydown\", keyDown);\n window.removeEventListener(\"resize\", closeOnResize);\n window.removeEventListener(\"scroll\", closeOnScroll, true);\n resizeObserver?.disconnect();\n };\n /** Clamps the rendered menu into the viewport beside the point that opened it. */\n const place = () => {\n if (!isOpen() || !menu?.isConnected) return;\n const point = dropdownPosition(\n new DOMRect(anchor.x, anchor.y, 0, 0),\n menu.getBoundingClientRect(),\n \"bottom-right\" satisfies DropdownPosition,\n { width: window.innerWidth, height: window.innerHeight },\n 0,\n );\n setPosition({ x: point.left, y: point.top });\n };\n const close = () => {\n detachOpenListeners();\n if (!isOpen()) return;\n setPosition();\n if (closeActiveContextMenu === close) closeActiveContextMenu = undefined;\n props.onClose?.();\n };\n const focusItem = (index: number) => {\n const items = focusableItems(menu);\n if (items.length === 0) return;\n items[(index + items.length) % items.length]?.focus();\n };\n const open = (x: number, y: number) => {\n if (props.disabled) return;\n closeActiveContextMenu?.();\n // Focus may sit on a descendant of the host, as in composite widgets; Escape returns it there.\n const focused = document.activeElement;\n opener = focused instanceof HTMLElement && focused !== host && host?.contains(focused) ? focused : undefined;\n hostRing = ringOnReturn(focused);\n anchor = { x, y };\n viewport = { width: window.innerWidth, height: window.innerHeight };\n setPosition({ x, y });\n closeActiveContextMenu = close;\n attachOpenListeners();\n props.onOpen?.();\n // The menu sizes to its entries, so it is measured once rendered and\n // clamped into the viewport before the next paint, and again whenever its\n // entries change its size while it is open.\n queueMicrotask(() => {\n if (!isOpen() || !menu?.isConnected) return;\n place();\n if (typeof ResizeObserver !== \"undefined\") {\n resizeObserver ??= new ResizeObserver(place);\n resizeObserver.observe(menu);\n }\n focusItem(0);\n });\n };\n const keyDown = (event: KeyboardEvent) => {\n if (!isOpen()) return;\n const items = focusableItems(menu);\n const current = items.indexOf(document.activeElement as HTMLElement);\n if (event.key === \"ArrowDown\" || event.key === \"ArrowUp\") {\n event.preventDefault();\n focusItem(current + (event.key === \"ArrowDown\" ? 1 : -1));\n } else if (focusRowSegment(items, event.key)) {\n event.preventDefault();\n } else if (event.key === \"Home\" || event.key === \"End\") {\n event.preventDefault();\n focusItem(event.key === \"Home\" ? 0 : -1);\n } else if (event.key === \"Escape\") {\n event.preventDefault();\n close();\n returnFocus(opener?.isConnected ? opener : host, hostRing);\n } else if (event.key === \"Tab\") {\n close();\n }\n };\n\n props.openAt?.(open);\n // A close from outside, such as a drag taking over the press, returns focus that sits in the menu to where it came from.\n props.closeWith?.(() => {\n if (isOpen() && menu?.contains(document.activeElement)) returnFocus(opener?.isConnected ? opener : host, hostRing);\n close();\n });\n\n onMount(() => {\n onCleanup(() => {\n detachOpenListeners();\n if (closeActiveContextMenu === close) closeActiveContextMenu = undefined;\n });\n });\n\n return (\n <>\n {/* biome-ignore lint/a11y/useAriaPropsSupportedByRole: the named group owns the context-menu relationship without pretending arbitrary children form one button. */}\n <div\n ref={host}\n id={props.id ?? generatedId}\n class={hostClass()}\n role=\"group\"\n tabIndex={props.disabled ? undefined : (props.tabIndex ?? 0)}\n aria-label={props.label ?? messages().contextMenu}\n aria-haspopup=\"menu\"\n aria-expanded={isOpen()}\n aria-controls={isOpen() ? menuId : undefined}\n aria-disabled={props.disabled ? \"true\" : undefined}\n onContextMenu={(event) => {\n if (props.disabled) return;\n // An enclosing context menu must not take over the browser's own either.\n if (keepsNativeMenu(event.target)) return void event.stopPropagation();\n event.preventDefault();\n event.stopPropagation();\n open(event.clientX, event.clientY);\n }}\n onKeyDown={(event) => {\n if (props.disabled || (event.key !== \"ContextMenu\" && !(event.shiftKey && event.key === \"F10\"))) return;\n // A nested context menu already opened its own; a field keeps the browser's.\n if (\n event.defaultPrevented ||\n (props.keepNativeMenu && event.target instanceof Element && event.target.closest(NATIVE_MENU_TARGETS))\n )\n return;\n event.preventDefault();\n // Beside the focused element, such as a row of a composite widget, rather than the corner of the whole host.\n const focused = document.activeElement;\n const rect = (focused instanceof HTMLElement && host?.contains(focused) ? focused : host)?.getBoundingClientRect();\n if (rect) open(rect.left + 12, rect.top + 12);\n }}\n >\n {props.children}\n </div>\n <Show when={position()}>\n {(point) => (\n <Portal>\n <div\n ref={menu}\n id={menuId}\n class=\"k2b-ui k2b-context-menu\"\n role=\"menu\"\n aria-label={props.label ?? messages().contextMenu}\n style={{ left: `${point().x}px`, top: `${point().y}px` }}\n onPointerDown={(event) => event.stopPropagation()}\n >\n {/* The menu carries the same name for assistive technology. */}\n <Show when={props.title}>\n <div class=\"k2b-context-menu__title\" aria-hidden=\"true\">\n {props.title}\n </div>\n </Show>\n <DropdownItems items={items()} close={close} />\n </div>\n </Portal>\n )}\n </Show>\n </>\n );\n}\n\nexport default ContextMenu;\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":[],"sources":["actions/ContextMenu.tsx"],"sourcesContent":["import { createMemo, createSignal, createUniqueId, type JSX, onCleanup, onMount, Show } from \"solid-js\";\nimport { Portal } from \"solid-js/web\";\nimport { returnFocus, ringOnReturn } from \"../internal/focus-return\";\nimport { useUiMessages } from \"../intl/messages\";\nimport { type DropdownItem, DropdownItems, type DropdownPosition, dropdownPosition } from \"./Dropdown\";\nimport { focusRowSegment } from \"./menu-rows\";\n\nexport type ContextMenuProps = {\n items: readonly DropdownItem[];\n children: JSX.Element;\n class?: string | ((isOpen: boolean) => string);\n /** Tab order of the context-menu host. Descendant-focused composite widgets use -1. */\n tabIndex?: number;\n disabled?: boolean;\n onClose?: () => void;\n onOpen?: () => void;\n id?: string;\n label?: string;\n /**\n * Links, form fields, editable text, and selected text inside the host keep the browser's own menu, with its Copy,\n * Paste, and Open link. Use it where the host wraps readable content rather than one row.\n */\n keepNativeMenu?: boolean;\n};\n\nconst NATIVE_MENU_TARGETS = \"a[href], input, textarea, select, [contenteditable]:not([contenteditable='false'])\";\n\nlet closeActiveContextMenu: (() => void) | undefined;\n\nconst focusableItems = (menu: HTMLElement | undefined): HTMLElement[] =>\n menu\n ? Array.from(\n menu.querySelectorAll<HTMLElement>(\n [\n \"[role='menuitem']:not([aria-disabled='true'])\",\n \"[role='menuitemcheckbox']:not([aria-disabled='true'])\",\n \"[role='menuitemradio']:not([aria-disabled='true'])\",\n ].join(\", \"),\n ),\n )\n : [];\n\n/** Right-click menu with keyboard invocation, one-open-at-a-time behavior, and viewport clamping. */\nexport function ContextMenu(props: ContextMenuProps): JSX.Element {\n return ContextMenuBase(props);\n}\n\n/**\n * Package-internal, not exported from the package index: `openAt` lets GestureMenu open the menu at a held finger, and\n * `title` names what was pressed above the entries, since the finger covers it.\n */\nexport function ContextMenuBase(\n props: ContextMenuProps & {\n openAt?: (open: (x: number, y: number) => void) => void;\n title?: string;\n closeWith?: (close: () => void) => void;\n },\n): JSX.Element {\n const messages = useUiMessages();\n const generatedId = `k2b-context-${createUniqueId()}`;\n const menuId = `${generatedId}-menu`;\n const [position, setPosition] = createSignal<{ x: number; y: number }>();\n let host: HTMLDivElement | undefined;\n let menu: HTMLDivElement | undefined;\n let listenersAttached = false;\n let hostRing = true;\n /** The element inside the host that had focus as the menu opened, such as a row or a day of a composite widget. */\n let opener: HTMLElement | undefined;\n let anchor = { x: 0, y: 0 };\n let viewport = { width: 0, height: 0 };\n let resizeObserver: ResizeObserver | undefined;\n\n const isOpen = () => position() !== undefined;\n const keepsNativeMenu = (target: EventTarget | null): boolean => {\n if (!props.keepNativeMenu || !(target instanceof Node)) return false;\n const element = target instanceof Element ? target : target.parentElement;\n const native = element?.closest(NATIVE_MENU_TARGETS);\n if (native && host?.contains(native)) return true;\n const selection = window.getSelection();\n return Boolean(selection && !selection.isCollapsed && selection.toString().trim() && selection.containsNode(target, true));\n };\n const hostClass = createMemo(() => (typeof props.class === \"function\" ? props.class(isOpen()) : props.class));\n const items = createMemo<readonly DropdownItem[]>(() => props.items);\n\n const dismiss = (event: PointerEvent) => {\n if (menu?.contains(event.target as Node)) return;\n close();\n };\n const closeOnScroll = (event: Event) => {\n const target = event.target;\n if (target instanceof Node && menu?.contains(target)) return;\n close();\n };\n // A resize event may leave the viewport's size unchanged; headless Chromium\n // was seen to fire one on a fresh page. The clamped menu is still in place.\n const closeOnResize = () => {\n if (window.innerWidth === viewport.width && window.innerHeight === viewport.height) return;\n close();\n };\n const attachOpenListeners = () => {\n if (listenersAttached) return;\n listenersAttached = true;\n document.addEventListener(\"pointerdown\", dismiss);\n document.addEventListener(\"keydown\", keyDown);\n window.addEventListener(\"resize\", closeOnResize);\n window.addEventListener(\"scroll\", closeOnScroll, true);\n };\n const detachOpenListeners = () => {\n if (!listenersAttached) return;\n listenersAttached = false;\n document.removeEventListener(\"pointerdown\", dismiss);\n document.removeEventListener(\"keydown\", keyDown);\n window.removeEventListener(\"resize\", closeOnResize);\n window.removeEventListener(\"scroll\", closeOnScroll, true);\n resizeObserver?.disconnect();\n };\n /** Clamps the rendered menu into the viewport beside the point that opened it. */\n const place = () => {\n if (!isOpen() || !menu?.isConnected) return;\n const point = dropdownPosition(\n new DOMRect(anchor.x, anchor.y, 0, 0),\n menu.getBoundingClientRect(),\n \"bottom-right\" satisfies DropdownPosition,\n { width: window.innerWidth, height: window.innerHeight },\n 0,\n );\n setPosition({ x: point.left, y: point.top });\n };\n const close = () => {\n detachOpenListeners();\n if (!isOpen()) return;\n // An activated entry closes the menu before its action runs: focus goes back to where the menu opened from, as\n // Escape returns it, so the keyboard never lands on the page body.\n if (menu?.contains(document.activeElement)) returnFocus(opener?.isConnected ? opener : host, hostRing);\n setPosition();\n if (closeActiveContextMenu === close) closeActiveContextMenu = undefined;\n props.onClose?.();\n };\n const focusItem = (index: number) => {\n const items = focusableItems(menu);\n if (items.length === 0) return;\n items[(index + items.length) % items.length]?.focus();\n };\n const open = (x: number, y: number) => {\n if (props.disabled) return;\n closeActiveContextMenu?.();\n // Focus may sit on a descendant of the host, as in composite widgets; Escape returns it there.\n const focused = document.activeElement;\n opener = focused instanceof HTMLElement && focused !== host && host?.contains(focused) ? focused : undefined;\n hostRing = ringOnReturn(focused);\n anchor = { x, y };\n viewport = { width: window.innerWidth, height: window.innerHeight };\n setPosition({ x, y });\n closeActiveContextMenu = close;\n attachOpenListeners();\n props.onOpen?.();\n // The menu sizes to its entries, so it is measured once rendered and\n // clamped into the viewport before the next paint, and again whenever its\n // entries change its size while it is open.\n queueMicrotask(() => {\n if (!isOpen() || !menu?.isConnected) return;\n place();\n if (typeof ResizeObserver !== \"undefined\") {\n resizeObserver ??= new ResizeObserver(place);\n resizeObserver.observe(menu);\n }\n focusItem(0);\n });\n };\n const keyDown = (event: KeyboardEvent) => {\n if (!isOpen()) return;\n const items = focusableItems(menu);\n const current = items.indexOf(document.activeElement as HTMLElement);\n if (event.key === \"ArrowDown\" || event.key === \"ArrowUp\") {\n event.preventDefault();\n focusItem(current + (event.key === \"ArrowDown\" ? 1 : -1));\n } else if (focusRowSegment(items, event.key)) {\n event.preventDefault();\n } else if (event.key === \"Home\" || event.key === \"End\") {\n event.preventDefault();\n focusItem(event.key === \"Home\" ? 0 : -1);\n } else if (event.key === \"Escape\") {\n event.preventDefault();\n close();\n returnFocus(opener?.isConnected ? opener : host, hostRing);\n } else if (event.key === \"Tab\") {\n close();\n }\n };\n\n props.openAt?.(open);\n // A close from outside, such as a drag taking over the press, returns focus that sits in the menu to where it came from.\n props.closeWith?.(() => {\n if (isOpen() && menu?.contains(document.activeElement)) returnFocus(opener?.isConnected ? opener : host, hostRing);\n close();\n });\n\n onMount(() => {\n onCleanup(() => {\n detachOpenListeners();\n if (closeActiveContextMenu === close) closeActiveContextMenu = undefined;\n });\n });\n\n return (\n <>\n {/* biome-ignore lint/a11y/useAriaPropsSupportedByRole: the named group owns the context-menu relationship without pretending arbitrary children form one button. */}\n <div\n ref={host}\n id={props.id ?? generatedId}\n class={hostClass()}\n role=\"group\"\n tabIndex={props.disabled ? undefined : (props.tabIndex ?? 0)}\n aria-label={props.label ?? messages().contextMenu}\n aria-haspopup=\"menu\"\n aria-expanded={isOpen()}\n aria-controls={isOpen() ? menuId : undefined}\n aria-disabled={props.disabled ? \"true\" : undefined}\n onContextMenu={(event) => {\n if (props.disabled) return;\n // An enclosing context menu must not take over the browser's own either.\n if (keepsNativeMenu(event.target)) return void event.stopPropagation();\n event.preventDefault();\n event.stopPropagation();\n open(event.clientX, event.clientY);\n }}\n onKeyDown={(event) => {\n if (props.disabled || (event.key !== \"ContextMenu\" && !(event.shiftKey && event.key === \"F10\"))) return;\n // A nested context menu already opened its own; a field keeps the browser's.\n if (\n event.defaultPrevented ||\n (props.keepNativeMenu && event.target instanceof Element && event.target.closest(NATIVE_MENU_TARGETS))\n )\n return;\n event.preventDefault();\n // Beside the focused element, such as a row of a composite widget, rather than the corner of the whole host.\n const focused = document.activeElement;\n const rect = (focused instanceof HTMLElement && host?.contains(focused) ? focused : host)?.getBoundingClientRect();\n if (rect) open(rect.left + 12, rect.top + 12);\n }}\n >\n {props.children}\n </div>\n <Show when={position()}>\n {(point) => (\n <Portal>\n <div\n ref={menu}\n id={menuId}\n class=\"k2b-ui k2b-context-menu\"\n role=\"menu\"\n aria-label={props.label ?? messages().contextMenu}\n style={{ left: `${point().x}px`, top: `${point().y}px` }}\n onPointerDown={(event) => event.stopPropagation()}\n >\n {/* The menu carries the same name for assistive technology. */}\n <Show when={props.title}>\n <div class=\"k2b-context-menu__title\" aria-hidden=\"true\">\n {props.title}\n </div>\n </Show>\n <DropdownItems items={items()} close={close} />\n </div>\n </Portal>\n )}\n </Show>\n </>\n );\n}\n\nexport default ContextMenu;\n"],"mappings":"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","ignoreList":[]}
@@ -468,6 +468,11 @@ function DropdownTrigger(props) {
468
468
  })];
469
469
  }
470
470
 
471
+ /**
472
+ * Internal: content in place of the entries, as `CommandMenu` renders its command list. It reports where the focus
473
+ * goes as the menu opens, like the search field, and `open` tells it when the menu closed.
474
+ */
475
+
471
476
  /** Accessible top-layer menu with explicit trigger ownership. */
472
477
  function DropdownRoot(props) {
473
478
  const messages = useUiMessages();
@@ -500,6 +505,8 @@ function DropdownRoot(props) {
500
505
  const isOpen = () => props.open ?? internalOpen();
501
506
  const position = () => typeof props.position === "function" ? props.position() : props.position ?? (props.align === "end" ? "bottom-left" : "bottom-right");
502
507
  const place = () => {
508
+ // Internal: `CommandMenu` docks its menu to a composer instead of its trigger.
509
+ if (props.placeMenu && menuRef) return props.placeMenu(menuRef);
503
510
  const at = anchor ?? triggerRef;
504
511
  if (!at || !menuRef) return;
505
512
  const rect = dropdownPosition(at.getBoundingClientRect(), menuRef.getBoundingClientRect(), position(), {
@@ -562,7 +569,7 @@ function DropdownRoot(props) {
562
569
  props.onOpenChange?.(next);
563
570
  return;
564
571
  }
565
- if (next && props.phone === "sheet" && prefersMenuSheet()) {
572
+ if (next && props.phone === "sheet" && !props.body && prefersMenuSheet()) {
566
573
  if (sheet) return;
567
574
  const current = new AbortController();
568
575
  sheet = current;
@@ -601,7 +608,7 @@ function DropdownRoot(props) {
601
608
  const handleMenuKeyDown = event => {
602
609
  const items = actionableItems(menuRef);
603
610
  // A searchable menu's field keeps the focus and moves the marked entry itself.
604
- if (!props.search && (focusMenuRow(items, event.key) || focusRowSegment(items, event.key))) {
611
+ if (!props.search && !props.body && (focusMenuRow(items, event.key) || focusRowSegment(items, event.key))) {
605
612
  event.preventDefault();
606
613
  } else if (event.key === "Escape") {
607
614
  event.preventDefault();
@@ -638,7 +645,7 @@ function DropdownRoot(props) {
638
645
  triggerRef = element;
639
646
  },
640
647
  toggle,
641
- popup: () => props.search ? "dialog" : "menu",
648
+ popup: () => props.search || props.body ? "dialog" : "menu",
642
649
  triggerKeyDown: event => triggerKey(event)
643
650
  };
644
651
  createEffect(() => {
@@ -688,23 +695,47 @@ function DropdownRoot(props) {
688
695
  return _$createComponent(DropdownContext.Provider, {
689
696
  value: context,
690
697
  get children() {
691
- return _$ssr(_tmpl$16, `k2b-dropdown ${_$escape(props.class ?? "", true)}`, _$escape(props.children), _$ssrAttribute("id", _$escape(menuId, true), false), _$ssrAttribute("role", props.search ? "dialog" : "menu", false) + _$ssrAttribute("aria-label", _$escape(props.label ?? messages().dropdownMenu, true), false) + _$ssrAttribute("aria-describedby", props.note ? `${_$escape(menuId, true)}-note` : _$escape(undefined, true), false), `k2b-dropdown__menu ${_$escape(props.menuClass ?? "", true)}`, _$ssrStyle(props.width ? {
698
+ return _$ssr(_tmpl$16, `k2b-dropdown ${_$escape(props.class ?? "", true)}`, _$escape(props.children), _$ssrAttribute("id", _$escape(menuId, true), false), _$ssrAttribute("role", props.search || props.body ? "dialog" : "menu", false) + _$ssrAttribute("aria-label", _$escape(props.label ?? messages().dropdownMenu, true), false) + _$ssrAttribute("aria-describedby", props.note ? `${_$escape(menuId, true)}-note` : _$escape(undefined, true), false), `k2b-dropdown__menu ${_$escape(props.menuClass ?? "", true)}`, _$ssrStyle(props.width ? {
692
699
  "--k2b-dropdown-width": props.width
693
- } : undefined), _$ssrAttribute("data-width", props.width ? "fixed" : _$escape(undefined, true), false) + _$ssrAttribute("data-variant", _$escape(props.variant ?? "default", true), false) + _$ssrAttribute("data-icons", props.icons === "tile" ? "tile" : _$escape(undefined, true), false) + _$ssrAttribute("data-search", props.search ? "" : _$escape(undefined, true), false) + _$ssrAttribute("data-position", _$escape(position(), true), false), _$escape(_$createComponent(Show, {
700
+ } : undefined), _$ssrAttribute("data-width", props.width ? "fixed" : _$escape(undefined, true), false) + _$ssrAttribute("data-variant", _$escape(props.variant ?? "default", true), false) + _$ssrAttribute("data-icons", props.icons === "tile" ? "tile" : _$escape(undefined, true), false) + _$ssrAttribute("data-search", props.search || props.body ? "" : _$escape(undefined, true), false) + _$ssrAttribute("data-position", _$escape(position(), true), false), _$escape(_$createComponent(Show, {
694
701
  get when() {
695
702
  return entriesShown();
696
703
  },
697
704
  get children() {
698
705
  return [_$createComponent(Show, {
699
706
  get when() {
700
- return props.search;
707
+ return props.body;
708
+ },
709
+ children: body => {
710
+ const Body = body();
711
+ return _$createComponent(Body, {
712
+ close: close,
713
+ open: isOpen,
714
+ api: api => {
715
+ searchApi = api;
716
+ onCleanup(() => {
717
+ if (searchApi === api) searchApi = undefined;
718
+ });
719
+ }
720
+ });
721
+ }
722
+ }), _$createComponent(Show, {
723
+ get when() {
724
+ return _$memo(() => !!!props.body)() && props.search;
701
725
  },
702
726
  get fallback() {
703
- return _$createComponent(DropdownItems, {
704
- get items() {
705
- return props.items;
727
+ return _$createComponent(Show, {
728
+ get when() {
729
+ return !props.body;
706
730
  },
707
- close: close
731
+ get children() {
732
+ return _$createComponent(DropdownItems, {
733
+ get items() {
734
+ return props.items;
735
+ },
736
+ close: close
737
+ });
738
+ }
708
739
  });
709
740
  },
710
741
  children: search => _$createComponent(MenuSearch, {
@@ -741,6 +772,8 @@ function DropdownRoot(props) {
741
772
  }
742
773
  });
743
774
  }
775
+ /** Internal: the menu with a `body`, for `CommandMenu`. */
776
+ export const DropdownShell = DropdownRoot;
744
777
  export const Dropdown = DropdownRoot;
745
778
  Dropdown.Root = DropdownRoot;
746
779
  Dropdown.Trigger = DropdownTrigger;