@leavepulse/ui 0.43.3 → 0.44.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 (340) hide show
  1. package/README.md +75 -7
  2. package/dist/assets/{LpCommandPalette-DH7sPcKP.css → LpCommandPalette-DCP5g2ik.css} +21 -21
  3. package/dist/assets/{LpDropzone-BBoWvi-J.css → LpDropzone-i4BdMi1H.css} +12 -12
  4. package/dist/assets/{LpImageEditor-Ct7Y3aNu.css → LpImageEditor-CbMA82g8.css} +6 -6
  5. package/dist/assets/{LpShortcutsDialog-C6YoQ8_M.css → LpShortcutsDialog-ChUyU7oV.css} +7 -7
  6. package/dist/assets/{LpSkeleton-D7xU8IPV.css → LpSkeleton-H3Z5dEIk.css} +4 -1
  7. package/dist/assets/{LpTable-BgPLJOXa.css → LpTable-DDQNdf86.css} +9 -9
  8. package/dist/chunks/ContextMenuItems-CrfeNPWT.js +123 -0
  9. package/dist/chunks/{LayoutCanvas-Dd20boUG.js → LayoutCanvas-D-jPOAvg.js} +26 -9
  10. package/dist/chunks/{LayoutNode-DGpZA9LX.js → LayoutNode-D8Xy9N-o.js} +20 -8
  11. package/dist/chunks/{LpActionBar-BlvtGB2P.js → LpActionBar-BbwCF6l5.js} +24 -10
  12. package/dist/chunks/{LpAddressInput-B-Zvxsn7.js → LpAddressInput-BrOqkZqg.js} +53 -48
  13. package/dist/chunks/{LpAlert-BAYHDSS1.js → LpAlert-DkOIjsbq.js} +15 -8
  14. package/dist/chunks/{LpAppShell-BGQVIY-3.js → LpAppShell-BUKPcHco.js} +51 -24
  15. package/dist/chunks/{LpAutocomplete-DExlIZe_.js → LpAutocomplete-DxV3Y9h4.js} +50 -23
  16. package/dist/chunks/{LpAvatar-B3-xAOH3.js → LpAvatar-ClBbEYZN.js} +17 -8
  17. package/dist/chunks/LpBreadcrumbs-B8IJgFIc.js +95 -0
  18. package/dist/chunks/{LpButton-5VXXCjwF.js → LpButton-kqJBHIIb.js} +44 -14
  19. package/dist/chunks/{LpCard-BhI1N_vL.js → LpCard-CpRByR0q.js} +1 -1
  20. package/dist/chunks/{LpCheckbox-CVccKYaH.js → LpCheckbox-DpqchzH4.js} +7 -3
  21. package/dist/chunks/{LpCodeBlock-Bo0B4TFR.js → LpCodeBlock-DeHJPq7p.js} +48 -16
  22. package/dist/chunks/{LpColorPicker-BlXea7LM.js → LpColorPicker-Bhf1qxhB.js} +32 -9
  23. package/dist/chunks/{LpConfirmDialog-Q-bxff8z.js → LpConfirmDialog-CIUOSnWo.js} +58 -16
  24. package/dist/chunks/LpConfirmHost-CDm0Wtpv.js +49 -0
  25. package/dist/chunks/LpContextMenu-DQw5dGfG.js +68 -0
  26. package/dist/chunks/LpDatePicker-Drirx1AK.js +191 -0
  27. package/dist/chunks/{LpDrawer-BZ6k3hvo.js → LpDrawer-bScx-KMO.js} +63 -26
  28. package/dist/chunks/{LpFileTree-_5vFBgaK.js → LpFileTree-CSI_5SK2.js} +23 -8
  29. package/dist/chunks/{LpFileTreeNode-BdcIYKIE.js → LpFileTreeNode-B4MiSQX2.js} +2 -2
  30. package/dist/chunks/LpFormField-CIk5qosh.js +87 -0
  31. package/dist/chunks/{LpInput-9EXWUM9B.js → LpInput-C0e8y8_d.js} +26 -11
  32. package/dist/chunks/{LpLightbox-2sYVMY-S.js → LpLightbox-Mr0W_6HK.js} +147 -60
  33. package/dist/chunks/{LpLink-DCND-zyu.js → LpLink-Krkjhe_y.js} +15 -6
  34. package/dist/chunks/{LpLogViewer-CaRy5MeS.js → LpLogViewer-YBOaFnc_.js} +68 -34
  35. package/dist/chunks/{LpMapPicker-ul4oYno6.js → LpMapPicker-NUzS9e37.js} +38 -13
  36. package/dist/chunks/{LpMediaGallery-FF-NquIo.js → LpMediaGallery-DfJmMW0I.js} +6 -3
  37. package/dist/chunks/{LpModal-Bt0pQCI_.js → LpModal-DPwGKBPv.js} +49 -26
  38. package/dist/chunks/{LpModalNav-YaifHrXC.js → LpModalNav-DPg5H9f3.js} +9 -6
  39. package/dist/chunks/{LpNotificationBell-DyGGsMAM.js → LpNotificationBell-t5yn-siX.js} +58 -24
  40. package/dist/chunks/{LpNumberField-CWuX08iX.js → LpNumberField-DWnQKktS.js} +20 -7
  41. package/dist/chunks/{LpNumberFlow-amWYaeuA.js → LpNumberFlow-z4WPZcZu.js} +22 -12
  42. package/dist/chunks/{LpOtpInput-y2v-pmiN.js → LpOtpInput-CziPF3Oq.js} +37 -8
  43. package/dist/chunks/{LpPagination-5FxjmmB5.js → LpPagination-DFngX7Xo.js} +30 -19
  44. package/dist/chunks/{LpPasswordInput--sjYCkLS.js → LpPasswordInput-CWVDuBJ5.js} +10 -7
  45. package/dist/chunks/{LpPhoneInput-BDSKVl_z.js → LpPhoneInput-CD-ZTeSd.js} +57 -33
  46. package/dist/chunks/{LpPie-D6OnzwlJ.js → LpPie-BLco31Nx.js} +78 -21
  47. package/dist/chunks/{LpPopover-8268UmlC.js → LpPopover-p_e_shN3.js} +4 -2
  48. package/dist/chunks/{LpProgress-Btq5W4Ut.js → LpProgress-CBU1iI69.js} +5 -4
  49. package/dist/chunks/{LpRadioGroup-xPIuVDO_.js → LpRadioGroup-DmEW0l78.js} +9 -2
  50. package/dist/chunks/{LpSegmented-fV0Sk92p.js → LpSegmented-Dejd7cIx.js} +7 -3
  51. package/dist/chunks/{LpSelect-ANIVtrpM.js → LpSelect-DrRD9I7L.js} +40 -18
  52. package/dist/chunks/{LpSidebar-ClBUwoEz.js → LpSidebar-BgwUNWpJ.js} +30 -22
  53. package/dist/chunks/{LpSidebarNav-llOcs_Fn.js → LpSidebarNav-Bqxz8aWT.js} +14 -9
  54. package/dist/chunks/{LpSkeleton-CTI-vBgW.js → LpSkeleton-BB6XIV-w.js} +1 -1
  55. package/dist/chunks/{LpSlider-BwNIBkAK.js → LpSlider-Cuzmrd7p.js} +7 -2
  56. package/dist/chunks/{LpSparkline-C6xQ2dwv.js → LpSparkline-CB80N8SJ.js} +11 -4
  57. package/dist/chunks/{LpStat-CQaW8R--.js → LpStat-dXtyrdX9.js} +1 -1
  58. package/dist/chunks/{LpSwitch-Blizvqyt.js → LpSwitch-B1aLKulj.js} +40 -26
  59. package/dist/chunks/{LpTableOfContents-CjvxPMpU.js → LpTableOfContents-BUcAfGPQ.js} +36 -41
  60. package/dist/chunks/{LpTabs-Cefe_lys.js → LpTabs-_qMVaZJ6.js} +19 -5
  61. package/dist/chunks/LpTextarea-yP8hGedR.js +77 -0
  62. package/dist/chunks/LpThemeProvider-Wjm7Tuit.js +35 -0
  63. package/dist/chunks/LpThemeSwitcher-CKLc10KZ.js +169 -0
  64. package/dist/chunks/{LpTilt-DuyKbpkA.js → LpTilt-B7KHX1zH.js} +2 -2
  65. package/dist/chunks/{LpTimeField-K6nAGboX.js → LpTimeField-C5HRgS5H.js} +13 -7
  66. package/dist/chunks/{LpToaster-gDB1EaU3.js → LpToaster--oT6lfhL.js} +57 -28
  67. package/dist/chunks/{LpTooltip-hCLPAqMG.js → LpTooltip-CBdzeKNf.js} +13 -6
  68. package/dist/chunks/LpTooltipProvider-CftjV7Xc.js +25 -0
  69. package/dist/chunks/{LpTopologyCanvas-Cm1L39uL.js → LpTopologyCanvas-DocsLal3.js} +6 -1
  70. package/dist/chunks/{LpUptimeBar-DvAMno0S.js → LpUptimeBar-DLtxOMRy.js} +43 -14
  71. package/dist/chunks/{LpThemeSwitcher-Cue-myST.js → useTheme-C8JHUlPM.js} +173 -215
  72. package/dist/component-names.d.ts +1 -1
  73. package/dist/components/ContextMenuItems.vue.d.ts +8 -0
  74. package/dist/components/ContextMenuItems.vue.js +4 -0
  75. package/dist/components/LayoutCanvas.vue.js +1 -1
  76. package/dist/components/LayoutNode.vue.d.ts +4 -0
  77. package/dist/components/LayoutNode.vue.js +1 -1
  78. package/dist/components/LpActionBar.vue.d.ts +3 -0
  79. package/dist/components/LpActionBar.vue.js +1 -1
  80. package/dist/components/LpAddressInput.vue.d.ts +1 -1
  81. package/dist/components/LpAddressInput.vue.js +1 -1
  82. package/dist/components/LpAlert.vue.d.ts +9 -0
  83. package/dist/components/LpAlert.vue.js +1 -1
  84. package/dist/components/LpAppShell.vue.d.ts +10 -0
  85. package/dist/components/LpAppShell.vue.js +1 -1
  86. package/dist/components/LpAutocomplete.vue.d.ts +31 -6
  87. package/dist/components/LpAutocomplete.vue.js +1 -1
  88. package/dist/components/LpAvatar.vue.d.ts +3 -3
  89. package/dist/components/LpAvatar.vue.js +1 -1
  90. package/dist/components/LpBadge.vue.d.ts +2 -2
  91. package/dist/components/LpBreadcrumbs.vue.d.ts +13 -9
  92. package/dist/components/LpBreadcrumbs.vue.js +1 -1
  93. package/dist/components/LpButton.vue.d.ts +35 -98
  94. package/dist/components/LpButton.vue.js +1 -1
  95. package/dist/components/LpCard.vue.js +1 -1
  96. package/dist/components/LpChart.vue.d.ts +31 -2
  97. package/dist/components/LpChart.vue.js +317 -95
  98. package/dist/components/LpCheckbox.vue.js +1 -1
  99. package/dist/components/LpCodeBlock.vue.d.ts +2 -0
  100. package/dist/components/LpCodeBlock.vue.js +1 -1
  101. package/dist/components/LpColorPicker.vue.js +1 -1
  102. package/dist/components/LpCommandPalette.vue.d.ts +8 -10
  103. package/dist/components/LpCommandPalette.vue.js +88 -78
  104. package/dist/components/LpConfirmDialog.vue.d.ts +15 -3
  105. package/dist/components/LpConfirmDialog.vue.js +1 -1
  106. package/dist/components/LpConfirmHost.vue.d.ts +9 -0
  107. package/dist/components/LpConfirmHost.vue.js +4 -0
  108. package/dist/components/LpContextMenu.vue.d.ts +3 -5
  109. package/dist/components/LpContextMenu.vue.js +1 -1
  110. package/dist/components/LpDatePicker.vue.d.ts +24 -6
  111. package/dist/components/LpDatePicker.vue.js +1 -1
  112. package/dist/components/LpDrawer.vue.d.ts +10 -0
  113. package/dist/components/LpDrawer.vue.js +1 -1
  114. package/dist/components/LpDropzone.vue.js +22 -6
  115. package/dist/components/LpFileTree.vue.d.ts +11 -2
  116. package/dist/components/LpFileTree.vue.js +1 -1
  117. package/dist/components/LpFileTreeNode.vue.js +1 -1
  118. package/dist/components/LpFormField.vue.d.ts +9 -0
  119. package/dist/components/LpFormField.vue.js +1 -1
  120. package/dist/components/LpImageEditor.vue.js +92 -57
  121. package/dist/components/LpInput.vue.d.ts +3 -3
  122. package/dist/components/LpInput.vue.js +1 -1
  123. package/dist/components/LpLightbox.vue.d.ts +17 -0
  124. package/dist/components/LpLightbox.vue.js +1 -1
  125. package/dist/components/LpLink.vue.d.ts +11 -11
  126. package/dist/components/LpLink.vue.js +1 -1
  127. package/dist/components/LpLogViewer.vue.d.ts +20 -2
  128. package/dist/components/LpLogViewer.vue.js +1 -1
  129. package/dist/components/LpMapPicker.vue.d.ts +4 -4
  130. package/dist/components/LpMapPicker.vue.js +1 -1
  131. package/dist/components/LpMediaGallery.vue.js +1 -1
  132. package/dist/components/LpModal.vue.d.ts +16 -6
  133. package/dist/components/LpModal.vue.js +1 -1
  134. package/dist/components/LpModalNav.vue.d.ts +0 -1
  135. package/dist/components/LpModalNav.vue.js +1 -1
  136. package/dist/components/LpNotificationBell.vue.d.ts +11 -2
  137. package/dist/components/LpNotificationBell.vue.js +1 -1
  138. package/dist/components/LpNumberField.vue.d.ts +2 -0
  139. package/dist/components/LpNumberField.vue.js +1 -1
  140. package/dist/components/LpNumberFlow.vue.js +1 -1
  141. package/dist/components/LpOtpInput.vue.js +1 -1
  142. package/dist/components/LpPagination.vue.d.ts +2 -0
  143. package/dist/components/LpPagination.vue.js +1 -1
  144. package/dist/components/LpPasswordInput.vue.js +1 -1
  145. package/dist/components/LpPhoneInput.vue.js +1 -1
  146. package/dist/components/LpPie.vue.d.ts +21 -2
  147. package/dist/components/LpPie.vue.js +1 -1
  148. package/dist/components/LpPopover.vue.d.ts +2 -0
  149. package/dist/components/LpPopover.vue.js +1 -1
  150. package/dist/components/LpProgress.vue.js +1 -1
  151. package/dist/components/LpRadioGroup.vue.js +1 -1
  152. package/dist/components/LpSection.vue.d.ts +1 -1
  153. package/dist/components/LpSegmented.vue.d.ts +5 -0
  154. package/dist/components/LpSegmented.vue.js +1 -1
  155. package/dist/components/LpSelect.vue.d.ts +1 -0
  156. package/dist/components/LpSelect.vue.js +1 -1
  157. package/dist/components/LpShortcutsDialog.vue.d.ts +1 -1
  158. package/dist/components/LpShortcutsDialog.vue.js +11 -8
  159. package/dist/components/LpSidebar.vue.d.ts +6 -2
  160. package/dist/components/LpSidebar.vue.js +1 -1
  161. package/dist/components/LpSidebarNav.vue.js +1 -1
  162. package/dist/components/LpSkeleton.vue.js +1 -1
  163. package/dist/components/LpSlider.vue.js +1 -1
  164. package/dist/components/LpSparkline.vue.d.ts +1 -0
  165. package/dist/components/LpSparkline.vue.js +1 -1
  166. package/dist/components/LpStat.vue.js +1 -1
  167. package/dist/components/LpSwitch.vue.js +1 -1
  168. package/dist/components/LpTable.vue.d.ts +23 -1
  169. package/dist/components/LpTable.vue.js +74 -36
  170. package/dist/components/LpTableOfContents.vue.d.ts +4 -2
  171. package/dist/components/LpTableOfContents.vue.js +1 -1
  172. package/dist/components/LpTabs.vue.d.ts +2 -0
  173. package/dist/components/LpTabs.vue.js +1 -1
  174. package/dist/components/LpTextarea.vue.d.ts +19 -6
  175. package/dist/components/LpTextarea.vue.js +1 -1
  176. package/dist/components/LpThemeProvider.vue.d.ts +22 -0
  177. package/dist/components/LpThemeProvider.vue.js +4 -0
  178. package/dist/components/LpThemeSwitcher.vue.d.ts +13 -0
  179. package/dist/components/LpThemeSwitcher.vue.js +1 -1
  180. package/dist/components/LpTilt.vue.js +1 -1
  181. package/dist/components/LpTimeField.vue.js +1 -1
  182. package/dist/components/LpToaster.vue.d.ts +6 -1
  183. package/dist/components/LpToaster.vue.js +1 -1
  184. package/dist/components/LpTooltip.vue.d.ts +1 -2
  185. package/dist/components/LpTooltip.vue.js +1 -1
  186. package/dist/components/LpTooltipProvider.vue.d.ts +22 -0
  187. package/dist/components/LpTooltipProvider.vue.js +4 -0
  188. package/dist/components/LpTopologyCanvas.vue.js +1 -1
  189. package/dist/components/LpUptimeBar.vue.d.ts +4 -0
  190. package/dist/components/LpUptimeBar.vue.js +1 -1
  191. package/dist/components/chart.d.ts +32 -1
  192. package/dist/components/chart.js +39 -4
  193. package/dist/components/codeHighlight.d.ts +6 -0
  194. package/dist/components/codeHighlight.js +92 -20
  195. package/dist/components/color.d.ts +1 -1
  196. package/dist/components/color.js +20 -9
  197. package/dist/components/commandSearch.d.ts +0 -1
  198. package/dist/components/commandSearch.js +1 -17
  199. package/dist/components/confirm.d.ts +25 -0
  200. package/dist/components/confirm.js +26 -0
  201. package/dist/components/countries.d.ts +6 -0
  202. package/dist/components/countries.js +7 -0
  203. package/dist/components/fileTree.js +16 -7
  204. package/dist/components/imageCrop.d.ts +42 -0
  205. package/dist/components/imageCrop.js +47 -0
  206. package/dist/components/link.d.ts +12 -0
  207. package/dist/components/link.js +19 -0
  208. package/dist/components/modalDepth.d.ts +18 -2
  209. package/dist/components/modalDepth.js +17 -5
  210. package/dist/components/otp.d.ts +5 -0
  211. package/dist/components/otp.js +10 -0
  212. package/dist/components/sidebar.d.ts +7 -1
  213. package/dist/components/tableSort.d.ts +8 -0
  214. package/dist/components/tableSort.js +31 -0
  215. package/dist/composables/useField.d.ts +34 -0
  216. package/dist/composables/useField.js +45 -0
  217. package/dist/composables/useFormDraft.d.ts +10 -3
  218. package/dist/composables/useFormDraft.js +9 -14
  219. package/dist/composables/useHotkeys.d.ts +17 -1
  220. package/dist/composables/useHotkeys.js +55 -18
  221. package/dist/composables/useInputFilter.d.ts +17 -0
  222. package/dist/composables/useInputFilter.js +47 -10
  223. package/dist/composables/useLpConfig.d.ts +24 -0
  224. package/dist/composables/useLpConfig.js +44 -0
  225. package/dist/composables/useRovingFocus.js +7 -0
  226. package/dist/composables/useTilt.d.ts +2 -2
  227. package/dist/composables/useTilt.js +5 -6
  228. package/dist/composables/useToast.d.ts +20 -0
  229. package/dist/composables/useToast.js +28 -4
  230. package/dist/composables/useZoomPan.d.ts +3 -3
  231. package/dist/composables/useZoomPan.js +4 -4
  232. package/dist/index.d.ts +33 -3
  233. package/dist/index.js +185 -139
  234. package/dist/layout/tree.d.ts +2 -0
  235. package/dist/layout/tree.js +16 -1
  236. package/dist/layout/useLayout.d.ts +15 -0
  237. package/dist/layout/useLayout.js +41 -14
  238. package/dist/theme/useTheme.d.ts +32 -9
  239. package/package.json +8 -7
  240. package/src/component-names.ts +5 -7
  241. package/src/components/ContextMenuItems.vue +88 -0
  242. package/src/components/LayoutCanvas.vue +26 -6
  243. package/src/components/LayoutNode.vue +19 -2
  244. package/src/components/LpActionBar.vue +30 -7
  245. package/src/components/LpAddressInput.vue +57 -41
  246. package/src/components/LpAlert.vue +16 -3
  247. package/src/components/LpAppShell.vue +45 -12
  248. package/src/components/LpAutocomplete.vue +46 -10
  249. package/src/components/LpAvatar.vue +19 -5
  250. package/src/components/LpBreadcrumbs.vue +65 -41
  251. package/src/components/LpButton.vue +59 -13
  252. package/src/components/LpChart.vue +272 -28
  253. package/src/components/LpCheckbox.vue +7 -3
  254. package/src/components/LpCodeBlock.vue +50 -14
  255. package/src/components/LpColorPicker.vue +39 -9
  256. package/src/components/LpCommandPalette.vue +36 -25
  257. package/src/components/LpConfirmDialog.vue +68 -17
  258. package/src/components/LpConfirmHost.vue +59 -0
  259. package/src/components/LpContextMenu.vue +14 -115
  260. package/src/components/LpDatePicker.vue +99 -68
  261. package/src/components/LpDrawer.vue +56 -19
  262. package/src/components/LpDropzone.vue +21 -4
  263. package/src/components/LpFileTree.vue +33 -7
  264. package/src/components/LpFormField.vue +30 -7
  265. package/src/components/LpImageEditor.vue +96 -57
  266. package/src/components/LpInput.vue +18 -7
  267. package/src/components/LpLightbox.vue +140 -29
  268. package/src/components/LpLink.vue +24 -13
  269. package/src/components/LpLogViewer.vue +86 -17
  270. package/src/components/LpMapPicker.vue +36 -13
  271. package/src/components/LpMediaGallery.vue +8 -2
  272. package/src/components/LpModal.vue +53 -27
  273. package/src/components/LpModalNav.vue +5 -2
  274. package/src/components/LpNotificationBell.vue +63 -17
  275. package/src/components/LpNumberField.vue +21 -6
  276. package/src/components/LpNumberFlow.vue +26 -10
  277. package/src/components/LpOtpInput.vue +43 -8
  278. package/src/components/LpPagination.vue +23 -7
  279. package/src/components/LpPasswordInput.vue +4 -1
  280. package/src/components/LpPhoneInput.vue +53 -27
  281. package/src/components/LpPie.vue +94 -15
  282. package/src/components/LpPopover.vue +3 -0
  283. package/src/components/LpProgress.vue +5 -3
  284. package/src/components/LpRadioGroup.vue +9 -2
  285. package/src/components/LpSegmented.vue +12 -2
  286. package/src/components/LpSelect.vue +0 -0
  287. package/src/components/LpShortcutsDialog.vue +8 -3
  288. package/src/components/LpSidebar.vue +14 -9
  289. package/src/components/LpSidebarNav.vue +17 -5
  290. package/src/components/LpSkeleton.vue +4 -1
  291. package/src/components/LpSlider.vue +7 -1
  292. package/src/components/LpSparkline.vue +11 -3
  293. package/src/components/LpSwitch.vue +30 -7
  294. package/src/components/LpTable.vue +91 -32
  295. package/src/components/LpTableOfContents.vue +50 -32
  296. package/src/components/LpTabs.vue +23 -6
  297. package/src/components/LpTextarea.vue +44 -6
  298. package/src/components/LpThemeProvider.vue +41 -0
  299. package/src/components/LpThemeSwitcher.vue +64 -17
  300. package/src/components/LpTilt.vue +2 -2
  301. package/src/components/LpTimeField.vue +14 -3
  302. package/src/components/LpToaster.vue +66 -26
  303. package/src/components/LpTooltip.vue +22 -5
  304. package/src/components/LpTooltipProvider.vue +24 -0
  305. package/src/components/LpTopologyCanvas.vue +12 -1
  306. package/src/components/LpUptimeBar.vue +46 -8
  307. package/src/components/chart.ts +77 -5
  308. package/src/components/codeHighlight.ts +111 -15
  309. package/src/components/color.ts +30 -9
  310. package/src/components/commandSearch.ts +0 -17
  311. package/src/components/confirm.ts +58 -0
  312. package/src/components/countries.ts +12 -0
  313. package/src/components/fileTree.ts +19 -7
  314. package/src/components/imageCrop.ts +107 -0
  315. package/src/components/link.ts +34 -0
  316. package/src/components/modalDepth.ts +48 -6
  317. package/src/components/otp.ts +16 -0
  318. package/src/components/sidebar.ts +7 -1
  319. package/src/components/tableSort.ts +37 -0
  320. package/src/composables/useField.ts +79 -0
  321. package/src/composables/useFormDraft.ts +25 -20
  322. package/src/composables/useHotkeys.ts +89 -18
  323. package/src/composables/useInputFilter.ts +77 -14
  324. package/src/composables/useLpConfig.ts +87 -0
  325. package/src/composables/useRovingFocus.ts +11 -0
  326. package/src/composables/useTilt.ts +5 -6
  327. package/src/composables/useToast.ts +56 -4
  328. package/src/composables/useZoomPan.ts +6 -6
  329. package/src/index.ts +38 -3
  330. package/src/layout/tree.ts +30 -0
  331. package/src/layout/useLayout.ts +68 -18
  332. package/src/nuxt.ts +59 -17
  333. package/src/runtime/config.plugin.ts +14 -0
  334. package/src/runtime/theme.plugin.ts +42 -22
  335. package/src/theme/useTheme.ts +206 -100
  336. package/dist/chunks/LpBreadcrumbs-p4jHe_V-.js +0 -62
  337. package/dist/chunks/LpContextMenu-CwW1QXe_.js +0 -217
  338. package/dist/chunks/LpDatePicker-CwOToxGq.js +0 -164
  339. package/dist/chunks/LpFormField-CazBc2-a.js +0 -62
  340. package/dist/chunks/LpTextarea-t7F6gv8E.js +0 -47
