@leavepulse/ui 0.43.4 → 0.45.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 (437) hide show
  1. package/README.md +121 -7
  2. package/dist/assets/{LpCommandPalette-B-0Est4Z.css → LpCommandPalette-nGNnzXqQ.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/{LpRollingText-CR1mb0Vt.css → LpRollingText-BGnE6q9j.css} +3 -0
  6. package/dist/assets/{LpShortcutsDialog-C6YoQ8_M.css → LpShortcutsDialog-CqYX3yy6.css} +28 -7
  7. package/dist/assets/{LpSkeleton-D7xU8IPV.css → LpSkeleton-H3Z5dEIk.css} +4 -1
  8. package/dist/assets/{LpTable-BgPLJOXa.css → LpTable-CPwWxTJS.css} +49 -9
  9. package/dist/chunks/ContextMenuItems-BtKU7074.js +124 -0
  10. package/dist/chunks/{LayoutCanvas-Dd20boUG.js → LayoutCanvas-BkaGXTjx.js} +26 -9
  11. package/dist/chunks/{LayoutNode-DGpZA9LX.js → LayoutNode-B3_9E1Xa.js} +28 -12
  12. package/dist/chunks/{LpActionBar-BlvtGB2P.js → LpActionBar-CnfFVIwC.js} +26 -12
  13. package/dist/chunks/{LpAddressInput-B-Zvxsn7.js → LpAddressInput-BwX8uo4_.js} +54 -49
  14. package/dist/chunks/{LpAlert-BAYHDSS1.js → LpAlert-B6ilrM7T.js} +16 -9
  15. package/dist/chunks/{LpAppShell-BGQVIY-3.js → LpAppShell-C53_RaGF.js} +53 -26
  16. package/dist/chunks/{LpAutocomplete-DExlIZe_.js → LpAutocomplete-C8IgSMsi.js} +52 -24
  17. package/dist/chunks/{LpAvatar-B3-xAOH3.js → LpAvatar-C1XStdOo.js} +19 -10
  18. package/dist/chunks/LpBreadcrumbs-CQJd73Gm.js +95 -0
  19. package/dist/chunks/{LpButton-5VXXCjwF.js → LpButton-CKSwC6Mu.js} +45 -15
  20. package/dist/chunks/{LpCalendar-B7Ko5RdR.js → LpCalendar-DrA2McTU.js} +1 -1
  21. package/dist/chunks/{LpCard-BhI1N_vL.js → LpCard-C2IvucmX.js} +1 -1
  22. package/dist/chunks/{LpCheckbox-CVccKYaH.js → LpCheckbox-Bkj13CbW.js} +8 -4
  23. package/dist/chunks/{LpCodeBlock-Bo0B4TFR.js → LpCodeBlock-ca7ANFyW.js} +49 -17
  24. package/dist/chunks/{LpColorPicker-BlXea7LM.js → LpColorPicker-zz4VGkG4.js} +75 -26
  25. package/dist/chunks/{LpConfirmDialog-Q-bxff8z.js → LpConfirmDialog-DCw5jR1t.js} +59 -17
  26. package/dist/chunks/LpConfirmHost-CbywMpMP.js +49 -0
  27. package/dist/chunks/LpContextMenu-BqkAYa9X.js +69 -0
  28. package/dist/chunks/LpDatePicker-DuusgT69.js +195 -0
  29. package/dist/chunks/LpDateRangePicker-DHeuznfC.js +208 -0
  30. package/dist/chunks/{LpDisclosure-ChQYmjlR.js → LpDisclosure-Cc23-JOT.js} +1 -1
  31. package/dist/chunks/{LpDrawer-BZ6k3hvo.js → LpDrawer-Dt4aB4Fr.js} +65 -28
  32. package/dist/chunks/{LpDropdownMenu-DJpoqRCb.js → LpDropdownMenu-DdJGQzPn.js} +2 -1
  33. package/dist/chunks/{LpEmptyState-Dsdqz1Wj.js → LpEmptyState-BJbZXC8D.js} +1 -1
  34. package/dist/chunks/LpFieldNotice-wtieLUTj.js +64 -0
  35. package/dist/chunks/{LpFileTree-_5vFBgaK.js → LpFileTree-CNurOvkV.js} +25 -10
  36. package/dist/chunks/{LpFileTreeNode-BdcIYKIE.js → LpFileTreeNode-D_qRRdsH.js} +3 -3
  37. package/dist/chunks/LpFormField-CtVYj6tO.js +101 -0
  38. package/dist/chunks/{LpIcon-CCnX5_2j.js → LpIcon-DYtaid0K.js} +20 -6
  39. package/dist/chunks/{LpInput-9EXWUM9B.js → LpInput-D-YGQbEv.js} +58 -20
  40. package/dist/chunks/{LpLightbox-2sYVMY-S.js → LpLightbox-DSDahF23.js} +148 -61
  41. package/dist/chunks/{LpLink-DCND-zyu.js → LpLink-Krkjhe_y.js} +15 -6
  42. package/dist/chunks/{LpLogViewer-CaRy5MeS.js → LpLogViewer-KypbgOyo.js} +300 -72
  43. package/dist/chunks/{LpMapPicker-ul4oYno6.js → LpMapPicker-Cc84LaM3.js} +39 -14
  44. package/dist/chunks/{LpMediaGallery-FF-NquIo.js → LpMediaGallery-YKr-cQPN.js} +7 -4
  45. package/dist/chunks/{LpModal-Bt0pQCI_.js → LpModal-DMMDQHAu.js} +52 -29
  46. package/dist/chunks/{LpModalNav-YaifHrXC.js → LpModalNav-BVPDyIup.js} +10 -7
  47. package/dist/chunks/{LpNotificationBell-DyGGsMAM.js → LpNotificationBell-CCwyJP5C.js} +79 -33
  48. package/dist/chunks/{LpNumberField-CWuX08iX.js → LpNumberField-B77O-z28.js} +21 -8
  49. package/dist/chunks/{LpNumberFlow-amWYaeuA.js → LpNumberFlow-z4WPZcZu.js} +22 -12
  50. package/dist/chunks/{LpOtpInput-y2v-pmiN.js → LpOtpInput-CziPF3Oq.js} +37 -8
  51. package/dist/chunks/{LpPagination-5FxjmmB5.js → LpPagination-BcDlo3r_.js} +31 -20
  52. package/dist/chunks/{LpPasswordInput--sjYCkLS.js → LpPasswordInput-eKzQhbQP.js} +11 -8
  53. package/dist/chunks/LpPhoneInput-BCbrrhgE.js +336 -0
  54. package/dist/chunks/{LpPie-D6OnzwlJ.js → LpPie-BEJ2SfI6.js} +84 -28
  55. package/dist/chunks/{LpPopover-8268UmlC.js → LpPopover-DCKeqiVn.js} +5 -2
  56. package/dist/chunks/{LpProgress-Btq5W4Ut.js → LpProgress-CBU1iI69.js} +5 -4
  57. package/dist/chunks/{LpRadioGroup-xPIuVDO_.js → LpRadioGroup-DmEW0l78.js} +9 -2
  58. package/dist/chunks/LpRangeCalendar-DZuaRV0W.js +331 -0
  59. package/dist/chunks/{LpRollingText-CM5gkSeF.js → LpRollingText-DB7upf-5.js} +1 -1
  60. package/dist/chunks/{LpScrollArea-D8xyKXcF.js → LpScrollArea-Bry1fdOM.js} +14 -2
  61. package/dist/chunks/{LpSection-aM6J_u51.js → LpSection-tKEH0jYf.js} +1 -1
  62. package/dist/chunks/{LpSegmented-fV0Sk92p.js → LpSegmented-C09EEam2.js} +8 -4
  63. package/dist/chunks/{LpSelect-ANIVtrpM.js → LpSelect-DNIL6MB9.js} +50 -31
  64. package/dist/chunks/{LpSidebar-ClBUwoEz.js → LpSidebar-CQNB0-yU.js} +30 -22
  65. package/dist/chunks/{LpSidebarNav-llOcs_Fn.js → LpSidebarNav-kx-LdqNU.js} +16 -11
  66. package/dist/chunks/{LpSkeleton-CTI-vBgW.js → LpSkeleton-BB6XIV-w.js} +1 -1
  67. package/dist/chunks/{LpSlider-BwNIBkAK.js → LpSlider-Cuzmrd7p.js} +7 -2
  68. package/dist/chunks/{LpSparkline-C6xQ2dwv.js → LpSparkline-CB80N8SJ.js} +11 -4
  69. package/dist/chunks/{LpStat-CQaW8R--.js → LpStat-B-7udBRP.js} +2 -2
  70. package/dist/chunks/{LpStepper-Bk-XaQYU.js → LpStepper-C7XiVKZj.js} +34 -19
  71. package/dist/chunks/{LpSwitch-Blizvqyt.js → LpSwitch-OrcOJX9m.js} +41 -27
  72. package/dist/chunks/LpTableFilter-BV8PpLM9.js +158 -0
  73. package/dist/chunks/{LpTableOfContents-CjvxPMpU.js → LpTableOfContents-BUcAfGPQ.js} +36 -41
  74. package/dist/chunks/{LpTabs-Cefe_lys.js → LpTabs-29iW1XOx.js} +20 -6
  75. package/dist/chunks/LpTagsInput-D1SuqbhB.js +300 -0
  76. package/dist/chunks/LpTextarea-uuScWo6-.js +77 -0
  77. package/dist/chunks/LpThemeProvider-Be4r2TQX.js +35 -0
  78. package/dist/chunks/LpThemeSwitcher-B4aVPbNC.js +166 -0
  79. package/dist/chunks/{LpTilt-DuyKbpkA.js → LpTilt-B7KHX1zH.js} +2 -2
  80. package/dist/chunks/{LpTimeField-K6nAGboX.js → LpTimeField-Cqe7fXnh.js} +14 -8
  81. package/dist/chunks/{LpToaster-gDB1EaU3.js → LpToaster-DpJvoCOh.js} +94 -31
  82. package/dist/chunks/{LpTooltip-hCLPAqMG.js → LpTooltip-CXVKcOXT.js} +14 -6
  83. package/dist/chunks/LpTooltipProvider-CftjV7Xc.js +25 -0
  84. package/dist/chunks/{LpTopologyCanvas-Cm1L39uL.js → LpTopologyCanvas-6ozNrQKh.js} +8 -2
  85. package/dist/chunks/{LpUptimeBar-DvAMno0S.js → LpUptimeBar-ugcv25xj.js} +44 -15
  86. package/dist/chunks/icons-CkA0njzm.js +43 -0
  87. package/dist/chunks/{LpThemeSwitcher-Cue-myST.js → useTheme-DJm1JSsY.js} +215 -260
  88. package/dist/component-names.d.ts +1 -1
  89. package/dist/components/ContextMenuItems.vue.d.ts +8 -0
  90. package/dist/components/ContextMenuItems.vue.js +4 -0
  91. package/dist/components/LayoutCanvas.vue.js +1 -1
  92. package/dist/components/LayoutNode.vue.d.ts +4 -0
  93. package/dist/components/LayoutNode.vue.js +1 -1
  94. package/dist/components/LpActionBar.vue.d.ts +3 -0
  95. package/dist/components/LpActionBar.vue.js +1 -1
  96. package/dist/components/LpAddressInput.vue.d.ts +1 -1
  97. package/dist/components/LpAddressInput.vue.js +1 -1
  98. package/dist/components/LpAlert.vue.d.ts +9 -0
  99. package/dist/components/LpAlert.vue.js +1 -1
  100. package/dist/components/LpAppShell.vue.d.ts +10 -0
  101. package/dist/components/LpAppShell.vue.js +1 -1
  102. package/dist/components/LpAutocomplete.vue.d.ts +31 -6
  103. package/dist/components/LpAutocomplete.vue.js +1 -1
  104. package/dist/components/LpAvatar.vue.d.ts +3 -3
  105. package/dist/components/LpAvatar.vue.js +1 -1
  106. package/dist/components/LpBadge.vue.d.ts +2 -2
  107. package/dist/components/LpBreadcrumbs.vue.d.ts +13 -9
  108. package/dist/components/LpBreadcrumbs.vue.js +1 -1
  109. package/dist/components/LpButton.vue.d.ts +35 -98
  110. package/dist/components/LpButton.vue.js +1 -1
  111. package/dist/components/LpCalendar.vue.js +1 -1
  112. package/dist/components/LpCard.vue.js +1 -1
  113. package/dist/components/LpChart.vue.d.ts +47 -3
  114. package/dist/components/LpChart.vue.js +377 -97
  115. package/dist/components/LpCheckbox.vue.js +1 -1
  116. package/dist/components/LpCodeBlock.vue.d.ts +2 -0
  117. package/dist/components/LpCodeBlock.vue.js +1 -1
  118. package/dist/components/LpColorPicker.vue.d.ts +2 -2
  119. package/dist/components/LpColorPicker.vue.js +1 -1
  120. package/dist/components/LpCommandPalette.vue.d.ts +14 -3
  121. package/dist/components/LpCommandPalette.vue.js +142 -77
  122. package/dist/components/LpConfirmDialog.vue.d.ts +15 -3
  123. package/dist/components/LpConfirmDialog.vue.js +1 -1
  124. package/dist/components/LpConfirmHost.vue.d.ts +9 -0
  125. package/dist/components/LpConfirmHost.vue.js +4 -0
  126. package/dist/components/LpContextMenu.vue.d.ts +3 -5
  127. package/dist/components/LpContextMenu.vue.js +1 -1
  128. package/dist/components/LpDatePicker.vue.d.ts +24 -6
  129. package/dist/components/LpDatePicker.vue.js +1 -1
  130. package/dist/components/LpDateRangePicker.vue.d.ts +60 -0
  131. package/dist/components/LpDateRangePicker.vue.js +4 -0
  132. package/dist/components/LpDisclosure.vue.js +1 -1
  133. package/dist/components/LpDrawer.vue.d.ts +10 -0
  134. package/dist/components/LpDrawer.vue.js +1 -1
  135. package/dist/components/LpDropdownMenu.vue.js +1 -1
  136. package/dist/components/LpDropzone.vue.js +23 -7
  137. package/dist/components/LpEmptyState.vue.js +1 -1
  138. package/dist/components/LpFieldNotice.vue.d.ts +8 -0
  139. package/dist/components/LpFieldNotice.vue.js +4 -0
  140. package/dist/components/LpFileTree.vue.d.ts +11 -2
  141. package/dist/components/LpFileTree.vue.js +1 -1
  142. package/dist/components/LpFileTreeNode.vue.js +1 -1
  143. package/dist/components/LpFormField.vue.d.ts +13 -1
  144. package/dist/components/LpFormField.vue.js +1 -1
  145. package/dist/components/LpIcon.vue.d.ts +0 -1
  146. package/dist/components/LpIcon.vue.js +1 -1
  147. package/dist/components/LpImageEditor.vue.js +93 -58
  148. package/dist/components/LpInput.vue.d.ts +22 -3
  149. package/dist/components/LpInput.vue.js +1 -1
  150. package/dist/components/LpLightbox.vue.d.ts +17 -0
  151. package/dist/components/LpLightbox.vue.js +1 -1
  152. package/dist/components/LpLink.vue.d.ts +11 -11
  153. package/dist/components/LpLink.vue.js +1 -1
  154. package/dist/components/LpLogViewer.vue.d.ts +72 -3
  155. package/dist/components/LpLogViewer.vue.js +1 -1
  156. package/dist/components/LpMapPicker.vue.d.ts +4 -4
  157. package/dist/components/LpMapPicker.vue.js +1 -1
  158. package/dist/components/LpMediaGallery.vue.js +1 -1
  159. package/dist/components/LpModal.vue.d.ts +16 -6
  160. package/dist/components/LpModal.vue.js +1 -1
  161. package/dist/components/LpModalNav.vue.d.ts +0 -1
  162. package/dist/components/LpModalNav.vue.js +1 -1
  163. package/dist/components/LpNotificationBell.vue.d.ts +11 -2
  164. package/dist/components/LpNotificationBell.vue.js +1 -1
  165. package/dist/components/LpNumberField.vue.d.ts +2 -0
  166. package/dist/components/LpNumberField.vue.js +1 -1
  167. package/dist/components/LpNumberFlow.vue.js +1 -1
  168. package/dist/components/LpOtpInput.vue.js +1 -1
  169. package/dist/components/LpPagination.vue.d.ts +2 -0
  170. package/dist/components/LpPagination.vue.js +1 -1
  171. package/dist/components/LpPasswordInput.vue.js +1 -1
  172. package/dist/components/LpPhoneInput.vue.d.ts +13 -0
  173. package/dist/components/LpPhoneInput.vue.js +1 -1
  174. package/dist/components/LpPie.vue.d.ts +21 -2
  175. package/dist/components/LpPie.vue.js +1 -1
  176. package/dist/components/LpPopover.vue.d.ts +2 -0
  177. package/dist/components/LpPopover.vue.js +1 -1
  178. package/dist/components/LpProgress.vue.d.ts +1 -1
  179. package/dist/components/LpProgress.vue.js +1 -1
  180. package/dist/components/LpRadioGroup.vue.js +1 -1
  181. package/dist/components/LpRangeCalendar.vue.d.ts +51 -0
  182. package/dist/components/LpRangeCalendar.vue.js +4 -0
  183. package/dist/components/LpRollingText.vue.d.ts +1 -1
  184. package/dist/components/LpRollingText.vue.js +1 -1
  185. package/dist/components/LpScrollArea.vue.d.ts +2 -2
  186. package/dist/components/LpScrollArea.vue.js +1 -1
  187. package/dist/components/LpSection.vue.d.ts +1 -1
  188. package/dist/components/LpSection.vue.js +1 -1
  189. package/dist/components/LpSegmented.vue.d.ts +5 -0
  190. package/dist/components/LpSegmented.vue.js +1 -1
  191. package/dist/components/LpSelect.vue.d.ts +1 -0
  192. package/dist/components/LpSelect.vue.js +1 -1
  193. package/dist/components/LpShortcutsDialog.vue.d.ts +7 -1
  194. package/dist/components/LpShortcutsDialog.vue.js +60 -15
  195. package/dist/components/LpSidebar.vue.d.ts +6 -2
  196. package/dist/components/LpSidebar.vue.js +1 -1
  197. package/dist/components/LpSidebarNav.vue.js +1 -1
  198. package/dist/components/LpSkeleton.vue.js +1 -1
  199. package/dist/components/LpSlider.vue.js +1 -1
  200. package/dist/components/LpSparkline.vue.d.ts +1 -0
  201. package/dist/components/LpSparkline.vue.js +1 -1
  202. package/dist/components/LpStat.vue.js +1 -1
  203. package/dist/components/LpStepper.vue.js +1 -1
  204. package/dist/components/LpSwitch.vue.js +1 -1
  205. package/dist/components/LpTable.vue.d.ts +107 -3
  206. package/dist/components/LpTable.vue.js +540 -128
  207. package/dist/components/LpTableFilter.vue.d.ts +31 -0
  208. package/dist/components/LpTableFilter.vue.js +4 -0
  209. package/dist/components/LpTableOfContents.vue.d.ts +4 -2
  210. package/dist/components/LpTableOfContents.vue.js +1 -1
  211. package/dist/components/LpTabs.vue.d.ts +2 -0
  212. package/dist/components/LpTabs.vue.js +1 -1
  213. package/dist/components/LpTagsInput.vue.d.ts +77 -0
  214. package/dist/components/LpTagsInput.vue.js +4 -0
  215. package/dist/components/LpTextarea.vue.d.ts +19 -6
  216. package/dist/components/LpTextarea.vue.js +1 -1
  217. package/dist/components/LpThemeProvider.vue.d.ts +22 -0
  218. package/dist/components/LpThemeProvider.vue.js +4 -0
  219. package/dist/components/LpThemeSwitcher.vue.d.ts +15 -2
  220. package/dist/components/LpThemeSwitcher.vue.js +1 -1
  221. package/dist/components/LpTilt.vue.js +1 -1
  222. package/dist/components/LpTimeField.vue.js +1 -1
  223. package/dist/components/LpToaster.vue.d.ts +6 -1
  224. package/dist/components/LpToaster.vue.js +1 -1
  225. package/dist/components/LpTooltip.vue.d.ts +1 -2
  226. package/dist/components/LpTooltip.vue.js +1 -1
  227. package/dist/components/LpTooltipProvider.vue.d.ts +22 -0
  228. package/dist/components/LpTooltipProvider.vue.js +4 -0
  229. package/dist/components/LpTopologyCanvas.vue.js +1 -1
  230. package/dist/components/LpUptimeBar.vue.d.ts +4 -0
  231. package/dist/components/LpUptimeBar.vue.js +1 -1
  232. package/dist/components/chart.d.ts +32 -1
  233. package/dist/components/chart.js +42 -6
  234. package/dist/components/codeHighlight.d.ts +6 -0
  235. package/dist/components/codeHighlight.js +92 -20
  236. package/dist/components/color.d.ts +1 -1
  237. package/dist/components/color.js +20 -9
  238. package/dist/components/commandSearch.js +3 -0
  239. package/dist/components/confirm.d.ts +25 -0
  240. package/dist/components/confirm.js +26 -0
  241. package/dist/components/countries.d.ts +6 -0
  242. package/dist/components/countries.js +7 -0
  243. package/dist/components/dateRange.d.ts +43 -0
  244. package/dist/components/dateRange.js +76 -0
  245. package/dist/components/exportData.d.ts +58 -0
  246. package/dist/components/exportData.js +165 -0
  247. package/dist/components/fileTree.js +16 -7
  248. package/dist/components/imageCrop.d.ts +42 -0
  249. package/dist/components/imageCrop.js +47 -0
  250. package/dist/components/link.d.ts +12 -0
  251. package/dist/components/link.js +19 -0
  252. package/dist/components/logSearch.d.ts +18 -0
  253. package/dist/components/logSearch.js +36 -0
  254. package/dist/components/modalDepth.d.ts +18 -2
  255. package/dist/components/modalDepth.js +17 -5
  256. package/dist/components/otp.d.ts +5 -0
  257. package/dist/components/otp.js +10 -0
  258. package/dist/components/phone.d.ts +41 -0
  259. package/dist/components/phone.js +80 -0
  260. package/dist/components/sidebar.d.ts +7 -1
  261. package/dist/components/tableFilter.d.ts +36 -0
  262. package/dist/components/tableFilter.js +84 -0
  263. package/dist/components/tableSort.d.ts +8 -0
  264. package/dist/components/tableSort.js +31 -0
  265. package/dist/components/tags.d.ts +20 -0
  266. package/dist/components/tags.js +37 -0
  267. package/dist/composables/useField.d.ts +38 -0
  268. package/dist/composables/useField.js +45 -0
  269. package/dist/composables/useFieldNotice.d.ts +17 -0
  270. package/dist/composables/useFieldNotice.js +28 -0
  271. package/dist/composables/useForm.d.ts +53 -0
  272. package/dist/composables/useForm.js +207 -0
  273. package/dist/composables/useFormDraft.d.ts +10 -3
  274. package/dist/composables/useFormDraft.js +9 -14
  275. package/dist/composables/useHotkeys.d.ts +81 -5
  276. package/dist/composables/useHotkeys.js +223 -25
  277. package/dist/composables/useInputFilter.d.ts +17 -0
  278. package/dist/composables/useInputFilter.js +47 -10
  279. package/dist/composables/useInputMask.d.ts +59 -0
  280. package/dist/composables/useInputMask.js +170 -0
  281. package/dist/composables/useLpConfig.d.ts +24 -0
  282. package/dist/composables/useLpConfig.js +44 -0
  283. package/dist/composables/usePaintSelect.d.ts +22 -0
  284. package/dist/composables/usePaintSelect.js +169 -0
  285. package/dist/composables/useRovingFocus.js +7 -0
  286. package/dist/composables/useShift.js +7 -2
  287. package/dist/composables/useTilt.d.ts +2 -2
  288. package/dist/composables/useTilt.js +5 -6
  289. package/dist/composables/useToast.d.ts +20 -0
  290. package/dist/composables/useToast.js +28 -4
  291. package/dist/composables/useZoomPan.d.ts +3 -3
  292. package/dist/composables/useZoomPan.js +4 -4
  293. package/dist/icons-all.d.ts +1 -0
  294. package/dist/icons-all.js +3 -0
  295. package/dist/icons.d.ts +14 -1
  296. package/dist/index.d.ts +60 -4
  297. package/dist/index.js +245 -141
  298. package/dist/kit-icons.d.ts +2 -0
  299. package/dist/layout/tree.d.ts +2 -0
  300. package/dist/layout/tree.js +16 -1
  301. package/dist/layout/useLayout.d.ts +15 -0
  302. package/dist/layout/useLayout.js +41 -14
  303. package/dist/theme/backdrop.d.ts +12 -0
  304. package/dist/theme/presets.d.ts +0 -2
  305. package/dist/theme/useTheme.d.ts +32 -9
  306. package/package.json +18 -8
  307. package/src/component-names.ts +9 -7
  308. package/src/components/ContextMenuItems.vue +88 -0
  309. package/src/components/LayoutCanvas.vue +26 -6
  310. package/src/components/LayoutNode.vue +30 -4
  311. package/src/components/LpActionBar.vue +31 -8
  312. package/src/components/LpAddressInput.vue +57 -41
  313. package/src/components/LpAlert.vue +16 -3
  314. package/src/components/LpAppShell.vue +45 -12
  315. package/src/components/LpAutocomplete.vue +47 -10
  316. package/src/components/LpAvatar.vue +20 -6
  317. package/src/components/LpBreadcrumbs.vue +65 -41
  318. package/src/components/LpButton.vue +60 -14
  319. package/src/components/LpChart.vue +351 -28
  320. package/src/components/LpCheckbox.vue +7 -3
  321. package/src/components/LpCodeBlock.vue +50 -14
  322. package/src/components/LpColorPicker.vue +73 -10
  323. package/src/components/LpCommandPalette.vue +115 -20
  324. package/src/components/LpConfirmDialog.vue +68 -17
  325. package/src/components/LpConfirmHost.vue +59 -0
  326. package/src/components/LpContextMenu.vue +15 -116
  327. package/src/components/LpDatePicker.vue +104 -68
  328. package/src/components/LpDateRangePicker.vue +224 -0
  329. package/src/components/LpDrawer.vue +56 -19
  330. package/src/components/LpDropdownMenu.vue +1 -0
  331. package/src/components/LpDropzone.vue +21 -4
  332. package/src/components/LpFieldNotice.vue +65 -0
  333. package/src/components/LpFileTree.vue +33 -7
  334. package/src/components/LpFormField.vue +59 -7
  335. package/src/components/LpIcon.vue +22 -4
  336. package/src/components/LpImageEditor.vue +96 -57
  337. package/src/components/LpInput.vue +62 -11
  338. package/src/components/LpLightbox.vue +140 -29
  339. package/src/components/LpLink.vue +24 -13
  340. package/src/components/LpLogViewer.vue +311 -39
  341. package/src/components/LpMapPicker.vue +36 -13
  342. package/src/components/LpMediaGallery.vue +8 -2
  343. package/src/components/LpModal.vue +54 -28
  344. package/src/components/LpModalNav.vue +5 -2
  345. package/src/components/LpNotificationBell.vue +77 -23
  346. package/src/components/LpNumberField.vue +21 -6
  347. package/src/components/LpNumberFlow.vue +26 -10
  348. package/src/components/LpOtpInput.vue +43 -8
  349. package/src/components/LpPagination.vue +23 -7
  350. package/src/components/LpPasswordInput.vue +4 -1
  351. package/src/components/LpPhoneInput.vue +224 -39
  352. package/src/components/LpPie.vue +102 -20
  353. package/src/components/LpPopover.vue +4 -0
  354. package/src/components/LpProgress.vue +5 -3
  355. package/src/components/LpRadioGroup.vue +9 -2
  356. package/src/components/LpRangeCalendar.vue +365 -0
  357. package/src/components/LpRollingText.vue +3 -0
  358. package/src/components/LpScrollArea.vue +22 -2
  359. package/src/components/LpSegmented.vue +12 -2
  360. package/src/components/LpSelect.vue +0 -0
  361. package/src/components/LpShortcutsDialog.vue +83 -9
  362. package/src/components/LpSidebar.vue +14 -9
  363. package/src/components/LpSidebarNav.vue +17 -5
  364. package/src/components/LpSkeleton.vue +4 -1
  365. package/src/components/LpSlider.vue +7 -1
  366. package/src/components/LpSparkline.vue +11 -3
  367. package/src/components/LpStepper.vue +23 -10
  368. package/src/components/LpSwitch.vue +31 -8
  369. package/src/components/LpTable.vue +668 -90
  370. package/src/components/LpTableFilter.vue +175 -0
  371. package/src/components/LpTableOfContents.vue +50 -32
  372. package/src/components/LpTabs.vue +23 -6
  373. package/src/components/LpTagsInput.vue +364 -0
  374. package/src/components/LpTextarea.vue +44 -6
  375. package/src/components/LpThemeProvider.vue +41 -0
  376. package/src/components/LpThemeSwitcher.vue +76 -33
  377. package/src/components/LpTilt.vue +2 -2
  378. package/src/components/LpTimeField.vue +14 -3
  379. package/src/components/LpToaster.vue +115 -27
  380. package/src/components/LpTooltip.vue +29 -5
  381. package/src/components/LpTooltipProvider.vue +24 -0
  382. package/src/components/LpTopologyCanvas.vue +19 -2
  383. package/src/components/LpUptimeBar.vue +46 -8
  384. package/src/components/chart.ts +82 -8
  385. package/src/components/codeHighlight.ts +111 -15
  386. package/src/components/color.ts +30 -9
  387. package/src/components/commandSearch.ts +6 -0
  388. package/src/components/confirm.ts +58 -0
  389. package/src/components/countries.ts +12 -0
  390. package/src/components/dateRange.ts +134 -0
  391. package/src/components/exportData.ts +228 -0
  392. package/src/components/fileTree.ts +19 -7
  393. package/src/components/imageCrop.ts +107 -0
  394. package/src/components/link.ts +34 -0
  395. package/src/components/logSearch.ts +46 -0
  396. package/src/components/modalDepth.ts +48 -6
  397. package/src/components/otp.ts +16 -0
  398. package/src/components/phone.ts +140 -0
  399. package/src/components/sidebar.ts +7 -1
  400. package/src/components/tableFilter.ts +122 -0
  401. package/src/components/tableSort.ts +37 -0
  402. package/src/components/tags.ts +62 -0
  403. package/src/composables/useField.ts +83 -0
  404. package/src/composables/useFieldNotice.ts +59 -0
  405. package/src/composables/useForm.ts +314 -0
  406. package/src/composables/useFormDraft.ts +25 -20
  407. package/src/composables/useHotkeys.ts +355 -28
  408. package/src/composables/useInputFilter.ts +77 -14
  409. package/src/composables/useInputMask.ts +254 -0
  410. package/src/composables/useLpConfig.ts +87 -0
  411. package/src/composables/usePaintSelect.ts +243 -0
  412. package/src/composables/useRovingFocus.ts +11 -0
  413. package/src/composables/useShift.ts +13 -2
  414. package/src/composables/useTilt.ts +5 -6
  415. package/src/composables/useToast.ts +56 -4
  416. package/src/composables/useZoomPan.ts +6 -6
  417. package/src/iconSubset.d.mts +10 -0
  418. package/src/iconSubset.mjs +51 -0
  419. package/src/icons-all.ts +10 -0
  420. package/src/icons.ts +59 -8
  421. package/src/index.ts +73 -4
  422. package/src/kit-icons.ts +5 -0
  423. package/src/layout/tree.ts +30 -0
  424. package/src/layout/useLayout.ts +68 -18
  425. package/src/nuxt.ts +87 -17
  426. package/src/runtime/config.plugin.ts +14 -0
  427. package/src/runtime/theme.plugin.ts +43 -23
  428. package/src/theme/backdrop.ts +69 -0
  429. package/src/theme/presets.ts +6 -64
  430. package/src/theme/useTheme.ts +206 -100
  431. package/src/tokens/tokens.css +46 -0
  432. package/dist/chunks/LpBreadcrumbs-p4jHe_V-.js +0 -62
  433. package/dist/chunks/LpContextMenu-CwW1QXe_.js +0 -217
  434. package/dist/chunks/LpDatePicker-CwOToxGq.js +0 -164
  435. package/dist/chunks/LpFormField-CazBc2-a.js +0 -62
  436. package/dist/chunks/LpPhoneInput-BDSKVl_z.js +0 -209
  437. package/dist/chunks/LpTextarea-t7F6gv8E.js +0 -47
@@ -1,7 +1,13 @@
1
- import { shallowReactive, computed, toValue, onMounted, onBeforeUnmount } from "vue";
1
+ import { shallowReactive, ref, computed, toValue, getCurrentInstance, onMounted, onBeforeUnmount } 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,59 +30,182 @@ 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
+ if (binding.key === void 0) return false;
36
+ const key = binding.key.toLowerCase();
28
37
  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;
33
- }
34
- const mounted = shallowReactive(/* @__PURE__ */ new Set());
35
- let mountOrder = 0;
36
- let listening = false;
38
+ const wantsCtrl = Boolean(binding.ctrl) || key === "control" || key === "meta";
39
+ if (ctrlHeld !== wantsCtrl) return false;
40
+ const symbol = key.length === 1 && key.toLowerCase() === key.toUpperCase();
41
+ const shiftFree = key === "shift" || binding.shift === void 0 && symbol;
42
+ if (!shiftFree && event.shiftKey !== Boolean(binding.shift)) return false;
43
+ if (key !== "alt" && event.altKey !== Boolean(binding.alt)) return false;
44
+ if (MODIFIER_KEYS.has(key)) return event.key.toLowerCase() === key;
45
+ return event.key.toLowerCase() === key || binding.code !== void 0 && event.code === binding.code;
46
+ }
47
+ function hotkeySteps(binding) {
48
+ const raw = binding.sequence;
49
+ if (raw === void 0) {
50
+ if (binding.key === void 0) return [];
51
+ const { key, code, ctrl, shift, alt } = binding;
52
+ return [{ key, code, ctrl, shift, alt }];
53
+ }
54
+ const list = typeof raw === "string" ? raw.trim().split(/\s+/) : raw;
55
+ return list.map((step) => typeof step === "string" ? { key: step } : step);
56
+ }
57
+ function sequenceProgress(presses, binding) {
58
+ const steps = hotkeySteps(binding);
59
+ if (!steps.length || presses.length > steps.length) return null;
60
+ for (let i = 0; i < presses.length; i++) {
61
+ if (!matchesHotkey(presses[i], steps[i])) return null;
62
+ }
63
+ return presses.length === steps.length ? "full" : "prefix";
64
+ }
65
+ const STATE_KEY = /* @__PURE__ */ Symbol.for("@leavepulse/ui:hotkeys");
66
+ const g = globalThis;
67
+ const state = g[STATE_KEY] ??= {
68
+ mounted: shallowReactive(/* @__PURE__ */ new Set()),
69
+ order: 0,
70
+ listening: false
71
+ };
72
+ const mounted = state.mounted;
37
73
  function inScope(target, scope) {
38
74
  const el = toValue(scope);
39
75
  if (!el) return true;
40
76
  const node = target instanceof Node ? target : null;
41
77
  return !!node && (el === node || el.contains(node));
42
78
  }
