@leavepulse/ui 0.43.4 → 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 (337) hide show
  1. package/README.md +75 -7
  2. package/dist/assets/{LpCommandPalette-B-0Est4Z.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 -3
  103. package/dist/components/LpCommandPalette.vue.js +86 -72
  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/confirm.d.ts +25 -0
  198. package/dist/components/confirm.js +26 -0
  199. package/dist/components/countries.d.ts +6 -0
  200. package/dist/components/countries.js +7 -0
  201. package/dist/components/fileTree.js +16 -7
  202. package/dist/components/imageCrop.d.ts +42 -0
  203. package/dist/components/imageCrop.js +47 -0
  204. package/dist/components/link.d.ts +12 -0
  205. package/dist/components/link.js +19 -0
  206. package/dist/components/modalDepth.d.ts +18 -2
  207. package/dist/components/modalDepth.js +17 -5
  208. package/dist/components/otp.d.ts +5 -0
  209. package/dist/components/otp.js +10 -0
  210. package/dist/components/sidebar.d.ts +7 -1
  211. package/dist/components/tableSort.d.ts +8 -0
  212. package/dist/components/tableSort.js +31 -0
  213. package/dist/composables/useField.d.ts +34 -0
  214. package/dist/composables/useField.js +45 -0
  215. package/dist/composables/useFormDraft.d.ts +10 -3
  216. package/dist/composables/useFormDraft.js +9 -14
  217. package/dist/composables/useHotkeys.d.ts +17 -1
  218. package/dist/composables/useHotkeys.js +55 -18
  219. package/dist/composables/useInputFilter.d.ts +17 -0
  220. package/dist/composables/useInputFilter.js +47 -10
  221. package/dist/composables/useLpConfig.d.ts +24 -0
  222. package/dist/composables/useLpConfig.js +44 -0
  223. package/dist/composables/useRovingFocus.js +7 -0
  224. package/dist/composables/useTilt.d.ts +2 -2
  225. package/dist/composables/useTilt.js +5 -6
  226. package/dist/composables/useToast.d.ts +20 -0
  227. package/dist/composables/useToast.js +28 -4
  228. package/dist/composables/useZoomPan.d.ts +3 -3
  229. package/dist/composables/useZoomPan.js +4 -4
  230. package/dist/index.d.ts +32 -2
  231. package/dist/index.js +184 -137
  232. package/dist/layout/tree.d.ts +2 -0
  233. package/dist/layout/tree.js +16 -1
  234. package/dist/layout/useLayout.d.ts +15 -0
  235. package/dist/layout/useLayout.js +41 -14
  236. package/dist/theme/useTheme.d.ts +32 -9
  237. package/package.json +8 -7
  238. package/src/component-names.ts +5 -7
  239. package/src/components/ContextMenuItems.vue +88 -0
  240. package/src/components/LayoutCanvas.vue +26 -6
  241. package/src/components/LayoutNode.vue +19 -2
  242. package/src/components/LpActionBar.vue +30 -7
  243. package/src/components/LpAddressInput.vue +57 -41
  244. package/src/components/LpAlert.vue +16 -3
  245. package/src/components/LpAppShell.vue +45 -12
  246. package/src/components/LpAutocomplete.vue +46 -10
  247. package/src/components/LpAvatar.vue +19 -5
  248. package/src/components/LpBreadcrumbs.vue +65 -41
  249. package/src/components/LpButton.vue +59 -13
  250. package/src/components/LpChart.vue +272 -28
  251. package/src/components/LpCheckbox.vue +7 -3
  252. package/src/components/LpCodeBlock.vue +50 -14
  253. package/src/components/LpColorPicker.vue +39 -9
  254. package/src/components/LpCommandPalette.vue +34 -13
  255. package/src/components/LpConfirmDialog.vue +68 -17
  256. package/src/components/LpConfirmHost.vue +59 -0
  257. package/src/components/LpContextMenu.vue +14 -115
  258. package/src/components/LpDatePicker.vue +99 -68
  259. package/src/components/LpDrawer.vue +56 -19
  260. package/src/components/LpDropzone.vue +21 -4
  261. package/src/components/LpFileTree.vue +33 -7
  262. package/src/components/LpFormField.vue +30 -7
  263. package/src/components/LpImageEditor.vue +96 -57
  264. package/src/components/LpInput.vue +18 -7
  265. package/src/components/LpLightbox.vue +140 -29
  266. package/src/components/LpLink.vue +24 -13
  267. package/src/components/LpLogViewer.vue +86 -17
  268. package/src/components/LpMapPicker.vue +36 -13
  269. package/src/components/LpMediaGallery.vue +8 -2
  270. package/src/components/LpModal.vue +53 -27
  271. package/src/components/LpModalNav.vue +5 -2
  272. package/src/components/LpNotificationBell.vue +63 -17
  273. package/src/components/LpNumberField.vue +21 -6
  274. package/src/components/LpNumberFlow.vue +26 -10
  275. package/src/components/LpOtpInput.vue +43 -8
  276. package/src/components/LpPagination.vue +23 -7
  277. package/src/components/LpPasswordInput.vue +4 -1
  278. package/src/components/LpPhoneInput.vue +53 -27
  279. package/src/components/LpPie.vue +94 -15
  280. package/src/components/LpPopover.vue +3 -0
  281. package/src/components/LpProgress.vue +5 -3
  282. package/src/components/LpRadioGroup.vue +9 -2
  283. package/src/components/LpSegmented.vue +12 -2
  284. package/src/components/LpSelect.vue +0 -0
  285. package/src/components/LpShortcutsDialog.vue +8 -3
  286. package/src/components/LpSidebar.vue +14 -9
  287. package/src/components/LpSidebarNav.vue +17 -5
  288. package/src/components/LpSkeleton.vue +4 -1
  289. package/src/components/LpSlider.vue +7 -1
  290. package/src/components/LpSparkline.vue +11 -3
  291. package/src/components/LpSwitch.vue +30 -7
  292. package/src/components/LpTable.vue +91 -32
  293. package/src/components/LpTableOfContents.vue +50 -32
  294. package/src/components/LpTabs.vue +23 -6
  295. package/src/components/LpTextarea.vue +44 -6
  296. package/src/components/LpThemeProvider.vue +41 -0
  297. package/src/components/LpThemeSwitcher.vue +64 -17
  298. package/src/components/LpTilt.vue +2 -2
  299. package/src/components/LpTimeField.vue +14 -3
  300. package/src/components/LpToaster.vue +66 -26
  301. package/src/components/LpTooltip.vue +22 -5
  302. package/src/components/LpTooltipProvider.vue +24 -0
  303. package/src/components/LpTopologyCanvas.vue +12 -1
  304. package/src/components/LpUptimeBar.vue +46 -8
  305. package/src/components/chart.ts +77 -5
  306. package/src/components/codeHighlight.ts +111 -15
  307. package/src/components/color.ts +30 -9
  308. package/src/components/confirm.ts +58 -0
  309. package/src/components/countries.ts +12 -0
  310. package/src/components/fileTree.ts +19 -7
  311. package/src/components/imageCrop.ts +107 -0
  312. package/src/components/link.ts +34 -0
  313. package/src/components/modalDepth.ts +48 -6
  314. package/src/components/otp.ts +16 -0
  315. package/src/components/sidebar.ts +7 -1
  316. package/src/components/tableSort.ts +37 -0
  317. package/src/composables/useField.ts +79 -0
  318. package/src/composables/useFormDraft.ts +25 -20
  319. package/src/composables/useHotkeys.ts +89 -18
  320. package/src/composables/useInputFilter.ts +77 -14
  321. package/src/composables/useLpConfig.ts +87 -0
  322. package/src/composables/useRovingFocus.ts +11 -0
  323. package/src/composables/useTilt.ts +5 -6
  324. package/src/composables/useToast.ts +56 -4
  325. package/src/composables/useZoomPan.ts +6 -6
  326. package/src/index.ts +37 -2
  327. package/src/layout/tree.ts +30 -0
  328. package/src/layout/useLayout.ts +68 -18
  329. package/src/nuxt.ts +59 -17
  330. package/src/runtime/config.plugin.ts +14 -0
  331. package/src/runtime/theme.plugin.ts +42 -22
  332. package/src/theme/useTheme.ts +206 -100
  333. package/dist/chunks/LpBreadcrumbs-p4jHe_V-.js +0 -62
  334. package/dist/chunks/LpContextMenu-CwW1QXe_.js +0 -217
  335. package/dist/chunks/LpDatePicker-CwOToxGq.js +0 -164
  336. package/dist/chunks/LpFormField-CazBc2-a.js +0 -62
  337. package/dist/chunks/LpTextarea-t7F6gv8E.js +0 -47
@@ -173,23 +173,58 @@ const BOOLEANS = /* @__PURE__ */ new Set([
173
173
  "Err"
174
174
  // rust common variants read as constants
175
175
  ]);
176
- const MASTER = new RegExp(
177
- [
178
- "(\\/\\/[^\\n]*|#[^\\n]*|\\/\\*[\\s\\S]*?\\*\\/)",
179
- // 1 comment
180
- "(\"(?:\\\\.|[^\"\\\\])*\"|'(?:\\\\.|[^'\\\\])*'|`(?:\\\\.|[^`\\\\])*`)",
181
- // 2 string
182
- "(@[A-Za-z_$][\\w$]*)",
183
- // 3 annotation (@Override, @ConfigSerializable — JVM)
184
- "(\\b\\d[\\d_]*(?:\\.\\d+)?(?:e[+-]?\\d+)?[fFlLdD]?\\b)",
185
- // 4 number (JVM suffixes)
186
- "([A-Za-z_$][\\w$]*)",
187
- // 5 identifier (keyword/bool/func/prop/plain)
188
- "([{}()\\[\\];:,.<>=+\\-*/%!&|?]+)"
189
- // 6 punctuation
190
- ].join("|"),
191
- "g"
192
- );
176
+ const COMMENTS = {
177
+ ts: "c",
178
+ js: "c",
179
+ json: "none",
180
+ bash: "hash",
181
+ html: "html",
182
+ python: "hash",
183
+ rust: "c",
184
+ yaml: "hash",
185
+ toml: "hash",
186
+ kotlin: "c",
187
+ java: "c",
188
+ groovy: "c",
189
+ plain: "none"
190
+ };
191
+ const COMMENT_PATTERN = {
192
+ c: "\\/\\/[^\\n]*|\\/\\*[\\s\\S]*?\\*\\/",
193
+ // A `#` only starts a comment at the start of a word, so `a#b` in a URL or
194
+ // `${#arr[@]}` in shell stay code.
195
+ hash: "(?<![\\w$])#[^\\n]*",
196
+ html: "<!--[\\s\\S]*?-->",
197
+ none: "(?!)"
198
+ };
199
+ const BLOCK = {
200
+ c: { open: "/*", close: "*/" },
201
+ html: { open: "<!--", close: "-->" }
202
+ };
203
+ const masters = /* @__PURE__ */ new Map();
204
+ function masterFor(style) {
205
+ let re = masters.get(style);
206
+ if (!re) {
207
+ re = new RegExp(
208
+ [
209
+ `(${COMMENT_PATTERN[style]})`,
210
+ // 1 comment
211
+ "(\"(?:\\\\.|[^\"\\\\])*\"|'(?:\\\\.|[^'\\\\])*'|`(?:\\\\.|[^`\\\\])*`)",
212
+ // 2 string
213
+ "(@[A-Za-z_$][\\w$]*)",
214
+ // 3 annotation (@Override, @ConfigSerializable — JVM)
215
+ "(\\b\\d[\\d_]*(?:\\.\\d+)?(?:e[+-]?\\d+)?[fFlLdD]?\\b)",
216
+ // 4 number (JVM suffixes)
217
+ "(#?[A-Za-z_$][\\w$]*)",
218
+ // 5 identifier (keyword/bool/func/prop/plain), incl. #private
219
+ "([{}()\\[\\];:,.<>=+\\-*/%!&|?]+)"
220
+ // 6 punctuation
221
+ ].join("|"),
222
+ "g"
223
+ );
224
+ masters.set(style, re);
225
+ }
226
+ return re;
227
+ }
193
228
  function classifyIdent(name, before, after) {
194
229
  if (KEYWORDS.has(name)) return C.keyword;
195
230
  if (BOOLEANS.has(name)) return C.boolean;
@@ -198,11 +233,13 @@ function classifyIdent(name, before, after) {
198
233
  return "";
199
234
  }
200
235
  function tokenizeLine(line, lang) {
236
+ if (lang === "plain") return line ? [{ text: line, cls: "" }] : [];
201
237
  const out = [];
202
238
  let last = 0;
203
239
  let m;
204
- MASTER.lastIndex = 0;
205
- while ((m = MASTER.exec(line)) !== null) {
240
+ const master = masterFor(COMMENTS[lang]);
241
+ master.lastIndex = 0;
242
+ while ((m = master.exec(line)) !== null) {
206
243
  if (m.index > last) out.push({ text: line.slice(last, m.index), cls: "" });
207
244
  const [full, comment, str, annotation, num, ident, punct] = m;
208
245
  if (comment != null) out.push({ text: full, cls: C.comment });
@@ -225,6 +262,41 @@ function tokenizeLine(line, lang) {
225
262
  if (last < line.length) out.push({ text: line.slice(last), cls: "" });
226
263
  return out;
227
264
  }
265
+ function tokenizeLines(lines, lang) {
266
+ const block = BLOCK[COMMENTS[lang]];
267
+ if (!block) return lines.map((line) => tokenizeLine(line, lang));
268
+ const out = [];
269
+ let open = false;
270
+ for (const line of lines) {
271
+ let rest = line;
272
+ const tokens = [];
273
+ if (open) {
274
+ const end = rest.indexOf(block.close);
275
+ if (end === -1) {
276
+ out.push(rest ? [{ text: rest, cls: C.comment }] : []);
277
+ continue;
278
+ }
279
+ tokens.push({ text: rest.slice(0, end + block.close.length), cls: C.comment });
280
+ rest = rest.slice(end + block.close.length);
281
+ open = false;
282
+ }
283
+ const lineTokens = tokenizeLine(rest, lang);
284
+ const at = lineTokens.findIndex(
285
+ (t) => t.cls !== C.comment && t.cls !== C.string && t.text.includes(block.open)
286
+ );
287
+ if (at >= 0) {
288
+ const cut = lineTokens[at].text.indexOf(block.open);
289
+ const tail = lineTokens.slice(at).map((t) => t.text).join("").slice(cut);
290
+ tokens.push(...lineTokens.slice(0, at));
291
+ if (cut > 0) tokens.push({ text: lineTokens[at].text.slice(0, cut), cls: lineTokens[at].cls });
292
+ tokens.push({ text: tail, cls: C.comment });
293
+ open = true;
294
+ } else tokens.push(...lineTokens);
295
+ out.push(tokens);
296
+ }
297
+ return out;
298
+ }
228
299
  export {
229
- tokenizeLine
300
+ tokenizeLine,
301
+ tokenizeLines
230
302
  };
@@ -17,7 +17,7 @@ export type ColorFormat = "hex" | "rgb" | "hsl";
17
17
  /** Wraps rather than clamps: hue is a circle, and 370° is 10°, not 360°. */
18
18
  export declare function normalizeHue(h: number): number;
19
19
  export declare function clampHsv(c: Hsv): Hsv;
20
- export declare function hsvToRgb({ h, s, v, a }: Hsv): Rgb;
20
+ export declare function hsvToRgb(color: Hsv): Rgb;
21
21
  export declare function rgbToHsv({ r, g, b, a }: Rgb): Hsv;
22
22
  /** "#rrggbb", or "#rrggbbaa" when the colour is not fully opaque. */
23
23
  export declare function rgbToHex({ r, g, b, a }: Rgb): string;
@@ -11,7 +11,12 @@ function clampHsv(c) {
11
11
  a: clamp(c.a, 0, 1)
12
12
  };
13
13
  }
14
- function hsvToRgb({ h, s, v, a }) {
14
+ const finite = (n) => Number.isFinite(n) ? n : 0;
15
+ function hsvToRgb(color) {
16
+ const h = finite(color.h);
17
+ const s = clamp(finite(color.s), 0, 1);
18
+ const v = clamp(finite(color.v), 0, 1);
19
+ const a = Number.isFinite(color.a) ? color.a : 1;
15
20
  const hue = normalizeHue(h) / 60;
16
21
  const c = v * s;
17
22
  const x = c * (1 - Math.abs(hue % 2 - 1));
@@ -52,9 +57,13 @@ function rgbToHsv({ r, g, b, a }) {
52
57
  };
53
58
  }
54
59
  const hex2 = (n) => clamp(Math.round(n), 0, 255).toString(16).padStart(2, "0");
60
+ function alphaByte(a) {
61
+ return Math.round(clamp(a, 0, 1) * 255);
62
+ }
55
63
  function rgbToHex({ r, g, b, a }) {
56
64
  const base = `#${hex2(r)}${hex2(g)}${hex2(b)}`;
57
- return a >= 1 ? base : base + hex2(a * 255);
65
+ const byte = alphaByte(a);
66
+ return byte >= 255 ? base : base + hex2(byte);
58
67
  }
59
68
  function parseHex(input) {
60
69
  const s = input.trim().replace(/^#/, "");
@@ -105,16 +114,18 @@ function hsvToHsl({ h, s, v }) {
105
114
  }
106
115
  function formatColor(c, format) {
107
116
  const rgb = hsvToRgb(c);
108
- const a = Math.round(clamp(c.a, 0, 1) * 100) / 100;
117
+ const byte = alphaByte(rgb.a);
118
+ const a = Math.round(byte / 255 * 1e3) / 1e3;
109
119
  if (format === "hex") return rgbToHex(rgb);
110
120
  if (format === "rgb") {
111
- return a >= 1 ? `rgb(${rgb.r}, ${rgb.g}, ${rgb.b})` : `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, ${a})`;
121
+ return byte >= 255 ? `rgb(${rgb.r}, ${rgb.g}, ${rgb.b})` : `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, ${a})`;
112
122
  }
113
- const { h, s, l } = hsvToHsl(c);
114
- const hh = Math.round(h);
115
- const ss = Math.round(s * 100);
116
- const ll = Math.round(l * 100);
117
- return a >= 1 ? `hsl(${hh}, ${ss}%, ${ll}%)` : `hsla(${hh}, ${ss}%, ${ll}%, ${a})`;
123
+ const { h, s, l } = hsvToHsl({ ...c, h: finite(c.h), s: clamp(finite(c.s), 0, 1), v: clamp(finite(c.v), 0, 1) });
124
+ const dec = (n) => Math.round(n * 10) / 10;
125
+ const hh = dec(h) % 360;
126
+ const ss = dec(s * 100);
127
+ const ll = dec(l * 100);
128
+ return byte >= 255 ? `hsl(${hh}, ${ss}%, ${ll}%)` : `hsla(${hh}, ${ss}%, ${ll}%, ${a})`;
118
129
  }
119
130
  function opaqueCss(c) {
120
131
  const { r, g, b } = hsvToRgb({ ...c, a: 1 });
@@ -0,0 +1,25 @@
1
+ export interface ConfirmOptions {
2
+ title: string;
3
+ description?: string;
4
+ danger?: boolean;
5
+ icon?: string;
6
+ confirmLabel?: string;
7
+ cancelLabel?: string;
8
+ loadingLabel?: string;
9
+ /**
10
+ * Work to run on confirm. The dialog stays open with a loading state while it
11
+ * runs and shows the error's message if it rejects; the promise from
12
+ * `confirm()` resolves true only once it succeeded.
13
+ */
14
+ action?: () => unknown;
15
+ }
16
+ export interface ConfirmRequest extends ConfirmOptions {
17
+ id: number;
18
+ resolve: (confirmed: boolean) => void;
19
+ }
20
+ export declare const confirmQueue: ConfirmRequest[];
21
+ /** Ask for confirmation. Resolves false when the user cancels or dismisses. */
22
+ export declare function confirm(options: ConfirmOptions): Promise<boolean>;
23
+ /** Settle a request and drop it from the queue. Used by the host. */
24
+ export declare function settleConfirm(id: number, confirmed: boolean): void;
25
+ export declare function useConfirm(): typeof confirm;
@@ -0,0 +1,26 @@
1
+ import { reactive } from "vue";
2
+ const STATE_KEY = /* @__PURE__ */ Symbol.for("@leavepulse/ui:confirm-queue");
3
+ const g = globalThis;
4
+ const state = g[STATE_KEY] ??= { queue: reactive([]), nextId: 0 };
5
+ const confirmQueue = state.queue;
6
+ function confirm(options) {
7
+ if (typeof window === "undefined") return Promise.resolve(false);
8
+ return new Promise((resolve) => {
9
+ state.queue.push({ ...options, id: state.nextId++, resolve });
10
+ });
11
+ }
12
+ function settleConfirm(id, confirmed) {
13
+ const i = state.queue.findIndex((r) => r.id === id);
14
+ if (i === -1) return;
15
+ const [request] = state.queue.splice(i, 1);
16
+ request?.resolve(confirmed);
17
+ }
18
+ function useConfirm() {
19
+ return confirm;
20
+ }
21
+ export {
22
+ confirm,
23
+ confirmQueue,
24
+ settleConfirm,
25
+ useConfirm
26
+ };
@@ -18,3 +18,9 @@ export declare function loadCountries(): Promise<Country[]>;
18
18
  * country is preferred. Pass the list (from loadCountries). Undefined if none.
19
19
  */
20
20
  export declare function matchCountryByValue(value: string, list: Country[]): Country | undefined;
21
+ /**
22
+ * Countries matching a search query: by name, or by dial code when the query
23
+ * carries digits ("+44", "44"). A query without digits must not match on the
24
+ * dial code at all, or every country would match the empty string.
25
+ */
26
+ export declare function filterCountries(list: Country[], query: string): Country[];
@@ -31,7 +31,14 @@ function matchCountryByValue(value, list) {
31
31
  }
32
32
  return best;
33
33
  }
34
+ function filterCountries(list, query) {
35
+ const q = query.trim().toLowerCase();
36
+ if (!q) return list;
37
+ const digits = q.replace(/\D/g, "");
38
+ return list.filter((c) => c.name.toLowerCase().includes(q) || digits !== "" && c.dial.includes(digits));
39
+ }
34
40
  export {
41
+ filterCountries,
35
42
  flagEmoji,
36
43
  loadCountries,
37
44
  matchCountryByValue
@@ -75,7 +75,7 @@ function formatSize(bytes) {
75
75
  const units = ["KB", "MB", "GB", "TB", "PB"];
76
76
  let value = bytes / 1024;
77
77
  let i = 0;
78
- while (value >= 1024 && i < units.length - 1) {
78
+ while (Math.round(value) >= 1024 && i < units.length - 1) {
79
79
  value /= 1024;
80
80
  i++;
81
81
  }
@@ -118,14 +118,18 @@ function checkStateOf(node, checked) {
118
118
  }
119
119
  let all = true;
120
120
  let any = false;
121
+ let considered = 0;
121
122
  for (const child of node.children) {
122
123
  const state = checkStateOf(child, checked);
124
+ if (child.disabled && state === "unchecked") continue;
125
+ considered++;
123
126
  if (state === "checked") any = true;
124
127
  else if (state === "indeterminate") {
125
128
  any = true;
126
129
  all = false;
127
130
  } else all = false;
128
131
  }
132
+ if (!considered) return checked.has(node.id) ? "checked" : "unchecked";
129
133
  if (all) return "checked";
130
134
  return any ? "indeterminate" : "unchecked";
131
135
  }
@@ -165,13 +169,17 @@ function computeStats(nodes, checked) {
165
169
  let total = 0;
166
170
  let bytes = 0;
167
171
  let sized = node.size !== void 0;
172
+ let considered = 0;
168
173
  for (const child of node.children) {
169
174
  const childStats = visit(child);
170
- if (childStats.state === "checked") any = true;
171
- else if (childStats.state === "indeterminate") {
172
- any = true;
173
- all = false;
174
- } else all = false;
175
+ if (!child.disabled || childStats.state !== "unchecked") {
176
+ considered++;
177
+ if (childStats.state === "checked") any = true;
178
+ else if (childStats.state === "indeterminate") {
179
+ any = true;
180
+ all = false;
181
+ } else all = false;
182
+ }
175
183
  count += childStats.checked;
176
184
  total += childStats.total;
177
185
  if (childStats.size !== void 0) {
@@ -179,8 +187,9 @@ function computeStats(nodes, checked) {
179
187
  sized = true;
180
188
  }
181
189
  }
190
+ const own = checked.has(node.id) ? "checked" : "unchecked";
182
191
  const self = {
183
- state: all ? "checked" : any ? "indeterminate" : "unchecked",
192
+ state: !considered ? own : all ? "checked" : any ? "indeterminate" : "unchecked",
184
193
  checked: count,
185
194
  total,
186
195
  // An explicit size on the directory wins: a server-side listing usually
@@ -0,0 +1,42 @@
1
+ export interface Point {
2
+ x: number;
3
+ y: number;
4
+ }
5
+ export interface CropInput {
6
+ sourceWidth: number;
7
+ sourceHeight: number;
8
+ frameWidth: number;
9
+ frameHeight: number;
10
+ /** Accumulated rotation in degrees; any angle, not only quarter turns. */
11
+ rotation: number;
12
+ /** Zoom factor, 1 = the picture just covers the frame. */
13
+ scale: number;
14
+ /** Pan in frame pixels before the zoom, as useZoomPan reports it. */
15
+ offset: Point;
16
+ }
17
+ export interface CropGeometry {
18
+ /** CSS pixels per source pixel at zoom 1. */
19
+ cover: number;
20
+ /** Crop size in upright (source-pixel) units. */
21
+ width: number;
22
+ height: number;
23
+ /** Crop centre in upright space. */
24
+ centre: Point;
25
+ }
26
+ /** Rotate a point clockwise by `deg` in a y-down space. */
27
+ export declare function rotatePoint(p: Point, deg: number): Point;
28
+ /** The source pixel (from the source's top-left) under an upright-space point. */
29
+ export declare function uprightToSource(u: Point, rotation: number, sourceWidth: number, sourceHeight: number): Point;
30
+ /**
31
+ * Smallest scale at which the turned picture still covers the whole frame.
32
+ *
33
+ * Covering the bounding box of a turned picture is not enough at a free angle:
34
+ * its corners are empty. The frame, turned back by the same angle, has to fit
35
+ * inside the unturned picture; for a quarter turn this reduces to the usual
36
+ * object-cover of the swapped dimensions.
37
+ */
38
+ export declare function coverScale(sourceWidth: number, sourceHeight: number, frameWidth: number, frameHeight: number, rotation: number): number;
39
+ /** What the frame holds, in upright space. */
40
+ export declare function cropGeometry(input: CropInput): CropGeometry;
41
+ /** Whether the turn is closer to sideways than to upright. */
42
+ export declare function isSideways(rotation: number): boolean;
@@ -0,0 +1,47 @@
1
+ const radians = (deg) => deg * Math.PI / 180;
2
+ function rotatePoint(p, deg) {
3
+ const a = radians(deg);
4
+ const cos = Math.cos(a);
5
+ const sin = Math.sin(a);
6
+ return { x: p.x * cos - p.y * sin, y: p.x * sin + p.y * cos };
7
+ }
8
+ function uprightToSource(u, rotation, sourceWidth, sourceHeight) {
9
+ const q = rotatePoint(u, -rotation);
10
+ return { x: q.x + sourceWidth / 2, y: q.y + sourceHeight / 2 };
11
+ }
12
+ function coverScale(sourceWidth, sourceHeight, frameWidth, frameHeight, rotation) {
13
+ const a = radians(rotation);
14
+ const cos = Math.abs(Math.cos(a));
15
+ const sin = Math.abs(Math.sin(a));
16
+ return Math.max(
17
+ (frameWidth * cos + frameHeight * sin) / sourceWidth,
18
+ (frameWidth * sin + frameHeight * cos) / sourceHeight
19
+ );
20
+ }
21
+ function cropGeometry(input) {
22
+ const cover = coverScale(
23
+ input.sourceWidth,
24
+ input.sourceHeight,
25
+ input.frameWidth,
26
+ input.frameHeight,
27
+ input.rotation
28
+ );
29
+ const shown = cover * input.scale;
30
+ return {
31
+ cover,
32
+ width: input.frameWidth / shown,
33
+ height: input.frameHeight / shown,
34
+ centre: { x: -input.offset.x / cover, y: -input.offset.y / cover }
35
+ };
36
+ }
37
+ function isSideways(rotation) {
38
+ const quarters = Math.round(rotation / 90);
39
+ return (quarters % 2 + 2) % 2 === 1;
40
+ }
41
+ export {
42
+ coverScale,
43
+ cropGeometry,
44
+ isSideways,
45
+ rotatePoint,
46
+ uprightToSource
47
+ };
@@ -0,0 +1,12 @@
1
+ import type { Component } from "vue";
2
+ export type LinkTarget = string | Record<string, unknown>;
3
+ export interface ResolvedLink {
4
+ is: Component | string;
5
+ props: Record<string, unknown>;
6
+ }
7
+ /** An app-relative path: "/x", not "//host" or "https://…". */
8
+ export declare function isInternalHref(href: string): boolean;
9
+ export declare function resolveLink(linkComponent: Component | string, target: {
10
+ to?: LinkTarget;
11
+ href?: string;
12
+ }): ResolvedLink | null;
@@ -0,0 +1,19 @@
1
+ function isInternalHref(href) {
2
+ return href.startsWith("/") && !href.startsWith("//");
3
+ }
4
+ function resolveLink(linkComponent, target) {
5
+ const router = linkComponent !== "a";
6
+ if (target.to != null) {
7
+ if (router) return { is: linkComponent, props: { to: target.to } };
8
+ return typeof target.to === "string" ? { is: "a", props: { href: target.to } } : null;
9
+ }
10
+ if (target.href != null) {
11
+ if (router && isInternalHref(target.href)) return { is: linkComponent, props: { to: target.href } };
12
+ return { is: "a", props: { href: target.href } };
13
+ }
14
+ return null;
15
+ }
16
+ export {
17
+ isInternalHref,
18
+ resolveLink
19
+ };
@@ -1,11 +1,27 @@
1
1
  import { type ComputedRef } from "vue";
2
- export declare function useModalLayer(): {
2
+ export interface ModalLayer {
3
+ /** Join the stack on top. Ignored on the server, where nothing would ever release it. */
3
4
  claim: () => void;
4
5
  release: () => void;
6
+ /** z-index values for this surface's scrim and panel, and whether another modal is under it. */
5
7
  layer: ComputedRef<{
6
8
  scrim: string;
7
9
  panel: string;
8
10
  nested: boolean;
9
11
  }>;
10
- };
12
+ /** Whether this surface is the topmost open one. */
13
+ top: ComputedRef<boolean>;
14
+ }
15
+ export interface ModalLayerOptions {
16
+ /** The surface's panel, so keyboard handling can tell what sits inside the top modal. */
17
+ element?: () => HTMLElement | null | undefined;
18
+ }
19
+ /**
20
+ * Put an overlay on the shared modal stack, so a surface opened from another
21
+ * one (a dialog from a drawer, a lightbox from a dialog) lands above it with
22
+ * its scrim, whatever component either of them is.
23
+ */
24
+ export declare function useModalLayer(options?: ModalLayerOptions): ModalLayer;
11
25
  export declare function anyModalOpen(): boolean;
26
+ /** The panel of the topmost modal, when it registered one. */
27
+ export declare function topModalElement(): HTMLElement | null;
@@ -1,18 +1,23 @@
1
1
  import { ref, computed } from "vue";
2
2
  const STEP = 20;
3
- const stack = ref([]);
4
- let nextId = 0;
5
- function useModalLayer() {
6
- const id = nextId++;
3
+ const STATE_KEY = /* @__PURE__ */ Symbol.for("@leavepulse/ui:modal-stack");
4
+ const g = globalThis;
5
+ const state = g[STATE_KEY] ??= { stack: ref([]), nextId: 0, elements: /* @__PURE__ */ new Map() };
6
+ const stack = state.stack;
7
+ function useModalLayer(options = {}) {
8
+ const id = state.nextId++;
7
9
  const fromTop = computed(() => {
8
10
  const at = stack.value.indexOf(id);
9
11
  return at === -1 ? 0 : stack.value.length - 1 - at;
10
12
  });
11
13
  return {
12
14
  claim: () => {
15
+ if (typeof window === "undefined") return;
16
+ if (options.element) state.elements.set(id, options.element);
13
17
  if (!stack.value.includes(id)) stack.value = [...stack.value, id];
14
18
  },
15
19
  release: () => {
20
+ state.elements.delete(id);
16
21
  stack.value = stack.value.filter((x) => x !== id);
17
22
  },
18
23
  layer: computed(() => {
@@ -22,13 +27,20 @@ function useModalLayer() {
22
27
  panel: `calc(var(--z-modal) - ${drop})`,
23
28
  nested: stack.value.indexOf(id) > 0
24
29
  };
25
- })
30
+ }),
31
+ top: computed(() => stack.value[stack.value.length - 1] === id)
26
32
  };
27
33
  }
28
34
  function anyModalOpen() {
29
35
  return stack.value.length > 0;
30
36
  }
37
+ function topModalElement() {
38
+ const id = stack.value[stack.value.length - 1];
39
+ if (id === void 0) return null;
40
+ return state.elements.get(id)?.() ?? null;
41
+ }
31
42
  export {
32
43
  anyModalOpen,
44
+ topModalElement,
33
45
  useModalLayer
34
46
  };
@@ -0,0 +1,5 @@
1
+ export type OtpCells = (string | number | undefined)[];
2
+ /** The code typed so far: the filled cells in order. */
3
+ export declare function joinCells(cells: OtpCells): string;
4
+ /** Cells for a code given from outside, one character each. */
5
+ export declare function splitCode(code: string | undefined, length: number): string[];
@@ -0,0 +1,10 @@
1
+ function joinCells(cells) {
2
+ return Array.from(cells, (c) => c === void 0 ? "" : String(c)).join("");
3
+ }
4
+ function splitCode(code, length) {
5
+ return (code ?? "").split("").slice(0, length);
6
+ }
7
+ export {
8
+ joinCells,
9
+ splitCode
10
+ };
@@ -3,8 +3,14 @@ export interface SidebarItem {
3
3
  id: string;
4
4
  label: string;
5
5
  icon?: string;
6
- /** Render as a link instead of a button. */
6
+ /**
7
+ * Render as a link instead of a button. An app-relative path goes through
8
+ * the link component from provideLpConfig (NuxtLink under the Nuxt module),
9
+ * so it navigates client-side; other URLs render a plain anchor.
10
+ */
7
11
  href?: string;
12
+ /** Router destination (rendered through the configured link component). */
13
+ to?: string | Record<string, unknown>;
8
14
  /** Count chip on the right (number or short string). */
9
15
  badge?: number | string;
10
16
  disabled?: boolean;
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Ascending order for raw cell values. Empty values (null, undefined, NaN, an
3
+ * invalid Date) come first; numbers, bigints and Dates compare by magnitude,
4
+ * booleans false before true, everything else as text with numeric runs read as
5
+ * numbers ("file 2" before "file 10"). Mixed kinds group by kind so the order
6
+ * is total and a sort is stable from one run to the next.
7
+ */
8
+ export declare function compareValues(a: unknown, b: unknown): number;
@@ -0,0 +1,31 @@
1
+ const COLLATOR = new Intl.Collator(void 0, { numeric: true });
2
+ const rank = (v) => {
3
+ if (v == null || typeof v === "number" && Number.isNaN(v)) return 0;
4
+ if (typeof v === "boolean") return 1;
5
+ if (typeof v === "number" || typeof v === "bigint") return 2;
6
+ if (v instanceof Date) return Number.isNaN(v.getTime()) ? 0 : 3;
7
+ return 4;
8
+ };
9
+ function compareValues(a, b) {
10
+ const ra = rank(a);
11
+ const rb = rank(b);
12
+ if (ra !== rb) return ra - rb;
13
+ switch (ra) {
14
+ case 0:
15
+ return 0;
16
+ case 1:
17
+ return Number(a) - Number(b);
18
+ case 2: {
19
+ const x = a;
20
+ const y = b;
21
+ return x < y ? -1 : x > y ? 1 : 0;
22
+ }
23
+ case 3:
24
+ return a.getTime() - b.getTime();
25
+ default:
26
+ return COLLATOR.compare(String(a), String(b));
27
+ }
28
+ }
29
+ export {
30
+ compareValues
31
+ };
@@ -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
+ }>;