@@ -0,0 +1,34 @@
1
+ import { type ComputedRef, type InjectionKey } from "vue";
2
+ export interface FieldContext {
3
+ id: string;
4
+ /** Id of the visible label, for controls a `<label for>` cannot name (groups). */
5
+ labelId?: string;
6
+ describedBy?: string;
7
+ invalid: boolean;
8
+ required: boolean;
9
+ disabled: boolean;
10
+ }
11
+ export declare const LP_FIELD: InjectionKey<ComputedRef<FieldContext>>;
12
+ export declare function provideField(context: ComputedRef<FieldContext>): void;
13
+ /** The nearest LpFormField's context, or null outside one. */
14
+ export declare function useField(): ComputedRef<FieldContext> | null;
15
+ export declare function fieldMessageId(id: string): string;
16
+ export interface FieldControlState {
17
+ /** The control wraps itself in its own LpFormField (it has a label, hint or error prop). */
18
+ wrapped: boolean;
19
+ /** That own field renders a hint or error line. */
20
+ hasMessage?: boolean;
21
+ /** An id the consumer set on the control, which must win over a generated one. */
22
+ id?: string;
23
+ invalid?: boolean;
24
+ required?: boolean;
25
+ disabled?: boolean;
26
+ }
27
+ /**
28
+ * The field state a control renders with: its own wrapping field when it has
29
+ * one, otherwise the field around it, with the control's own flags or-ed in.
30
+ * `id` is undefined only for a bare control outside any field.
31
+ */
32
+ export declare function useFieldControl(own: () => FieldControlState): ComputedRef<Omit<FieldContext, "id"> & {
33
+ id?: string;
34
+ }>;
@@ -0,0 +1,45 @@
1
+ import { provide, useId, computed, inject } from "vue";
2
+ const LP_FIELD = /* @__PURE__ */ Symbol.for("lp-field");
3
+ function provideField(context) {
4
+ provide(LP_FIELD, context);
5
+ }
6
+ function useField() {
7
+ return inject(LP_FIELD, null);
8
+ }
9
+ function fieldMessageId(id) {
10
+ return `${id}-message`;
11
+ }
12
+ function useFieldControl(own) {
13
+ const outer = useField();
14
+ const generated = useId();
15
+ return computed(() => {
16
+ const state = own();
17
+ if (state.wrapped) {
18
+ const id = state.id ?? generated;
19
+ return {
20
+ id,
21
+ labelId: void 0,
22
+ describedBy: state.hasMessage ? fieldMessageId(id) : void 0,
23
+ invalid: !!state.invalid,
24
+ required: !!state.required,
25
+ disabled: !!state.disabled
26
+ };
27
+ }
28
+ const field = outer?.value;
29
+ return {
30
+ id: state.id ?? field?.id,
31
+ labelId: field?.labelId,
32
+ describedBy: field?.describedBy,
33
+ invalid: !!state.invalid || !!field?.invalid,
34
+ required: !!state.required || !!field?.required,
35
+ disabled: !!state.disabled || !!field?.disabled
36
+ };
37
+ });
38
+ }
39
+ export {
40
+ LP_FIELD,
41
+ fieldMessageId,
42
+ provideField,
43
+ useField,
44
+ useFieldControl
45
+ };
@@ -24,9 +24,16 @@ export interface UseFormDraftOptions<T> {
24
24
  disabled?: MaybeRefOrGetter<boolean>;
25
25
  }