43
- function onKeydown(event) {
44
- if (event.isComposing) return;
79
+ function topLayer() {
80
+ const layers = document.querySelectorAll("[data-dismissable-layer]");
81
+ return layers[layers.length - 1] ?? null;
82
+ }
83
+ function insideOf(entry, layer) {
84
+ const scope = toValue(entry.scope);
85
+ const node = scope ?? entry.host();
86
+ return !!node && layer.contains(node);
87
+ }
88
+ const DEFAULT_TIMEOUT = 1e3;
89
+ const pressed = [];
90
+ let held = [];
91
+ let holdTimer;
92
+ const pendingKeys = ref([]);
93
+ const pendingHotkey = computed(() => pendingKeys.value);
94
+ function snapshot(event) {
95
+ const { key, code, ctrlKey, metaKey, shiftKey, altKey } = event;
96
+ return { key, code, ctrlKey, metaKey, shiftKey, altKey };
97
+ }
98
+ function eligible(event) {
45
99
  const inTextEntry = isTextEntry(event.target);
100
+ const blocker = event.key === "Escape" ? topLayer() : topModalElement();
46
101
  const entries = [...mounted].sort(
47
102
  (a, b) => Number(toValue(b.priority) || 0) - Number(toValue(a.priority) || 0) || b.order - a.order
48
103
  );
104
+ const out = [];
49
105
  for (const entry of entries) {
50
106
  if (toValue(entry.enabled) === false || !inScope(event.target, entry.scope)) continue;
107
+ const covered = !!blocker && !insideOf(entry, blocker);
51
108
  for (const binding of entry.read()) {
52
109
  if (inTextEntry && !binding.allowInInput) continue;
53
- if (!matches(event, binding)) continue;
54
- if (binding.handler(event) === false) continue;
110
+ if (event.repeat && binding.repeat === false) continue;
111
+ if (covered && !binding.overLayers) continue;
112
+ if (binding.when && !binding.when(event)) continue;
113
+ out.push(binding);
114
+ }
115
+ }
116
+ return out;
117
+ }
118
+ function run(candidates) {
119
+ for (const { binding, event } of candidates) {
120
+ if (binding.handler(event) !== false) return true;
121
+ }
122
+ return false;
123
+ }
124
+ function resetSequence() {
125
+ clearTimeout(holdTimer);
126
+ holdTimer = void 0;
127
+ pressed.length = 0;
128
+ held = [];
129
+ pendingKeys.value = [];
130
+ }
131
+ function flushHeld() {
132
+ const waiting = held;
133
+ resetSequence();
134
+ run(waiting);
135
+ }
136
+ function onKeydown(event) {
137
+ if (event.isComposing || event.defaultPrevented) return;
138
+ if (pressed.length && MODIFIER_KEYS.has(event.key.toLowerCase())) return;
139
+ if (pressed.length && event.key === "Escape") {
140
+ resetSequence();
141
+ }
142
+ const presses = [...pressed, snapshot(event)];
143
+ const bindings = eligible(event);
144
+ const full = [];
145
+ let waitFor = 0;
146
+ for (const binding of bindings) {
147
+ const progress = sequenceProgress(presses, binding);
148
+ if (progress === "full") full.push({ binding, event });
149
+ else if (progress === "prefix") waitFor = Math.max(waitFor, binding.timeout ?? DEFAULT_TIMEOUT);
150
+ }
151
+ if (waitFor) {
152
+ clearTimeout(holdTimer);
153
+ pressed.push(snapshot(event));
154
+ held = full;
155
+ pendingKeys.value = pressed.map(pressLabel);
156
+ holdTimer = setTimeout(flushHeld, waitFor);
157
+ event.preventDefault();
158
+ return;
159
+ }
160
+ if (full.length) {
161
+ resetSequence();
162
+ if (run(full)) {
55
163
  event.preventDefault();
56
164
  return;
57
165
  }
58
166
  }
167
+ if (pressed.length) {
168
+ flushHeld();
169
+ onKeydown(event);
170
+ }
171
+ }
172
+ function pressLabel(press) {
173
+ return chordOf({
174
+ key: press.key,
175
+ ctrl: press.ctrlKey || press.metaKey,
176
+ alt: press.altKey,
177
+ shift: press.shiftKey && press.key.length !== 1
178
+ });
59
179
  }
60
180
  function useHotkeys(bindings, options = {}) {
181
+ const instance = getCurrentInstance();
61
182
  const entry = {
62
183
  read: () => toValue(bindings),
63
184
  scope: options.scope,
64
185
  enabled: options.enabled,
65
186
  priority: options.priority,
66
- order: ++mountOrder
187
+ order: ++state.order,
188
+ host: () => {
189
+ const el = instance?.vnode.el;
190
+ return el instanceof Node ? el : null;
191
+ }
67
192
  };
68
193
  onMounted(() => {
69
194
  mounted.add(entry);
70
- if (!listening) {
195
+ warnConflicts();
196
+ if (!state.listening) {
71
197
  window.addEventListener("keydown", onKeydown);
72
- listening = true;
198
+ window.addEventListener("blur", resetSequence);
199
+ state.listening = true;
73
200
  }
74
201
  });
75
202
  onBeforeUnmount(() => {
76
203
  mounted.delete(entry);
77
- if (!mounted.size && listening) {
204
+ if (!mounted.size && state.listening) {
78
205
  window.removeEventListener("keydown", onKeydown);
79
- listening = false;
206
+ window.removeEventListener("blur", resetSequence);
207
+ state.listening = false;
208
+ resetSequence();
80
209
  }
81
210
  });
82
211
  }
@@ -92,20 +221,82 @@ const KEY_NAMES = {
92
221
  arrowleft: "←",
93
222
  arrowright: "→"
94
223
  };
224
+ function chordOf(step) {
225
+ const key = step.key.toLowerCase();
226
+ const name = KEY_NAMES[key] ?? (key.length === 1 || /^f\d+$/.test(key) ? key.toUpperCase() : step.key);
227
+ return [step.ctrl && "Ctrl", step.alt && "Alt", step.shift && "Shift", name].filter(Boolean).join("+");
228
+ }
95
229
  function comboOf(binding) {
96
- const key = binding.key.toLowerCase();
97
- const name = KEY_NAMES[key] ?? (key.length === 1 || /^f\d+$/.test(key) ? key.toUpperCase() : binding.key);
98
- return [binding.ctrl && "Ctrl", binding.alt && "Alt", binding.shift && "Shift", name].filter(Boolean).join("+");
230
+ return hotkeySteps(binding).map(chordOf).join(" ");
231
+ }
232
+ function signatureOf(binding) {
233
+ return hotkeySteps(binding).map((step) => {
234
+ const key = step.key.toLowerCase();
235
+ const symbol = key.length === 1 && key === key.toUpperCase();
236
+ const shift = step.shift === void 0 && symbol ? "*" : String(Boolean(step.shift));
237
+ return `${Boolean(step.ctrl)}:${Boolean(step.alt)}:${shift}:${key}`;
238
+ }).join(" ");
239
+ }
240
+ function findHotkeyConflicts(groups) {
241
+ const scopeIds = /* @__PURE__ */ new Map();
242
+ const seen = /* @__PURE__ */ new Map();
243
+ groups.forEach((group, owner) => {
244
+ if (!scopeIds.has(group.scope)) scopeIds.set(group.scope, scopeIds.size);
245
+ for (const binding of group.bindings) {
246
+ if (binding.when || !hotkeySteps(binding).length) continue;
247
+ const id = `${group.priority}|${scopeIds.get(group.scope)}|${signatureOf(binding)}`;
248
+ const slot = seen.get(id) ?? {
249
+ combo: binding.help?.combo ?? comboOf(binding),
250
+ labels: [],
251
+ owners: /* @__PURE__ */ new Set(),
252
+ priority: group.priority
253
+ };
254
+ slot.owners.add(owner);
255
+ if (binding.help && !slot.labels.includes(binding.help.label)) slot.labels.push(binding.help.label);
256
+ seen.set(id, slot);
257
+ }
258
+ });
259
+ return [...seen.values()].filter((slot) => slot.owners.size > 1).map(({ combo, labels, priority }) => ({ combo, labels, priority }));
260
+ }
261
+ const hotkeyConflicts = computed(
262
+ () => findHotkeyConflicts(
263
+ [...mounted].filter((entry) => toValue(entry.enabled) !== false).map((entry) => ({
264
+ bindings: entry.read(),
265
+ priority: Number(toValue(entry.priority) || 0),
266
+ scope: toValue(entry.scope) ?? null
267
+ }))
268
+ )
269
+ );
270
+ const warned = /* @__PURE__ */ new Set();
271
+ function isDev() {
272
+ try {
273
+ return process.env.NODE_ENV !== "production";
274
+ } catch {
275
+ return false;
276
+ }
277
+ }
278
+ function warnConflicts() {
279
+ if (!isDev()) return;
280
+ for (const conflict of hotkeyConflicts.value) {
281
+ const id = `${conflict.priority}|${conflict.combo}`;
282
+ if (warned.has(id)) continue;
283
+ warned.add(id);
284
+ console.warn(
285
+ `[@leavepulse/ui] ${conflict.combo} is bound more than once at priority ${conflict.priority}` + (conflict.labels.length ? ` (${conflict.labels.join(", ")})` : "") + "; only the most recently mounted one runs unless it declines."
286
+ );
287
+ }
99
288
  }
100
289
  const activeShortcuts = computed(() => {
101
290
  const groups = /* @__PURE__ */ new Map();
291
+ const clashing = new Set(hotkeyConflicts.value.map((c) => c.combo));
102
292
  for (const entry of mounted) {
103
293
  if (toValue(entry.enabled) === false) continue;
104
294
  for (const binding of entry.read()) {
105
295
  if (!binding.help) continue;
106
296
  const combo = binding.help.combo ?? comboOf(binding);
107
297
  const entries = groups.get(binding.help.group) ?? [];
108
- if (!entries.some((e) => e.combo === combo)) entries.push({ combo, label: binding.help.label });
298
+ const conflict = clashing.has(combo) || void 0;
299
+ if (!entries.some((e) => e.combo === combo)) entries.push({ combo, label: binding.help.label, conflict });
109
300
  groups.set(binding.help.group, entries);
110
301
  }
111
302
  }
@@ -127,7 +318,14 @@ function mergeShortcutGroups(...lists) {
127
318
  export {
128
319
  activeShortcuts,
129
320
  appleModifierLabel,
321
+ findHotkeyConflicts,
322
+ hotkeyConflicts,
323
+ hotkeySteps,
130
324
  isAppleKeyboard,
325
+ matchesHotkey,
131
326
  mergeShortcutGroups,
327
+ pendingHotkey,
328
+ sequenceProgress,
329
+ useAppleKeyboard,
132
330
  useHotkeys
133
331
  };
@@ -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,59 @@
1
+ import { type MaybeRefOrGetter } from "vue";
2
+ export type MaskToken = RegExp | {
3
+ pattern: RegExp;
4
+ transform?: (ch: string) => string;
5
+ };
6
+ export type MaskTokens = Record<string, MaskToken>;
7
+ export type MaskSpec = string | readonly string[] | ((raw: string) => string);
8
+ export declare const DEFAULT_MASK_TOKENS: MaskTokens;
9
+ type Slot = {
10
+ literal: string;
11
+ } | {
12
+ test: (ch: string) => boolean;
13
+ transform: (ch: string) => string;
14
+ };
15
+ export interface MaskResult {
16
+ masked: string;
17
+ raw: string;
18
+ /** Caret offset in `masked`. */
19
+ caret: number;
20
+ /** Every token of the mask is filled. */
21
+ complete: boolean;
22
+ }
23
+ export interface MaskOptions {
24
+ mask: MaskSpec;
25
+ tokens?: MaskTokens;
26
+ /**
27
+ * Caret position: an offset into `input`, or with `fromRaw` the number of raw
28
+ * characters before it. Defaults to the end.
29
+ */
30
+ caret?: number;
31
+ /** `input` holds raw characters only; literals in it are never consumed as mask literals. */
32
+ fromRaw?: boolean;
33
+ }
34
+ export declare function parseMask(mask: string, tokens?: MaskTokens): Slot[];
35
+ /** Format `input` through a mask and map the caret into the result. */
36
+ export declare function applyMask(input: string, options: MaskOptions): MaskResult;
37
+ /**
38
+ * The value after deleting one accepted character next to a collapsed caret,
39
+ * skipping over literals, or null when there is nothing to delete that way.
40
+ */
41
+ export declare function maskDelete(value: string, caret: number, direction: "backward" | "forward", options: Omit<MaskOptions, "caret" | "fromRaw">): MaskResult | null;
42
+ export interface UseInputMaskOptions {
43
+ mask: MaybeRefOrGetter<MaskSpec | undefined>;
44
+ tokens?: MaybeRefOrGetter<MaskTokens | undefined>;
45
+ /** Called with every value the user produces. */
46
+ onChange?: (masked: string, raw: string, complete: boolean) => void;
47
+ }
48
+ /**
49
+ * Bind `onBeforeInput`, `onInput` and `onCompositionEnd` to the input, and show
50
+ * `format(model).masked` as its value.
51
+ */
52
+ export declare function useInputMask(options: UseInputMaskOptions): {
53
+ active: import("vue").ComputedRef<boolean>;
54
+ format: (value: string | null | undefined) => MaskResult;
55
+ onBeforeInput: (event: InputEvent) => void;
56
+ onInput: (event: Event) => void;
57
+ onCompositionEnd: (event: CompositionEvent) => void;
58
+ };
59
+ export {};
@@ -0,0 +1,170 @@
1
+ import { computed, toValue } from "vue";
2
+ const DEFAULT_MASK_TOKENS = {
3
+ "0": /\d/,
4
+ a: new RegExp("\\p{L}", "u"),
5
+ A: { pattern: new RegExp("\\p{L}", "u"), transform: (ch) => ch.toLocaleUpperCase() },
6
+ "*": /[\p{L}\d]/u
7
+ };
8
+ function tester(token) {
9
+ const pattern = token instanceof RegExp ? token : token.pattern;
10
+ const re = new RegExp(pattern.source, pattern.flags.replace(/[gy]/g, ""));
11
+ const transform = token instanceof RegExp ? void 0 : token.transform;
12
+ return { test: (ch) => re.test(ch), transform: transform ?? ((ch) => ch) };
13
+ }
14
+ function parseMask(mask, tokens = DEFAULT_MASK_TOKENS) {
15
+ const slots = [];
16
+ const chars = Array.from(mask);
17
+ for (let i = 0; i < chars.length; i++) {
18
+ const ch = chars[i];
19
+ if (ch === "\\" && i + 1 < chars.length) {
20
+ slots.push({ literal: chars[++i] });
21
+ continue;
22
+ }
23
+ const token = tokens[ch];
24
+ slots.push(token ? tester(token) : { literal: ch });
25
+ }
26
+ return slots;
27
+ }
28
+ function run(slots, input, caret, fromRaw) {
29
+ const tokenStarts = [];
30
+ const tokenEnds = [];
31
+ const tokenOffsets = [];
32
+ let out = "";
33
+ let raw = "";
34
+ let pending = "";
35
+ let si = 0;
36
+ let offset = 0;
37
+ let before = 0;
38
+ let overflow = false;
39
+ for (const ch of input) {
40
+ const at2 = offset;
41
+ offset += ch.length;
42
+ if (si >= slots.length) {
43
+ if (slots.some((s) => "test" in s && s.test(ch))) overflow = true;
44
+ continue;
45
+ }
46
+ while (si < slots.length) {
47
+ const slot = slots[si];
48
+ if ("literal" in slot) {
49
+ pending += slot.literal;
50
+ si++;
51
+ if (!fromRaw && slot.literal === ch) break;
52
+ continue;
53
+ }
54
+ if (slot.test(ch)) {
55
+ const value = slot.transform(ch);
56
+ out += pending;
57
+ pending = "";
58
+ tokenStarts.push(out.length);
59
+ out += value;
60
+ tokenEnds.push(out.length);
61
+ raw += value;
62
+ tokenOffsets.push(at2);
63
+ si++;
64
+ if (fromRaw ? raw.length <= caret : at2 < caret) before++;
65
+ }
66
+ break;
67
+ }
68
+ }
69
+ const rest = slots.slice(si);
70
+ const complete = !rest.some((s) => "test" in s);
71
+ if (complete && out) out += pending + rest.map((s) => "literal" in s ? s.literal : "").join("");
72
+ const at = before === 0 ? tokenStarts[0] ?? 0 : tokenEnds[before - 1];
73
+ return {
74
+ masked: out,
75
+ raw,
76
+ caret: complete && before === tokenEnds.length ? out.length : at,
77
+ complete,
78
+ overflow,
79
+ tokenOffsets
80
+ };
81
+ }
82
+ function resolve(options, input, caret) {
83
+ const tokens = options.tokens ?? DEFAULT_MASK_TOKENS;
84
+ const fromRaw = !!options.fromRaw;
85
+ const { mask } = options;
86
+ if (typeof mask === "string") return run(parseMask(mask, tokens), input, caret, fromRaw);
87
+ if (typeof mask === "function") {
88
+ let current = mask("");
89
+ let result = run(parseMask(current, tokens), input, caret, fromRaw);
90
+ for (let i = 0; i < 4; i++) {
91
+ const next = mask(result.raw);
92
+ if (next === current) break;
93
+ current = next;
94
+ result = run(parseMask(current, tokens), input, caret, fromRaw);
95
+ }
96
+ return result;
97
+ }
98
+ let last;
99
+ for (const m of mask) {
100
+ last = run(parseMask(m, tokens), input, caret, fromRaw);
101
+ if (!last.overflow) return last;
102
+ }
103
+ return last ?? run([], input, caret, fromRaw);
104
+ }
105
+ function applyMask(input, options) {
106
+ const caret = options.caret ?? (options.fromRaw ? Number.POSITIVE_INFINITY : input.length);
107
+ const { masked, raw, caret: at, complete } = resolve(options, input, caret);
108
+ return { masked, raw, caret: at, complete };
109
+ }
110
+ function maskDelete(value, caret, direction, options) {
111
+ const { tokenOffsets, raw } = resolve(options, value, caret);
112
+ const index = direction === "backward" ? tokenOffsets.filter((o) => o < caret).length - 1 : tokenOffsets.findIndex((o) => o >= caret);
113
+ if (index < 0) return null;
114
+ const chars = Array.from(raw);
115
+ chars.splice(index, 1);
116
+ return applyMask(chars.join(""), { ...options, caret: index, fromRaw: true });
117
+ }
118
+ function useInputMask(options) {
119
+ const spec = computed(() => {
120
+ const mask = toValue(options.mask);
121
+ return mask === void 0 || mask === "" ? void 0 : { mask, tokens: toValue(options.tokens) };
122
+ });
123
+ function format(value) {
124
+ const s = spec.value;
125
+ const text = value ?? "";
126
+ return s ? applyMask(text, s) : { masked: text, raw: text, caret: text.length, complete: true };
127
+ }
128
+ function commit(el, result) {
129
+ if (el.value !== result.masked) el.value = result.masked;
130
+ if (el.ownerDocument.activeElement === el) {
131
+ try {
132
+ el.setSelectionRange(result.caret, result.caret);
133
+ } catch {
134
+ }
135
+ }
136
+ options.onChange?.(result.masked, result.raw, result.complete);
137
+ }
138
+ function onBeforeInput(event) {
139
+ const s = spec.value;
140
+ const el = event.target;
141
+ if (!s || event.isComposing || !(el instanceof HTMLInputElement)) return;
142
+ const backward = event.inputType === "deleteContentBackward";
143
+ if (!backward && event.inputType !== "deleteContentForward") return;
144
+ const start = el.selectionStart;
145
+ if (start === null || start !== el.selectionEnd) return;
146
+ event.preventDefault();
147
+ const result = maskDelete(el.value, start, backward ? "backward" : "forward", s);
148
+ if (result) commit(el, result);
149
+ }
150
+ function reformat(el) {
151
+ const s = spec.value;
152
+ if (!s) return;
153
+ commit(el, applyMask(el.value, { ...s, caret: el.selectionStart ?? el.value.length }));
154
+ }
155
+ function onInput(event) {
156
+ if (event.isComposing || !(event.target instanceof HTMLInputElement)) return;
157
+ reformat(event.target);
158
+ }
159
+ function onCompositionEnd(event) {
160
+ if (event.target instanceof HTMLInputElement) reformat(event.target);
161
+ }
162
+ return { active: computed(() => !!spec.value), format, onBeforeInput, onInput, onCompositionEnd };
163
+ }
164
+ export {
165
+ DEFAULT_MASK_TOKENS,
166
+ applyMask,
167
+ maskDelete,
168
+ parseMask,
169
+ useInputMask
170
+ };
@@ -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>;