@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,47 +1,68 @@
1
- import { defineComponent, ref, shallowRef, computed, onMounted, onBeforeUnmount, watch, nextTick, openBlock, createElementBlock, mergeProps, unref, createVNode, Transition, withCtx, toDisplayString, createCommentVNode, normalizeStyle, createElementVNode, Fragment, createBlock, resolveDynamicComponent, TransitionGroup, renderList, normalizeClass, createTextVNode } from "vue";
1
+ import { defineComponent, useModel, computed, ref, shallowRef, onMounted, onBeforeUnmount, watch, nextTick, openBlock, createElementBlock, mergeProps, unref, createVNode, Transition, withCtx, toDisplayString, createCommentVNode, createElementVNode, withDirectives, vModelText, Fragment, renderList, normalizeClass, createTextVNode, normalizeStyle, createBlock, resolveDynamicComponent, TransitionGroup, mergeModels } from "vue";
2
2
  import { prefersReducedMotion } from "../composables/easing.js";
3
3
  import { useClipboard } from "../composables/useClipboard.js";
4
4
  import { useHotkeys } from "../composables/useHotkeys.js";
5
- import { _ as _sfc_main$3 } from "./LpContextMenu-CwW1QXe_.js";
6
- import { _ as _sfc_main$2 } from "./LpIcon-CCnX5_2j.js";
7
- import { _ as _sfc_main$1 } from "./LpScrollArea-D8xyKXcF.js";
5
+ import { _ as _sfc_main$3 } from "./LpContextMenu-BqkAYa9X.js";
6
+ import { _ as _sfc_main$1 } from "./LpIcon-DYtaid0K.js";
7
+ import { _ as _sfc_main$2 } from "./LpScrollArea-Bry1fdOM.js";
8
8
  import { useMergedAttrs } from "../composables/useMergedClass.js";
9
+ import { useLabels } from "../composables/useLpConfig.js";
10
+ import { ringWindow, matchPositions, countLevels, stepMatch } from "../components/logSearch.js";
9
11
  const _hoisted_1 = {
10
12
  key: 0,
11
13
  class: "pointer-events-none absolute top-2 left-1/2 z-10 -translate-x-1/2 rounded-pill bg-brand px-2.5 py-1 text-[11px] font-medium text-ink-inverse"
12
14
  };
13
15
  const _hoisted_2 = {
16
+ key: 0,
17
+ class: "flex flex-wrap items-center gap-2 border-b border-line px-2 py-1.5 font-sans"
18
+ };
19
+ const _hoisted_3 = { class: "flex min-w-48 flex-1 items-center gap-1.5 rounded-control bg-surface-soft px-2 focus-within:ring-2 focus-within:ring-ring" };
20
+ const _hoisted_4 = ["aria-label", "placeholder"];
21
+ const _hoisted_5 = {
22
+ key: 0,
23
+ class: "shrink-0 text-[11px] tabular-nums text-muted",
24
+ "aria-live": "polite"
25
+ };
26
+ const _hoisted_6 = ["aria-label"];
27
+ const _hoisted_7 = { class: "flex items-center" };
28
+ const _hoisted_8 = ["aria-label", "disabled"];
29
+ const _hoisted_9 = ["aria-label", "disabled"];
30
+ const _hoisted_10 = ["aria-label"];
31
+ const _hoisted_11 = ["aria-pressed", "onClick"];
32
+ const _hoisted_12 = { class: "font-normal tabular-nums text-muted" };
33
+ const _hoisted_13 = {
14
34
  key: 0,
15
35
  class: "flex h-full flex-col items-center justify-center gap-1 px-4 py-10 text-center"
16
36
  };