26
26
  export interface UseFormDraft<T> {
27
- /** A draft was found for this key, and has not been restored or discarded. */
27
+ /**
28
+ * A draft was found for this key, and has not been restored or discarded.
29
+ * Only a draft found on reading counts: the writes this composable makes as
30
+ * the user types never raise it. While it is up, automatic writes are held
31
+ * back, so the draft on offer cannot be overwritten by the form's own state
32
+ * (an async load of the record, or typing past the banner) before the user
33
+ * has answered.
34
+ */
28
35
  hasDraft: Ref<boolean>;
29
- /** When that draft was written, ISO-8601, or `null` when there is none. */
36
+ /** When the found draft was written, ISO-8601, or `null` when there is none. */
30
37
  savedAt: Ref<string | null>;
31
38
  /**
32
39
  * The stored value, or `null`. Reading does not apply it — the caller decides
@@ -35,7 +42,7 @@ export interface UseFormDraft<T> {
35
42
  read: () => T | null;
36
43
  /** Forget the draft. Call after applying it, and after a successful save. */
37
44
  discard: () => void;
38
- /** Write now, ignoring `dirty`. For "save and come back to this later". */
45
+ /** Write now, ignoring `dirty` and a pending draft. For "save and come back to this later". */
39
46
  save: () => void;
40
47
  }
