@sakoa/ui 0.1.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 (345) hide show
  1. package/README.md +171 -0
  2. package/dist/App.d.ts +2 -0
  3. package/dist/cli/index.js +9243 -0
  4. package/dist/components/DemoSection.d.ts +30 -0
  5. package/dist/components/SApiKeyboard.d.ts +22 -0
  6. package/dist/components/SApiSection.d.ts +21 -0
  7. package/dist/components/SApiTable.d.ts +46 -0
  8. package/dist/components/STableOfContents.d.ts +2 -0
  9. package/dist/components/ui/SAlert.d.ts +76 -0
  10. package/dist/components/ui/SBadge.d.ts +56 -0
  11. package/dist/components/ui/SButton.d.ts +67 -0
  12. package/dist/components/ui/SCheckbox.d.ts +64 -0
  13. package/dist/components/ui/SChip.d.ts +43 -0
  14. package/dist/components/ui/SDatePicker.d.ts +77 -0
  15. package/dist/components/ui/SGlassButton.d.ts +70 -0
  16. package/dist/components/ui/SIcon.d.ts +29 -0
  17. package/dist/components/ui/SInput.d.ts +129 -0
  18. package/dist/components/ui/SKbd.d.ts +24 -0
  19. package/dist/components/ui/SKbdShortcut.d.ts +14 -0
  20. package/dist/components/ui/SSelect.d.ts +148 -0
  21. package/dist/components/ui/SSkeleton.d.ts +37 -0
  22. package/dist/components/ui/SSwitch.d.ts +61 -0
  23. package/dist/components/ui/STooltip.d.ts +82 -0
  24. package/dist/components/ui/accordion/SAccordionContent.d.ts +23 -0
  25. package/dist/components/ui/accordion/SAccordionItem.d.ts +70 -0
  26. package/dist/components/ui/accordion/SAccordionTrigger.d.ts +37 -0
  27. package/dist/components/ui/accordion/index.d.ts +4 -0
  28. package/dist/components/ui/avatar/SAvatar.d.ts +36 -0
  29. package/dist/components/ui/avatar/SAvatarFallback.d.ts +26 -0
  30. package/dist/components/ui/avatar/SAvatarGroup.d.ts +30 -0
  31. package/dist/components/ui/avatar/SAvatarImage.d.ts +23 -0
  32. package/dist/components/ui/avatar/index.d.ts +4 -0
  33. package/dist/components/ui/breadcrumb/SBreadcrumb.d.ts +22 -0
  34. package/dist/components/ui/breadcrumb/SBreadcrumbEllipsis.d.ts +17 -0
  35. package/dist/components/ui/breadcrumb/SBreadcrumbItem.d.ts +17 -0
  36. package/dist/components/ui/breadcrumb/SBreadcrumbLink.d.ts +26 -0
  37. package/dist/components/ui/breadcrumb/SBreadcrumbList.d.ts +17 -0
  38. package/dist/components/ui/breadcrumb/SBreadcrumbPage.d.ts +17 -0
  39. package/dist/components/ui/breadcrumb/SBreadcrumbSeparator.d.ts +17 -0
  40. package/dist/components/ui/breadcrumb/index.d.ts +7 -0
  41. package/dist/components/ui/card/SCard.d.ts +103 -0
  42. package/dist/components/ui/card/SCardActions.d.ts +44 -0
  43. package/dist/components/ui/card/SCardContent.d.ts +35 -0
  44. package/dist/components/ui/card/SCardFooter.d.ts +38 -0
  45. package/dist/components/ui/card/SCardHeader.d.ts +53 -0
  46. package/dist/components/ui/card/SCardMedia.d.ts +83 -0
  47. package/dist/components/ui/card/SGlassCard.d.ts +103 -0
  48. package/dist/components/ui/card/SMorphingCardContent.d.ts +18 -0
  49. package/dist/components/ui/card/index.d.ts +24 -0
  50. package/dist/components/ui/carousel/SCarousel.d.ts +166 -0
  51. package/dist/components/ui/carousel/index.d.ts +2 -0
  52. package/dist/components/ui/color-picker/SColorPickerAlphaSlider.d.ts +4 -0
  53. package/dist/components/ui/color-picker/SColorPickerCopy.d.ts +19 -0
  54. package/dist/components/ui/color-picker/SColorPickerEyeDropper.d.ts +17 -0
  55. package/dist/components/ui/color-picker/SColorPickerHueSlider.d.ts +4 -0
  56. package/dist/components/ui/color-picker/SColorPickerInputs.d.ts +2 -0
  57. package/dist/components/ui/color-picker/SColorPickerPresets.d.ts +9 -0
  58. package/dist/components/ui/color-picker/SColorPickerPreview.d.ts +2 -0
  59. package/dist/components/ui/color-picker/SColorPickerRecent.d.ts +7 -0
  60. package/dist/components/ui/color-picker/SColorPickerSpectrum.d.ts +4 -0
  61. package/dist/components/ui/color-picker/index.d.ts +11 -0
  62. package/dist/components/ui/drawer/index.d.ts +11 -0
  63. package/dist/components/ui/dropdown/SDropdownDivider.d.ts +8 -0
  64. package/dist/components/ui/dropdown/SDropdownGroup.d.ts +25 -0
  65. package/dist/components/ui/dropdown/SDropdownItem.d.ts +56 -0
  66. package/dist/components/ui/dropdown/index.d.ts +4 -0
  67. package/dist/components/ui/form/SForm.d.ts +38 -0
  68. package/dist/components/ui/form/SFormField.d.ts +31 -0
  69. package/dist/components/ui/form/index.d.ts +5 -0
  70. package/dist/components/ui/modal/index.d.ts +19 -0
  71. package/dist/components/ui/option/SOption.d.ts +32 -0
  72. package/dist/components/ui/option/SOptionGroup.d.ts +28 -0
  73. package/dist/components/ui/option/index.d.ts +2 -0
  74. package/dist/components/ui/otp/SOTP.d.ts +122 -0
  75. package/dist/components/ui/otp/SOTPGroup.d.ts +23 -0
  76. package/dist/components/ui/otp/SOTPSeparator.d.ts +17 -0
  77. package/dist/components/ui/otp/SOTPSlot.d.ts +49 -0
  78. package/dist/components/ui/otp/index.d.ts +7 -0
  79. package/dist/components/ui/otp/types.d.ts +26 -0
  80. package/dist/components/ui/otp/useOTPContext.d.ts +42 -0
  81. package/dist/components/ui/pagination/SPagination.d.ts +151 -0
  82. package/dist/components/ui/pagination/index.d.ts +2 -0
  83. package/dist/components/ui/progress/SProgress.d.ts +62 -0
  84. package/dist/components/ui/progress/SProgressRange.d.ts +91 -0
  85. package/dist/components/ui/progress/index.d.ts +4 -0
  86. package/dist/components/ui/radio/SRadio.d.ts +58 -0
  87. package/dist/components/ui/radio/SRadioGroup.d.ts +52 -0
  88. package/dist/components/ui/radio/index.d.ts +2 -0
  89. package/dist/components/ui/stepper/SStepper.d.ts +83 -0
  90. package/dist/components/ui/stepper/SStepperContent.d.ts +24 -0
  91. package/dist/components/ui/stepper/SStepperDescription.d.ts +20 -0
  92. package/dist/components/ui/stepper/SStepperIndicator.d.ts +37 -0
  93. package/dist/components/ui/stepper/SStepperItem.d.ts +37 -0
  94. package/dist/components/ui/stepper/SStepperSeparator.d.ts +5 -0
  95. package/dist/components/ui/stepper/SStepperTitle.d.ts +20 -0
  96. package/dist/components/ui/stepper/SStepperTrigger.d.ts +22 -0
  97. package/dist/components/ui/stepper/index.d.ts +11 -0
  98. package/dist/components/ui/table/STableBody.d.ts +27 -0
  99. package/dist/components/ui/table/STableCell.d.ts +55 -0
  100. package/dist/components/ui/table/STableColumn.d.ts +87 -0
  101. package/dist/components/ui/table/STableEmpty.d.ts +54 -0
  102. package/dist/components/ui/table/STableHeader.d.ts +25 -0
  103. package/dist/components/ui/table/STableRow.d.ts +38 -0
  104. package/dist/components/ui/table/STableSkeleton.d.ts +29 -0
  105. package/dist/components/ui/table/index.d.ts +98 -0
  106. package/dist/components/ui/table/useDataTable.d.ts +80 -0
  107. package/dist/components/ui/tabs/STabPane.d.ts +31 -0
  108. package/dist/components/ui/tabs/STabsContent.d.ts +21 -0
  109. package/dist/components/ui/tabs/STabsIndicator.d.ts +9 -0
  110. package/dist/components/ui/tabs/STabsTrigger.d.ts +28 -0
  111. package/dist/components/ui/tabs/index.d.ts +6 -0
  112. package/dist/components/ui/toast/SToast.d.ts +49 -0
  113. package/dist/components/ui/toast/SToastContainer.d.ts +21 -0
  114. package/dist/components/ui/toast/index.d.ts +2 -0
  115. package/dist/composables/useAsync.d.ts +134 -0
  116. package/dist/composables/useClickOutside.d.ts +69 -0
  117. package/dist/composables/useClipboard.d.ts +46 -0
  118. package/dist/composables/useDebounce.d.ts +150 -0
  119. package/dist/composables/useDialog.d.ts +118 -0
  120. package/dist/composables/useForm.d.ts +204 -0
  121. package/dist/composables/useHotkey.d.ts +128 -0
  122. package/dist/composables/useIntersectionObserver.d.ts +156 -0
  123. package/dist/composables/useLocalStorage.d.ts +120 -0
  124. package/dist/composables/useMediaQuery.d.ts +115 -0
  125. package/dist/composables/useTheme.d.ts +8 -0
  126. package/dist/composables/useToast.d.ts +1619 -0
  127. package/dist/index.d.ts +71 -0
  128. package/dist/layouts/UILayout.d.ts +2 -0
  129. package/dist/lib/utils.d.ts +2 -0
  130. package/dist/main.d.ts +0 -0
  131. package/dist/router.d.ts +2 -0
  132. package/dist/saka-ui.css +1 -0
  133. package/dist/saka-ui.js +18513 -0
  134. package/dist/saka-ui.umd.cjs +38 -0
  135. package/dist/views/docs/CustomizationView.d.ts +2 -0
  136. package/dist/views/docs/FormValidationView.d.ts +2 -0
  137. package/dist/views/docs/StylingGuideView.d.ts +2 -0
  138. package/dist/views/docs/UseAsyncView.d.ts +2 -0
  139. package/dist/views/docs/UseClickOutsideView.d.ts +124 -0
  140. package/dist/views/docs/UseClipboardView.d.ts +4 -0
  141. package/dist/views/docs/UseDebounceView.d.ts +2 -0
  142. package/dist/views/docs/UseHotkeyView.d.ts +205 -0
  143. package/dist/views/docs/UseIntersectionObserverView.d.ts +5 -0
  144. package/dist/views/docs/UseLocalStorageView.d.ts +2 -0
  145. package/dist/views/docs/UseMediaQueryView.d.ts +2 -0
  146. package/dist/views/docs/UseThemeView.d.ts +2 -0
  147. package/dist/views/examples/AuthFormView.d.ts +2 -0
  148. package/dist/views/examples/CreditCardFormView.d.ts +6 -0
  149. package/dist/views/examples/FormFieldExampleView.d.ts +2 -0
  150. package/dist/views/examples/ProjectFormView.d.ts +2 -0
  151. package/dist/views/ui/AccordionView.d.ts +2 -0
  152. package/dist/views/ui/AlertView.d.ts +2 -0
  153. package/dist/views/ui/AvatarView.d.ts +2 -0
  154. package/dist/views/ui/BadgeView.d.ts +2 -0
  155. package/dist/views/ui/BreadcrumbView.d.ts +2 -0
  156. package/dist/views/ui/ButtonView.d.ts +2 -0
  157. package/dist/views/ui/CardView.d.ts +2 -0
  158. package/dist/views/ui/CarouselView.d.ts +274 -0
  159. package/dist/views/ui/CheckboxView.d.ts +2 -0
  160. package/dist/views/ui/ChipView.d.ts +2 -0
  161. package/dist/views/ui/ColorPickerView.d.ts +2 -0
  162. package/dist/views/ui/DatePickerView.d.ts +2 -0
  163. package/dist/views/ui/DialogView.d.ts +2 -0
  164. package/dist/views/ui/DrawerView.d.ts +2 -0
  165. package/dist/views/ui/DropdownView.d.ts +2 -0
  166. package/dist/views/ui/GlassButtonView.d.ts +2 -0
  167. package/dist/views/ui/GlassCardView.d.ts +2 -0
  168. package/dist/views/ui/HomeView.d.ts +2 -0
  169. package/dist/views/ui/IconsView.d.ts +2 -0
  170. package/dist/views/ui/InputView.d.ts +2 -0
  171. package/dist/views/ui/KbdView.d.ts +2 -0
  172. package/dist/views/ui/ModalView.d.ts +2 -0
  173. package/dist/views/ui/MorphingCardView.d.ts +2 -0
  174. package/dist/views/ui/MorphingModalView.d.ts +2 -0
  175. package/dist/views/ui/OTPView.d.ts +206 -0
  176. package/dist/views/ui/PaginationView.d.ts +2 -0
  177. package/dist/views/ui/ProgressView.d.ts +2 -0
  178. package/dist/views/ui/RadioView.d.ts +2 -0
  179. package/dist/views/ui/SelectView.d.ts +2 -0
  180. package/dist/views/ui/SkeletonView.d.ts +2 -0
  181. package/dist/views/ui/StepperView.d.ts +2 -0
  182. package/dist/views/ui/SwitchView.d.ts +2 -0
  183. package/dist/views/ui/TableView.d.ts +2 -0
  184. package/dist/views/ui/TabsView.d.ts +2 -0
  185. package/dist/views/ui/ToastView.d.ts +2 -0
  186. package/dist/views/ui/TooltipView.d.ts +2 -0
  187. package/dist/vite.svg +1 -0
  188. package/package.json +64 -0
  189. package/registry/components/accordion.json +19 -0
  190. package/registry/components/alert.json +17 -0
  191. package/registry/components/avatar.json +18 -0
  192. package/registry/components/badge.json +14 -0
  193. package/registry/components/breadcrumb.json +24 -0
  194. package/registry/components/button.json +17 -0
  195. package/registry/components/card.json +23 -0
  196. package/registry/components/carousel.json +19 -0
  197. package/registry/components/checkbox.json +17 -0
  198. package/registry/components/chip.json +17 -0
  199. package/registry/components/color-picker.json +24 -0
  200. package/registry/components/date-picker.json +17 -0
  201. package/registry/components/drawer.json +26 -0
  202. package/registry/components/dropdown.json +21 -0
  203. package/registry/components/form.json +16 -0
  204. package/registry/components/glass-button.json +17 -0
  205. package/registry/components/icon.json +17 -0
  206. package/registry/components/input.json +17 -0
  207. package/registry/components/kbd.json +16 -0
  208. package/registry/components/modal.json +32 -0
  209. package/registry/components/option.json +16 -0
  210. package/registry/components/otp.json +23 -0
  211. package/registry/components/pagination.json +18 -0
  212. package/registry/components/progress.json +16 -0
  213. package/registry/components/radio.json +19 -0
  214. package/registry/components/select.json +17 -0
  215. package/registry/components/skeleton.json +14 -0
  216. package/registry/components/switch.json +17 -0
  217. package/registry/components/table.json +26 -0
  218. package/registry/components/tabs.json +19 -0
  219. package/registry/components/toast.json +19 -0
  220. package/registry/components/tooltip.json +14 -0
  221. package/registry/index.json +4 -0
  222. package/registry/source/components/ui/SAlert.vue +388 -0
  223. package/registry/source/components/ui/SBadge.vue +243 -0
  224. package/registry/source/components/ui/SButton.vue +387 -0
  225. package/registry/source/components/ui/SCheckbox.vue +310 -0
  226. package/registry/source/components/ui/SChip.vue +130 -0
  227. package/registry/source/components/ui/SDatePicker.vue +1290 -0
  228. package/registry/source/components/ui/SGlassButton.vue +547 -0
  229. package/registry/source/components/ui/SIcon.vue +78 -0
  230. package/registry/source/components/ui/SInput.vue +1054 -0
  231. package/registry/source/components/ui/SKbd.vue +96 -0
  232. package/registry/source/components/ui/SKbdShortcut.vue +36 -0
  233. package/registry/source/components/ui/SSelect.vue +1290 -0
  234. package/registry/source/components/ui/SSkeleton.vue +185 -0
  235. package/registry/source/components/ui/SSwitch.vue +275 -0
  236. package/registry/source/components/ui/STooltip.vue +491 -0
  237. package/registry/source/components/ui/accordion/SAccordion.vue +248 -0
  238. package/registry/source/components/ui/accordion/SAccordionItem.vue +353 -0
  239. package/registry/source/components/ui/accordion/index.ts +5 -0
  240. package/registry/source/components/ui/avatar/SAvatar.vue +169 -0
  241. package/registry/source/components/ui/avatar/SAvatarFallback.vue +66 -0
  242. package/registry/source/components/ui/avatar/SAvatarGroup.vue +69 -0
  243. package/registry/source/components/ui/avatar/SAvatarImage.vue +92 -0
  244. package/registry/source/components/ui/avatar/index.ts +5 -0
  245. package/registry/source/components/ui/breadcrumb/SBreadcrumb.vue +23 -0
  246. package/registry/source/components/ui/breadcrumb/SBreadcrumbEllipsis.vue +17 -0
  247. package/registry/source/components/ui/breadcrumb/SBreadcrumbItem.vue +14 -0
  248. package/registry/source/components/ui/breadcrumb/SBreadcrumbLink.vue +46 -0
  249. package/registry/source/components/ui/breadcrumb/SBreadcrumbList.vue +17 -0
  250. package/registry/source/components/ui/breadcrumb/SBreadcrumbPage.vue +15 -0
  251. package/registry/source/components/ui/breadcrumb/SBreadcrumbSeparator.vue +18 -0
  252. package/registry/source/components/ui/breadcrumb/index.ts +7 -0
  253. package/registry/source/components/ui/card/SCard.vue +517 -0
  254. package/registry/source/components/ui/card/SCardActions.vue +129 -0
  255. package/registry/source/components/ui/card/SCardContent.vue +117 -0
  256. package/registry/source/components/ui/card/SCardFooter.vue +103 -0
  257. package/registry/source/components/ui/card/SCardHeader.vue +163 -0
  258. package/registry/source/components/ui/card/SCardMedia.vue +312 -0
  259. package/registry/source/components/ui/card/index.ts +34 -0
  260. package/registry/source/components/ui/carousel/SCarousel.vue +1069 -0
  261. package/registry/source/components/ui/carousel/SCarouselSlide.vue +107 -0
  262. package/registry/source/components/ui/carousel/index.ts +3 -0
  263. package/registry/source/components/ui/color-picker/SColorPicker.vue +772 -0
  264. package/registry/source/components/ui/color-picker/SColorPickerAlphaSlider.vue +158 -0
  265. package/registry/source/components/ui/color-picker/SColorPickerCopy.vue +76 -0
  266. package/registry/source/components/ui/color-picker/SColorPickerEyeDropper.vue +68 -0
  267. package/registry/source/components/ui/color-picker/SColorPickerHueSlider.vue +138 -0
  268. package/registry/source/components/ui/color-picker/SColorPickerInputs.vue +227 -0
  269. package/registry/source/components/ui/color-picker/SColorPickerPresets.vue +87 -0
  270. package/registry/source/components/ui/color-picker/SColorPickerPreview.vue +46 -0
  271. package/registry/source/components/ui/color-picker/SColorPickerRecent.vue +74 -0
  272. package/registry/source/components/ui/color-picker/SColorPickerSpectrum.vue +149 -0
  273. package/registry/source/components/ui/color-picker/index.ts +11 -0
  274. package/registry/source/components/ui/drawer/SDrawer.vue +797 -0
  275. package/registry/source/components/ui/drawer/SDrawerClose.vue +64 -0
  276. package/registry/source/components/ui/drawer/SDrawerContent.vue +81 -0
  277. package/registry/source/components/ui/drawer/SDrawerDescription.vue +40 -0
  278. package/registry/source/components/ui/drawer/SDrawerFooter.vue +97 -0
  279. package/registry/source/components/ui/drawer/SDrawerHandle.vue +79 -0
  280. package/registry/source/components/ui/drawer/SDrawerHeader.vue +117 -0
  281. package/registry/source/components/ui/drawer/SDrawerTitle.vue +40 -0
  282. package/registry/source/components/ui/drawer/SDrawerTrigger.vue +51 -0
  283. package/registry/source/components/ui/drawer/index.ts +20 -0
  284. package/registry/source/components/ui/dropdown/SDropdown.vue +843 -0
  285. package/registry/source/components/ui/dropdown/SDropdownDivider.vue +23 -0
  286. package/registry/source/components/ui/dropdown/SDropdownGroup.vue +53 -0
  287. package/registry/source/components/ui/dropdown/SDropdownItem.vue +179 -0
  288. package/registry/source/components/ui/dropdown/index.ts +5 -0
  289. package/registry/source/components/ui/form/SForm.vue +84 -0
  290. package/registry/source/components/ui/form/SFormField.vue +78 -0
  291. package/registry/source/components/ui/form/index.ts +8 -0
  292. package/registry/source/components/ui/modal/SModal.vue +648 -0
  293. package/registry/source/components/ui/modal/SModalClose.vue +49 -0
  294. package/registry/source/components/ui/modal/SModalContent.vue +74 -0
  295. package/registry/source/components/ui/modal/SModalDescription.vue +39 -0
  296. package/registry/source/components/ui/modal/SModalFooter.vue +84 -0
  297. package/registry/source/components/ui/modal/SModalHeader.vue +107 -0
  298. package/registry/source/components/ui/modal/SModalTitle.vue +39 -0
  299. package/registry/source/components/ui/modal/SModalTrigger.vue +61 -0
  300. package/registry/source/components/ui/modal/SMorphingModal.vue +429 -0
  301. package/registry/source/components/ui/modal/SMorphingModalClose.vue +42 -0
  302. package/registry/source/components/ui/modal/SMorphingModalDescription.vue +49 -0
  303. package/registry/source/components/ui/modal/SMorphingModalImage.vue +44 -0
  304. package/registry/source/components/ui/modal/SMorphingModalSubtitle.vue +29 -0
  305. package/registry/source/components/ui/modal/SMorphingModalTitle.vue +34 -0
  306. package/registry/source/components/ui/modal/SMorphingModalTrigger.vue +95 -0
  307. package/registry/source/components/ui/modal/index.ts +32 -0
  308. package/registry/source/components/ui/option/SOption.vue +180 -0
  309. package/registry/source/components/ui/option/SOptionGroup.vue +77 -0
  310. package/registry/source/components/ui/option/index.ts +3 -0
  311. package/registry/source/components/ui/otp/SOTP.vue +843 -0
  312. package/registry/source/components/ui/otp/SOTPGroup.vue +29 -0
  313. package/registry/source/components/ui/otp/SOTPSeparator.vue +15 -0
  314. package/registry/source/components/ui/otp/SOTPSlot.vue +462 -0
  315. package/registry/source/components/ui/otp/index.ts +7 -0
  316. package/registry/source/components/ui/otp/types.ts +27 -0
  317. package/registry/source/components/ui/otp/useOTPContext.ts +62 -0
  318. package/registry/source/components/ui/pagination/SPagination.vue +923 -0
  319. package/registry/source/components/ui/pagination/index.ts +8 -0
  320. package/registry/source/components/ui/progress/SProgress.vue +635 -0
  321. package/registry/source/components/ui/progress/SProgressRange.vue +715 -0
  322. package/registry/source/components/ui/progress/index.ts +4 -0
  323. package/registry/source/components/ui/radio/SRadio.vue +407 -0
  324. package/registry/source/components/ui/radio/SRadioGroup.vue +200 -0
  325. package/registry/source/components/ui/radio/index.ts +3 -0
  326. package/registry/source/components/ui/table/SDataTable.vue +828 -0
  327. package/registry/source/components/ui/table/STableBody.vue +70 -0
  328. package/registry/source/components/ui/table/STableCell.vue +147 -0
  329. package/registry/source/components/ui/table/STableColumn.vue +120 -0
  330. package/registry/source/components/ui/table/STableEmpty.vue +159 -0
  331. package/registry/source/components/ui/table/STableHeader.vue +132 -0
  332. package/registry/source/components/ui/table/STableRow.vue +106 -0
  333. package/registry/source/components/ui/table/STableSkeleton.vue +208 -0
  334. package/registry/source/components/ui/table/index.ts +126 -0
  335. package/registry/source/components/ui/table/useDataTable.ts +519 -0
  336. package/registry/source/components/ui/tabs/STabPane.vue +130 -0
  337. package/registry/source/components/ui/tabs/STabs.vue +467 -0
  338. package/registry/source/components/ui/tabs/index.ts +7 -0
  339. package/registry/source/components/ui/toast/SToast.vue +261 -0
  340. package/registry/source/components/ui/toast/SToastContainer.vue +209 -0
  341. package/registry/source/components/ui/toast/index.ts +2 -0
  342. package/registry/source/composables/useForm.ts +960 -0
  343. package/registry/source/composables/useTheme.ts +86 -0
  344. package/registry/source/composables/useToast.ts +440 -0
  345. package/registry/source/lib/utils.ts +6 -0
