@leavepulse/ui 0.77.3 → 0.78.1

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 (621) hide show
  1. package/README.md +68 -0
  2. package/dist/assets/{LpCommandPalette-DOIZHw-g.css → LpCommandPalette-DDJKICKh.css} +19 -19
  3. package/dist/assets/{LpDock-Cbh0wQUv.css → LpDock-Dw82tWVD.css} +3 -3
  4. package/dist/assets/{LpDropzone-B_qRq1-R.css → LpDropzone-DNbh_NFJ.css} +10 -10
  5. package/dist/assets/{LpImageEditor-XM5bAziW.css → LpImageEditor-Bgu20XLs.css} +6 -6
  6. package/dist/assets/{LpTable-Bv-EcQs7.css → LpTable-CCk0ZHo7.css} +19 -19
  7. package/dist/assets/LpTabs-Bh7a-Bdl.css +18 -0
  8. package/dist/chunks/AppShellContextNav-C6Ho2mof.js +49 -0
  9. package/dist/chunks/ChartRangeSelector-HO0sMMz6.js +129 -0
  10. package/dist/chunks/{ContextMenuItems-BXumicbh.js → ContextMenuItems-DmaKSJVv.js} +1 -1
  11. package/dist/chunks/{DropzoneLinkField-C-9BCGJn.js → DropzoneLinkField-CLLhd3WB.js} +2 -2
  12. package/dist/chunks/FieldLeading-mr81aEAP.js +27 -0
  13. package/dist/chunks/{FieldWrapper-CORPzo9s.js → FieldWrapper-DnuMTrqW.js} +1 -1
  14. package/dist/chunks/IconCloseButton-COZEsa9u.js +29 -0
  15. package/dist/chunks/{LayoutCanvas-CNOAUk7D.js → LayoutCanvas-CZKOltfA.js} +1 -1
  16. package/dist/chunks/{LayoutNode-DF5BMN0J.js → LayoutNode-D2f7v683.js} +45 -45
  17. package/dist/chunks/{LpActionBar-BP1ld7-S.js → LpActionBar-BGMk5KoG.js} +3 -3
  18. package/dist/chunks/{LpActivityLine-CJvzrNpj.js → LpActivityLine-Ea-t5Vza.js} +4 -2
  19. package/dist/chunks/{LpAddressInput-E8KtwU7-.js → LpAddressInput-BSS49jpm.js} +12 -11
  20. package/dist/chunks/{LpAlert-n5XPAZfv.js → LpAlert-CjvTZIKF.js} +3 -3
  21. package/dist/chunks/LpAppShell-BKbYCHkx.js +601 -0
  22. package/dist/chunks/{LpAutocomplete-C-SpPfBG.js → LpAutocomplete-DkY6CSyD.js} +24 -42
  23. package/dist/chunks/{LpAvatar-Cg6Az3wz.js → LpAvatar-cQVsNk6F.js} +2 -2
  24. package/dist/chunks/{LpBadge-wUYLN4U9.js → LpBadge-D5QQdDQ_.js} +2 -2
  25. package/dist/chunks/{LpBottomNav-CbNQQPuL.js → LpBottomNav-zxLGGbjm.js} +9 -2
  26. package/dist/chunks/{LpBreadcrumbs-DPdbth-c.js → LpBreadcrumbs-CIIBsygI.js} +4 -3
  27. package/dist/chunks/{LpButton-CFb44IjC.js → LpButton-DSHioIfD.js} +5 -4
  28. package/dist/chunks/{LpCalendar-CuoWks-0.js → LpCalendar-D4-LVjfF.js} +1 -1
  29. package/dist/chunks/{LpCard-r13WRqox.js → LpCard-BPtYXwnT.js} +1 -1
  30. package/dist/chunks/{LpCheckbox-Cs4SHaHX.js → LpCheckbox-D6RuDW4X.js} +38 -16
  31. package/dist/chunks/{LpCodeBlock-DRC8VbXW.js → LpCodeBlock-DBqy4RLd.js} +19 -41
  32. package/dist/chunks/{LpCodeDisplay-CE9TxCA4.js → LpCodeDisplay-D3BUAhV1.js} +5 -5
  33. package/dist/chunks/{LpCollapse-CWS9M_lm.js → LpCollapse-DrAw5DBZ.js} +5 -4
  34. package/dist/chunks/{LpColorPicker-1y1QJHZR.js → LpColorPicker-COHzV68R.js} +11 -12
  35. package/dist/chunks/{LpCommandScope-CtUhJe8T.js → LpCommandScope-DRUvHiX7.js} +1 -1
  36. package/dist/chunks/{LpConfirmDialog-DlD45Bi_.js → LpConfirmDialog-CnrmzkuN.js} +3 -3
  37. package/dist/chunks/{LpConfirmHost-BIWjBLmI.js → LpConfirmHost-CwbObVGH.js} +1 -1
  38. package/dist/chunks/{LpContextMenu-rx2tCjwk.js → LpContextMenu-Bx_IhQDS.js} +17 -19
  39. package/dist/chunks/{LpContextSwitcher-Dwh6dyID.js → LpContextSwitcher-1C1tExdl.js} +2 -2
  40. package/dist/chunks/{LpCopyButton-xF7wFVoU.js → LpCopyButton-sAMvWeLP.js} +3 -3
  41. package/dist/chunks/{LpCountdown-DgeY3cLG.js → LpCountdown-DVl7vXI1.js} +4 -3
  42. package/dist/chunks/{LpDataList-Jxyl9H5w.js → LpDataList-CaVfsozH.js} +13 -4
  43. package/dist/chunks/{LpDatePicker-CA0QTfBC.js → LpDatePicker-DwSDY0mt.js} +12 -18
  44. package/dist/chunks/{LpDateRangePicker-u3J51xXk.js → LpDateRangePicker-CNQXdTVv.js} +10 -16
  45. package/dist/chunks/{LpDisclosure-Cpa7Hc5T.js → LpDisclosure-DG7JCo-d.js} +2 -2
  46. package/dist/chunks/{LpDrawer-CrG8t_KP.js → LpDrawer-DXNQFpAA.js} +61 -61
  47. package/dist/chunks/{LpDropdownMenu-Dl7Z4ZhS.js → LpDropdownMenu-CLzxIOgM.js} +9 -17
  48. package/dist/chunks/{LpEditable-Cy6GLbFx.js → LpEditable-DVT0Rh8F.js} +9 -6
  49. package/dist/chunks/{LpEmptyState-EQHiRYhG.js → LpEmptyState-DurPF001.js} +1 -1
  50. package/dist/chunks/{LpFieldNotice-CzQ2_5rQ.js → LpFieldNotice-DJ10cYIo.js} +1 -1
  51. package/dist/chunks/LpFileTree-C-rJKzEQ.js +735 -0
  52. package/dist/chunks/{LpFileTreeNode-cT6BIWvz.js → LpFileTreeNode-BgYn4U1J.js} +116 -34
  53. package/dist/chunks/{LpFormField-Ch69Jd-X.js → LpFormField-BKYn9dyP.js} +3 -3
  54. package/dist/chunks/{LpFrame-BVQCQLDI.js → LpFrame-Bv5Fphte.js} +25 -11
  55. package/dist/chunks/{LpHintExample-9Py0wc-L.js → LpHintExample-YzCXiSUp.js} +1 -1
  56. package/dist/chunks/{LpHintLayer-CgObdUsM.js → LpHintLayer-BeKRsRon.js} +2 -2
  57. package/dist/chunks/{LpHints-Bz-BlaSl.js → LpHints-qf3xYsza.js} +3 -3
  58. package/dist/chunks/{LpHoverCard-spGxyw7T.js → LpHoverCard-CHE9jAJG.js} +29 -11
  59. package/dist/chunks/{LpIcon--5WSb3jJ.js → LpIcon-C6JpQ5td.js} +6 -3
  60. package/dist/chunks/{LpIdenticon-BzdC_qz9.js → LpIdenticon-Dbbr4fvt.js} +2 -1
  61. package/dist/chunks/{LpInfraNode-46XOCkfq.js → LpInfraNode-Bb5nbuFY.js} +19 -2
  62. package/dist/chunks/{LpInput-Tw-yxT4I.js → LpInput-D0O6dpuA.js} +32 -47
  63. package/dist/chunks/LpInspector-DO3fTCQ1.js +209 -0
  64. package/dist/chunks/{LpLaneNode-HtnQf2FF.js → LpLaneNode-Bqcdm8Rf.js} +19 -1
  65. package/dist/chunks/{LpLightbox-B95yu22B.js → LpLightbox-CtDTQV01.js} +57 -32
  66. package/dist/chunks/{LpLoader-DVwkOmt9.js → LpLoader-Bf1yZwaU.js} +1 -1
  67. package/dist/chunks/LpLogInspector-BdQlX6S-.js +119 -0
  68. package/dist/chunks/{LpLogViewer-ngqkns4m.js → LpLogViewer-umCZBapN.js} +234 -53
  69. package/dist/chunks/{LpMapPicker-DRGgh89B.js → LpMapPicker-D5_YLLBC.js} +4 -3
  70. package/dist/chunks/{LpMasonry--k0571qG.js → LpMasonry-DPYekFxs.js} +8 -5
  71. package/dist/chunks/{LpMediaGallery-Bkram-MO.js → LpMediaGallery-BYEwySoF.js} +3 -3
  72. package/dist/chunks/{LpModal-CoGhLTyH.js → LpModal-DDvrSAnf.js} +11 -13
  73. package/dist/chunks/{LpModalNav-BGvs2y5Q.js → LpModalNav-gOi1Giz1.js} +11 -37
  74. package/dist/chunks/{LpNotificationBell-B0034Lk-.js → LpNotificationBell-DUbVyK6R.js} +9 -9
  75. package/dist/chunks/{LpNumberField-e0IBkWU1.js → LpNumberField-Csg-1Zh_.js} +25 -20
  76. package/dist/chunks/{LpOtpInput-CeBPsM7D.js → LpOtpInput-BRpLBbOD.js} +2 -2
  77. package/dist/chunks/LpPageScrollbar-D2O0xhJw.js +164 -0
  78. package/dist/chunks/{LpPagination-BIIiYHXR.js → LpPagination-snQ020xQ.js} +6 -4
  79. package/dist/chunks/{LpPaletteTheme-DiLYKQiZ.js → LpPaletteTheme-BIXpZLGe.js} +4 -4
  80. package/dist/chunks/{LpPasswordInput-BkHKQDhM.js → LpPasswordInput-D4HPhqfV.js} +2 -2
  81. package/dist/chunks/{LpPhoneInput-CETEp5W7.js → LpPhoneInput-BSL7NX4z.js} +15 -26
  82. package/dist/chunks/{LpPie-DrZepi0p.js → LpPie-oVNHjsKD.js} +22 -21
  83. package/dist/chunks/{LpPipeline-B3aOVOkV.js → LpPipeline-BSXT6oUJ.js} +16 -7
  84. package/dist/chunks/{LpPopover-DmZ3wUtP.js → LpPopover-BQSuxtai.js} +10 -1
  85. package/dist/chunks/{LpProgress-Yr6ONG5t.js → LpProgress-D_MSjowb.js} +2 -1
  86. package/dist/chunks/{LpQuota-Dk2MyI2Z.js → LpQuota-CgWPgdVt.js} +1 -1
  87. package/dist/chunks/{LpRadioGroup-ggaPL92T.js → LpRadioGroup-BrazjLY_.js} +4 -4
  88. package/dist/chunks/{LpRangeCalendar-CYYUYqJ7.js → LpRangeCalendar-BrqlGZzE.js} +1 -1
  89. package/dist/chunks/{LpRangeSlider-CM-0ZITZ.js → LpRangeSlider-fz61tzc-.js} +5 -9
  90. package/dist/chunks/{LpRelativeTime-DwgCb5-8.js → LpRelativeTime-0zI-44ve.js} +1 -1
  91. package/dist/chunks/{LpRepeater-D7ZmnIYd.js → LpRepeater-BkJHSPI1.js} +3 -3
  92. package/dist/chunks/{LpRevealOnScroll-DcQjexLy.js → LpRevealOnScroll-CPwyiQAr.js} +1 -1
  93. package/dist/chunks/{LpScramble-Bn9OoOtC.js → LpScramble-DsE77iVp.js} +1 -1
  94. package/dist/chunks/{LpScrollArea-MyEnVB_5.js → LpScrollArea-CqvwfZs2.js} +31 -22
  95. package/dist/chunks/{LpSecretField-BbmqM9ye.js → LpSecretField-B2roc4Iz.js} +10 -9
  96. package/dist/chunks/{LpSection-DFK_uoJE.js → LpSection-BfteipxU.js} +1 -1
  97. package/dist/chunks/{LpSegmented-CeACsMMA.js → LpSegmented-DbEJhbv-.js} +8 -10
  98. package/dist/chunks/{LpSelect-Cxq4yBGd.js → LpSelect-Y-iuSymW.js} +47 -30
  99. package/dist/chunks/{LpServiceNode-D8uJ8sGk.js → LpServiceNode-Cln2ntdw.js} +17 -0
  100. package/dist/chunks/{LpShaderBackdrop-Bote0iuy.js → LpShaderBackdrop-wQygYb5h.js} +13 -10
  101. package/dist/chunks/{LpShift-CCq7dofl.js → LpShift-DAgS_d2x.js} +18 -15
  102. package/dist/chunks/{LpSidebar-DzE1783C.js → LpSidebar-DDNJzb69.js} +74 -87
  103. package/dist/chunks/{LpSidebarNav-DE3PhXVP.js → LpSidebarNav-CE0jQS8i.js} +8 -6
  104. package/dist/chunks/{LpSidebarRow-BRYhNDSo.js → LpSidebarRow-DOTg1txp.js} +6 -5
  105. package/dist/chunks/{LpSlider-DxYoCJJO.js → LpSlider-A4ixovgS.js} +5 -9
  106. package/dist/chunks/{LpSpotlight-4F3NeUMY.js → LpSpotlight-DwxkhFgR.js} +2 -1
  107. package/dist/chunks/{LpStat-f2LfDCJ4.js → LpStat-DPjc6_fX.js} +19 -6
  108. package/dist/chunks/{LpStatus-DglxttQ7.js → LpStatus-DGJFwk5F.js} +2 -2
  109. package/dist/chunks/{LpStepMark-DpzKVyh8.js → LpStepMark-Dw2MRTrt.js} +2 -2
  110. package/dist/chunks/{LpStepper-DpsocBNJ.js → LpStepper-DNnh7lCu.js} +1 -1
  111. package/dist/chunks/{LpSwap-C96c0LWh.js → LpSwap-M7nFeW3C.js} +1 -1
  112. package/dist/chunks/{LpSwitch-BnXd1llc.js → LpSwitch-DnC2-0aV.js} +3 -3
  113. package/dist/chunks/{LpTabFace-DPCwKkH2.js → LpTabFace-DQoV8mQG.js} +2 -2
  114. package/dist/chunks/{LpTableFilter-CiVBpaq0.js → LpTableFilter-B_XMOeAh.js} +4 -4
  115. package/dist/chunks/{LpTableOfContents-BN5zvpnx.js → LpTableOfContents-CKkWEK6R.js} +14 -9
  116. package/dist/chunks/{LpTagsInput-C-mDG648.js → LpTagsInput-Dt0mteSj.js} +19 -27
  117. package/dist/chunks/{LpTextarea-TE-yZv2U.js → LpTextarea-Co0b9PVx.js} +8 -16
  118. package/dist/chunks/LpThemeProvider-XK6ZeWAE.js +81 -0
  119. package/dist/chunks/{LpThemeStudio-BpORDvH6.js → LpThemeStudio-ChU0_Ga8.js} +12 -195
  120. package/dist/chunks/{LpThemeSwitcher-BnEn_mvf.js → LpThemeSwitcher-DmCZ21P_.js} +8 -6
  121. package/dist/chunks/{LpTimeField-BawSVsmt.js → LpTimeField-DeOcKWJq.js} +6 -9
  122. package/dist/chunks/{LpToaster-IwTXjbbU.js → LpToaster-Ct_ZOhCh.js} +10 -8
  123. package/dist/chunks/{LpTooltip-BcBvIx4z.js → LpTooltip-Bz_rrq5S.js} +56 -24
  124. package/dist/chunks/LpTopologyCanvas-jqz1KCq2.js +678 -0
  125. package/dist/chunks/{LpTour-BZq-mUMv.js → LpTour-ClKYhx4h.js} +7 -5
  126. package/dist/chunks/{LpTruncate-CflAIwiJ.js → LpTruncate-ellq9RYM.js} +6 -5
  127. package/dist/chunks/{LpTypewriter-BCL_a6wE.js → LpTypewriter-CZIzpdbe.js} +2 -1
  128. package/dist/chunks/{LpUptimeBar-DqNvvMBK.js → LpUptimeBar-BoxcCDVY.js} +3 -3
  129. package/dist/chunks/{LpVideoBackdrop-DS1wGv-X.js → LpVideoBackdrop-Ct4St4ZL.js} +10 -13
  130. package/dist/chunks/LpWindow-B8YSRVTH.js +297 -0
  131. package/dist/chunks/LpWorkspaceSwitcher-BeNHCLd5.js +139 -0
  132. package/dist/chunks/{MenuTitle-BmCNNTKH.js → MenuTitle-Bh5dAdV1.js} +1 -1
  133. package/dist/chunks/{OptionContent-22UT8zLn.js → OptionContent-CGb8QlHA.js} +1 -1
  134. package/dist/chunks/{PickerField-Bfh8id3d.js → PickerField-BM1dyafh.js} +4 -4
  135. package/dist/chunks/{RevealToggle-BEit1n6Z.js → RevealToggle-D_iyrB8d.js} +3 -3
  136. package/dist/chunks/SliderRail-DhPREa_R.js +18 -0
  137. package/dist/chunks/{TourCard-DNclH3u_.js → TourCard-DAzTYfav.js} +4 -4
  138. package/dist/chunks/{icons-DMITlfw5.js → icons-CYfcpSDS.js} +26 -10
  139. package/dist/component-names.d.ts +1 -1
  140. package/dist/components/AppShellContextNav.vue.d.ts +13 -0
  141. package/dist/components/AppShellContextNav.vue.js +4 -0
  142. package/dist/components/ChartRangeSelector.vue.d.ts +21 -0
  143. package/dist/components/ChartRangeSelector.vue.js +4 -0
  144. package/dist/components/ContextMenuItems.vue.js +1 -1
  145. package/dist/components/DropzoneLinkField.vue.d.ts +2 -2
  146. package/dist/components/DropzoneLinkField.vue.js +1 -1
  147. package/dist/components/FieldLeading.vue.d.ts +16 -0
  148. package/dist/components/FieldLeading.vue.js +4 -0
  149. package/dist/components/FieldWrapper.vue.js +1 -1
  150. package/dist/components/IconCloseButton.vue.d.ts +7 -0
  151. package/dist/components/IconCloseButton.vue.js +4 -0
  152. package/dist/components/LayoutCanvas.vue.js +1 -1
  153. package/dist/components/LayoutNode.vue.js +1 -1
  154. package/dist/components/LpActionBar.vue.js +1 -1
  155. package/dist/components/LpActivityLine.vue.js +1 -1
  156. package/dist/components/LpAddressInput.vue.js +1 -1
  157. package/dist/components/LpAlert.vue.js +1 -1
  158. package/dist/components/LpAppShell.vue.d.ts +125 -2
  159. package/dist/components/LpAppShell.vue.js +1 -1
  160. package/dist/components/LpAutocomplete.vue.js +1 -1
  161. package/dist/components/LpAvatar.vue.js +1 -1
  162. package/dist/components/LpBadge.vue.js +1 -1
  163. package/dist/components/LpBottomNav.vue.d.ts +5 -0
  164. package/dist/components/LpBottomNav.vue.js +1 -1
  165. package/dist/components/LpBreadcrumbs.vue.js +1 -1
  166. package/dist/components/LpButton.vue.d.ts +14 -2
  167. package/dist/components/LpButton.vue.js +1 -1
  168. package/dist/components/LpCalendar.vue.js +1 -1
  169. package/dist/components/LpCard.vue.js +1 -1
  170. package/dist/components/LpChart.vue.d.ts +74 -2
  171. package/dist/components/LpChart.vue.js +326 -85
  172. package/dist/components/LpCheckbox.vue.d.ts +6 -2
  173. package/dist/components/LpCheckbox.vue.js +1 -1
  174. package/dist/components/LpCodeBlock.vue.js +1 -1
  175. package/dist/components/LpCodeDisplay.vue.js +1 -1
  176. package/dist/components/LpCollapse.vue.js +1 -1
  177. package/dist/components/LpColorPicker.vue.js +1 -1
  178. package/dist/components/LpCommandPalette.vue.d.ts +8 -0
  179. package/dist/components/LpCommandPalette.vue.js +107 -56
  180. package/dist/components/LpCommandScope.vue.js +1 -1
  181. package/dist/components/LpConfirmDialog.vue.js +1 -1
  182. package/dist/components/LpConfirmHost.vue.js +1 -1
  183. package/dist/components/LpContextMenu.vue.js +1 -1
  184. package/dist/components/LpContextSwitcher.vue.js +1 -1
  185. package/dist/components/LpCopyButton.vue.js +1 -1
  186. package/dist/components/LpCountdown.vue.js +1 -1
  187. package/dist/components/LpDataList.vue.d.ts +1 -1
  188. package/dist/components/LpDataList.vue.js +1 -1
  189. package/dist/components/LpDatePicker.vue.d.ts +3 -15
  190. package/dist/components/LpDatePicker.vue.js +1 -1
  191. package/dist/components/LpDateRangePicker.vue.d.ts +3 -13
  192. package/dist/components/LpDateRangePicker.vue.js +1 -1
  193. package/dist/components/LpDisclosure.vue.js +1 -1
  194. package/dist/components/LpDock.vue.js +21 -18
  195. package/dist/components/LpDrawer.vue.d.ts +1 -1
  196. package/dist/components/LpDrawer.vue.js +1 -1
  197. package/dist/components/LpDropdownMenu.vue.js +1 -1
  198. package/dist/components/LpDropzone.vue.js +14 -11
  199. package/dist/components/LpEditable.vue.js +1 -1
  200. package/dist/components/LpEmptyState.vue.js +1 -1
  201. package/dist/components/LpFieldNotice.vue.js +1 -1
  202. package/dist/components/LpFileTree.vue.d.ts +96 -6
  203. package/dist/components/LpFileTree.vue.js +1 -1
  204. package/dist/components/LpFileTreeNode.vue.d.ts +48 -0
  205. package/dist/components/LpFileTreeNode.vue.js +1 -1
  206. package/dist/components/LpFormField.vue.js +1 -1
  207. package/dist/components/LpFrame.vue.js +1 -1
  208. package/dist/components/LpGauge.vue.d.ts +1 -1
  209. package/dist/components/LpHintExample.vue.js +1 -1
  210. package/dist/components/LpHintLayer.vue.js +1 -1
  211. package/dist/components/LpHints.vue.js +1 -1
  212. package/dist/components/LpHoverCard.vue.js +1 -1
  213. package/dist/components/LpIcon.vue.d.ts +2 -0
  214. package/dist/components/LpIcon.vue.js +1 -1
  215. package/dist/components/LpIdenticon.vue.js +1 -1
  216. package/dist/components/LpImageEditor.vue.js +7 -6
  217. package/dist/components/LpInfraNode.vue.d.ts +11 -2
  218. package/dist/components/LpInfraNode.vue.js +1 -1
  219. package/dist/components/LpInput.vue.d.ts +1 -1
  220. package/dist/components/LpInput.vue.js +1 -1
  221. package/dist/components/LpInspector.vue.d.ts +87 -0
  222. package/dist/components/LpInspector.vue.js +4 -0
  223. package/dist/components/LpLaneNode.vue.d.ts +2 -3
  224. package/dist/components/LpLaneNode.vue.js +1 -1
  225. package/dist/components/LpLightbox.vue.d.ts +8 -0
  226. package/dist/components/LpLightbox.vue.js +1 -1
  227. package/dist/components/LpLoader.vue.d.ts +1 -1
  228. package/dist/components/LpLoader.vue.js +1 -1
  229. package/dist/components/LpLogInspector.vue.d.ts +18 -0
  230. package/dist/components/LpLogInspector.vue.js +4 -0
  231. package/dist/components/LpLogViewer.vue.d.ts +93 -0
  232. package/dist/components/LpLogViewer.vue.js +1 -1
  233. package/dist/components/LpMapPicker.vue.js +1 -1
  234. package/dist/components/LpMasonry.vue.js +1 -1
  235. package/dist/components/LpMediaGallery.vue.js +1 -1
  236. package/dist/components/LpModal.vue.d.ts +4 -2
  237. package/dist/components/LpModal.vue.js +1 -1
  238. package/dist/components/LpModalNav.vue.d.ts +5 -5
  239. package/dist/components/LpModalNav.vue.js +1 -1
  240. package/dist/components/LpNotificationBell.vue.d.ts +2 -2
  241. package/dist/components/LpNotificationBell.vue.js +1 -1
  242. package/dist/components/LpNumberField.vue.d.ts +13 -2
  243. package/dist/components/LpNumberField.vue.js +1 -1
  244. package/dist/components/LpOtpInput.vue.js +1 -1
  245. package/dist/components/LpPageScrollbar.vue.d.ts +10 -0
  246. package/dist/components/LpPageScrollbar.vue.js +4 -0
  247. package/dist/components/LpPagination.vue.js +1 -1
  248. package/dist/components/LpPaletteFacts.vue.js +1 -1
  249. package/dist/components/LpPaletteHeader.vue.js +2 -2
  250. package/dist/components/LpPaletteTheme.vue.js +1 -1
  251. package/dist/components/LpPasswordInput.vue.js +1 -1
  252. package/dist/components/LpPhoneInput.vue.js +1 -1
  253. package/dist/components/LpPie.vue.d.ts +2 -2
  254. package/dist/components/LpPie.vue.js +1 -1
  255. package/dist/components/LpPipeline.vue.d.ts +4 -0
  256. package/dist/components/LpPipeline.vue.js +1 -1
  257. package/dist/components/LpPopover.vue.d.ts +7 -3
  258. package/dist/components/LpPopover.vue.js +1 -1
  259. package/dist/components/LpProgress.vue.d.ts +1 -1
  260. package/dist/components/LpProgress.vue.js +1 -1
  261. package/dist/components/LpQuota.vue.js +1 -1
  262. package/dist/components/LpRadioGroup.vue.js +1 -1
  263. package/dist/components/LpRangeCalendar.vue.js +1 -1
  264. package/dist/components/LpRangeSlider.vue.js +1 -1
  265. package/dist/components/LpRelativeTime.vue.js +1 -1
  266. package/dist/components/LpRepeater.vue.js +1 -1
  267. package/dist/components/LpRevealOnScroll.vue.js +1 -1
  268. package/dist/components/LpScramble.vue.js +1 -1
  269. package/dist/components/LpScrollArea.vue.js +1 -1
  270. package/dist/components/LpSecretField.vue.js +1 -1
  271. package/dist/components/LpSection.vue.js +1 -1
  272. package/dist/components/LpSegmented.vue.js +1 -1
  273. package/dist/components/LpSelect.vue.js +1 -1
  274. package/dist/components/LpServiceNode.vue.d.ts +8 -2
  275. package/dist/components/LpServiceNode.vue.js +1 -1
  276. package/dist/components/LpShaderBackdrop.vue.js +1 -1
  277. package/dist/components/LpShift.vue.js +1 -1
  278. package/dist/components/LpShortcutsDialog.vue.js +1 -1
  279. package/dist/components/LpSidebar.vue.d.ts +1 -1
  280. package/dist/components/LpSidebar.vue.js +1 -1
  281. package/dist/components/LpSidebarNav.vue.js +1 -1
  282. package/dist/components/LpSidebarRow.vue.js +1 -1
  283. package/dist/components/LpSlider.vue.js +1 -1
  284. package/dist/components/LpSparkline.vue.d.ts +1 -1
  285. package/dist/components/LpSpotlight.vue.js +1 -1
  286. package/dist/components/LpStat.vue.d.ts +16 -0
  287. package/dist/components/LpStat.vue.js +1 -1
  288. package/dist/components/LpStatus.vue.js +1 -1
  289. package/dist/components/LpStepMark.vue.js +1 -1
  290. package/dist/components/LpStepper.vue.js +1 -1
  291. package/dist/components/LpSwap.vue.js +1 -1
  292. package/dist/components/LpSwitch.vue.js +1 -1
  293. package/dist/components/LpTabFace.vue.js +1 -1
  294. package/dist/components/LpTable.vue.d.ts +132 -0
  295. package/dist/components/LpTable.vue.js +547 -135
  296. package/dist/components/LpTableFilter.vue.js +1 -1
  297. package/dist/components/LpTableOfContents.vue.js +1 -1
  298. package/dist/components/LpTabs.vue.js +6 -5
  299. package/dist/components/LpTagsInput.vue.js +1 -1
  300. package/dist/components/LpTextarea.vue.js +1 -1
  301. package/dist/components/LpThemeProvider.vue.d.ts +2 -0
  302. package/dist/components/LpThemeProvider.vue.js +1 -1
  303. package/dist/components/LpThemeStudio.vue.js +1 -1
  304. package/dist/components/LpThemeSwitcher.vue.js +1 -1
  305. package/dist/components/LpTimeField.vue.js +1 -1
  306. package/dist/components/LpToaster.vue.js +1 -1
  307. package/dist/components/LpTooltip.vue.js +1 -1
  308. package/dist/components/LpTopologyCanvas.vue.d.ts +131 -5
  309. package/dist/components/LpTopologyCanvas.vue.js +1 -1
  310. package/dist/components/LpTour.vue.js +1 -1
  311. package/dist/components/LpTruncate.vue.js +1 -1
  312. package/dist/components/LpTypewriter.vue.js +1 -1
  313. package/dist/components/LpUptimeBar.vue.js +1 -1
  314. package/dist/components/LpVideoBackdrop.vue.js +1 -1
  315. package/dist/components/LpWindow.vue.d.ts +99 -0
  316. package/dist/components/LpWindow.vue.js +4 -0
  317. package/dist/components/LpWorkspaceSwitcher.vue.d.ts +18 -0
  318. package/dist/components/LpWorkspaceSwitcher.vue.js +4 -0
  319. package/dist/components/MenuTitle.vue.js +1 -1
  320. package/dist/components/OptionContent.vue.js +1 -1
  321. package/dist/components/PickerField.vue.d.ts +2 -2
  322. package/dist/components/PickerField.vue.js +1 -1
  323. package/dist/components/RevealToggle.vue.js +1 -1
  324. package/dist/components/SliderRail.vue.d.ts +3 -0
  325. package/dist/components/SliderRail.vue.js +4 -0
  326. package/dist/components/TourCard.vue.js +1 -1
  327. package/dist/components/address.js +2 -1
  328. package/dist/components/appShell.d.ts +36 -0
  329. package/dist/components/appShell.js +30 -0
  330. package/dist/components/calendar.d.ts +12 -3
  331. package/dist/components/calendar.js +2 -5
  332. package/dist/components/chart.d.ts +21 -0
  333. package/dist/components/chart.js +4 -3
  334. package/dist/components/chartWindow.d.ts +57 -0
  335. package/dist/components/chartWindow.js +136 -0
  336. package/dist/components/color.js +1 -1
  337. package/dist/components/commandPalette.d.ts +16 -2
  338. package/dist/components/commandPalette.js +39 -4
  339. package/dist/components/controlSize.d.ts +5 -0
  340. package/dist/components/controlSize.js +8 -0
  341. package/dist/components/dropdown.d.ts +5 -0
  342. package/dist/components/dropdown.js +2 -0
  343. package/dist/components/exportData.d.ts +6 -1
  344. package/dist/components/exportData.js +25 -18
  345. package/dist/components/fileTree.d.ts +67 -0
  346. package/dist/components/fileTree.js +141 -1
  347. package/dist/components/identicon.js +3 -2
  348. package/dist/components/logTools.d.ts +93 -0
  349. package/dist/components/logTools.js +210 -0
  350. package/dist/components/menuWhen.js +1 -1
  351. package/dist/components/meter.js +2 -1
  352. package/dist/components/pipeline.d.ts +2 -0
  353. package/dist/components/pipeline.js +5 -0
  354. package/dist/components/relativeTime.js +2 -1
  355. package/dist/components/reveal.js +2 -1
  356. package/dist/components/scrollbar.d.ts +34 -0
  357. package/dist/components/scrollbar.js +47 -0
  358. package/dist/components/select.d.ts +5 -0
  359. package/dist/components/select.js +10 -0
  360. package/dist/components/sidebar.d.ts +1 -0
  361. package/dist/components/tableFeatures.d.ts +58 -0
  362. package/dist/components/tableFeatures.js +87 -0
  363. package/dist/components/topologyGraph.d.ts +164 -0
  364. package/dist/components/topologyGraph.js +416 -0
  365. package/dist/components/tour.js +5 -3
  366. package/dist/components/videoBackdrop.js +7 -6
  367. package/dist/composables/clamp.d.ts +2 -0
  368. package/dist/composables/clamp.js +4 -0
  369. package/dist/composables/devWarn.d.ts +3 -0
  370. package/dist/composables/devWarn.js +14 -0
  371. package/dist/composables/easing.d.ts +13 -4
  372. package/dist/composables/easing.js +16 -10
  373. package/dist/composables/overlayHistory.js +14 -1
  374. package/dist/composables/pointerDrag.d.ts +15 -0
  375. package/dist/composables/pointerDrag.js +40 -0
  376. package/dist/composables/propCheck.d.ts +10 -0
  377. package/dist/composables/propCheck.js +89 -0
  378. package/dist/composables/realm.d.ts +6 -0
  379. package/dist/composables/realm.js +23 -0
  380. package/dist/composables/scroll.js +4 -2
  381. package/dist/composables/scrollMemory.d.ts +12 -1
  382. package/dist/composables/scrollMemory.js +36 -12
  383. package/dist/composables/spatialNav.js +2 -1
  384. package/dist/composables/textEntry.d.ts +17 -0
  385. package/dist/composables/textEntry.js +19 -0
  386. package/dist/composables/useAsyncTask.d.ts +6 -0
  387. package/dist/composables/useChartSync.d.ts +5 -0
  388. package/dist/composables/useChartSync.js +33 -0
  389. package/dist/composables/useCloseGuard.d.ts +3 -1
  390. package/dist/composables/useCloseGuard.js +6 -3
  391. package/dist/composables/useCommands.d.ts +50 -0
  392. package/dist/composables/useCommands.js +66 -0
  393. package/dist/composables/useField.d.ts +37 -0
  394. package/dist/composables/useField.js +27 -2
  395. package/dist/composables/useFitScale.js +4 -1
  396. package/dist/composables/useFormDraft.d.ts +13 -2
  397. package/dist/composables/useFormDraft.js +17 -9
  398. package/dist/composables/useHintSystem.js +2 -2
  399. package/dist/composables/useHotkeys.js +11 -32
  400. package/dist/composables/useInView.js +2 -1
  401. package/dist/composables/useInputFilter.js +7 -5
  402. package/dist/composables/useInputMask.js +5 -3
  403. package/dist/composables/useLinkedView.d.ts +97 -0
  404. package/dist/composables/useLinkedView.js +139 -0
  405. package/dist/composables/useOptimisticToggle.d.ts +3 -1
  406. package/dist/composables/useOptimisticToggle.js +2 -1
  407. package/dist/composables/useOverlayHistory.d.ts +7 -0
  408. package/dist/composables/useOverlayHistory.js +16 -2
  409. package/dist/composables/usePaintSelect.js +18 -14
  410. package/dist/composables/usePaletteCommands.d.ts +7 -0
  411. package/dist/composables/usePaletteCommands.js +16 -3
  412. package/dist/composables/usePersisted.d.ts +10 -0
  413. package/dist/composables/usePersisted.js +1 -1
  414. package/dist/composables/usePillTransition.d.ts +2 -2
  415. package/dist/composables/usePillTransition.js +5 -5
  416. package/dist/composables/useResizeObserver.js +2 -1
  417. package/dist/composables/useReveal.js +2 -1
  418. package/dist/composables/useRovingFocus.d.ts +2 -2
  419. package/dist/composables/useRovingFocus.js +9 -11
  420. package/dist/composables/useScramble.js +7 -1
  421. package/dist/composables/useShift.js +8 -6
  422. package/dist/composables/useTilt.js +2 -1
  423. package/dist/composables/useTween.js +9 -5
  424. package/dist/composables/useView.d.ts +1 -0
  425. package/dist/composables/useView.js +14 -2
  426. package/dist/composables/useZoomPan.js +2 -4
  427. package/dist/composables/windowing.d.ts +40 -0
  428. package/dist/composables/windowing.js +118 -0
  429. package/dist/icons-all.js +1 -1
  430. package/dist/icons.d.ts +4 -0
  431. package/dist/index.d.ts +31 -5
  432. package/dist/index.js +312 -264
  433. package/dist/layout/tree.js +19 -15
  434. package/dist/layout/useLayout.d.ts +2 -0
  435. package/dist/layout/useLayout.js +5 -1
  436. package/dist/layout/useWorkspaces.d.ts +52 -0
  437. package/dist/layout/useWorkspaces.js +140 -0
  438. package/dist/{chunks/backdrop-Dkf2vM81.js → theme/backdrop.js} +5 -5
  439. package/dist/theme/config.js +25 -0
  440. package/dist/theme/define.js +61 -0
  441. package/dist/{chunks/palette-Co8tSASo.js → theme/palette.js} +2 -2
  442. package/dist/theme/presets.js +239 -0
  443. package/dist/theme/studio.js +134 -0
  444. package/dist/theme/tokens.js +63 -0
  445. package/dist/theme/useTheme.d.ts +3 -2
  446. package/dist/theme/useTheme.js +325 -0
  447. package/package.json +8 -1
  448. package/src/component-names.ts +6 -1
  449. package/src/components/AppShellContextNav.vue +44 -0
  450. package/src/components/ChartRangeSelector.vue +120 -0
  451. package/src/components/FieldLeading.vue +17 -0
  452. package/src/components/IconCloseButton.vue +21 -0
  453. package/src/components/LayoutCanvas.vue +3 -0
  454. package/src/components/LayoutNode.vue +37 -38
  455. package/src/components/LpActivityLine.vue +4 -2
  456. package/src/components/LpAddressInput.vue +3 -3
  457. package/src/components/LpAppShell.vue +385 -24
  458. package/src/components/LpAutocomplete.vue +13 -30
  459. package/src/components/LpBottomNav.vue +9 -1
  460. package/src/components/LpBreadcrumbs.vue +2 -1
  461. package/src/components/LpButton.vue +11 -4
  462. package/src/components/LpChart.vue +336 -37
  463. package/src/components/LpCheckbox.vue +43 -9
  464. package/src/components/LpCodeBlock.vue +17 -23
  465. package/src/components/LpCollapse.vue +5 -4
  466. package/src/components/LpColorPicker.vue +8 -9
  467. package/src/components/LpCommandPalette.vue +133 -50
  468. package/src/components/LpContextMenu.vue +22 -13
  469. package/src/components/LpCountdown.vue +2 -1
  470. package/src/components/LpDataList.vue +13 -1
  471. package/src/components/LpDatePicker.vue +5 -17
  472. package/src/components/LpDateRangePicker.vue +5 -16
  473. package/src/components/LpDock.vue +25 -16
  474. package/src/components/LpDrawer.vue +70 -61
  475. package/src/components/LpDropdownMenu.vue +6 -10
  476. package/src/components/LpDropzone.vue +12 -7
  477. package/src/components/LpEditable.vue +6 -2
  478. package/src/components/LpFileTree.vue +507 -66
  479. package/src/components/LpFileTreeNode.vue +106 -5
  480. package/src/components/LpFormField.vue +1 -1
  481. package/src/components/LpFrame.vue +33 -13
  482. package/src/components/LpHoverCard.vue +37 -5
  483. package/src/components/LpIcon.vue +6 -2
  484. package/src/components/LpIdenticon.vue +2 -1
  485. package/src/components/LpImageEditor.vue +5 -2
  486. package/src/components/LpInfraNode.vue +4 -3
  487. package/src/components/LpInput.vue +19 -26
  488. package/src/components/LpInspector.vue +197 -0
  489. package/src/components/LpLaneNode.vue +5 -1
  490. package/src/components/LpLightbox.vue +74 -29
  491. package/src/components/LpLogInspector.vue +85 -0
  492. package/src/components/LpLogViewer.vue +239 -29
  493. package/src/components/LpMapPicker.vue +2 -1
  494. package/src/components/LpMasonry.vue +8 -5
  495. package/src/components/LpModal.vue +12 -12
  496. package/src/components/LpModalNav.vue +2 -21
  497. package/src/components/LpNumberField.vue +13 -16
  498. package/src/components/LpOtpInput.vue +2 -2
  499. package/src/components/LpPageScrollbar.vue +195 -0
  500. package/src/components/LpPagination.vue +5 -3
  501. package/src/components/LpPhoneInput.vue +8 -19
  502. package/src/components/LpPie.vue +25 -23
  503. package/src/components/LpPipeline.vue +14 -1
  504. package/src/components/LpPopover.vue +23 -2
  505. package/src/components/LpProgress.vue +2 -1
  506. package/src/components/LpRadioGroup.vue +2 -2
  507. package/src/components/LpRangeSlider.vue +5 -6
  508. package/src/components/LpRevealOnScroll.vue +1 -1
  509. package/src/components/LpScrollArea.vue +55 -34
  510. package/src/components/LpSecretField.vue +2 -1
  511. package/src/components/LpSegmented.vue +6 -8
  512. package/src/components/LpSelect.vue +54 -24
  513. package/src/components/LpServiceNode.vue +4 -2
  514. package/src/components/LpShaderBackdrop.vue +12 -9
  515. package/src/components/LpShift.vue +18 -15
  516. package/src/components/LpSidebar.vue +77 -74
  517. package/src/components/LpSidebarNav.vue +3 -2
  518. package/src/components/LpSidebarRow.vue +2 -1
  519. package/src/components/LpSlider.vue +5 -6
  520. package/src/components/LpSpotlight.vue +2 -1
  521. package/src/components/LpStat.vue +25 -5
  522. package/src/components/LpSwitch.vue +5 -3
  523. package/src/components/LpTable.vue +609 -93
  524. package/src/components/LpTableFilter.vue +1 -1
  525. package/src/components/LpTableOfContents.vue +16 -9
  526. package/src/components/LpTabs.vue +2 -1
  527. package/src/components/LpTagsInput.vue +12 -19
  528. package/src/components/LpTextarea.vue +5 -11
  529. package/src/components/LpThemeProvider.vue +29 -13
  530. package/src/components/LpTimeField.vue +4 -7
  531. package/src/components/LpToaster.vue +7 -6
  532. package/src/components/LpTooltip.vue +69 -18
  533. package/src/components/LpTopologyCanvas.vue +569 -42
  534. package/src/components/LpTour.vue +7 -5
  535. package/src/components/LpTruncate.vue +4 -3
  536. package/src/components/LpTypewriter.vue +2 -1
  537. package/src/components/LpVideoBackdrop.vue +11 -13
  538. package/src/components/LpWindow.vue +373 -0
  539. package/src/components/LpWorkspaceSwitcher.vue +116 -0
  540. package/src/components/PickerField.vue +2 -2
  541. package/src/components/SliderRail.vue +10 -0
  542. package/src/components/address.ts +3 -1
  543. package/src/components/appShell.ts +74 -0
  544. package/src/components/calendar.ts +12 -5
  545. package/src/components/chart.ts +27 -3
  546. package/src/components/chartWindow.ts +198 -0
  547. package/src/components/color.ts +2 -1
  548. package/src/components/commandPalette.ts +66 -5
  549. package/src/components/controlSize.ts +6 -0
  550. package/src/components/dropdown.ts +3 -0
  551. package/src/components/exportData.ts +33 -18
  552. package/src/components/fileTree.ts +215 -0
  553. package/src/components/identicon.ts +4 -2
  554. package/src/components/logTools.ts +298 -0
  555. package/src/components/meter.ts +2 -1
  556. package/src/components/pipeline.ts +6 -0
  557. package/src/components/relativeTime.ts +2 -1
  558. package/src/components/reveal.ts +3 -1
  559. package/src/components/scrollbar.ts +71 -0
  560. package/src/components/select.ts +14 -0
  561. package/src/components/sidebar.ts +1 -0
  562. package/src/components/tableFeatures.ts +149 -0
  563. package/src/components/topologyGraph.ts +655 -0
  564. package/src/components/tour.ts +5 -3
  565. package/src/components/videoBackdrop.ts +7 -6
  566. package/src/composables/clamp.ts +2 -0
  567. package/src/composables/devWarn.ts +19 -0
  568. package/src/composables/easing.ts +37 -12
  569. package/src/composables/overlayHistory.ts +24 -0
  570. package/src/composables/pointerDrag.ts +54 -0
  571. package/src/composables/propCheck.ts +105 -0
  572. package/src/composables/realm.ts +25 -0
  573. package/src/composables/scroll.ts +4 -2
  574. package/src/composables/scrollMemory.ts +56 -14
  575. package/src/composables/spatialNav.ts +2 -1
  576. package/src/composables/textEntry.ts +33 -0
  577. package/src/composables/useAsyncTask.ts +6 -0
  578. package/src/composables/useChartSync.ts +52 -0
  579. package/src/composables/useCloseGuard.ts +22 -10
  580. package/src/composables/useCommands.ts +123 -0
  581. package/src/composables/useField.ts +41 -2
  582. package/src/composables/useFitScale.ts +4 -1
  583. package/src/composables/useFormDraft.ts +38 -14
  584. package/src/composables/useHintSystem.ts +2 -2
  585. package/src/composables/useHotkeys.ts +19 -48
  586. package/src/composables/useInView.ts +2 -1
  587. package/src/composables/useInputFilter.ts +8 -5
  588. package/src/composables/useInputMask.ts +8 -3
  589. package/src/composables/useLinkedView.ts +222 -0
  590. package/src/composables/useOptimisticToggle.ts +7 -1
  591. package/src/composables/useOverlayHistory.ts +20 -0
  592. package/src/composables/usePaintSelect.ts +20 -14
  593. package/src/composables/usePaletteCommands.ts +18 -2
  594. package/src/composables/usePersisted.ts +10 -0
  595. package/src/composables/usePillTransition.ts +9 -6
  596. package/src/composables/useResizeObserver.ts +2 -1
  597. package/src/composables/useReveal.ts +2 -1
  598. package/src/composables/useRovingFocus.ts +11 -14
  599. package/src/composables/useScramble.ts +12 -1
  600. package/src/composables/useShift.ts +8 -6
  601. package/src/composables/useTilt.ts +2 -1
  602. package/src/composables/useTween.ts +10 -5
  603. package/src/composables/useView.ts +17 -3
  604. package/src/composables/useZoomPan.ts +2 -5
  605. package/src/composables/windowing.ts +190 -0
  606. package/src/icons.ts +27 -6
  607. package/src/index.ts +42 -4
  608. package/src/kit-icons.ts +1 -1
  609. package/src/layout/tree.ts +31 -16
  610. package/src/layout/useLayout.ts +6 -0
  611. package/src/layout/useWorkspaces.ts +234 -0
  612. package/src/nuxt.ts +9 -1
  613. package/src/runtime/propCheck.plugin.ts +10 -0
  614. package/src/theme/studio.ts +7 -5
  615. package/src/theme/useTheme.ts +89 -15
  616. package/src/tokens/tokens.css +8 -1
  617. package/dist/assets/LpTabs-CJ0rYQbx.css +0 -18
  618. package/dist/chunks/LpAppShell-Dgejipzz.js +0 -319
  619. package/dist/chunks/LpFileTree-CooHinsC.js +0 -425
  620. package/dist/chunks/LpThemeProvider-8MG6yqU9.js +0 -640
  621. package/dist/chunks/LpTopologyCanvas-B1gIbS0n.js +0 -298