41
48
  /**
@@ -16,6 +16,11 @@ function useFormDraft(options) {
16
16
  function currentKey() {
17
17
  return String(toValue(options.key) || "").trim();
18
18
  }
19
+ function fresh(parsed) {
20
+ if (!parsed || parsed.version !== ENVELOPE_VERSION) return false;
21
+ if (maxAge <= 0) return true;
22
+ return !(Date.now() - Date.parse(parsed.savedAt) > maxAge);
23
+ }
19
24
  function read() {
20
25
  const store = storage();
21
26
  const key = currentKey();
@@ -29,17 +34,10 @@ function useFormDraft(options) {
29
34
  if (!raw) return null;
30
35
  try {
31
36
  const parsed = JSON.parse(raw);
32
- if (!parsed || parsed.version !== ENVELOPE_VERSION) {
37
+ if (!fresh(parsed)) {
33
38
  discard();
34
39
  return null;
35
40
  }
36
- if (maxAge > 0) {
37
- const age = Date.now() - Date.parse(parsed.savedAt);
38
- if (age > maxAge) {
39
- discard();
40
- return null;
41
- }
42
- }
43
41
  return parsed.value;
44
42
  } catch {
45
43
  discard();
@@ -50,21 +48,18 @@ function useFormDraft(options) {
50
48
  const store = storage();
51
49
  const key = currentKey();
52
50
  if (!store || !key) return;
53
- const stamp = (/* @__PURE__ */ new Date()).toISOString();
54
51
  try {
55
52
  store.setItem(
56
53
  key,
57
54
  JSON.stringify({
58
55
  version: ENVELOPE_VERSION,
59
- savedAt: stamp,
56
+ savedAt: (/* @__PURE__ */ new Date()).toISOString(),
60
57
  value
61
58
  })
62
59
  );
63
60
  } catch {
64
61
  return;
65
62
  }