17
- const _hoisted_3 = { class: "text-muted" };
18
- const _hoisted_4 = {
37
+ const _hoisted_14 = { class: "text-muted" };
38
+ const _hoisted_15 = {
19
39
  key: 0,
20
40
  class: "text-muted/70"
21
41
  };
22
- const _hoisted_5 = {
42
+ const _hoisted_16 = {
23
43
  key: 0,
24
44
  class: "flex items-center justify-center gap-2 py-2 text-muted"
25
45
  };
26
- const _hoisted_6 = ["data-log-row"];
27
- const _hoisted_7 = {
46
+ const _hoisted_17 = { class: "text-[11px]" };
47
+ const _hoisted_18 = ["data-log-row", "aria-current"];
48
+ const _hoisted_19 = {
28
49
  key: 0,
29
50
  class: "mr-3 w-10 shrink-0 select-none text-right tabular-nums text-muted/70"
30
51
  };
31
- const _hoisted_8 = {
52
+ const _hoisted_20 = {
32
53
  key: 1,
33
54
  class: "mr-3 shrink-0 tabular-nums text-muted"
34
55
  };
35
- const _hoisted_9 = {
56
+ const _hoisted_21 = {
36
57
  key: 3,
37
58
  class: "mr-2 shrink-0 text-muted-strong"
38
59
  };
39
- const _hoisted_10 = {
60
+ const _hoisted_22 = {
40
61
  key: 0,
41
62
  class: "rounded-xs bg-accent/30 text-ink"
42
63
  };
43
- const _hoisted_11 = ["title"];
44
- const _hoisted_12 = {
64
+ const _hoisted_23 = ["title"];
65
+ const _hoisted_24 = {
45
66
  key: 0,
46
67
  class: "absolute inset-x-0 bottom-3 flex justify-center"
47
68
  };
@@ -49,7 +70,7 @@ const __default__ = { inheritAttrs: false };
49
70
  const _sfc_main = /* @__PURE__ */ defineComponent({
50
71
  ...__default__,
51
72
  __name: "LpLogViewer",
52
- props: {
73
+ props: /* @__PURE__ */ mergeModels({
53
74
  lines: {},
54
75
  showTime: { type: Boolean, default: true },
55
76
  showLevel: { type: Boolean, default: true },
@@ -60,18 +81,54 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
60
81
  compact: { type: Boolean },
61
82
  tail: { type: Boolean, default: true },
62
83
  height: { default: "20rem" },
63
- emptyLabel: { default: "No logs yet" },
64
- frozenLabel: { default: "Held — release Ctrl to resume" },
84
+ emptyLabel: {},
85
+ frozenLabel: {},
65
86
  loadingOlder: { type: Boolean },
66
87
  loadOlder: { type: Boolean },
67
88
  rowMenu: { type: Boolean, default: true },
68
89
  extraRowItems: {},
69
- parse: { type: Boolean, default: false }
70
- },
71
- emits: ["filter", "reach-top"],
72
- setup(__props, { emit: __emit }) {
90
+ parse: { type: Boolean, default: false },
91
+ maxLines: {},
92
+ toolbar: { type: Boolean },
93
+ labels: {}
94
+ }, {
95
+ "search": { default: "" },
96
+ "searchModifiers": {},
97
+ "levels": { default: () => [] },
98
+ "levelsModifiers": {}
99
+ }),
100
+ emits: /* @__PURE__ */ mergeModels(["filter", "reach-top"], ["update:search", "update:levels"]),
101
+ setup(__props, { expose: __expose, emit: __emit }) {
73
102
  const props = __props;
74
103
  const emit = __emit;
104
+ const query = useModel(__props, "search");
105
+ const levels = useModel(__props, "levels");
106
+ const term = computed(() => (props.toolbar && query.value ? query.value : props.highlight ?? "").trim());
107
+ const text = useLabels(
108
+ "logViewer",
109
+ {
110
+ empty: "No logs yet",
111
+ frozen: "Held — release Ctrl to resume",
112
+ noMatch: "No lines match",
113
+ loadingOlder: "loading older…",
114
+ copyMessage: "Copy message",
115
+ copyLine: "Copy line",
116
+ copyTimestamp: "Copy timestamp",
117
+ copied: "Copied to clipboard",
118
+ filterSource: "Filter by [{source}]",
119
+ filterLevel: "Filter by {level}",
120
+ identical: "{n} identical lines",
121
+ jump: "Jump to latest",
122
+ search: "Search logs",
123
+ clearSearch: "Clear search",
124
+ previousMatch: "Previous match",
125
+ nextMatch: "Next match",
126
+ matchCount: "{current} / {total}",
127
+ noMatches: "No matches",
128
+ levels: "Levels"
129
+ },
130
+ () => props.labels
131
+ );
75
132
  const levelMeta = {
76
133
  trace: { rail: "bg-line-strong", text: "text-muted", chip: "text-muted", sel: "selection:bg-muted/40" },
77
134
  debug: { rail: "bg-line-strong", text: "text-muted-strong", chip: "text-muted-strong", sel: "selection:bg-muted-strong/40" },
@@ -139,11 +196,13 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
139
196
  const root = ref(null);
140
197
  const frozen = ref(false);
141
198
  const frozenLines = shallowRef(null);
142
- const sourceLines = computed(() => frozenLines.value ?? props.lines);
199
+ const windowed = computed(() => ringWindow(frozenLines.value ?? props.lines, props.maxLines));
200
+ const sourceLines = computed(() => windowed.value.lines);
201
+ const lineOffset = computed(() => windowed.value.offset);
143
202
  function freeze() {
144
203
  if (!hovered.value && !focusWithin()) return false;
145
204
  if (frozen.value) return true;
146
- frozenLines.value = props.lines;
205
+ frozenLines.value = props.maxLines ? props.lines.slice(-props.maxLines) : props.lines;
147
206
  frozen.value = true;
148
207
  return true;
149
208
  }
@@ -156,9 +215,10 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
156
215
  const el = root.value;
157
216
  return !!el && el.contains(document.activeElement);
158
217
  }
218
+ const lookedAt = () => hovered.value || focusWithin();
159
219
  useHotkeys(() => [
160
- { key: "control", allowInInput: true, handler: freeze },
161
- { key: "meta", allowInInput: true, handler: freeze }
220
+ { key: "control", allowInInput: true, when: lookedAt, handler: freeze },
221
+ { key: "meta", allowInInput: true, when: lookedAt, handler: freeze }
162
222
  ]);
163
223
  function onKeyup(event) {
164
224
  if (event.key === "Control" || event.key === "Meta") thaw();
@@ -175,8 +235,9 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
175
235
  () => props.parse ? sourceLines.value.map(parseLine) : sourceLines.value
176
236
  );
177
237
  const visibleLines = computed(() => {
178
- const term = props.filterMatches ? props.highlight?.trim().toLowerCase() : "";
179
- const filtered = parsedLines.value.map((line, n) => ({ line, n })).filter(({ line }) => !term || line.message.toLowerCase().includes(term));
238
+ const needle = props.filterMatches ? term.value.toLowerCase() : "";
239
+ const shown = levels.value.length ? new Set(levels.value) : null;
240
+ const filtered = parsedLines.value.map((line, n) => ({ line, n })).filter(({ line }) => !shown || shown.has(line.level ?? "info")).filter(({ line }) => !needle || matchPositions([line], needle).length > 0);
180
241
  if (!props.compact) return filtered.map((row) => ({ ...row, count: 1 }));
181
242
  const folded = [];
182
243
  for (const row of filtered) {
@@ -189,6 +250,82 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
189
250
  }
190
251
  return folded;
191
252
  });
253
+ const lineIds = /* @__PURE__ */ new WeakMap();
254
+ let nextLineId = 0;
255
+ function lineKey(n) {
256
+ const line = sourceLines.value[n];
257
+ if (!line) return -1 - n;
258
+ let id = lineIds.get(line);
259
+ if (id === void 0) {
260
+ id = nextLineId++;
261
+ lineIds.set(line, id);
262
+ }
263
+ return id;
264
+ }
265
+ const LEVEL_ORDER = ["trace", "debug", "info", "success", "warn", "error", "fatal"];
266
+ const levelCounts = computed(() => countLevels(parsedLines.value, "info"));
267
+ const presentLevels = computed(() => LEVEL_ORDER.filter((l) => levelCounts.value.has(l)));
268
+ function toggleLevel(level) {
269
+ levels.value = levels.value.includes(level) ? levels.value.filter((l) => l !== level) : [...levels.value, level];
270
+ }
271
+ const matches = computed(() => matchPositions(visibleLines.value.map((r) => r.line), term.value));
272
+ const current = ref(-1);
273
+ const currentRow = computed(() => {
274
+ const pos = matches.value[current.value];
275
+ return pos === void 0 ? -1 : visibleLines.value[pos]?.n ?? -1;
276
+ });
277
+ watch(term, () => {
278
+ current.value = -1;
279
+ });
280
+ watch(matches, (list) => {
281
+ if (current.value >= list.length) current.value = list.length - 1;
282
+ });
283
+ const matchLabel = computed(() => {
284
+ if (!term.value) return "";
285
+ const total = matches.value.length;
286
+ if (!total) return text.value.noMatches;
287
+ return text.value.matchCount.replace("{current}", current.value >= 0 ? String(current.value + 1) : "–").replace("{total}", String(total));
288
+ });
289
+ function step(direction) {
290
+ const next = stepMatch(current.value, matches.value.length, direction);
291
+ if (next < 0) return;
292
+ current.value = next;
293
+ pinned.value = false;
294
+ nextTick(() => revealMatch(matches.value[next]));
295
+ }
296
+ function revealMatch(position) {
297
+ const el = viewport();
298
+ if (!el || position === void 0) return;
299
+ const behavior = prefersReducedMotion() ? "auto" : "smooth";
300
+ if (virtualise.value) {
301
+ el.scrollTo({ top: Math.max(0, position * ROW_HEIGHT - el.clientHeight / 2), behavior });
302
+ return;
303
+ }
304
+ const n = visibleLines.value[position]?.n;
305
+ el.querySelector(`[data-log-row="${n}"]`)?.scrollIntoView({ block: "center", behavior });
306
+ }
307
+ const searchEl = ref(null);
308
+ function onSearchKeydown(event) {
309
+ if (event.isComposing) return;
310
+ if (event.key === "Enter") {
311
+ event.preventDefault();
312
+ step(event.shiftKey ? -1 : 1);
313
+ } else if (event.key === "Escape" && query.value) {
314
+ event.preventDefault();
315
+ event.stopPropagation();
316
+ query.value = "";
317
+ }
318
+ }
319
+ const searching = () => !!term.value && lookedAt();
320
+ useHotkeys(() => [
321
+ { key: "f3", allowInInput: true, when: searching, handler: () => step(1) },
322
+ { key: "f3", shift: true, allowInInput: true, when: searching, handler: () => step(-1) }
323
+ ]);
324
+ __expose({
325
+ next: () => step(1),
326
+ previous: () => step(-1),
327
+ focusSearch: () => searchEl.value?.focus()
328
+ });
192
329
  const filteredEmpty = computed(
193
330
  () => props.lines.length > 0 && visibleLines.value.length === 0
194
331
  );
@@ -202,7 +339,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
202
339
  return time;
203
340
  }
204
341
  const { copy: writeClipboard } = useClipboard();
205
- const copy = (text) => writeClipboard(text, { toast: "Copied to clipboard" });
342
+ const copy = (value) => writeClipboard(value, { toast: text.value.copied });
206
343
  function lineText(line) {
207
344
  return [fmtTime(line.time), line.level?.toUpperCase(), line.source && `[${line.source}]`, line.message].filter(Boolean).join(" ");
208
345
  }
@@ -223,15 +360,15 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
223
360
  function menuFor(line, index) {
224
361
  if (!props.rowMenu) return [];
225
362
  const items = [
226
- { label: "Copy message", icon: "lucide:copy", onSelect: () => copy(line.message) },
227
- { label: "Copy line", icon: "lucide:clipboard-list", onSelect: () => copy(lineText(line)) }
363
+ { label: text.value.copyMessage, icon: "lucide:copy", onSelect: () => copy(line.message) },
364
+ { label: text.value.copyLine, icon: "lucide:clipboard-list", onSelect: () => copy(lineText(line)) }
228
365
  ];
229
366
  if (line.time != null) {
230
- items.push({ label: "Copy timestamp", icon: "lucide:clock", onSelect: () => copy(fmtTime(line.time)) });
367
+ items.push({ label: text.value.copyTimestamp, icon: "lucide:clock", onSelect: () => copy(fmtTime(line.time)) });
231
368
  }
232
369
  if (line.source) {
233
370
  items.push({
234
- label: `Filter by [${line.source}]`,
371
+ label: text.value.filterSource.replace("{source}", line.source),
235
372
  icon: "lucide:filter",
236
373
  separatorBefore: true,
237
374
  onSelect: () => emit("filter", { source: line.source })
@@ -239,10 +376,13 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
239
376
  }
240
377
  if (line.level) {
241
378
  items.push({
242
- label: `Filter by ${line.level}`,
379
+ label: text.value.filterLevel.replace("{level}", line.level),
243
380
  icon: "lucide:filter",
244
381
  separatorBefore: !line.source,
245
- onSelect: () => emit("filter", { level: line.level })
382
+ onSelect: () => {
383
+ if (props.toolbar && line.level) levels.value = [line.level];
384
+ emit("filter", { level: line.level });
385
+ }
246
386
  });
247
387
  }
248
388
  const extra = props.extraRowItems?.(line, index) ?? [];
@@ -250,11 +390,10 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
250
390
  return [...items, ...extra];
251
391
  }
252
392
  function splitHighlight(message) {
253
- const term = props.highlight?.trim();
254
- if (!term) return [{ text: message, hit: false }];
393
+ if (!term.value) return [{ text: message, hit: false }];
255
394
  const parts = [];
256
395
  const lower = message.toLowerCase();
257
- const needle = term.toLowerCase();
396
+ const needle = term.value.toLowerCase();
258
397
  let i = 0;
259
398
  while (i < message.length) {
260
399
  const at = lower.indexOf(needle, i);
@@ -341,21 +480,23 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
341
480
  el.scrollTo({ top: el.scrollHeight, behavior: smooth && !reduce && !far ? "smooth" : "auto" });
342
481
  }
343
482
  function scrollToBottom() {
483
+ current.value = -1;
344
484
  rideToBottom(true, true);
345
485
  pinned.value = true;
346
486
  }
487
+ const linesSignal = () => [props.lines, props.lines.length, props.lines[props.lines.length - 1]];
347
488
  watch(
348
- () => props.lines.length,
489
+ linesSignal,
349
490
  () => {
350
491
  if (!pinned.value) captureScrollAnchor();
351
492
  },
352
493
  { flush: "pre" }
353
494
  );
354
495
  watch(
355
- () => props.lines.length,
496
+ linesSignal,
356
497
  async () => {
357
498
  await nextTick();
358
- if (props.tail && pinned.value) {
499
+ if (props.tail && pinned.value && current.value < 0) {
359
500
  requestAnimationFrame(() => rideToBottom(true));
360
501
  } else {
361
502
  restoreScrollAnchor();
@@ -382,12 +523,12 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
382
523
  });
383
524
  const transitionProps = {
384
525
  tag: "ol",
385
- "enter-active-class": "transition duration-200 ease-[var(--ease-emphasized)]",
526
+ "enter-active-class": "transition duration-[var(--duration-medium)] ease-[var(--ease-emphasized)]",
386
527
  "enter-from-class": "-translate-x-1 opacity-0",
387
- "leave-active-class": "overflow-hidden transition-all duration-200 ease-[var(--ease-emphasized)]",
528
+ "leave-active-class": "overflow-hidden transition-all duration-[var(--duration-medium)] ease-[var(--ease-emphasized)]",
388
529
  "leave-from-class": "max-h-8 opacity-100",
389
530
  "leave-to-class": "max-h-0 -translate-y-1 opacity-0",
390
- "move-class": "transition-transform duration-200 ease-[var(--ease-emphasized)]"
531
+ "move-class": "transition-transform duration-[var(--duration-medium)] ease-[var(--ease-emphasized)]"
391
532
  };
392
533
  const { class: rootClass, attrs: rest } = useMergedAttrs(
393
534
  () => [
@@ -402,8 +543,8 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
402
543
  tabindex: "-1",
403
544
  class: unref(rootClass)
404
545
  }, unref(rest), {
405
- onPointerenter: _cache[0] || (_cache[0] = ($event) => hovered.value = true),
406
- onPointerleave: _cache[1] || (_cache[1] = ($event) => hovered.value = false)
546
+ onPointerenter: _cache[4] || (_cache[4] = ($event) => hovered.value = true),
547
+ onPointerleave: _cache[5] || (_cache[5] = ($event) => hovered.value = false)
407
548
  }), [
408
549
  createVNode(Transition, {
409
550
  "enter-active-class": "transition duration-[var(--duration-fast)] ease-[var(--ease-emphasized)] motion-reduce:transition-none",
@@ -412,11 +553,97 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
412
553
  "leave-to-class": "-translate-y-1 opacity-0"
413
554
  }, {
414
555
  default: withCtx(() => [
415
- frozen.value ? (openBlock(), createElementBlock("div", _hoisted_1, toDisplayString(__props.frozenLabel), 1)) : createCommentVNode("", true)
556
+ frozen.value ? (openBlock(), createElementBlock("div", _hoisted_1, toDisplayString(__props.frozenLabel ?? unref(text).frozen), 1)) : createCommentVNode("", true)
416
557
  ]),
417
558
  _: 1
418
559
  }),
419
- createVNode(_sfc_main$1, {
560
+ __props.toolbar ? (openBlock(), createElementBlock("div", _hoisted_2, [
561
+ createElementVNode("div", _hoisted_3, [
562
+ createVNode(_sfc_main$1, {
563
+ name: "lucide:search",
564
+ size: 14,
565
+ class: "shrink-0 text-muted"
566
+ }),
567
+ withDirectives(createElementVNode("input", {
568
+ ref_key: "searchEl",
569
+ ref: searchEl,
570
+ "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => query.value = $event),
571
+ type: "search",
572
+ "aria-label": unref(text).search,
573
+ placeholder: unref(text).search,
574
+ class: "h-7 min-w-0 flex-1 bg-transparent text-xs text-ink outline-none placeholder:text-muted [&::-webkit-search-cancel-button]:hidden",
575
+ onKeydown: onSearchKeydown
576
+ }, null, 40, _hoisted_4), [
577
+ [vModelText, query.value]
578
+ ]),
579
+ term.value ? (openBlock(), createElementBlock("span", _hoisted_5, toDisplayString(matchLabel.value), 1)) : createCommentVNode("", true),
580
+ query.value ? (openBlock(), createElementBlock("button", {
581
+ key: 1,
582
+ type: "button",
583
+ class: "rounded-xs p-0.5 text-muted outline-none hover:text-ink focus-visible:ring-2 focus-visible:ring-ring",
584
+ "aria-label": unref(text).clearSearch,
585
+ onClick: _cache[1] || (_cache[1] = ($event) => {
586
+ query.value = "";
587
+ searchEl.value?.focus();
588
+ })
589
+ }, [
590
+ createVNode(_sfc_main$1, {
591
+ name: "lucide:x",
592
+ size: 12
593
+ })
594
+ ], 8, _hoisted_6)) : createCommentVNode("", true)
595
+ ]),
596
+ createElementVNode("div", _hoisted_7, [
597
+ createElementVNode("button", {
598
+ type: "button",
599
+ class: "rounded-xs p-1 text-muted outline-none hover:text-ink focus-visible:ring-2 focus-visible:ring-ring disabled:opacity-40",
600
+ "aria-label": unref(text).previousMatch,
601
+ disabled: !matches.value.length,
602
+ onClick: _cache[2] || (_cache[2] = ($event) => step(-1))
603
+ }, [
604
+ createVNode(_sfc_main$1, {
605
+ name: "lucide:chevron-up",
606
+ size: 14
607
+ })
608
+ ], 8, _hoisted_8),
609
+ createElementVNode("button", {
610
+ type: "button",
611
+ class: "rounded-xs p-1 text-muted outline-none hover:text-ink focus-visible:ring-2 focus-visible:ring-ring disabled:opacity-40",
612
+ "aria-label": unref(text).nextMatch,
613
+ disabled: !matches.value.length,
614
+ onClick: _cache[3] || (_cache[3] = ($event) => step(1))
615
+ }, [
616
+ createVNode(_sfc_main$1, {
617
+ name: "lucide:chevron-down",
618
+ size: 14
619
+ })
620
+ ], 8, _hoisted_9)
621
+ ]),
622
+ presentLevels.value.length > 1 ? (openBlock(), createElementBlock("div", {
623
+ key: 0,
624
+ role: "group",
625
+ "aria-label": unref(text).levels,
626
+ class: "flex flex-wrap items-center gap-1"
627
+ }, [
628
+ (openBlock(true), createElementBlock(Fragment, null, renderList(presentLevels.value, (level) => {
629
+ return openBlock(), createElementBlock("button", {
630
+ key: level,
631
+ type: "button",
632
+ class: normalizeClass(["flex items-center gap-1 rounded-pill border px-2 py-0.5 text-[10px] font-semibold uppercase tracking-[0.06em] outline-none transition-colors focus-visible:ring-2 focus-visible:ring-ring", levels.value.includes(level) ? "border-line-strong bg-surface-soft text-ink" : "border-line text-muted hover:text-ink"]),
633
+ "aria-pressed": levels.value.includes(level),
634
+ onClick: ($event) => toggleLevel(level)
635
+ }, [
636
+ createElementVNode("span", {
637
+ class: normalizeClass(["size-1.5 rounded-full", metaFor(level).rail]),
638
+ "aria-hidden": "true"
639
+ }, null, 2),
640
+ createTextVNode(" " + toDisplayString(level) + " ", 1),
641
+ createElementVNode("span", _hoisted_12, toDisplayString(levelCounts.value.get(level)), 1)
642
+ ], 10, _hoisted_11);
643
+ }), 128))
644
+ ], 8, _hoisted_10)) : createCommentVNode("", true)
645
+ ])) : createCommentVNode("", true),
646
+ createVNode(_sfc_main$2, {
420
647
  ref_key: "scrollRef",
421
648
  ref: scrollRef,
422
649
  instant: "",
@@ -425,17 +652,17 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
425
652
  onScroll
426
653
  }, {
427
654
  default: withCtx(() => [
428
- __props.lines.length === 0 || filteredEmpty.value ? (openBlock(), createElementBlock("div", _hoisted_2, [
429
- createElementVNode("span", _hoisted_3, toDisplayString(filteredEmpty.value ? "No lines match" : __props.emptyLabel), 1),
430
- filteredEmpty.value ? (openBlock(), createElementBlock("span", _hoisted_4, "“" + toDisplayString(__props.highlight) + "”", 1)) : createCommentVNode("", true)
655
+ __props.lines.length === 0 || filteredEmpty.value ? (openBlock(), createElementBlock("div", _hoisted_13, [
656
+ createElementVNode("span", _hoisted_14, toDisplayString(filteredEmpty.value ? unref(text).noMatch : __props.emptyLabel ?? unref(text).empty), 1),
657
+ filteredEmpty.value && term.value ? (openBlock(), createElementBlock("span", _hoisted_15, "“" + toDisplayString(term.value) + "”", 1)) : createCommentVNode("", true)
431
658
  ])) : (openBlock(), createElementBlock(Fragment, { key: 1 }, [
432
- __props.loadingOlder ? (openBlock(), createElementBlock("div", _hoisted_5, [
433
- createVNode(_sfc_main$2, {
659
+ __props.loadingOlder ? (openBlock(), createElementBlock("div", _hoisted_16, [
660
+ createVNode(_sfc_main$1, {
434
661
  name: "lucide:loader-circle",
435
662
  size: 14,
436
663
  class: "animate-spin"
437
664
  }),
438
- _cache[2] || (_cache[2] = createElementVNode("span", { class: "text-[11px]" }, "loading older…", -1))
665
+ createElementVNode("span", _hoisted_17, toDisplayString(unref(text).loadingOlder), 1)
439
666
  ])) : createCommentVNode("", true),
440
667
  createVNode(_sfc_main$3, {
441
668
  items: menuItems.value,
@@ -455,50 +682,51 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
455
682
  }, null, 4)) : createCommentVNode("", true),
456
683
  (openBlock(true), createElementBlock(Fragment, null, renderList(renderedLines.value, ({ line, n, count }) => {
457
684
  return openBlock(), createElementBlock("li", {
458
- key: n,
685
+ key: lineKey(n),
459
686
  "data-log-row": n,
460
- class: normalizeClass(["group relative flex items-start gap-0 px-0 leading-5 transition-colors hover:bg-surface-soft/60", metaFor(line.level).sel])
687
+ class: normalizeClass(["group relative flex items-start gap-0 px-0 leading-5 transition-colors hover:bg-surface-soft/60", [metaFor(line.level).sel, n === currentRow.value ? "bg-accent/15" : ""]]),
688
+ "aria-current": n === currentRow.value ? "true" : void 0
461
689
  }, [
462
690
  createElementVNode("span", {
463
691
  class: normalizeClass(["absolute inset-y-0 left-0 w-0.5", metaFor(line.level).rail]),
464
692
  "aria-hidden": "true"
465
693
  }, null, 2),
466
- _cache[3] || (_cache[3] = createElementVNode("span", {
694
+ _cache[6] || (_cache[6] = createElementVNode("span", {
467
695
  class: "mr-2 w-0.5 shrink-0",
468
696
  "aria-hidden": "true"
469
697
  }, null, -1)),
470
- __props.lineNumbers ? (openBlock(), createElementBlock("span", _hoisted_7, toDisplayString(n + 1), 1)) : createCommentVNode("", true),
471
- __props.showTime ? (openBlock(), createElementBlock("span", _hoisted_8, toDisplayString(fmtTime(line.time)), 1)) : createCommentVNode("", true),
698
+ __props.lineNumbers ? (openBlock(), createElementBlock("span", _hoisted_19, toDisplayString(n + lineOffset.value + 1), 1)) : createCommentVNode("", true),
699
+ __props.showTime ? (openBlock(), createElementBlock("span", _hoisted_20, toDisplayString(fmtTime(line.time)), 1)) : createCommentVNode("", true),
472
700
  __props.showLevel ? (openBlock(), createElementBlock("span", {
473
701
  key: 2,
474
702
  class: normalizeClass(["mr-3 w-12 shrink-0 text-[10px] font-semibold uppercase tracking-[0.06em]", metaFor(line.level).chip])
475
703
  }, toDisplayString(line.level ?? "info"), 3)) : createCommentVNode("", true),
476
- line.source ? (openBlock(), createElementBlock("span", _hoisted_9, "[" + toDisplayString(line.source) + "]", 1)) : createCommentVNode("", true),
704
+ line.source ? (openBlock(), createElementBlock("span", _hoisted_21, "[" + toDisplayString(line.source) + "]", 1)) : createCommentVNode("", true),
477
705
  createElementVNode("span", {
478
706
  class: normalizeClass(["min-w-0 pr-3", [metaFor(line.level).text, __props.wrap ? "whitespace-pre-wrap break-words" : "whitespace-pre"]])
479
707
  }, [
480
- (openBlock(true), createElementBlock(Fragment, null, renderList(splitHighlight(line.message), (part, p) => {
708
+ (openBlock(true), createElementBlock(Fragment, null, renderList(splitHighlight(virtualise.value ? line.message.replace(/\r?\n/g, " ↵ ") : line.message), (part, p) => {
481
709
  return openBlock(), createElementBlock(Fragment, { key: p }, [
482
- part.hit ? (openBlock(), createElementBlock("mark", _hoisted_10, toDisplayString(part.text), 1)) : (openBlock(), createElementBlock(Fragment, { key: 1 }, [
710
+ part.hit ? (openBlock(), createElementBlock("mark", _hoisted_22, toDisplayString(part.text), 1)) : (openBlock(), createElementBlock(Fragment, { key: 1 }, [
483
711
  createTextVNode(toDisplayString(part.text), 1)
484
712
  ], 64))
485
713
  ], 64);
486
714
  }), 128)),
487
715
  createVNode(Transition, {
488
- "enter-active-class": "inline-block transition duration-200 ease-[var(--ease-emphasized)]",
716
+ "enter-active-class": "transition duration-[var(--duration-medium)] ease-[var(--ease-emphasized)]",
489
717
  "enter-from-class": "scale-50 opacity-0"
490
718
  }, {
491
719
  default: withCtx(() => [
492
720
  count > 1 ? (openBlock(), createElementBlock("span", {
493
721
  key: count,
494
- class: "ml-2 select-none rounded-pill bg-surface-soft px-1.5 align-[1px] text-[10px] font-semibold tabular-nums text-muted-strong",
495
- title: `${count} identical lines`
496
- }, "×" + toDisplayString(count), 9, _hoisted_11)) : createCommentVNode("", true)
722
+ class: "ml-2 inline-block select-none rounded-pill bg-surface-soft px-1.5 align-[1px] text-[10px] font-semibold tabular-nums text-muted-strong",
723
+ title: unref(text).identical.replace("{n}", String(count))
724
+ }, "×" + toDisplayString(count), 9, _hoisted_23)) : createCommentVNode("", true)
497
725
  ]),
498
726
  _: 2
499
727
  }, 1024)
500
728
  ], 2)
501
- ], 10, _hoisted_6);
729
+ ], 10, _hoisted_18);
502
730
  }), 128)),
503
731
  virtualise.value && padBottom.value > 0 ? (openBlock(), createElementBlock("li", {
504
732
  key: "pad-bottom",
@@ -516,24 +744,24 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
516
744
  _: 1
517
745
  }, 8, ["content-class", "style"]),
518
746
  createVNode(Transition, {
519
- "enter-active-class": "transition duration-200 ease-[var(--ease-emphasized)]",
747
+ "enter-active-class": "transition duration-[var(--duration-medium)] ease-[var(--ease-emphasized)]",
520
748
  "enter-from-class": "translate-y-3 scale-90 opacity-0",
521
- "leave-active-class": "transition duration-150 ease-in",
749
+ "leave-active-class": "transition duration-[var(--duration-fast)] ease-in",
522
750
  "leave-to-class": "translate-y-3 scale-90 opacity-0"
523
751
  }, {
524
752
  default: withCtx(() => [
525
- showJump.value ? (openBlock(), createElementBlock("div", _hoisted_12, [
753
+ showJump.value ? (openBlock(), createElementBlock("div", _hoisted_24, [
526
754
  createElementVNode("button", {
527
755
  type: "button",
528
756
  class: "group flex items-center gap-1.5 rounded-pill border border-line bg-surface-overlay px-3 py-1 text-xs font-medium text-ink shadow-[var(--shadow-panel)] backdrop-blur outline-none transition-colors hover:bg-surface-soft focus-visible:ring-2 focus-visible:ring-ring",
529
757
  onClick: scrollToBottom
530
758
  }, [
531
- createVNode(_sfc_main$2, {
759
+ createVNode(_sfc_main$1, {
532
760
  name: "lucide:arrow-down",
533
761
  size: 14,
534
- class: "transition-transform duration-200 ease-[var(--ease-emphasized)] group-hover:translate-y-0.5"
762
+ class: "transition-transform duration-[var(--duration-medium)] ease-[var(--ease-emphasized)] group-hover:translate-y-0.5"
535
763
  }),
536
- _cache[4] || (_cache[4] = createTextVNode(" Jump to latest ", -1))
764
+ createTextVNode(" " + toDisplayString(unref(text).jump), 1)
537
765
  ])
538
766
  ])) : createCommentVNode("", true)
539
767
  ]),