@@ -1,4 +1,6 @@
1
1
  <script setup lang="ts">
2
+ import { useModelOverlayHistory, type OverlayHistoryMode } from "../composables/useOverlayHistory"
3
+ import { nodeWindow } from "../composables/realm"
2
4
  /*
3
5
  * Command palette (⌘K). A centered dialog with a filter box and a keyboard-
4
6
  * navigable, grouped command list. Built on reka Dialog (focus trap + overlay);
@@ -28,6 +30,7 @@
28
30
  * someone runs hourly sits wherever the alphabet put it. With `recent`
29
31
  * bound, picks float to a group of their own.
30
32
  */
33
+ import { clamp } from "../composables/clamp"
31
34
  import {
32
35
  DialogContent,
33
36
  DialogDescription,
@@ -66,7 +69,11 @@ import {
66
69
  type PaletteQuery,
67
70
  } from "./commandSearch"
68
71
  import {
72
+ absoluteHref,
69
73
  commandHasPreview,
74
+ commandKey,
75
+ isSafeHref,
76
+ moreRowId,
70
77
  PALETTE_MODES,
71
78
  type PaletteMode,
72
79
  fallbackRows,
@@ -74,13 +81,14 @@ import {
74
81
  modeChipLabel,
75
82
  pushRecent,
76
83
  readRecent,
84
+ recentKey,
77
85
  recentVisible,
78
86
  resolveRecentItems,
79
87
  toRecentItem,
80
88
  type RecentEntry,
81
89
  type RecentItem,
82
90
  } from "./commandPalette"
83
- import { useOutsideGuard, usePortalTarget } from "../composables/useView"
91
+ import { useOutsideGuard, usePortalTarget, useView, viewWindow } from "../composables/useView"
84
92
 
85
93
  /**
86
94
  * A picture in a row's icon slot: an avatar, a project logo, a world's
@@ -323,6 +331,12 @@ export type PaletteLabels = Partial<Record<PaletteMode, string>> & {
323
331
  const props = withDefaults(
324
332
  defineProps<{
325
333
  open?: boolean
334
+ /**
335
+ * Browser Back closes it, and opening it adds a history entry. Unset
336
+ * follows `provideOverlayHistory` (off without one); `"reopen"` also opens
337
+ * it again on Forward; `false` keeps it out of history.
338
+ */
339
+ history?: OverlayHistoryMode
326
340
  commands?: Command[]
327
341
  /** Include live commands registered by enclosing LpCommandScope components. */
328
342
  context?: boolean
@@ -428,6 +442,7 @@ const props = withDefaults(
428
442
  glass?: boolean
429
443
  }>(),
430
444
  {
445
+ history: undefined,
431
446
  placeholder: "Type a command or search…",
432
447
  emptyText: "No results",
433
448
  commands: () => [],
@@ -528,6 +543,13 @@ const emit = defineEmits<{
528
543
  (e: "remember", item: RecentItem, command: Command): void
529
544
  }>()
530
545
 
546
+ useModelOverlayHistory({
547
+ mode: () => props.history,
548
+ open: () => !!props.open,
549
+ setOpen: (open) => emit("update:open", open),
550
+ allowClose: async () => true,
551
+ })
552
+
531
553
  const query = ref("")
532
554
  /*
533
555
  * The input is a combobox over a listbox: focus never leaves the box, so the
@@ -538,7 +560,13 @@ const listId = `lp-cmd-${useId()}`
538
560
  function optionId(index: number): string {
539
561
  return `${listId}-${index}`
540
562
  }
541
- const activeId = computed(() => (flat.value.length ? optionId(selectedIndex.value) : undefined))
563
+ /* The list is on screen and has rows: only then does the box point into it. */
564
+ const listShown = computed(() => !editing.value && !promptCommand.value && flat.value.length > 0)
565
+ const activeId = computed(() => (listShown.value ? optionId(selectedIndex.value) : undefined))
566
+ /* The placeholder goes away with the first letter; the box keeps saying what it is for. */
567
+ const inputName = computed(() =>
568
+ promptCommand.value?.label ?? (mode.value ? modeChipLabel(mode.value) : text.value.title),
569
+ )
542
570
  const selectedIndex = ref(0)
543
571
  const selectedId = ref<string | null>(null)
544
572
  const inputRef = ref<HTMLInputElement | null>(null)
@@ -566,26 +594,32 @@ const mode = computed<Command | null>(() => trail.value[trail.value.length - 1]
566
594
  const modeItems = shallowRef<Command[]>([])
567
595
 
568
596
  const { copy } = useClipboard()
597
+ const view = useView()
598
+
599
+ /* The command's link, unless it is one the palette will not follow. */
600
+ function linkOf(c: Command | undefined): string | undefined {
601
+ return c?.href && isSafeHref(c.href) ? c.href : undefined
602
+ }
569
603
 
570
604
  function actionsOf(c: Command | undefined): Command[] {
571
605
  if (!c || c.disabled || moreOf.has(c)) return []
572
606
  const own = c.actions ?? []
573
- const href = c.href
607
+ // Read when used, not here: this runs while rendering, on the server too.
608
+ const href = linkOf(c)
574
609
  if (!href) return own
575
- const link = new URL(href, window.location.href).href
576
610
  return [
577
611
  ...own,
578
612
  {
579
613
  id: `${c.id}:open-in-new-tab`,
580
614
  label: text.value.openInNewTab,
581
615
  icon: "lucide:external-link",
582
- onSelect: () => window.open(href, "_blank", "noopener"),
616
+ onSelect: () => viewWindow(view.value).open(href, "_blank", "noopener"),
583
617
  },
584
618
  {
585
619
  id: `${c.id}:copy-link`,
586
620
  label: text.value.copyLink,
587
621
  icon: "lucide:link",
588
- onSelect: () => void copy(link, { toast: text.value.linkCopied || false }),
622
+ onSelect: () => void copy(absoluteHref(href, viewWindow(view.value).document.baseURI), { toast: text.value.linkCopied || false }),
589
623
  },
590
624
  ]
591
625
  }
@@ -648,9 +682,13 @@ watch(
648
682
  next.push(fresh)
649
683
  level = Array.isArray(fresh.children) ? fresh.children : []
650
684
  }
685
+ const fetcherBefore = mode.value?.children
651
686
  trail.value = next
652
- const last = next[next.length - 1]
653
- if (last && Array.isArray(last.children)) modeItems.value = last.children
687
+ const children = next[next.length - 1]?.children
688
+ if (Array.isArray(children)) modeItems.value = children
689
+ // A new fetcher may answer differently: ask again, with the old rows up
690
+ // until it does, so a refresh of the app's commands does not blank the list.
691
+ else if (children !== fetcherBefore) refresh(true)
654
692
  },
655
693
  )
656
694
 
@@ -679,7 +717,7 @@ function popTo(depth: number) {
679
717
  select(0)
680
718
  refresh()
681
719
  void nextTick(() => {
682
- const index = state.selectedId ? flat.value.findIndex((c) => c.id === state.selectedId) : -1
720
+ const index = state.selectedId ? flat.value.findIndex((c) => rowId(c) === state.selectedId) : -1
683
721
  select(index >= 0 ? index : 0)
684
722
  })
685
723
  inputRef.value?.focus()
@@ -725,9 +763,9 @@ function cancel() {
725
763
  */
726
764
  const failed = ref(false)
727
765
 
728
- function refresh() {
766
+ function refresh(keepRows = false) {
729
767
  cancel()
730
- found.value = []
768
+ if (!keepRows) found.value = []
731
769
  failed.value = false
732
770
  const run = fetcher()
733
771
  if (!run) return
@@ -786,15 +824,18 @@ const ranked = computed<Command[]>(() => local.value.items)
786
824
  /*
787
825
  * Fetched results sit under their own heading unless they brought a group of
788
826
  * their own, so they never look like they were part of the static list. An id
789
- * already matched locally is dropped: the same command listed twice is a
790
- * misclick waiting to happen.
827
+ * already matched locally, or already answered by the provider, is dropped:
828
+ * the same command listed twice is a misclick waiting to happen.
791
829
  */
792
830
  const fetched = computed<Command[]>(() => {
793
831
  if (!found.value.length) return []
794
832
  const seen = new Set(ranked.value.map((c) => c.id))
795
- const rows = found.value
796
- .filter((c) => !seen.has(c.id))
797
- .map((c) => (c.group ? c : { ...c, group: props.resultsLabel }))
833
+ const rows: Command[] = []
834
+ for (const c of found.value) {
835
+ if (seen.has(c.id)) continue
836
+ seen.add(c.id)
837
+ rows.push(c.group ? c : { ...c, group: props.resultsLabel })
838
+ }
798
839
  return applyQueryFilters(rows, parseCommandQuery(query.value))
799
840
  })
800
841
 
@@ -836,10 +877,19 @@ const ownRecent = computed<RecentItem[]>({
836
877
  const recentPath = new WeakMap<Command, string[]>()
837
878
  const syntheticModes = new WeakSet<Command>()
838
879
 
880
+ function pathOf(c: Command): string[] {
881
+ return recentPath.get(c) ?? trail.value.map((step) => step.id)
882
+ }
883
+
884
+ /* A root pick that is not a root command is something a search found. */
885
+ function historyItem(c: Command): RecentItem {
886
+ const path = pathOf(c)
887
+ return toRecentItem(c, path, !path.length && !rootCommands.value.some((root) => root.id === c.id))
888
+ }
889
+
839
890
  function remember(c: Command) {
840
891
  if (c.remember === false || trail.value.some((step) => syntheticModes.has(step))) return
841
- const path = recentPath.get(c) ?? trail.value.map((step) => step.id)
842
- const item = toRecentItem(c, path)
892
+ const item = historyItem(c)
843
893
  emit("remember", item, c)
844
894
  const key = props.recentKey
845
895
  if (!key || props.recent) return
@@ -866,10 +916,10 @@ const recentItems = computed<Command[]>(() => {
866
916
  })
867
917
  const out: Command[] = []
868
918
  for (const { command, path } of found) {
919
+ if (out.length >= props.recentLimit) break
869
920
  if (out.includes(command) || !recentVisible(command, terms, props.recentLabel)) continue
870
921
  recentPath.set(command, path)
871
922
  out.push(command)
872
- if (out.length >= props.recentLimit) break
873
923
  }
874
924
  return out
875
925
  })
@@ -882,18 +932,26 @@ const pinnedItems = computed(() => {
882
932
  return pinResolved.value.filter(({ command }) => recentVisible(command, parseCommandQuery(query.value), pinnedHeading.value)).map(({ command, path }) => { recentPath.set(command, path); return command })
883
933
  })
884
934
  function isPinned(command: Command) {
885
- const path = recentPath.get(command) ?? trail.value.map(step => step.id)
886
- return pinList.value.some(item => typeof item === "string" ? !path.length && item === command.id : item.id === command.id && item.path.join("\0") === path.join("\0"))
935
+ const key = commandKey(command.id, pathOf(command))
936
+ return pinList.value.some(item => recentKey(item) === key)
887
937
  }
888
938
  function togglePin(command: Command | undefined) {
889
939
  if (!command || moreOf.has(command) || command.children || trail.value.some(step => syntheticModes.has(step))) return
890
- const path = recentPath.get(command) ?? trail.value.map(step => step.id)
891
- const next = isPinned(command) ? pinList.value.filter(item => typeof item === "string" ? item !== command.id : item.id !== command.id || item.path.join("\0") !== path.join("\0"))
892
- : pushRecent(pinList.value, toRecentItem(command, path), Infinity)
940
+ const key = commandKey(command.id, pathOf(command))
941
+ const next = isPinned(command) ? pinList.value.filter(item => recentKey(item) !== key)
942
+ : pushRecent(pinList.value, historyItem(command), Infinity)
893
943
  if (props.pinned === undefined) storedPinned.value = next
894
944
  emit("update:pinned", next)
895
945
  }
896
946
 
947
+ /*
948
+ * A row's identity on screen. The same id can sit in one list twice, a root
949
+ * command beside a recent pick from a mode, and they are different rows.
950
+ */
951
+ function rowId(c: Command): string {
952
+ return commandKey(c.id, recentPath.get(c))
953
+ }
954
+
897
955
  // Group preserving first-seen order; ungrouped commands sit under "".
898
956
  // Recent first (it answers "the thing I always run"), then the matched list,
899
957
  // then whatever the provider found.
@@ -909,11 +967,15 @@ const grouped = computed<{ name: string; items: Command[] }[]>(() => {
909
967
  }
910
968
  const pinned = pinnedItems.value
911
969
  for (const c of pinned) push(c, pinnedHeading.value)
912
- const recent = recentItems.value.filter(c => !pinned.some(p => p.id === c.id))
913
- for (const c of recent) push(c, props.recentLabel)
970
+ const shown = new Set(pinned.map(rowId))
971
+ const recent = recentItems.value.filter(c => !shown.has(rowId(c)))
972
+ for (const c of recent) {
973
+ push(c, props.recentLabel)
974
+ shown.add(rowId(c))
975
+ }
914
976
  // A recent entry is shown once: leaving the copy in its own group would put
915
977
  // the same row on screen twice with nothing to tell them apart.
916
- for (const c of ranked.value) if (!recent.includes(c) && !pinned.some(p => p.id === c.id)) push(c, c.group ?? "")
978
+ for (const c of ranked.value) if (!shown.has(rowId(c))) push(c, c.group ?? "")
917
979
  for (const c of fetched.value) push(c, c.group ?? "")
918
980
  // Last, whatever their group: they are the way out when nothing above is it.
919
981
  const tail = new Map<string, Command[]>()
@@ -948,13 +1010,13 @@ function folded(name: string, items: Command[]): Command[] {
948
1010
  const limit = props.groupLimit
949
1011
  if (!limit || items.length <= limit + 1 || expanded.value.has(name)) return items
950
1012
  const more: Command = {
951
- id: `lp-cmd-more:${name}`,
1013
+ id: moreRowId(name),
952
1014
  label: text.value.showMore.replace("{count}", String(items.length - limit)),
953
1015
  icon: "lucide:chevron-down",
954
1016
  keepOpen: true,
955
1017
  }
956
1018
  moreOf.set(more, name)
957
- firstHidden.set(more, items[limit].id)
1019
+ firstHidden.set(more, rowId(items[limit]))
958
1020
  return [...items.slice(0, limit), more]
959
1021
  }
960
1022
 
@@ -1128,15 +1190,17 @@ function enterByPrefix(value: string): boolean {
1128
1190
  }
1129
1191
  watch([query, trail, () => props.open], () => {
1130
1192
  expanded.value = new Set()
1193
+ keyboardSelection.value = true
1131
1194
  })
1132
1195
  watch(
1133
- () => flat.value.map((c) => c.id).join("|"),
1196
+ () => flat.value.map(rowId).join("|"),
1134
1197
  () => {
1135
- const index = selectedId.value ? flat.value.findIndex((c) => c.id === selectedId.value) : -1
1198
+ const index = selectedId.value ? flat.value.findIndex((c) => rowId(c) === selectedId.value) : -1
1199
+ keyboardSelection.value = true
1136
1200
  select(index >= 0 ? index : 0)
1137
1201
  },
1138
1202
  )
1139
- watch([selectedIndex, () => flat.value.map((c) => c.id).join("|")], async () => {
1203
+ watch([selectedIndex, () => flat.value.map(rowId).join("|")], async () => {
1140
1204
  await nextTick()
1141
1205
  scrollSelectedIntoView()
1142
1206
  })
@@ -1152,8 +1216,9 @@ const keyboardSelection = ref(false)
1152
1216
 
1153
1217
  function select(index: number, keyboard = false) {
1154
1218
  const len = flat.value.length
1155
- selectedIndex.value = len ? Math.max(0, Math.min(index, len - 1)) : 0
1156
- selectedId.value = flat.value[selectedIndex.value]?.id ?? null
1219
+ selectedIndex.value = len ? clamp(index, 0, len - 1) : 0
1220
+ const row = flat.value[selectedIndex.value]
1221
+ selectedId.value = row ? rowId(row) : null
1157
1222
  if (keyboard) keyboardSelection.value = true
1158
1223
  }
1159
1224
 
@@ -1177,7 +1242,7 @@ function onPaletteKeydown(event: KeyboardEvent) {
1177
1242
  }
1178
1243
  if (!(["ArrowDown", "ArrowUp", "Home", "End", "PageDown", "PageUp"] as string[]).includes(event.key)) return
1179
1244
  // Home and End belong to the caret while there is text to move it through.
1180
- const typing = event.target instanceof HTMLInputElement && event.target.value !== ""
1245
+ const typing = inputRef.value?.value !== ""
1181
1246
  if (typing && (event.key === "Home" || event.key === "End")) return
1182
1247
  event.preventDefault()
1183
1248
  event.stopPropagation()
@@ -1187,8 +1252,17 @@ function onPaletteKeydown(event: KeyboardEvent) {
1187
1252
  else if (event.key === "End") select(flat.value.length - 1, true)
1188
1253
  else movePage(event.key === "PageDown" ? 1 : -1)
1189
1254
  }
1190
- function onPointerMove() {
1255
+ /*
1256
+ * A row that appears under a still pointer gets a pointerenter of its own, and
1257
+ * browsers can send a move of zero after a layout: neither is the user choosing
1258
+ * it. The selection stays where the keyboard or the list put it until the
1259
+ * pointer really moves, and that first move picks the row it is over.
1260
+ */
1261
+ let hovered: Command | null = null
1262
+ function onPointerMove(event: PointerEvent) {
1263
+ if (!keyboardSelection.value || (!event.movementX && !event.movementY)) return
1191
1264
  keyboardSelection.value = false
1265
+ if (hovered) select(flatIndexOf(hovered))
1192
1266
  }
1193
1267
  function onCloseAutoFocus(event: Event) {
1194
1268
  if (!afterClose) return
@@ -1211,19 +1285,23 @@ async function focusEditor() {
1211
1285
  return !!field
1212
1286
  }
1213
1287
  if (focus()) return
1214
- const observer = new MutationObserver(() => { if (focus()) { observer.disconnect(); stopEditorFocus = undefined } })
1288
+ const observer = new (nodeWindow(root).MutationObserver)(() => { if (focus()) { observer.disconnect(); stopEditorFocus = undefined } })
1215
1289
  observer.observe(root, { childList: true, subtree: true })
1216
1290
  stopEditorFocus = () => { observer.disconnect(); stopEditorFocus = undefined }
1217
1291
  }
1218
1292
  watch([editing, () => props.open], () => { if (!editing.value || !props.open) stopEditorFocus?.() })
1219
1293
  onBeforeUnmount(() => stopEditorFocus?.())
1220
1294
  function onPointerEnter(c: Command) {
1295
+ hovered = c
1221
1296
  if (!keyboardSelection.value) select(flatIndexOf(c))
1222
1297
  }
1298
+ function onPointerLeave() {
1299
+ hovered = null
1300
+ }
1223
1301
  function runSelected(event?: KeyboardEvent) {
1224
1302
  if (promptCommand.value) { void submitPrompt(); return }
1225
1303
  const c = flat.value[selectedIndex.value]
1226
- if (c?.href && !c.disabled && (event?.ctrlKey || event?.metaKey)) {
1304
+ if (c && linkOf(c) && !c.disabled && (event?.ctrlKey || event?.metaKey)) {
1227
1305
  openInNewTab(c)
1228
1306
  return
1229
1307
  }
@@ -1231,8 +1309,9 @@ function runSelected(event?: KeyboardEvent) {
1231
1309
  }
1232
1310
 
1233
1311
  function openInNewTab(c: Command) {
1234
- if (!c.href) return
1235
- window.open(c.href, "_blank", "noopener")
1312
+ const href = linkOf(c)
1313
+ if (!href) return
1314
+ viewWindow(view.value).open(href, "_blank", "noopener")
1236
1315
  emit("run", c.id, c)
1237
1316
  remember(c)
1238
1317
  emit("update:open", false)
@@ -1244,7 +1323,7 @@ function openInNewTab(c: Command) {
1244
1323
  * command nor closes. Only the plain click is taken over.
1245
1324
  */
1246
1325
  function onRowClick(event: MouseEvent, c: Command) {
1247
- if (c.href && (event.ctrlKey || event.metaKey || event.shiftKey || event.altKey || event.button !== 0)) return
1326
+ if (linkOf(c) && (event.ctrlKey || event.metaKey || event.shiftKey || event.altKey || event.button !== 0)) return
1248
1327
  event.preventDefault()
1249
1328
  run(c)
1250
1329
  }
@@ -1279,7 +1358,8 @@ async function run(row: Command | undefined) {
1279
1358
  return
1280
1359
  }
1281
1360
  if (!await execute(c, () => c.onSelect?.())) return
1282
- if (!c.onSelect && c.href && !c.children) window.location.assign(c.href)
1361
+ const href = linkOf(c)
1362
+ if (!c.onSelect && href && !c.children) viewWindow(view.value).location.assign(href)
1283
1363
  // A command with children drills in instead of closing, and is navigation
1284
1364
  // rather than a pick — so it stays out of the recency history.
1285
1365
  if (c.children) {
@@ -1405,7 +1485,8 @@ watch(
1405
1485
  failed.value = false
1406
1486
  if (o) {
1407
1487
  await nextTick()
1408
- inputRef.value?.focus()
1488
+ // Closed again meanwhile: the box belongs to a dialog on its way out.
1489
+ if (props.open) inputRef.value?.focus()
1409
1490
  }
1410
1491
  },
1411
1492
  { immediate: true },
@@ -1504,8 +1585,9 @@ const guardOutside = useOutsideGuard()
1504
1585
  type="text"
1505
1586
  role="combobox"
1506
1587
  aria-autocomplete="list"
1507
- aria-expanded="true"
1508
- :aria-controls="listId"
1588
+ :aria-label="inputName"
1589
+ :aria-expanded="listShown"
1590
+ :aria-controls="listShown ? listId : undefined"
1509
1591
  :aria-activedescendant="activeId"
1510
1592
  :placeholder="promptCommand?.prompt?.placeholder ?? mode?.childPlaceholder ?? placeholder"
1511
1593
  class="h-12 min-w-0 flex-1 bg-transparent text-sm text-ink outline-none placeholder:text-muted"
@@ -1556,18 +1638,18 @@ const guardOutside = useOutsideGuard()
1556
1638
  <!-- tabindex -1: the rows are reached with the arrows from the box,
1557
1639
  so Tab should not walk through every one of them. -->
1558
1640
  <component
1559
- :is="c.href ? 'a' : 'button'"
1641
+ :is="linkOf(c) ? 'a' : 'button'"
1560
1642
  v-for="c in group.items"
1561
1643
  :id="optionId(flatIndexOf(c))"
1562
- :key="c.id"
1563
- :href="c.disabled ? undefined : c.href"
1564
- :type="c.href ? undefined : 'button'"
1644
+ :key="rowId(c)"
1645
+ :href="c.disabled ? undefined : linkOf(c)"
1646
+ :type="linkOf(c) ? undefined : 'button'"
1565
1647
  role="option"
1566
1648
  tabindex="-1"
1567
1649
  :aria-selected="flatIndexOf(c) === selectedIndex"
1568
1650
  :aria-disabled="c.disabled || undefined"
1569
1651
  :data-cmd-index="flatIndexOf(c)"
1570
- :disabled="c.href ? undefined : c.disabled"
1652
+ :disabled="linkOf(c) ? undefined : c.disabled"
1571
1653
  class="lp-cmd-item flex w-full gap-3 rounded-inner px-2.5 py-2 text-left text-sm outline-none transition-colors duration-[var(--duration-fast)] disabled:pointer-events-none disabled:opacity-45 aria-disabled:pointer-events-none aria-disabled:opacity-45"
1572
1654
  :class="[
1573
1655
  c.excerpt ? 'items-start' : 'items-center',
@@ -1579,6 +1661,7 @@ const guardOutside = useOutsideGuard()
1579
1661
  ]"
1580
1662
  @click="onRowClick($event, c)"
1581
1663
  @pointerenter="onPointerEnter(c)"
1664
+ @pointerleave="onPointerLeave"
1582
1665
  >
1583
1666
  <!-- A picture takes the icon's slot at the icon's footprint, with
1584
1667
  a negative margin so a 20px avatar does not make its row
@@ -1,7 +1,5 @@
1
1
  <script setup lang="ts">
2
- import { useId } from "vue"
3
- import { menuPaletteCommands } from "./commandPalette"
4
- import { usePaletteCommands, usePaletteScope, type PaletteControlOptions } from "../composables/usePaletteCommands"
2
+ import { useMenuPalette, type PaletteControlOptions } from "../composables/usePaletteCommands"
5
3
  /*
6
4
  * Right-click context menu (reka ContextMenu). Same items as LpDropdownMenu,
7
5
  * drawn by the same renderer: nested submenus (`children`), tick-box items and
@@ -84,16 +82,22 @@ const PANEL = `${POPOVER_PANEL} z-(--z-popover) min-w-48 p-1 outline-none`
84
82
  // next keystroke goes nowhere. Hand focus back to the field instead, with its
85
83
  // selection if the menu action left the text as it was.
86
84
  type TextField = HTMLInputElement | HTMLTextAreaElement
85
+ type SelectionDirection = TextField["selectionDirection"]
87
86
  const SELECTABLE = new Set(["text", "search", "url", "tel", "password"])
88
87
  const view = useView()
89
- let field: { el: TextField; value: string; start: number; end: number } | null = null
88
+ let field: { el: TextField; value: string; start: number; end: number; direction: SelectionDirection } | null = null
90
89
 
91
90
  function rememberField() {
91
+ // No menu will open, so nothing would ever hand this reference back.
92
+ if (!enabled.value) {
93
+ field = null
94
+ return
95
+ }
92
96
  const el = viewDocument(view.value).activeElement
93
97
  const text =
94
98
  el?.tagName === "TEXTAREA" || (el?.tagName === "INPUT" && SELECTABLE.has((el as HTMLInputElement).type))
95
99
  field = text
96
- ? { el: el as TextField, value: (el as TextField).value, start: (el as TextField).selectionStart ?? 0, end: (el as TextField).selectionEnd ?? 0 }
100
+ ? { el: el as TextField, value: (el as TextField).value, start: (el as TextField).selectionStart ?? 0, end: (el as TextField).selectionEnd ?? 0, direction: (el as TextField).selectionDirection }
97
101
  : null
98
102
  }
99
103
 
@@ -140,9 +144,12 @@ function returnFocus(event: Event) {
140
144
  const saved = field
141
145
  field = null
142
146
  if (!saved || !saved.el.isConnected) return
143
- event.preventDefault()
147
+ // A field the action hid or disabled refuses focus: reka then keeps its own
148
+ // fallback to the trigger, so focus does not fall to the body.
144
149
  saved.el.focus()
145
- if (saved.el.value === saved.value) saved.el.setSelectionRange(saved.start, saved.end)
150
+ if (saved.el.ownerDocument.activeElement !== saved.el) return
151
+ event.preventDefault()
152
+ if (saved.el.value === saved.value) saved.el.setSelectionRange(saved.start, saved.end, saved.direction ?? undefined)
146
153
  }
147
154
 
148
155
  // Overlays open in the window this component renders in (an LpFrame's, inside one).
@@ -151,12 +158,13 @@ const portalTo = usePortalTarget()
151
158
  // the page) is not "outside" for this layer.
152
159
  const guardOutside = useOutsideGuard()
153
160
 
154
- const paletteScope = usePaletteScope()
155
- const paletteId = useId()
156
- usePaletteCommands(() => props.palette === false || !props.title || !props.items.length ? [] : [{
157
- id: `${paletteScope?.id}/${props.palette?.id ?? paletteId}`, label: props.palette?.label ?? props.title,
158
- children: menuPaletteCommands(props.items, `${paletteScope?.id}/${props.palette?.id ?? paletteId}`),
159
- }], { automatic: true })
161
+ useMenuPalette(props)
162
+
163
+ // Several roots (trigger and portal), so Vue cannot hand attributes on by
164
+ // itself and dropped them: a trigger wrapped around this one from outside (an
165
+ // LpPopover's, as-child) lost its id, ARIA state and click, and its popover
166
+ // never opened. They go to the trigger, which merges them onto the slot's element.
167
+ defineOptions({ inheritAttrs: false })
160
168
  </script>
161
169
 
162
170
  <template>
@@ -167,6 +175,7 @@ usePaletteCommands(() => props.palette === false || !props.title || !props.items
167
175
  <ContextMenuRoot @update:open="opened">
168
176
  <ContextMenuTrigger
169
177
  as-child
178
+ v-bind="$attrs"
170
179
  :disabled="!enabled"
171
180
  :data-lp-context-menu="hinted ? '' : undefined"
172
181
  @click.capture="leftClick"
@@ -28,6 +28,7 @@ export default { inheritAttrs: false }
28
28
  * round marks (10 minutes, 1 minute, 10 seconds…) and at the end — a
29
29
  * screen reader hears the countdown matter, not every second of it.
30
30
  */
31
+ import { clamp } from "../composables/clamp"
31
32
  import { computed, ref, watch } from "vue"
32
33
  import { useLabels } from "../composables/useLpConfig"
33
34
  import { useMergedAttrs } from "../composables/useMergedClass"
@@ -231,7 +232,7 @@ const urgent = computed(() =>
231
232
 
232
233
  const fraction = computed(() => {
233
234
  if (!(total.value > 0)) return null
234
- return Math.max(0, Math.min(1, remaining.value / total.value))
235
+ return clamp(remaining.value / total.value, 0, 1)
235
236
  })
236
237
 
237
238
  const { class: rootClass, attrs: rest } = useMergedAttrs(() =>
@@ -70,6 +70,18 @@ const text = useLabels<DataListLabels>("dataList", { empty: "—" }, () => props
70
70
  const slots = useSlots()
71
71
 
72
72
  const keyOf = (item: DataListItem) => item.key ?? item.label
73
+
74
+ // Row identity: the key, numbered from its second use, so two rows with one
75
+ // label stay two rows. A slot name still addresses them by `keyOf`.
76
+ const rowKeys = computed(() => {
77
+ const uses = new Map<string, number>()
78
+ return props.items.map((item) => {
79
+ const key = keyOf(item)
80
+ const use = uses.get(key) ?? 0
81
+ uses.set(key, use + 1)
82
+ return use ? `${key}#${use}` : key
83
+ })
84
+ })
73
85
  const isEmpty = (value: DataListItem["value"]) => value === null || value === undefined || value === ""
74
86
  // Long text wraps; rolling a paragraph would clip it to one line.
75
87
  const rolls = (value: DataListItem["value"]) => !isEmpty(value) && String(value).length <= 48
@@ -109,7 +121,7 @@ const pad = computed(() => (props.size === "sm" ? "py-1.5 text-xs" : "py-2.5 tex
109
121
  >
110
122
  <div
111
123
  v-for="(item, i) in items"
112
- :key="keyOf(item)"
124
+ :key="rowKeys[i]"
113
125
  class="group/row grid items-baseline"
114
126
  :class="[ROW[layout], pad, divided && i > 0 ? 'border-t border-line' : '']"
115
127
  >
@@ -32,11 +32,11 @@ export interface DatePickerLabels extends Record<string, string> {
32
32
  * week") and, unlike the range picker's, are opt-in, so forms that already use
33
33
  * the picker keep the plain calendar they were laid out around.
34
34
  */
35
- import { computed, ref, useAttrs } from "vue"
36
- import { useFieldControl } from "../composables/useField"
35
+ import { computed, ref } from "vue"
36
+ import { useAttrsField } from "../composables/useField"
37
37
  import { useLocale } from "../composables/useLocale"
38
38
  import { useLabels } from "../composables/useLpConfig"
39
- import type { CalendarLabels } from "./calendar"
39
+ import type { CalendarLabels, PickerFieldProps } from "./calendar"
40
40
  import { type DatePreset, dayAllowed, defaultDatePresets } from "./dateRange"
41
41
  import LpCalendar from "./LpCalendar.vue"
42
42
  import LpIcon from "./LpIcon.vue"
@@ -44,7 +44,7 @@ import PickerField from "./PickerField.vue"
44
44
  import LpTimeField from "./LpTimeField.vue"
45
45
 
46
46
  const props = withDefaults(
47
- defineProps<{
47
+ defineProps<PickerFieldProps & {
48
48
  /** Selected date "YYYY-MM-DD" (v-model). */
49
49
  modelValue?: string
50
50
  placeholder?: string
@@ -58,12 +58,6 @@ const props = withDefaults(
58
58
  * Tomorrow, In a week); a list replaces it. Off by default.
59
59
  */
60
60
  presets?: DatePreset[] | boolean
61
- clearable?: boolean
62
- disabled?: boolean
63
- invalid?: boolean
64
- size?: "sm" | "md" | "lg"
65
- /** Locale of the shown date and the calendar; defaults to reka's ConfigProvider, then the browser. */
66
- locale?: string
67
61
  /** Intl format for the displayed date. */
68
62
  format?: Intl.DateTimeFormatOptions
69
63
  /** Also pick a minute; the model becomes "YYYY-MM-DDTHH:mm". */
@@ -137,13 +131,7 @@ function clear() {
137
131
  emit("update:modelValue", undefined)
138
132
  }
139
133
 
140
- const attrs = useAttrs()
141
- const field = useFieldControl(() => ({
142
- wrapped: false,
143
- id: typeof attrs.id === "string" ? attrs.id : undefined,
144
- invalid: props.invalid,
145
- disabled: props.disabled,
146
- }))
134
+ const { attrs, field } = useAttrsField(() => ({ invalid: props.invalid, disabled: props.disabled }))
147
135
  const text = useLabels<DatePickerLabels>(
148
136
  "datePicker",
149
137
  {