66
- hasDraft.value = true;
67
- savedAt.value = stamp;
68
63
  }
69
64
  function discard() {
70
65
  const store = storage();
@@ -97,7 +92,7 @@ function useFormDraft(options) {
97
92
  if (!raw) return;
98
93
  try {
99
94
  const parsed = JSON.parse(raw);
100
- if (parsed?.version !== ENVELOPE_VERSION) return;
95
+ if (!fresh(parsed)) return;
101
96
  hasDraft.value = true;
102
97
  savedAt.value = parsed.savedAt;
103
98
  } catch {
@@ -108,7 +103,7 @@ function useFormDraft(options) {
108
103
  watch(
109
104
  () => [toValue(options.value), toValue(options.dirty), toValue(options.disabled)],
110
105
  ([value, dirty, disabled]) => {
111
- if (disabled) return;
106
+ if (disabled || hasDraft.value) return;
112
107
  if (options.dirty !== void 0 && !dirty) return;
113
108
  write(value);
114
109
  },
@@ -16,6 +16,16 @@ export interface HotkeyBinding {
16
16
  * something there — Escape, and the palette the user reaches from anywhere.
17
17
  */
18
18
  allowInInput?: boolean;
19
+ /**
20
+ * Runs even while an overlay owns the keyboard. By default a binding declared
21
+ * outside the topmost modal stays quiet while that modal is open, and an
22
+ * Escape binding declared outside the topmost dismissable layer (dialog,
23
+ * popover, menu) leaves Escape to that layer, so a page-level shortcut can
24
+ * neither act behind a dialog nor stop the dialog from closing.
25
+ */
26
+ overLayers?: boolean;
27
+ /** Set `false` to ignore auto-repeat while the key is held. */
28
+ repeat?: boolean;
19
29
  /**
20
30
  * How the key reference lists this binding while it is mounted. Bindings
21
31
  * without it still work, they just stay out of `activeShortcuts`.
@@ -57,11 +67,17 @@ export interface ShortcutGroup {
57
67
  * used to pick a label.
58
68
  */
59
69
  export declare const isAppleKeyboard: boolean;
70
+ /**
71
+ * `isAppleKeyboard` for render paths: false until mounted, so the server and
72
+ * the hydrating client print the same label and the client switches after.
73
+ */
74
+ export declare function useAppleKeyboard(): import("vue").Ref<boolean, boolean>;
60
75
  /**
61
76
  * The symbol to print for a modifier on this platform. Bindings treat Ctrl and
62
77
  * Meta as one modifier, so only the label may differ — never the binding.
63
78
  */
64
- export declare function appleModifierLabel(key: string): string;
79
+ export declare function appleModifierLabel(key: string, apple?: boolean): string;
80
+ export declare function matchesHotkey(event: KeyboardEvent, binding: HotkeyBinding): boolean;
65
81
  /**
66
82
  * Bind a list of hotkeys for as long as the calling component is mounted.
67
83
  *
@@ -1,7 +1,13 @@
1
- import { shallowReactive, computed, toValue, onMounted, onBeforeUnmount } from "vue";
1
+ import { shallowReactive, computed, toValue, getCurrentInstance, onMounted, onBeforeUnmount, ref } from "vue";
2
+ import { topModalElement } from "../components/modalDepth.js";
2
3
  const isAppleKeyboard = typeof navigator !== "undefined" && /Mac|iPhone|iPad|iPod/.test(navigator.platform || "");
3
- function appleModifierLabel(key) {
4
- if (!isAppleKeyboard) return key;
4
+ function useAppleKeyboard() {
5
+ const apple = ref(false);
6
+ onMounted(() => apple.value = isAppleKeyboard);
7
+ return apple;
8
+ }
9
+ function appleModifierLabel(key, apple = isAppleKeyboard) {
10
+ if (!apple) return key;
5
11
  if (key === "Ctrl") return "⌘";
6
12
  if (key === "Alt") return "⌥";
7
13
  return key;
@@ -24,33 +30,57 @@ function isTextEntry(target) {
24
30
  }
25
31
  return false;
26
32
  }
27
- function matches(event, binding) {
33
+ const MODIFIER_KEYS = /* @__PURE__ */ new Set(["control", "meta", "shift", "alt"]);
34
+ function matchesHotkey(event, binding) {
35
+ const key = binding.key.toLowerCase();
28
36
  const ctrlHeld = event.ctrlKey || event.metaKey;
29
- if (ctrlHeld !== Boolean(binding.ctrl)) return false;
30
- if (event.shiftKey !== Boolean(binding.shift)) return false;
31
- if (event.altKey !== Boolean(binding.alt)) return false;
32
- return event.key.toLowerCase() === binding.key.toLowerCase() || binding.code !== void 0 && event.code === binding.code;
37
+ const wantsCtrl = Boolean(binding.ctrl) || key === "control" || key === "meta";
38
+ if (ctrlHeld !== wantsCtrl) return false;
39
+ const symbol = key.length === 1 && key.toLowerCase() === key.toUpperCase();
40
+ const shiftFree = key === "shift" || binding.shift === void 0 && symbol;
41
+ if (!shiftFree && event.shiftKey !== Boolean(binding.shift)) return false;
42
+ if (key !== "alt" && event.altKey !== Boolean(binding.alt)) return false;
43
+ if (MODIFIER_KEYS.has(key)) return event.key.toLowerCase() === key;
44
+ return event.key.toLowerCase() === key || binding.code !== void 0 && event.code === binding.code;
33
45
  }
34
- const mounted = shallowReactive(/* @__PURE__ */ new Set());
35
- let mountOrder = 0;
36
- let listening = false;
46
+ const STATE_KEY = /* @__PURE__ */ Symbol.for("@leavepulse/ui:hotkeys");
47
+ const g = globalThis;
48
+ const state = g[STATE_KEY] ??= {
49
+ mounted: shallowReactive(/* @__PURE__ */ new Set()),
50
+ order: 0,
51
+ listening: false
52
+ };
53
+ const mounted = state.mounted;
37
54
  function inScope(target, scope) {
38
55
  const el = toValue(scope);
39
56
  if (!el) return true;
40
57
  const node = target instanceof Node ? target : null;
41
58
  return !!node && (el === node || el.contains(node));
42
59
  }
60
+ function topLayer() {
61
+ const layers = document.querySelectorAll("[data-dismissable-layer]");
62
+ return layers[layers.length - 1] ?? null;
63
+ }
64
+ function insideOf(entry, layer) {
65
+ const scope = toValue(entry.scope);
66
+ const node = scope ?? entry.host();
67
+ return !!node && layer.contains(node);
68
+ }
43
69
  function onKeydown(event) {
44
- if (event.isComposing) return;
70
+ if (event.isComposing || event.defaultPrevented) return;
45
71
  const inTextEntry = isTextEntry(event.target);
72
+ const blocker = event.key === "Escape" ? topLayer() : topModalElement();
46
73
  const entries = [...mounted].sort(
47
74
  (a, b) => Number(toValue(b.priority) || 0) - Number(toValue(a.priority) || 0) || b.order - a.order
48
75
  );
49
76
  for (const entry of entries) {
50
77
  if (toValue(entry.enabled) === false || !inScope(event.target, entry.scope)) continue;
78
+ const covered = !!blocker && !insideOf(entry, blocker);
51
79
  for (const binding of entry.read()) {
52
80
  if (inTextEntry && !binding.allowInInput) continue;
53
- if (!matches(event, binding)) continue;
81
+ if (event.repeat && binding.repeat === false) continue;
82
+ if (covered && !binding.overLayers) continue;
83
+ if (!matchesHotkey(event, binding)) continue;
54
84
  if (binding.handler(event) === false) continue;
55
85
  event.preventDefault();
56
86
  return;
@@ -58,25 +88,30 @@ function onKeydown(event) {
58
88
  }
59
89
  }
60
90
  function useHotkeys(bindings, options = {}) {
91
+ const instance = getCurrentInstance();
61
92
  const entry = {
62
93
  read: () => toValue(bindings),
63
94
  scope: options.scope,
64
95
  enabled: options.enabled,
65
96
  priority: options.priority,
66
- order: ++mountOrder
97
+ order: ++state.order,
98
+ host: () => {
99
+ const el = instance?.vnode.el;
100
+ return el instanceof Node ? el : null;
101
+ }
67
102
  };
68
103
  onMounted(() => {
69
104
  mounted.add(entry);
70
- if (!listening) {
105
+ if (!state.listening) {
71
106
  window.addEventListener("keydown", onKeydown);
72
- listening = true;
107
+ state.listening = true;
73
108
  }
74
109
  });
75
110
  onBeforeUnmount(() => {
76
111
  mounted.delete(entry);
77
- if (!mounted.size && listening) {
112
+ if (!mounted.size && state.listening) {
78
113
  window.removeEventListener("keydown", onKeydown);
79
- listening = false;
114
+ state.listening = false;
80
115
  }
81
116
  });
82
117
  }
@@ -128,6 +163,8 @@ export {
128
163
  activeShortcuts,
129
164
  appleModifierLabel,
130
165
  isAppleKeyboard,
166
+ matchesHotkey,
131
167
  mergeShortcutGroups,
168
+ useAppleKeyboard,
132
169
  useHotkeys
133
170
  };
@@ -5,9 +5,26 @@ export interface UseInputFilterOptions {
5
5
  /** RegExp/string the full value must match to be valid. Validation only. */
6
6
  pattern?: MaybeRefOrGetter<RegExp | string | undefined>;
7
7
  }
8
+ /**
9
+ * Anchor a pattern to the whole string, like HTML's `pattern` attribute. The
10
+ * source is wrapped, never edited: anchors the caller wrote stay valid inside
11
+ * the group, while trimming a trailing `$` broke an escaped `\$` into an
12
+ * unterminated group.
13
+ */
14
+ export declare function anchorPattern(p: RegExp | string): RegExp;
15
+ /**
16
+ * `text` with every disallowed character removed, and where `caret` lands once
17
+ * the characters before it that were removed are gone.
18
+ */
19
+ export declare function stripDisallowed(text: string, charRe: RegExp, caret?: number): {
20
+ text: string;
21
+ caret: number;
22
+ };
8
23
  export declare function useInputFilter(options?: UseInputFilterOptions): {
9
24
  isInvalid: (value: string | undefined) => boolean;
10
25
  onBeforeInput: (event: InputEvent) => void;
26
+ onInput: (event: Event) => void;
27
+ onCompositionEnd: (event: CompositionEvent) => void;
11
28
  onPaste: (event: ClipboardEvent) => void;
12
29
  patternRe: import("vue").ComputedRef<RegExp | undefined>;
13
30
  restrict: import("vue").ComputedRef<RegExp | undefined>;
@@ -1,23 +1,38 @@
1
1
  import { computed, toValue } from "vue";
2
- function toAnchored(p) {
3
- if (p instanceof RegExp) {
4
- const src = p.source.replace(/^\^/, "").replace(/\$$/, "");
5
- return new RegExp(`^(?:${src})$`, p.flags.replace(/[gy]/g, ""));
6
- }
2
+ function anchorPattern(p) {
3
+ if (p instanceof RegExp) return new RegExp(`^(?:${p.source})$`, p.flags.replace(/[gy]/g, ""));
7
4
  return new RegExp(`^(?:${p})$`);
8
5
  }
9
- function allAllowed(text, charRe) {
6
+ function charTester(charRe) {
10
7
  const re = new RegExp(charRe.source, charRe.flags.replace(/[gy]/g, ""));
8
+ return (ch) => re.test(ch);
9
+ }
10
+ function allAllowed(text, charRe) {
11
+ const ok = charTester(charRe);
11
12
  for (const ch of text) {
12
- if (!re.test(ch)) return false;
13
+ if (!ok(ch)) return false;
13
14
  }
14
15
  return true;
15
16
  }
17
+ function stripDisallowed(text, charRe, caret = text.length) {
18
+ const ok = charTester(charRe);
19
+ let kept = "";
20
+ let at = 0;
21
+ let offset = 0;
22
+ for (const ch of text) {
23
+ if (ok(ch)) {
24
+ kept += ch;
25
+ if (offset < caret) at += ch.length;
26
+ }
27
+ offset += ch.length;
28
+ }
29
+ return { text: kept, caret: at };
30
+ }
16
31
  function useInputFilter(options = {}) {
17
32
  const restrict = computed(() => toValue(options.restrict));
18
33
  const patternRe = computed(() => {
19
34
  const p = toValue(options.pattern);
20
- return p === void 0 ? void 0 : toAnchored(p);
35
+ return p === void 0 ? void 0 : anchorPattern(p);
21
36
  });
22
37
  function isInvalid(value) {
23
38
  const re = patternRe.value;
@@ -27,18 +42,40 @@ function useInputFilter(options = {}) {
27
42
  function onBeforeInput(event) {
28
43
  const re = restrict.value;
29
44
  if (!re || event.isComposing) return;
30
- const data = event.data;
45
+ const data = event.data ?? event.dataTransfer?.getData("text") ?? null;
31
46
  if (data == null) return;
32
47
  if (!allAllowed(data, re)) event.preventDefault();
33
48
  }
49
+ function sanitize(target) {
50
+ const re = restrict.value;
51
+ if (!re) return false;
52
+ if (!(target instanceof HTMLInputElement || target instanceof HTMLTextAreaElement)) return false;
53
+ const { text, caret } = stripDisallowed(target.value, re, target.selectionStart ?? target.value.length);
54
+ if (text === target.value) return false;
55
+ target.value = text;
56
+ try {
57
+ target.setSelectionRange(caret, caret);
58
+ } catch {
59
+ }
60
+ return true;
61
+ }
62
+ function onInput(event) {
63
+ if (event.isComposing) return;
64
+ sanitize(event.target);
65
+ }
66
+ function onCompositionEnd(event) {
67
+ if (sanitize(event.target)) event.target?.dispatchEvent(new Event("input", { bubbles: true }));
68
+ }
34
69
  function onPaste(event) {
35
70
  const re = restrict.value;
36
71
  if (!re) return;
37
72
  const text = event.clipboardData?.getData("text") ?? "";
38
73
  if (text && !allAllowed(text, re)) event.preventDefault();
39
74
  }
40
- return { isInvalid, onBeforeInput, onPaste, patternRe, restrict };
75
+ return { isInvalid, onBeforeInput, onInput, onCompositionEnd, onPaste, patternRe, restrict };
41
76
  }
42
77
  export {
78
+ anchorPattern,
79
+ stripDisallowed,
43
80
  useInputFilter
44
81
  };
@@ -0,0 +1,24 @@
1
+ import { type App, type Component, type ComputedRef, type InjectionKey, type MaybeRefOrGetter } from "vue";
2
+ export type LabelScope = Record<string, string>;
3
+ export interface LpConfig {
4
+ /** Component rendered for internal links (RouterLink, NuxtLink). Plain `<a>` when unset. */
5
+ linkComponent?: Component | string;
6
+ /** Text overrides by scope: `{ lightbox: { previous: "Back" } }`. */
7
+ labels?: Partial<Record<string, Partial<LabelScope>>>;
8
+ }
9
+ export declare const LP_CONFIG: InjectionKey<MaybeRefOrGetter<LpConfig>>;
10
+ /** Provide kit configuration to every component below the caller. */
11
+ export declare function provideLpConfig(config: MaybeRefOrGetter<LpConfig>): void;
12
+ /** Install the configuration app-wide: `app.use(lpConfig({ ... }))`. */
13
+ export declare function lpConfig(config: MaybeRefOrGetter<LpConfig>): {
14
+ install: (app: App) => void;
15
+ };
16
+ export declare function mergeConfig(outer: LpConfig, inner: LpConfig): LpConfig;
17
+ export declare function useLpConfig(): ComputedRef<LpConfig>;
18
+ /**
19
+ * The labels a component renders: its own `labels` prop over the configured
20
+ * scope over its defaults.
21
+ */
22
+ export declare function useLabels<T extends LabelScope>(scope: string, defaults: T, own?: () => Partial<T> | undefined): ComputedRef<T>;
23
+ /** The link component to render for an internal destination. */
24
+ export declare function useLinkComponent(): ComputedRef<Component | string>;
@@ -0,0 +1,44 @@
1
+ import { computed, inject, provide, toValue } from "vue";
2
+ const LP_CONFIG = /* @__PURE__ */ Symbol.for("lp-config");
3
+ function provideLpConfig(config) {
4
+ provide(LP_CONFIG, layered(inject(LP_CONFIG, {}), config));
5
+ }
6
+ function lpConfig(config) {
7
+ return {
8
+ install: (app) => {
9
+ const outer = app.runWithContext(() => inject(LP_CONFIG, {}));
10
+ app.provide(LP_CONFIG, layered(outer, config));
11
+ }
12
+ };
13
+ }
14
+ function layered(outer, inner) {
15
+ return () => mergeConfig(toValue(outer), toValue(inner));
16
+ }
17
+ function mergeConfig(outer, inner) {
18
+ const labels = { ...outer.labels };
19
+ for (const [scope, values] of Object.entries(inner.labels ?? {})) {
20
+ labels[scope] = { ...labels[scope], ...values };
21
+ }
22
+ return { ...outer, ...inner, linkComponent: inner.linkComponent ?? outer.linkComponent, labels };
23
+ }
24
+ function useLpConfig() {
25
+ const config = inject(LP_CONFIG, {});
26
+ return computed(() => toValue(config));
27
+ }
28
+ function useLabels(scope, defaults, own) {
29
+ const config = useLpConfig();
30
+ return computed(() => ({ ...defaults, ...config.value.labels?.[scope], ...own?.() }));
31
+ }
32
+ function useLinkComponent() {
33
+ const config = useLpConfig();
34
+ return computed(() => config.value.linkComponent ?? "a");
35
+ }
36
+ export {
37
+ LP_CONFIG,
38
+ lpConfig,
39
+ mergeConfig,
40
+ provideLpConfig,
41
+ useLabels,
42
+ useLinkComponent,
43
+ useLpConfig
44
+ };
@@ -1,4 +1,5 @@
1
1
  import { ref, computed, toValue, watch } from "vue";
2
+ const NON_TEXT_INPUTS = /* @__PURE__ */ new Set(["checkbox", "radio", "button", "submit", "reset", "range", "color", "file", "image"]);
2
3
  const TYPEAHEAD_RESET_MS = 700;
3
4
  function useRovingFocus(items, options = {}) {
4
5
  const {
@@ -69,7 +70,13 @@ function useRovingFocus(items, options = {}) {
69
70
  }
70
71
  }
71
72
  }
73
+ function isTextEntry(target) {
74
+ if (!(target instanceof HTMLElement)) return false;
75
+ if (target.isContentEditable || target instanceof HTMLTextAreaElement || target instanceof HTMLSelectElement) return true;
76
+ return target instanceof HTMLInputElement && !NON_TEXT_INPUTS.has(target.type);
77
+ }
72
78
  function onKeydown(event) {
79
+ if (event.isComposing || isTextEntry(event.target)) return;
73
80
  const vertical = orientation === "vertical" || orientation === "both";
74
81
  const horizontal = orientation === "horizontal" || orientation === "both";
75
82
  switch (event.key) {
@@ -1,4 +1,4 @@
1
- import { type ComputedRef, type CSSProperties, type Ref } from "vue";
1
+ import { type ComputedRef, type CSSProperties, type MaybeRefOrGetter, type Ref } from "vue";
2
2
  export interface UseTiltOptions {
3
3
  /** Max rotation toward the pointer, in degrees (per axis). Default 10. */
4
4
  max?: number;
@@ -20,4 +20,4 @@ export interface UseTilt {
20
20
  /** True while the pointer is over the element (drives lift/scale). */
21
21
  active: Ref<boolean>;
22
22
  }
23
- export declare function useTilt(options?: UseTiltOptions): UseTilt;
23
+ export declare function useTilt(source?: MaybeRefOrGetter<UseTiltOptions>): UseTilt;
@@ -1,9 +1,7 @@
1
1
  import { useReducedMotion } from "motion-v";
2
- import { ref, computed } from "vue";
3
- function useTilt(options = {}) {
4
- const max = options.max ?? 10;
5
- const lift = options.lift ?? 8;
6
- const scale = options.scale ?? 1.03;
2
+ import { computed, toValue, ref } from "vue";
3
+ function useTilt(source = {}) {
4
+ const options = computed(() => toValue(source));
7
5
  const reduceMotion = useReducedMotion();
8
6
  const active = ref(false);
9
7
  const nx = ref(0);
@@ -28,6 +26,7 @@ function useTilt(options = {}) {
28
26
  if (reduceMotion.value) {
29
27
  return { transition: "transform 0.2s ease" };
30
28
  }
29
+ const { max = 10, lift = 8, scale = 1.03 } = options.value;
31
30
  const rx = active.value ? -ny.value * max : 0;
32
31
  const ry = active.value ? nx.value * max : 0;
33
32
  const z = active.value ? lift : 0;
@@ -39,7 +38,7 @@ function useTilt(options = {}) {
39
38
  };
40
39
  });
41
40
  const glareStyle = computed(() => {
42
- if (!options.glare || reduceMotion.value || !active.value) {
41
+ if (!options.value.glare || reduceMotion.value || !active.value) {
43
42
  return { opacity: 0 };
44
43
  }
45
44
  const px = (nx.value + 1) * 50;
@@ -7,6 +7,9 @@ export interface ToastAction {
7
7
  }
8
8
  export interface ToastItem {
9
9
  id: number;
10
+ /** Bumped when a toast with the same `key` replaces this one in place. */
11
+ rev: number;
12
+ key?: string;
10
13
  title?: string;
11
14
  message: string;
12
15
  variant: ToastVariant;
@@ -18,12 +21,28 @@ export interface ToastItem {
18
21
  onClick?: () => void | Promise<void>;
19
22
  }
20
23
  export interface ToastOptions {
24
+ /**
25
+ * A toast with the same key replaces the one on screen instead of stacking
26
+ * beside it: "Saved" ten times is one toast, and a progress toast can turn
27
+ * into its result.
28
+ */
29
+ key?: string;
21
30
  title?: string;
22
31
  duration?: number;
23
32
  actions?: ToastAction[];
24
33
  onClick?: () => void | Promise<void>;
25
34
  }
26
35
  declare function push(variant: ToastVariant, message: string, options?: ToastOptions): number;
36
+ export interface ToastPromiseMessages<T> {
37
+ loading: string;
38
+ success: string | ((value: T) => string);
39
+ error: string | ((error: unknown) => string);
40
+ }
41
+ /**
42
+ * One toast that follows a promise: a persistent "loading" toast that turns
43
+ * into the success or error toast when it settles. Returns the promise itself.
44
+ */
45
+ declare function promise<T>(task: Promise<T>, messages: ToastPromiseMessages<T>, options?: ToastOptions): Promise<T>;
27
46
  declare function dismiss(id: number): void;
28
47
  declare function clear(): void;
29
48
  export declare function useToast(): {
@@ -33,6 +52,7 @@ export declare function useToast(): {
33
52
  success: (message: string, o?: ToastOptions) => number;
34
53
  warning: (message: string, o?: ToastOptions) => number;
35
54
  error: (message: string, o?: ToastOptions) => number;
55
+ promise: typeof promise;
36
56
  /** Low-level push for bridges (e.g. @leavepulse/ui-sdk apiError). */
37
57
  push: typeof push;
38
58
  dismiss: typeof dismiss;