@@ -0,0 +1,715 @@
1
+ <script setup lang="ts">
2
+ defineOptions({ inheritAttrs: false })
3
+
4
+ import { computed, ref, watch, onMounted, onUnmounted } from 'vue'
5
+ import { cn } from '../../../lib/utils'
6
+
7
+ export interface RangeValue {
8
+ min: number
9
+ max: number
10
+ }
11
+
12
+ export interface Props {
13
+ // Core
14
+ modelValue?: number | RangeValue
15
+ min?: number
16
+ max?: number
17
+ step?: number
18
+ range?: boolean // Enable dual-handle range mode
19
+
20
+ // Visual
21
+ size?: 'small' | 'medium' | 'large'
22
+ orientation?: 'horizontal' | 'vertical'
23
+ rounded?: 'none' | 'sm' | 'md' | 'lg' | 'full'
24
+ color?: string
25
+ trackColor?: string
26
+ activeTrackColor?: string
27
+ handleColor?: string
28
+
29
+ // Display
30
+ showValue?: boolean
31
+ showTooltip?: boolean
32
+ tooltipPosition?: 'top' | 'bottom'
33
+ showTicks?: boolean
34
+ tickCount?: number
35
+ showLabels?: boolean
36
+ valueFormat?: (value: number) => string
37
+ minLabel?: string
38
+ maxLabel?: string
39
+ label?: string
40
+
41
+ // Behavior
42
+ disabled?: boolean
43
+ readonly?: boolean
44
+ pushable?: number // Minimum distance between handles in range mode
45
+ maxRange?: number // Maximum distance between handles in range mode
46
+ swappable?: boolean // Allow handles to swap positions when crossing
47
+ lazy?: boolean // Only emit on drag end
48
+ marks?: { value: number; label?: string }[]
49
+ snap?: boolean // Snap to marks/steps
50
+
51
+ // Styling
52
+ handleSize?: number
53
+ trackHeight?: number
54
+ }
55
+
56
+ const props = withDefaults(defineProps<Props>(), {
57
+ modelValue: 0,
58
+ min: 0,
59
+ max: 100,
60
+ step: 1,
61
+ range: false,
62
+ size: 'medium',
63
+ orientation: 'horizontal',
64
+ rounded: 'full',
65
+ color: 'var(--s-primary)',
66
+ trackColor: 'var(--s-accent)',
67
+ activeTrackColor: undefined,
68
+ handleColor: undefined,
69
+ showValue: false,
70
+ showTooltip: true,
71
+ tooltipPosition: 'top',
72
+ showTicks: false,
73
+ tickCount: 5,
74
+ showLabels: false,
75
+ valueFormat: undefined,
76
+ minLabel: undefined,
77
+ maxLabel: undefined,
78
+ label: undefined,
79
+ disabled: false,
80
+ readonly: false,
81
+ pushable: 0,
82
+ maxRange: undefined,
83
+ swappable: true,
84
+ lazy: false,
85
+ marks: undefined,
86
+ snap: false,
87
+ handleSize: undefined,
88
+ trackHeight: undefined
89
+ })
90
+
91
+ const emit = defineEmits<{
92
+ 'update:modelValue': [value: number | RangeValue]
93
+ 'change': [value: number | RangeValue]
94
+ 'drag-start': [handle: 'min' | 'max' | 'single']
95
+ 'drag-end': [value: number | RangeValue]
96
+ }>()
97
+
98
+ // Refs
99
+ const trackRef = ref<HTMLElement | null>(null)
100
+ const isDragging = ref(false)
101
+ const activeHandle = ref<'min' | 'max' | 'single' | null>(null)
102
+ const hoverHandle = ref<'min' | 'max' | 'single' | null>(null)
103
+
104
+ // Internal values
105
+ const internalMin = ref(0)
106
+ const internalMax = ref(100)
107
+
108
+ // Initialize values
109
+ const initValues = () => {
110
+ if (props.range && typeof props.modelValue === 'object') {
111
+ internalMin.value = (props.modelValue as RangeValue).min
112
+ internalMax.value = (props.modelValue as RangeValue).max
113
+ } else if (typeof props.modelValue === 'number') {
114
+ internalMin.value = props.modelValue
115
+ internalMax.value = props.modelValue
116
+ }
117
+ }
118
+
119
+ onMounted(() => {
120
+ initValues()
121
+ document.addEventListener('mousemove', handleMouseMove)
122
+ document.addEventListener('mouseup', handleMouseUp)
123
+ document.addEventListener('touchmove', handleTouchMove, { passive: false })
124
+ document.addEventListener('touchend', handleTouchEnd)
125
+ })
126
+
127
+ onUnmounted(() => {
128
+ document.removeEventListener('mousemove', handleMouseMove)
129
+ document.removeEventListener('mouseup', handleMouseUp)
130
+ document.removeEventListener('touchmove', handleTouchMove)
131
+ document.removeEventListener('touchend', handleTouchEnd)
132
+ })
133
+
134
+ watch(() => props.modelValue, () => {
135
+ if (!isDragging.value) {
136
+ initValues()
137
+ }
138
+ }, { deep: true })
139
+
140
+ // Computed
141
+ const sizeConfig = computed(() => {
142
+ const sizes = {
143
+ small: { track: 4, handle: 14, fontSize: 'text-xs' },
144
+ medium: { track: 6, handle: 18, fontSize: 'text-sm' },
145
+ large: { track: 8, handle: 24, fontSize: 'text-base' }
146
+ }
147
+ return sizes[props.size]
148
+ })
149
+
150
+ const trackHeightValue = computed(() => props.trackHeight || sizeConfig.value.track)
151
+ const handleSizeValue = computed(() => props.handleSize || sizeConfig.value.handle)
152
+
153
+ const roundedClasses = computed(() => {
154
+ const radii = {
155
+ none: 'rounded-none',
156
+ sm: 'rounded',
157
+ md: 'rounded-lg',
158
+ lg: 'rounded-xl',
159
+ full: 'rounded-full'
160
+ }
161
+ return radii[props.rounded]
162
+ })
163
+
164
+ const valueToPercent = (value: number): number => {
165
+ return ((value - props.min) / (props.max - props.min)) * 100
166
+ }
167
+
168
+ const percentToValue = (percent: number): number => {
169
+ let value = (percent / 100) * (props.max - props.min) + props.min
170
+ value = Math.round(value / props.step) * props.step
171
+ return Math.min(Math.max(value, props.min), props.max)
172
+ }
173
+
174
+ const minPercent = computed(() => valueToPercent(internalMin.value))
175
+ const maxPercent = computed(() => valueToPercent(internalMax.value))
176
+
177
+ const formatValue = (value: number): string => {
178
+ if (props.valueFormat) return props.valueFormat(value)
179
+ return value.toString()
180
+ }
181
+
182
+ // Calculate ticks
183
+ const ticks = computed(() => {
184
+ if (!props.showTicks && !props.marks) return []
185
+
186
+ if (props.marks) {
187
+ return props.marks.map(mark => ({
188
+ value: mark.value,
189
+ percent: valueToPercent(mark.value),
190
+ label: mark.label || formatValue(mark.value)
191
+ }))
192
+ }
193
+
194
+ const result = []
195
+ const step = (props.max - props.min) / (props.tickCount - 1)
196
+
197
+ for (let i = 0; i < props.tickCount; i++) {
198
+ const value = props.min + step * i
199
+ result.push({
200
+ value,
201
+ percent: valueToPercent(value),
202
+ label: formatValue(Math.round(value))
203
+ })
204
+ }
205
+
206
+ return result
207
+ })
208
+
209
+ // Track style
210
+ const activeTrackStyle = computed(() => {
211
+ if (props.range) {
212
+ return {
213
+ left: `${minPercent.value}%`,
214
+ width: `${maxPercent.value - minPercent.value}%`
215
+ }
216
+ }
217
+ return {
218
+ left: '0%',
219
+ width: `${minPercent.value}%`
220
+ }
221
+ })
222
+
223
+ // Event handlers
224
+ const getPercentFromEvent = (event: MouseEvent | Touch): number => {
225
+ if (!trackRef.value) return 0
226
+ const rect = trackRef.value.getBoundingClientRect()
227
+
228
+ if (props.orientation === 'vertical') {
229
+ const y = event.clientY - rect.top
230
+ return 100 - (y / rect.height) * 100
231
+ }
232
+
233
+ const x = event.clientX - rect.left
234
+ return (x / rect.width) * 100
235
+ }
236
+
237
+ const updateValue = (percent: number) => {
238
+ if (props.disabled || props.readonly) return
239
+
240
+ let newValue = percentToValue(Math.min(100, Math.max(0, percent)))
241
+
242
+ if (props.range) {
243
+ if (activeHandle.value === 'min') {
244
+ // Check if we should swap handles (when swappable and crossing over)
245
+ if (props.swappable && newValue > internalMax.value) {
246
+ // Swap: the min handle becomes max, max becomes min
247
+ const oldMax = internalMax.value
248
+ internalMax.value = newValue
249
+ internalMin.value = oldMax
250
+ activeHandle.value = 'max'
251
+ } else {
252
+ // Apply pushable constraint
253
+ const maxAllowed = internalMax.value - props.pushable
254
+ internalMin.value = Math.min(newValue, maxAllowed)
255
+ }
256
+
257
+ // Apply maxRange constraint
258
+ if (props.maxRange !== undefined) {
259
+ if (internalMax.value - internalMin.value > props.maxRange) {
260
+ if (activeHandle.value === 'min') {
261
+ internalMin.value = internalMax.value - props.maxRange
262
+ } else {
263
+ internalMax.value = internalMin.value + props.maxRange
264
+ }
265
+ }
266
+ }
267
+ } else if (activeHandle.value === 'max') {
268
+ // Check if we should swap handles (when swappable and crossing over)
269
+ if (props.swappable && newValue < internalMin.value) {
270
+ // Swap: the max handle becomes min, min becomes max
271
+ const oldMin = internalMin.value
272
+ internalMin.value = newValue
273
+ internalMax.value = oldMin
274
+ activeHandle.value = 'min'
275
+ } else {
276
+ // Apply pushable constraint
277
+ const minAllowed = internalMin.value + props.pushable
278
+ internalMax.value = Math.max(newValue, minAllowed)
279
+ }
280
+
281
+ // Apply maxRange constraint
282
+ if (props.maxRange !== undefined) {
283
+ if (internalMax.value - internalMin.value > props.maxRange) {
284
+ if (activeHandle.value === 'max') {
285
+ internalMax.value = internalMin.value + props.maxRange
286
+ } else {
287
+ internalMin.value = internalMax.value - props.maxRange
288
+ }
289
+ }
290
+ }
291
+ }
292
+
293
+ // Ensure values stay within bounds
294
+ internalMin.value = Math.max(props.min, Math.min(internalMin.value, props.max))
295
+ internalMax.value = Math.max(props.min, Math.min(internalMax.value, props.max))
296
+
297
+ if (!props.lazy || !isDragging.value) {
298
+ emit('update:modelValue', { min: internalMin.value, max: internalMax.value })
299
+ }
300
+ } else {
301
+ internalMin.value = newValue
302
+ if (!props.lazy || !isDragging.value) {
303
+ emit('update:modelValue', newValue)
304
+ }
305
+ }
306
+ }
307
+
308
+ const handleTrackClick = (event: MouseEvent) => {
309
+ if (props.disabled || props.readonly) return
310
+
311
+ const percent = getPercentFromEvent(event)
312
+ const clickValue = percentToValue(percent)
313
+
314
+ if (props.range) {
315
+ // Determine which handle to move
316
+ const minDist = Math.abs(clickValue - internalMin.value)
317
+ const maxDist = Math.abs(clickValue - internalMax.value)
318
+ activeHandle.value = minDist <= maxDist ? 'min' : 'max'
319
+ } else {
320
+ activeHandle.value = 'single'
321
+ }
322
+
323
+ updateValue(percent)
324
+ emit('change', props.range ? { min: internalMin.value, max: internalMax.value } : internalMin.value)
325
+ }
326
+
327
+ const handleMouseDown = (event: MouseEvent, handle: 'min' | 'max' | 'single') => {
328
+ if (props.disabled || props.readonly) return
329
+ event.preventDefault()
330
+ isDragging.value = true
331
+ activeHandle.value = handle
332
+ emit('drag-start', handle)
333
+ }
334
+
335
+ const handleMouseMove = (event: MouseEvent) => {
336
+ if (!isDragging.value || !activeHandle.value) return
337
+ const percent = getPercentFromEvent(event)
338
+ updateValue(percent)
339
+ }
340
+
341
+ const handleMouseUp = () => {
342
+ if (isDragging.value) {
343
+ isDragging.value = false
344
+ if (props.lazy) {
345
+ const value = props.range
346
+ ? { min: internalMin.value, max: internalMax.value }
347
+ : internalMin.value
348
+ emit('update:modelValue', value)
349
+ emit('change', value)
350
+ }
351
+ emit('drag-end', props.range ? { min: internalMin.value, max: internalMax.value } : internalMin.value)
352
+ activeHandle.value = null
353
+ }
354
+ }
355
+
356
+ const handleTouchStart = (event: TouchEvent, handle: 'min' | 'max' | 'single') => {
357
+ if (props.disabled || props.readonly) return
358
+ isDragging.value = true
359
+ activeHandle.value = handle
360
+ emit('drag-start', handle)
361
+ }
362
+
363
+ const handleTouchMove = (event: TouchEvent) => {
364
+ if (!isDragging.value || !activeHandle.value) return
365
+ event.preventDefault()
366
+ const percent = getPercentFromEvent(event.touches[0])
367
+ updateValue(percent)
368
+ }
369
+
370
+ const handleTouchEnd = () => {
371
+ handleMouseUp()
372
+ }
373
+
374
+ const handleKeyDown = (event: KeyboardEvent, handle: 'min' | 'max' | 'single') => {
375
+ if (props.disabled || props.readonly) return
376
+
377
+ let delta = 0
378
+ if (event.key === 'ArrowLeft' || event.key === 'ArrowDown') {
379
+ delta = -props.step
380
+ } else if (event.key === 'ArrowRight' || event.key === 'ArrowUp') {
381
+ delta = props.step
382
+ } else if (event.key === 'Home') {
383
+ delta = props.min - (handle === 'max' && props.range ? internalMax.value : internalMin.value)
384
+ } else if (event.key === 'End') {
385
+ delta = props.max - (handle === 'max' && props.range ? internalMax.value : internalMin.value)
386
+ }
387
+
388
+ if (delta !== 0) {
389
+ event.preventDefault()
390
+ activeHandle.value = handle
391
+
392
+ if (props.range) {
393
+ let newMin = internalMin.value
394
+ let newMax = internalMax.value
395
+
396
+ if (handle === 'min') {
397
+ newMin = internalMin.value + delta
398
+ // Check for swap
399
+ if (props.swappable && newMin > internalMax.value) {
400
+ const oldMax = internalMax.value
401
+ newMax = newMin
402
+ newMin = oldMax
403
+ } else {
404
+ newMin = Math.min(Math.max(newMin, props.min), internalMax.value - props.pushable)
405
+ }
406
+ } else {
407
+ newMax = internalMax.value + delta
408
+ // Check for swap
409
+ if (props.swappable && newMax < internalMin.value) {
410
+ const oldMin = internalMin.value
411
+ newMin = newMax
412
+ newMax = oldMin
413
+ } else {
414
+ newMax = Math.max(Math.min(newMax, props.max), internalMin.value + props.pushable)
415
+ }
416
+ }
417
+
418
+ // Apply maxRange constraint
419
+ if (props.maxRange !== undefined && newMax - newMin > props.maxRange) {
420
+ if (handle === 'min') {
421
+ newMin = newMax - props.maxRange
422
+ } else {
423
+ newMax = newMin + props.maxRange
424
+ }
425
+ }
426
+
427
+ // Clamp to bounds
428
+ newMin = Math.max(props.min, Math.min(newMin, props.max))
429
+ newMax = Math.max(props.min, Math.min(newMax, props.max))
430
+
431
+ internalMin.value = newMin
432
+ internalMax.value = newMax
433
+
434
+ emit('update:modelValue', { min: internalMin.value, max: internalMax.value })
435
+ emit('change', { min: internalMin.value, max: internalMax.value })
436
+ } else {
437
+ internalMin.value = Math.min(Math.max(internalMin.value + delta, props.min), props.max)
438
+ emit('update:modelValue', internalMin.value)
439
+ emit('change', internalMin.value)
440
+ }
441
+ }
442
+ }
443
+
444
+ // Computed z-index for handles - active/hovered handle should be on top
445
+ const minHandleZIndex = computed(() => {
446
+ if (activeHandle.value === 'min' || activeHandle.value === 'single') return 20
447
+ if (hoverHandle.value === 'min' || hoverHandle.value === 'single') return 15
448
+ return 10
449
+ })
450
+
451
+ const maxHandleZIndex = computed(() => {
452
+ if (activeHandle.value === 'max') return 20
453
+ if (hoverHandle.value === 'max') return 15
454
+ return 10
455
+ })
456
+ </script>
457
+
458
+ <template>
459
+ <div
460
+ v-bind="$attrs"
461
+ :class="cn(
462
+ 's-progress-range',
463
+ orientation === 'vertical' ? 'flex flex-col items-center' : 'w-full',
464
+ disabled && 'opacity-50 cursor-not-allowed',
465
+ $attrs.class ?? ''
466
+ )"
467
+ >
468
+ <!-- Label -->
469
+ <div
470
+ v-if="label || showValue"
471
+ class="flex items-center justify-between mb-2"
472
+ :class="sizeConfig.fontSize"
473
+ >
474
+ <span v-if="label" class="text-muted-foreground font-medium">{{ label }}</span>
475
+ <span
476
+ v-if="showValue && !range"
477
+ class="text-foreground font-semibold tabular-nums"
478
+ >
479
+ {{ formatValue(internalMin) }}
480
+ </span>
481
+ <span
482
+ v-else-if="showValue && range"
483
+ class="text-foreground font-semibold tabular-nums"
484
+ >
485
+ {{ formatValue(internalMin) }} – {{ formatValue(internalMax) }}
486
+ </span>
487
+ </div>
488
+
489
+ <!-- Track wrapper -->
490
+ <div
491
+ class="s-progress-range__wrapper relative"
492
+ :style="{
493
+ height: orientation === 'vertical' ? '200px' : `${handleSizeValue + 8}px`,
494
+ width: orientation === 'vertical' ? `${handleSizeValue + 8}px` : '100%'
495
+ }"
496
+ >
497
+ <!-- Track -->
498
+ <div
499
+ ref="trackRef"
500
+ class="s-progress-range__track absolute cursor-pointer"
501
+ :class="[
502
+ roundedClasses,
503
+ orientation === 'vertical' ? 'w-full' : 'top-1/2 -translate-y-1/2 left-0 right-0'
504
+ ]"
505
+ :style="{
506
+ background: trackColor,
507
+ height: orientation === 'vertical' ? '100%' : `${trackHeightValue}px`,
508
+ width: orientation === 'vertical' ? `${trackHeightValue}px` : undefined,
509
+ left: orientation === 'vertical' ? '50%' : undefined,
510
+ transform: orientation === 'vertical' ? 'translateX(-50%)' : undefined
511
+ }"
512
+ @click="handleTrackClick"
513
+ >
514
+ <!-- Active track -->
515
+ <div
516
+ class="s-progress-range__active-track absolute transition-all duration-100"
517
+ :class="roundedClasses"
518
+ :style="{
519
+ background: activeTrackColor || color,
520
+ height: orientation === 'vertical' ? `${maxPercent - minPercent}%` : '100%',
521
+ width: orientation === 'vertical' ? '100%' : `${range ? maxPercent - minPercent : minPercent}%`,
522
+ left: orientation === 'vertical' ? '0' : `${range ? minPercent : 0}%`,
523
+ bottom: orientation === 'vertical' ? `${minPercent}%` : undefined
524
+ }"
525
+ />
526
+
527
+ <!-- Tick marks -->
528
+ <div
529
+ v-if="(showTicks || marks) && ticks.length > 0"
530
+ class="absolute inset-0"
531
+ >
532
+ <div
533
+ v-for="tick in ticks"
534
+ :key="tick.value"
535
+ class="absolute"
536
+ :style="{
537
+ left: orientation === 'horizontal' ? `${tick.percent}%` : '50%',
538
+ bottom: orientation === 'vertical' ? `${tick.percent}%` : undefined,
539
+ top: orientation === 'horizontal' ? '50%' : undefined,
540
+ transform: 'translate(-50%, -50%)'
541
+ }"
542
+ >
543
+ <div
544
+ class="w-1.5 h-1.5 rounded-full transition-colors"
545
+ :class="[
546
+ (range ? tick.value >= internalMin && tick.value <= internalMax : tick.value <= internalMin)
547
+ ? 'bg-primary-foreground'
548
+ : 'bg-muted-foreground'
549
+ ]"
550
+ />
551
+ </div>
552
+ </div>
553
+ </div>
554
+
555
+ <!-- Min handle (or single handle) -->
556
+ <div
557
+ class="s-progress-range__handle absolute"
558
+ :class="[
559
+ 'transition-shadow duration-200',
560
+ (isDragging && activeHandle === (range ? 'min' : 'single')) && 'ring-4 ring-opacity-30',
561
+ disabled ? 'cursor-not-allowed' : 'cursor-grab'
562
+ ]"
563
+ :style="{
564
+ width: `${handleSizeValue}px`,
565
+ height: `${handleSizeValue}px`,
566
+ background: handleColor || color,
567
+ borderRadius: rounded === 'none' ? '2px' : '50%',
568
+ left: orientation === 'horizontal' ? `calc(${minPercent}% - ${handleSizeValue / 2}px)` : '50%',
569
+ top: orientation === 'horizontal' ? '50%' : undefined,
570
+ bottom: orientation === 'vertical' ? `calc(${minPercent}% - ${handleSizeValue / 2}px)` : undefined,
571
+ transform: orientation === 'horizontal' ? 'translateY(-50%)' : 'translateX(-50%)',
572
+ '--tw-ring-color': color,
573
+ zIndex: minHandleZIndex
574
+ }"
575
+ role="slider"
576
+ tabindex="0"
577
+ :aria-valuenow="internalMin"
578
+ :aria-valuemin="min"
579
+ :aria-valuemax="range ? internalMax - pushable : max"
580
+ :aria-label="range ? 'Minimum value' : 'Value'"
581
+ @mousedown="handleMouseDown($event, range ? 'min' : 'single')"
582
+ @touchstart="handleTouchStart($event, range ? 'min' : 'single')"
583
+ @keydown="handleKeyDown($event, range ? 'min' : 'single')"
584
+ @mouseenter="hoverHandle = range ? 'min' : 'single'"
585
+ @mouseleave="hoverHandle = null"
586
+ >
587
+ <!-- Tooltip -->
588
+ <Transition
589
+ enter-active-class="transition-all duration-150 ease-out"
590
+ enter-from-class="opacity-0 scale-90"
591
+ enter-to-class="opacity-100 scale-100"
592
+ leave-active-class="transition-all duration-100"
593
+ leave-from-class="opacity-100 scale-100"
594
+ leave-to-class="opacity-0 scale-90"
595
+ >
596
+ <div
597
+ v-if="showTooltip && (isDragging && activeHandle === (range ? 'min' : 'single') || hoverHandle === (range ? 'min' : 'single'))"
598
+ class="absolute whitespace-nowrap px-2 py-1 rounded-md bg-muted border border-border shadow-lg text-xs font-semibold text-foreground"
599
+ :class="[
600
+ tooltipPosition === 'top' ? 'bottom-full mb-2' : 'top-full mt-2',
601
+ 'left-1/2 -translate-x-1/2'
602
+ ]"
603
+ >
604
+ {{ formatValue(internalMin) }}
605
+ </div>
606
+ </Transition>
607
+ </div>
608
+
609
+ <!-- Max handle (range mode only) -->
610
+ <div
611
+ v-if="range"
612
+ class="s-progress-range__handle absolute"
613
+ :class="[
614
+ 'transition-shadow duration-200',
615
+ (isDragging && activeHandle === 'max') && 'ring-4 ring-opacity-30',
616
+ disabled ? 'cursor-not-allowed' : 'cursor-grab'
617
+ ]"
618
+ :style="{
619
+ width: `${handleSizeValue}px`,
620
+ height: `${handleSizeValue}px`,
621
+ background: handleColor || color,
622
+ borderRadius: rounded === 'none' ? '2px' : '50%',
623
+ left: orientation === 'horizontal' ? `calc(${maxPercent}% - ${handleSizeValue / 2}px)` : '50%',
624
+ top: orientation === 'horizontal' ? '50%' : undefined,
625
+ bottom: orientation === 'vertical' ? `calc(${maxPercent}% - ${handleSizeValue / 2}px)` : undefined,
626
+ transform: orientation === 'horizontal' ? 'translateY(-50%)' : 'translateX(-50%)',
627
+ '--tw-ring-color': color,
628
+ zIndex: maxHandleZIndex
629
+ }"
630
+ role="slider"
631
+ tabindex="0"
632
+ :aria-valuenow="internalMax"
633
+ :aria-valuemin="internalMin + pushable"
634
+ :aria-valuemax="max"
635
+ aria-label="Maximum value"
636
+ @mousedown="handleMouseDown($event, 'max')"
637
+ @touchstart="handleTouchStart($event, 'max')"
638
+ @keydown="handleKeyDown($event, 'max')"
639
+ @mouseenter="hoverHandle = 'max'"
640
+ @mouseleave="hoverHandle = null"
641
+ >
642
+ <!-- Tooltip -->
643
+ <Transition
644
+ enter-active-class="transition-all duration-150 ease-out"
645
+ enter-from-class="opacity-0 scale-90"
646
+ enter-to-class="opacity-100 scale-100"
647
+ leave-active-class="transition-all duration-100"
648
+ leave-from-class="opacity-100 scale-100"
649
+ leave-to-class="opacity-0 scale-90"
650
+ >
651
+ <div
652
+ v-if="showTooltip && (isDragging && activeHandle === 'max' || hoverHandle === 'max')"
653
+ class="absolute whitespace-nowrap px-2 py-1 rounded-md bg-muted border border-border shadow-lg text-xs font-semibold text-foreground"
654
+ :class="[
655
+ tooltipPosition === 'top' ? 'bottom-full mb-2' : 'top-full mt-2',
656
+ 'left-1/2 -translate-x-1/2'
657
+ ]"
658
+ >
659
+ {{ formatValue(internalMax) }}
660
+ </div>
661
+ </Transition>
662
+ </div>
663
+ </div>
664
+
665
+ <!-- Labels / Ticks below -->
666
+ <div
667
+ v-if="showLabels || (showTicks && ticks.length > 0)"
668
+ class="s-progress-range__labels relative mt-2"
669
+ :class="orientation === 'horizontal' ? 'w-full' : 'h-full'"
670
+ >
671
+ <div
672
+ v-if="showLabels"
673
+ class="flex justify-between text-xs text-muted-foreground"
674
+ >
675
+ <span>{{ minLabel || formatValue(min) }}</span>
676
+ <span>{{ maxLabel || formatValue(max) }}</span>
677
+ </div>
678
+ <div
679
+ v-else-if="showTicks"
680
+ class="relative h-5"
681
+ >
682
+ <span
683
+ v-for="tick in ticks"
684
+ :key="tick.value"
685
+ class="absolute text-xs text-muted-foreground -translate-x-1/2"
686
+ :style="{ left: `${tick.percent}%` }"
687
+ >
688
+ {{ tick.label }}
689
+ </span>
690
+ </div>
691
+ </div>
692
+ </div>
693
+ </template>
694
+
695
+ <style scoped>
696
+ .s-progress-range__handle {
697
+ box-shadow: 0 2px 6px rgba(0, 0, 0, 0.15);
698
+ }
699
+
700
+ .s-progress-range__handle:hover {
701
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
702
+ }
703
+
704
+ .s-progress-range__handle:active {
705
+ cursor: grabbing;
706
+ }
707
+
708
+ .s-progress-range__handle:focus {
709
+ outline: none;
710
+ }
711
+
712
+ .s-progress-range__handle:focus-visible {
713
+ box-shadow: 0 0 0 3px color-mix(in srgb, var(--s-primary) 15%, transparent);
714
+ }
715
+ </style>