@mkbabb/glass-ui 0.2.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 (335) hide show
  1. package/README.md +172 -0
  2. package/dist/glass-ui.css +1 -0
  3. package/dist/glass-ui.js +10019 -0
  4. package/dist/index.d.ts +6619 -0
  5. package/package.json +65 -0
  6. package/src/components/custom/aurora/Aurora.vue +34 -0
  7. package/src/components/custom/aurora/composables/color.ts +122 -0
  8. package/src/components/custom/aurora/composables/useAurora.ts +355 -0
  9. package/src/components/custom/aurora/index.ts +8 -0
  10. package/src/components/custom/confirm-dialog/ConfirmDialog.vue +88 -0
  11. package/src/components/custom/confirm-dialog/index.ts +1 -0
  12. package/src/components/custom/controls/DarkModeToggle.vue +96 -0
  13. package/src/components/custom/controls/index.ts +1 -0
  14. package/src/components/custom/dock/DockLayerGroup.vue +21 -0
  15. package/src/components/custom/dock/DockPopover.vue +263 -0
  16. package/src/components/custom/dock/GlassDock.vue +276 -0
  17. package/src/components/custom/dock/composables/index.ts +16 -0
  18. package/src/components/custom/dock/composables/isTeleportedTarget.ts +19 -0
  19. package/src/components/custom/dock/composables/useDockActionBar.ts +33 -0
  20. package/src/components/custom/dock/composables/useDockState.ts +301 -0
  21. package/src/components/custom/dock/composables/useDockTransition.ts +146 -0
  22. package/src/components/custom/dock/composables/useLayerTransition.ts +135 -0
  23. package/src/components/custom/dock/composables/usePopupMutex.ts +83 -0
  24. package/src/components/custom/dock/index.ts +9 -0
  25. package/src/components/custom/expandable-container/ExpandableContainer.vue +64 -0
  26. package/src/components/custom/expandable-container/index.ts +1 -0
  27. package/src/components/custom/glass-panel/GlassPanel.vue +98 -0
  28. package/src/components/custom/glass-panel/index.ts +2 -0
  29. package/src/components/custom/icon-tooltip/IconTooltip.vue +20 -0
  30. package/src/components/custom/icon-tooltip/index.ts +1 -0
  31. package/src/components/custom/index.ts +15 -0
  32. package/src/components/custom/infinite-scroll/InfiniteScroll.vue +55 -0
  33. package/src/components/custom/infinite-scroll/composables/index.ts +2 -0
  34. package/src/components/custom/infinite-scroll/composables/types.ts +23 -0
  35. package/src/components/custom/infinite-scroll/composables/useInfiniteScroll.ts +73 -0
  36. package/src/components/custom/infinite-scroll/index.ts +1 -0
  37. package/src/components/custom/labeled-field/LabeledInput.vue +29 -0
  38. package/src/components/custom/labeled-field/LabeledSelect.vue +59 -0
  39. package/src/components/custom/labeled-field/LabeledSlider.vue +32 -0
  40. package/src/components/custom/labeled-field/LabeledSwitch.vue +27 -0
  41. package/src/components/custom/labeled-field/index.ts +4 -0
  42. package/src/components/custom/metaballs/MetaballCanvas.vue +23 -0
  43. package/src/components/custom/metaballs/index.ts +4 -0
  44. package/src/components/custom/metaballs/shaders.ts +63 -0
  45. package/src/components/custom/metaballs/types.ts +29 -0
  46. package/src/components/custom/metaballs/useMetaballs.ts +252 -0
  47. package/src/components/custom/search/FuzzySearch.vue +589 -0
  48. package/src/components/custom/search/SearchBar.vue +44 -0
  49. package/src/components/custom/search/composables/fuzzySearchIndex.ts +224 -0
  50. package/src/components/custom/search/composables/index.ts +5 -0
  51. package/src/components/custom/search/composables/types.ts +34 -0
  52. package/src/components/custom/search/composables/useFuzzySearch.ts +115 -0
  53. package/src/components/custom/search/index.ts +7 -0
  54. package/src/components/custom/sidebar/ProgressiveSidebar.vue +256 -0
  55. package/src/components/custom/sidebar/composables/index.ts +6 -0
  56. package/src/components/custom/sidebar/composables/useScrollTracker.ts +242 -0
  57. package/src/components/custom/sidebar/composables/useSidebarFollow.ts +247 -0
  58. package/src/components/custom/sidebar/composables/useSidebarState.ts +72 -0
  59. package/src/components/custom/sidebar/composables/useTreeIndex.ts +152 -0
  60. package/src/components/custom/sidebar/index.ts +15 -0
  61. package/src/components/custom/sidebar/types.ts +50 -0
  62. package/src/components/custom/tabs/BouncyTabs.vue +39 -0
  63. package/src/components/custom/tabs/BouncyToggle.vue +352 -0
  64. package/src/components/custom/tabs/UnderlineTabs.vue +115 -0
  65. package/src/components/custom/tabs/index.ts +5 -0
  66. package/src/components/custom/timeline/GlassTimeline.vue +174 -0
  67. package/src/components/custom/timeline/index.ts +1 -0
  68. package/src/components/custom/typewriter/TypewriterText.vue +239 -0
  69. package/src/components/custom/typewriter/composables/index.ts +1 -0
  70. package/src/components/custom/typewriter/composables/useTypewriter.ts +413 -0
  71. package/src/components/custom/typewriter/index.ts +7 -0
  72. package/src/components/custom/typewriter/types.ts +159 -0
  73. package/src/components/custom/typewriter/utils/keyboard.ts +213 -0
  74. package/src/components/custom/typewriter/utils/pausePatterns.ts +55 -0
  75. package/src/components/custom/typewriter/utils/timing.ts +104 -0
  76. package/src/components/custom/typewriter/utils/typoStateMachine.ts +197 -0
  77. package/src/components/index.ts +2 -0
  78. package/src/components/ui/accordion/Accordion.vue +19 -0
  79. package/src/components/ui/accordion/AccordionContent.vue +24 -0
  80. package/src/components/ui/accordion/AccordionItem.vue +24 -0
  81. package/src/components/ui/accordion/AccordionTrigger.vue +39 -0
  82. package/src/components/ui/accordion/index.ts +4 -0
  83. package/src/components/ui/alert/Alert.vue +20 -0
  84. package/src/components/ui/alert/AlertDescription.vue +17 -0
  85. package/src/components/ui/alert/AlertTitle.vue +17 -0
  86. package/src/components/ui/alert/index.ts +23 -0
  87. package/src/components/ui/avatar/Avatar.vue +21 -0
  88. package/src/components/ui/avatar/AvatarFallback.vue +11 -0
  89. package/src/components/ui/avatar/AvatarImage.vue +9 -0
  90. package/src/components/ui/avatar/index.ts +24 -0
  91. package/src/components/ui/badge/Badge.vue +16 -0
  92. package/src/components/ui/badge/index.ts +25 -0
  93. package/src/components/ui/button/Button.vue +26 -0
  94. package/src/components/ui/button/index.ts +43 -0
  95. package/src/components/ui/card/Card.vue +28 -0
  96. package/src/components/ui/card/CardContent.vue +14 -0
  97. package/src/components/ui/card/CardDescription.vue +14 -0
  98. package/src/components/ui/card/CardFooter.vue +14 -0
  99. package/src/components/ui/card/CardHeader.vue +14 -0
  100. package/src/components/ui/card/CardTitle.vue +21 -0
  101. package/src/components/ui/card/index.ts +6 -0
  102. package/src/components/ui/carousel/Carousel.vue +53 -0
  103. package/src/components/ui/carousel/CarouselContent.vue +35 -0
  104. package/src/components/ui/carousel/CarouselItem.vue +24 -0
  105. package/src/components/ui/carousel/CarouselNext.vue +40 -0
  106. package/src/components/ui/carousel/CarouselPrevious.vue +40 -0
  107. package/src/components/ui/carousel/index.ts +10 -0
  108. package/src/components/ui/carousel/interface.ts +26 -0
  109. package/src/components/ui/carousel/useCarousel.ts +56 -0
  110. package/src/components/ui/checkbox/Checkbox.vue +33 -0
  111. package/src/components/ui/checkbox/index.ts +1 -0
  112. package/src/components/ui/collapsible/Collapsible.vue +15 -0
  113. package/src/components/ui/collapsible/CollapsibleContent.vue +11 -0
  114. package/src/components/ui/collapsible/CollapsibleTrigger.vue +11 -0
  115. package/src/components/ui/collapsible/index.ts +3 -0
  116. package/src/components/ui/combobox/Combobox.vue +17 -0
  117. package/src/components/ui/combobox/ComboboxAnchor.vue +23 -0
  118. package/src/components/ui/combobox/ComboboxEmpty.vue +21 -0
  119. package/src/components/ui/combobox/ComboboxGroup.vue +27 -0
  120. package/src/components/ui/combobox/ComboboxInput.vue +41 -0
  121. package/src/components/ui/combobox/ComboboxItem.vue +24 -0
  122. package/src/components/ui/combobox/ComboboxItemIndicator.vue +23 -0
  123. package/src/components/ui/combobox/ComboboxList.vue +29 -0
  124. package/src/components/ui/combobox/ComboboxSeparator.vue +21 -0
  125. package/src/components/ui/combobox/ComboboxViewport.vue +23 -0
  126. package/src/components/ui/combobox/index.ts +12 -0
  127. package/src/components/ui/command/Command.vue +30 -0
  128. package/src/components/ui/command/CommandDialog.vue +21 -0
  129. package/src/components/ui/command/CommandEmpty.vue +20 -0
  130. package/src/components/ui/command/CommandGroup.vue +29 -0
  131. package/src/components/ui/command/CommandInput.vue +33 -0
  132. package/src/components/ui/command/CommandItem.vue +26 -0
  133. package/src/components/ui/command/CommandList.vue +27 -0
  134. package/src/components/ui/command/CommandSeparator.vue +23 -0
  135. package/src/components/ui/command/CommandShortcut.vue +14 -0
  136. package/src/components/ui/command/index.ts +9 -0
  137. package/src/components/ui/context-menu/ContextMenu.vue +15 -0
  138. package/src/components/ui/context-menu/ContextMenuCheckboxItem.vue +40 -0
  139. package/src/components/ui/context-menu/ContextMenuContent.vue +36 -0
  140. package/src/components/ui/context-menu/ContextMenuGroup.vue +11 -0
  141. package/src/components/ui/context-menu/ContextMenuItem.vue +34 -0
  142. package/src/components/ui/context-menu/ContextMenuLabel.vue +25 -0
  143. package/src/components/ui/context-menu/ContextMenuPortal.vue +11 -0
  144. package/src/components/ui/context-menu/ContextMenuRadioGroup.vue +19 -0
  145. package/src/components/ui/context-menu/ContextMenuRadioItem.vue +40 -0
  146. package/src/components/ui/context-menu/ContextMenuSeparator.vue +20 -0
  147. package/src/components/ui/context-menu/ContextMenuShortcut.vue +14 -0
  148. package/src/components/ui/context-menu/ContextMenuSub.vue +19 -0
  149. package/src/components/ui/context-menu/ContextMenuSubContent.vue +35 -0
  150. package/src/components/ui/context-menu/ContextMenuSubTrigger.vue +34 -0
  151. package/src/components/ui/context-menu/ContextMenuTrigger.vue +13 -0
  152. package/src/components/ui/context-menu/index.ts +14 -0
  153. package/src/components/ui/data-table/DataTable.vue +167 -0
  154. package/src/components/ui/data-table/DataTablePagination.vue +112 -0
  155. package/src/components/ui/data-table/index.ts +3 -0
  156. package/src/components/ui/data-table/types.ts +48 -0
  157. package/src/components/ui/dialog/Dialog.vue +14 -0
  158. package/src/components/ui/dialog/DialogClose.vue +11 -0
  159. package/src/components/ui/dialog/DialogContent.vue +61 -0
  160. package/src/components/ui/dialog/DialogDescription.vue +24 -0
  161. package/src/components/ui/dialog/DialogFooter.vue +19 -0
  162. package/src/components/ui/dialog/DialogHeader.vue +16 -0
  163. package/src/components/ui/dialog/DialogScrollContent.vue +65 -0
  164. package/src/components/ui/dialog/DialogTitle.vue +29 -0
  165. package/src/components/ui/dialog/DialogTrigger.vue +11 -0
  166. package/src/components/ui/dialog/index.ts +9 -0
  167. package/src/components/ui/drawer/Drawer.vue +19 -0
  168. package/src/components/ui/drawer/DrawerContent.vue +28 -0
  169. package/src/components/ui/drawer/DrawerDescription.vue +20 -0
  170. package/src/components/ui/drawer/DrawerFooter.vue +14 -0
  171. package/src/components/ui/drawer/DrawerHeader.vue +14 -0
  172. package/src/components/ui/drawer/DrawerOverlay.vue +18 -0
  173. package/src/components/ui/drawer/DrawerTitle.vue +20 -0
  174. package/src/components/ui/drawer/index.ts +8 -0
  175. package/src/components/ui/dropdown-menu/DropdownMenu.vue +14 -0
  176. package/src/components/ui/dropdown-menu/DropdownMenuCheckboxItem.vue +40 -0
  177. package/src/components/ui/dropdown-menu/DropdownMenuContent.vue +44 -0
  178. package/src/components/ui/dropdown-menu/DropdownMenuGroup.vue +11 -0
  179. package/src/components/ui/dropdown-menu/DropdownMenuItem.vue +28 -0
  180. package/src/components/ui/dropdown-menu/DropdownMenuLabel.vue +24 -0
  181. package/src/components/ui/dropdown-menu/DropdownMenuRadioGroup.vue +19 -0
  182. package/src/components/ui/dropdown-menu/DropdownMenuRadioItem.vue +40 -0
  183. package/src/components/ui/dropdown-menu/DropdownMenuSeparator.vue +22 -0
  184. package/src/components/ui/dropdown-menu/DropdownMenuShortcut.vue +14 -0
  185. package/src/components/ui/dropdown-menu/DropdownMenuSub.vue +19 -0
  186. package/src/components/ui/dropdown-menu/DropdownMenuSubContent.vue +36 -0
  187. package/src/components/ui/dropdown-menu/DropdownMenuSubTrigger.vue +33 -0
  188. package/src/components/ui/dropdown-menu/DropdownMenuTrigger.vue +13 -0
  189. package/src/components/ui/dropdown-menu/index.ts +16 -0
  190. package/src/components/ui/hover-card/HoverCard.vue +14 -0
  191. package/src/components/ui/hover-card/HoverCardContent.vue +41 -0
  192. package/src/components/ui/hover-card/HoverCardTrigger.vue +11 -0
  193. package/src/components/ui/hover-card/index.ts +3 -0
  194. package/src/components/ui/index.ts +41 -0
  195. package/src/components/ui/input/Input.vue +24 -0
  196. package/src/components/ui/input/index.ts +1 -0
  197. package/src/components/ui/label/Label.vue +27 -0
  198. package/src/components/ui/label/index.ts +1 -0
  199. package/src/components/ui/multi-select/MultiSelect.vue +141 -0
  200. package/src/components/ui/multi-select/index.ts +7 -0
  201. package/src/components/ui/notification/Notification.vue +85 -0
  202. package/src/components/ui/notification/index.ts +1 -0
  203. package/src/components/ui/number-field/NumberField.vue +23 -0
  204. package/src/components/ui/number-field/NumberFieldContent.vue +14 -0
  205. package/src/components/ui/number-field/NumberFieldDecrement.vue +25 -0
  206. package/src/components/ui/number-field/NumberFieldIncrement.vue +25 -0
  207. package/src/components/ui/number-field/NumberFieldInput.vue +8 -0
  208. package/src/components/ui/number-field/index.ts +5 -0
  209. package/src/components/ui/popover/Popover.vue +15 -0
  210. package/src/components/ui/popover/PopoverContent.vue +61 -0
  211. package/src/components/ui/popover/PopoverTrigger.vue +11 -0
  212. package/src/components/ui/popover/index.ts +3 -0
  213. package/src/components/ui/progress/Progress.vue +39 -0
  214. package/src/components/ui/progress/index.ts +1 -0
  215. package/src/components/ui/radio-group/RadioGroup.vue +25 -0
  216. package/src/components/ui/radio-group/RadioGroupItem.vue +39 -0
  217. package/src/components/ui/radio-group/index.ts +2 -0
  218. package/src/components/ui/scroll-area/ScrollArea.vue +29 -0
  219. package/src/components/ui/scroll-area/ScrollBar.vue +30 -0
  220. package/src/components/ui/scroll-area/index.ts +2 -0
  221. package/src/components/ui/scroll-pane/ScrollPane.vue +25 -0
  222. package/src/components/ui/scroll-pane/ScrollPaneHeader.vue +75 -0
  223. package/src/components/ui/scroll-pane/index.ts +2 -0
  224. package/src/components/ui/select/Select.vue +15 -0
  225. package/src/components/ui/select/SelectContent.vue +57 -0
  226. package/src/components/ui/select/SelectGroup.vue +19 -0
  227. package/src/components/ui/select/SelectItem.vue +47 -0
  228. package/src/components/ui/select/SelectItemText.vue +11 -0
  229. package/src/components/ui/select/SelectLabel.vue +13 -0
  230. package/src/components/ui/select/SelectScrollDownButton.vue +24 -0
  231. package/src/components/ui/select/SelectScrollUpButton.vue +24 -0
  232. package/src/components/ui/select/SelectSeparator.vue +17 -0
  233. package/src/components/ui/select/SelectTrigger.vue +45 -0
  234. package/src/components/ui/select/SelectValue.vue +11 -0
  235. package/src/components/ui/select/index.ts +11 -0
  236. package/src/components/ui/separator/Separator.vue +35 -0
  237. package/src/components/ui/separator/index.ts +1 -0
  238. package/src/components/ui/sheet/Sheet.vue +14 -0
  239. package/src/components/ui/sheet/SheetClose.vue +11 -0
  240. package/src/components/ui/sheet/SheetContent.vue +56 -0
  241. package/src/components/ui/sheet/SheetDescription.vue +22 -0
  242. package/src/components/ui/sheet/SheetFooter.vue +19 -0
  243. package/src/components/ui/sheet/SheetHeader.vue +16 -0
  244. package/src/components/ui/sheet/SheetTitle.vue +22 -0
  245. package/src/components/ui/sheet/SheetTrigger.vue +11 -0
  246. package/src/components/ui/sheet/index.ts +31 -0
  247. package/src/components/ui/skeleton/Skeleton.vue +14 -0
  248. package/src/components/ui/skeleton/index.ts +1 -0
  249. package/src/components/ui/slider/Slider.vue +66 -0
  250. package/src/components/ui/slider/index.ts +1 -0
  251. package/src/components/ui/switch/Switch.vue +37 -0
  252. package/src/components/ui/switch/index.ts +1 -0
  253. package/src/components/ui/table/Table.vue +16 -0
  254. package/src/components/ui/table/TableBody.vue +14 -0
  255. package/src/components/ui/table/TableCaption.vue +14 -0
  256. package/src/components/ui/table/TableCell.vue +14 -0
  257. package/src/components/ui/table/TableEmpty.vue +39 -0
  258. package/src/components/ui/table/TableFooter.vue +16 -0
  259. package/src/components/ui/table/TableHead.vue +21 -0
  260. package/src/components/ui/table/TableHeader.vue +14 -0
  261. package/src/components/ui/table/TableRow.vue +21 -0
  262. package/src/components/ui/table/index.ts +9 -0
  263. package/src/components/ui/tabs/Tabs.vue +15 -0
  264. package/src/components/ui/tabs/TabsContent.vue +22 -0
  265. package/src/components/ui/tabs/TabsIndicator.vue +22 -0
  266. package/src/components/ui/tabs/TabsList.vue +25 -0
  267. package/src/components/ui/tabs/TabsTrigger.vue +29 -0
  268. package/src/components/ui/tabs/index.ts +5 -0
  269. package/src/components/ui/tags-input/TagsInput.vue +22 -0
  270. package/src/components/ui/tags-input/TagsInputInput.vue +19 -0
  271. package/src/components/ui/tags-input/TagsInputItem.vue +22 -0
  272. package/src/components/ui/tags-input/TagsInputItemDelete.vue +24 -0
  273. package/src/components/ui/tags-input/TagsInputItemText.vue +19 -0
  274. package/src/components/ui/tags-input/index.ts +5 -0
  275. package/src/components/ui/textarea/Textarea.vue +24 -0
  276. package/src/components/ui/textarea/index.ts +1 -0
  277. package/src/components/ui/toast/Toast.vue +57 -0
  278. package/src/components/ui/toast/ToastAction.vue +30 -0
  279. package/src/components/ui/toast/ToastClose.vue +31 -0
  280. package/src/components/ui/toast/ToastDescription.vue +25 -0
  281. package/src/components/ui/toast/ToastTitle.vue +25 -0
  282. package/src/components/ui/toast/Toaster.vue +31 -0
  283. package/src/components/ui/toast/index.ts +8 -0
  284. package/src/components/ui/toast/use-toast.ts +136 -0
  285. package/src/components/ui/toggle/Toggle.vue +35 -0
  286. package/src/components/ui/toggle/index.ts +27 -0
  287. package/src/components/ui/toggle-group/ToggleGroup.vue +34 -0
  288. package/src/components/ui/toggle-group/ToggleGroupItem.vue +35 -0
  289. package/src/components/ui/toggle-group/index.ts +2 -0
  290. package/src/components/ui/tooltip/Tooltip.vue +14 -0
  291. package/src/components/ui/tooltip/TooltipContent.vue +31 -0
  292. package/src/components/ui/tooltip/TooltipProvider.vue +11 -0
  293. package/src/components/ui/tooltip/TooltipTrigger.vue +11 -0
  294. package/src/components/ui/tooltip/index.ts +4 -0
  295. package/src/composables/glass/index.ts +8 -0
  296. package/src/composables/glass/useGlassRenderer.ts +252 -0
  297. package/src/composables/glass/webgl/frostShader.ts +221 -0
  298. package/src/composables/glass/webgpu/glassShader.wgsl +173 -0
  299. package/src/composables/index.ts +32 -0
  300. package/src/composables/infinite-scroll/index.ts +2 -0
  301. package/src/composables/infinite-scroll/types.ts +25 -0
  302. package/src/composables/infinite-scroll/useInfiniteScroll.ts +101 -0
  303. package/src/composables/interaction/index.ts +5 -0
  304. package/src/composables/interaction/useHeightTransition.ts +82 -0
  305. package/src/composables/interaction/useHoverPopover.ts +64 -0
  306. package/src/composables/interaction/useHoverToggle.ts +103 -0
  307. package/src/composables/interaction/useLeaveTimer.ts +17 -0
  308. package/src/composables/interaction/useTouchGate.ts +207 -0
  309. package/src/composables/pagination/index.ts +2 -0
  310. package/src/composables/pagination/useOffsetPagination.ts +70 -0
  311. package/src/composables/prng.ts +32 -0
  312. package/src/composables/useCharSplit.ts +31 -0
  313. package/src/composables/useClipboard.ts +46 -0
  314. package/src/composables/useGlobalDark.ts +61 -0
  315. package/src/composables/useKeyboardShortcuts.ts +205 -0
  316. package/src/composables/useWatercolorBlob.ts +136 -0
  317. package/src/composables/virtual/index.ts +22 -0
  318. package/src/composables/virtual/useVirtualSectionWindow.ts +338 -0
  319. package/src/composables/virtual/useWindowedStore.ts +86 -0
  320. package/src/composables/virtual/virtualSectionLayout.ts +212 -0
  321. package/src/index.ts +9 -0
  322. package/src/styles/animations.css +233 -0
  323. package/src/styles/cards.css +66 -0
  324. package/src/styles/dock.css +221 -0
  325. package/src/styles/floating-panel.css +49 -0
  326. package/src/styles/glass.css +266 -0
  327. package/src/styles/index.css +26 -0
  328. package/src/styles/scroll-pane.css +10 -0
  329. package/src/styles/theme.css +138 -0
  330. package/src/styles/tokens.css +333 -0
  331. package/src/styles/transitions.css +226 -0
  332. package/src/styles/typography.css +277 -0
  333. package/src/styles/utilities.css +697 -0
  334. package/src/utils/cn.ts +6 -0
  335. package/src/utils/index.ts +1 -0
@@ -0,0 +1,9 @@
1
+ export { default as GlassDock } from "./GlassDock.vue";
2
+ export { default as DockPopover } from "./DockPopover.vue";
3
+ export { default as DockLayerGroup } from "./DockLayerGroup.vue";
4
+ export { useDockState, useDockTransition, useLayerTransition, usePopupMutex, DOCK_ACTION_BAR_KEY, isTeleportedTarget } from "./composables";
5
+ export type { UseDockStateOptions, DockState } from "./composables";
6
+ export type { UseDockTransitionOptions } from "./composables";
7
+ export type { UseLayerTransitionOptions, UseLayerTransitionReturn } from "./composables";
8
+ export type { UsePopupMutexOptions, UsePopupMutexReturn } from "./composables";
9
+ export type { DockAction, DockActionBar } from "./composables";
@@ -0,0 +1,64 @@
1
+ <template>
2
+ <!-- Normal mode: render inline -->
3
+ <div v-if="!isFullscreen" class="relative" v-bind="$attrs">
4
+ <button
5
+ class="absolute z-10 rounded-lg bg-card/70 [backdrop-filter:var(--glass-blur-subtle)] p-1.5 text-muted-foreground hover:text-foreground transition-colors shadow-sm border border-border/40"
6
+ :class="buttonPosition === 'left' ? 'left-2 top-2' : 'right-2 top-2'"
7
+ title="Fullscreen"
8
+ @click="isFullscreen = true"
9
+ >
10
+ <Maximize2 class="h-4 w-4" />
11
+ </button>
12
+ <slot :fullscreen="false" />
13
+ </div>
14
+
15
+ <!-- Fullscreen mode: teleport to body -->
16
+ <Teleport to="body">
17
+ <div
18
+ v-if="isFullscreen"
19
+ class="fixed inset-0 z-modal flex flex-col bg-background"
20
+ >
21
+ <button
22
+ class="absolute z-10 rounded-lg bg-card/70 [backdrop-filter:var(--glass-blur-subtle)] p-2 text-muted-foreground hover:text-foreground transition-colors shadow-sm border border-border/40"
23
+ :class="buttonPosition === 'left' ? 'left-3 top-3' : 'right-3 top-3'"
24
+ title="Exit fullscreen"
25
+ @click="isFullscreen = false"
26
+ >
27
+ <Minimize2 class="h-4 w-4" />
28
+ </button>
29
+ <div class="h-full w-full">
30
+ <slot :fullscreen="true" />
31
+ </div>
32
+ </div>
33
+ </Teleport>
34
+ </template>
35
+
36
+ <script setup lang="ts">
37
+ import { ref, watch, onUnmounted, defineOptions } from "vue";
38
+
39
+ defineOptions({ inheritAttrs: false });
40
+ import { Maximize2, Minimize2 } from "lucide-vue-next";
41
+
42
+ withDefaults(defineProps<{
43
+ buttonPosition?: "left" | "right";
44
+ }>(), {
45
+ buttonPosition: "right",
46
+ });
47
+
48
+ const isFullscreen = ref(false);
49
+
50
+ watch(isFullscreen, (fs) => {
51
+ document.body.style.overflow = fs ? "hidden" : "";
52
+ });
53
+
54
+ function onKeydown(e: KeyboardEvent) {
55
+ if (e.key === "Escape" && isFullscreen.value) {
56
+ isFullscreen.value = false;
57
+ }
58
+ }
59
+ document.addEventListener("keydown", onKeydown);
60
+ onUnmounted(() => {
61
+ document.removeEventListener("keydown", onKeydown);
62
+ document.body.style.overflow = "";
63
+ });
64
+ </script>
@@ -0,0 +1 @@
1
+ export { default as ExpandableContainer } from "./ExpandableContainer.vue";
@@ -0,0 +1,98 @@
1
+ <script setup lang="ts">
2
+ import { ref, computed, onMounted, onBeforeUnmount } from "vue";
3
+ import {
4
+ useGlassRenderer,
5
+ createGlassFilter,
6
+ destroyGlassFilter,
7
+ type GlassTier,
8
+ type GlassFilterState,
9
+ } from "../../../composables/glass/useGlassRenderer";
10
+ import { cn } from "../../../utils/cn";
11
+
12
+ export interface GlassPanelProps {
13
+ /** Force a specific rendering tier */
14
+ tier?: GlassTier;
15
+ /** Blur radius (default: 16) */
16
+ blur?: number;
17
+ /** Refraction strength 0-1 (default: 0.3) */
18
+ refraction?: number;
19
+ /** Chromatic aberration strength 0-1 (default: 0) */
20
+ chromaticAberration?: boolean;
21
+ /** Glass variant for CSS tier */
22
+ variant?: "default" | "medium" | "elevated";
23
+ /** Additional classes */
24
+ class?: string;
25
+ }
26
+
27
+ const props = withDefaults(defineProps<GlassPanelProps>(), {
28
+ blur: 16,
29
+ refraction: 0.3,
30
+ chromaticAberration: false,
31
+ variant: "default",
32
+ });
33
+
34
+ const panelRef = ref<HTMLElement | null>(null);
35
+ const renderer = useGlassRenderer({ preferredTier: props.tier });
36
+ const activeTier = computed(() => props.tier ?? renderer.tier.value);
37
+
38
+ const cssClass = computed(() => {
39
+ // SVG-filter tier: no glass CSS class (filter applied directly via JS)
40
+ if (activeTier.value === "svg-filter") {
41
+ return cn("glass-panel glass-panel--svg", props.class);
42
+ }
43
+
44
+ if (activeTier.value === "fallback") {
45
+ return cn("glass-panel glass-panel--fallback", props.class);
46
+ }
47
+
48
+ // CSS tier
49
+ const variantClass =
50
+ props.variant === "elevated"
51
+ ? "glass-elevated"
52
+ : props.variant === "medium"
53
+ ? "glass-medium"
54
+ : "glass-default";
55
+
56
+ return cn("glass-panel", variantClass, props.class);
57
+ });
58
+
59
+ let filterState: GlassFilterState | null = null;
60
+
61
+ onMounted(() => {
62
+ if (panelRef.value && activeTier.value === "svg-filter") {
63
+ filterState = createGlassFilter(panelRef.value, {
64
+ blur: props.blur,
65
+ refraction: props.refraction,
66
+ chromaticAberration: props.chromaticAberration ? 0.5 : 0,
67
+ });
68
+ }
69
+ });
70
+
71
+ onBeforeUnmount(() => {
72
+ if (filterState) {
73
+ destroyGlassFilter(filterState);
74
+ }
75
+ });
76
+ </script>
77
+
78
+ <template>
79
+ <div ref="panelRef" :class="cssClass">
80
+ <slot />
81
+ </div>
82
+ </template>
83
+
84
+ <style scoped>
85
+ .glass-panel {
86
+ position: relative;
87
+ }
88
+
89
+ .glass-panel--svg {
90
+ /* Background tint for SVG filter tier */
91
+ background: color-mix(in srgb, var(--card) 15%, transparent);
92
+ }
93
+
94
+ .glass-panel--fallback {
95
+ background: color-mix(in srgb, var(--card) 92%, transparent);
96
+ border: 1px solid color-mix(in srgb, var(--border) 35%, transparent);
97
+ }
98
+ </style>
@@ -0,0 +1,2 @@
1
+ export { default as GlassPanel } from "./GlassPanel.vue";
2
+ export type { GlassPanelProps } from "./GlassPanel.vue";
@@ -0,0 +1,20 @@
1
+ <template>
2
+ <Tooltip>
3
+ <TooltipTrigger as-child>
4
+ <slot />
5
+ </TooltipTrigger>
6
+ <TooltipContent class="font-display text-base">{{ text }}</TooltipContent>
7
+ </Tooltip>
8
+ </template>
9
+
10
+ <script setup lang="ts">
11
+ import {
12
+ Tooltip,
13
+ TooltipContent,
14
+ TooltipTrigger,
15
+ } from "../../ui/tooltip";
16
+
17
+ defineProps<{
18
+ text: string;
19
+ }>();
20
+ </script>
@@ -0,0 +1 @@
1
+ export { default as IconTooltip } from "./IconTooltip.vue";
@@ -0,0 +1,15 @@
1
+ export * from "./confirm-dialog";
2
+ export * from "./controls";
3
+ export * from "./dock";
4
+ export * from "./expandable-container";
5
+ export * from "./icon-tooltip";
6
+ export * from "./infinite-scroll";
7
+ export * from "./labeled-field";
8
+ export * from "./metaballs";
9
+ export * from "./search";
10
+ export * from "./sidebar";
11
+ export * from "./tabs";
12
+ export * from "./timeline";
13
+ export * from "./typewriter";
14
+ export * from "./glass-panel";
15
+ export * from "./aurora";
@@ -0,0 +1,55 @@
1
+ <script setup lang="ts">
2
+ import { ref, toRef } from "vue";
3
+ import { useInfiniteScroll } from "./composables";
4
+
5
+ const props = withDefaults(
6
+ defineProps<{
7
+ /** Whether more data is available */
8
+ hasMore: boolean;
9
+ /** Whether data is currently loading */
10
+ isLoading: boolean;
11
+ /** Distance from bottom to trigger (px) */
12
+ threshold?: number;
13
+ }>(),
14
+ {
15
+ threshold: 200,
16
+ },
17
+ );
18
+
19
+ const emit = defineEmits<{
20
+ "load-more": [];
21
+ }>();
22
+
23
+ const scrollContainer = ref<HTMLElement | null>(null);
24
+
25
+ const { sentinelRef } = useInfiniteScroll({
26
+ scrollContainer,
27
+ threshold: props.threshold,
28
+ hasMore: toRef(() => props.hasMore),
29
+ isLoading: toRef(() => props.isLoading),
30
+ onLoadMore: () => emit("load-more"),
31
+ });
32
+ </script>
33
+
34
+ <template>
35
+ <div ref="scrollContainer">
36
+ <slot />
37
+
38
+ <!-- Sentinel observed by IntersectionObserver -->
39
+ <div ref="sentinelRef" class="h-px w-full" aria-hidden="true" />
40
+
41
+ <!-- Loading indicator -->
42
+ <div v-if="isLoading" class="flex justify-center py-4">
43
+ <slot name="loading">
44
+ <div
45
+ class="h-5 w-5 animate-spin rounded-full border-2 border-muted-foreground border-t-transparent"
46
+ />
47
+ </slot>
48
+ </div>
49
+
50
+ <!-- End of list -->
51
+ <div v-else-if="!hasMore" class="py-4 text-center text-sm text-muted-foreground">
52
+ <slot name="end" />
53
+ </div>
54
+ </div>
55
+ </template>
@@ -0,0 +1,2 @@
1
+ export { useInfiniteScroll } from "./useInfiniteScroll";
2
+ export type { InfiniteScrollOptions, InfiniteScrollReturn } from "./types";
@@ -0,0 +1,23 @@
1
+ import type { Ref, MaybeRefOrGetter } from "vue";
2
+
3
+ export interface InfiniteScrollOptions {
4
+ /** The scrollable container element. Defaults to window if not provided. */
5
+ scrollContainer?: Ref<HTMLElement | null>;
6
+ /** Distance in pixels from the bottom to trigger loading (default: 200) */
7
+ threshold?: number;
8
+ /** Whether more data is available */
9
+ hasMore: MaybeRefOrGetter<boolean>;
10
+ /** Whether data is currently loading */
11
+ isLoading: MaybeRefOrGetter<boolean>;
12
+ /** Callback invoked when the sentinel enters the viewport */
13
+ onLoadMore: () => void;
14
+ }
15
+
16
+ export interface InfiniteScrollReturn {
17
+ /** Ref to bind to the sentinel element */
18
+ sentinelRef: Ref<HTMLElement | null>;
19
+ /** Manually trigger a check (e.g., after DOM updates) */
20
+ check: () => void;
21
+ /** Stop observing */
22
+ stop: () => void;
23
+ }
@@ -0,0 +1,73 @@
1
+ import { ref, watch, onScopeDispose, toValue, type MaybeRefOrGetter } from "vue";
2
+ import type { InfiniteScrollOptions, InfiniteScrollReturn } from "./types";
3
+
4
+ /**
5
+ * Composable for infinite scroll with IntersectionObserver.
6
+ *
7
+ * Watches a sentinel element at the bottom of the scrollable area.
8
+ * When it enters the viewport and `hasMore` is true / `isLoading` is false,
9
+ * the `onLoadMore` callback fires.
10
+ */
11
+ export function useInfiniteScroll(options: InfiniteScrollOptions): InfiniteScrollReturn {
12
+ const { threshold = 200, hasMore, isLoading, onLoadMore } = options;
13
+ const sentinelRef = ref<HTMLElement | null>(null);
14
+ let observer: IntersectionObserver | null = null;
15
+
16
+ function shouldLoad(): boolean {
17
+ return toValue(hasMore) && !toValue(isLoading);
18
+ }
19
+
20
+ function handleIntersect(entries: IntersectionObserverEntry[]) {
21
+ for (const entry of entries) {
22
+ if (entry.isIntersecting && shouldLoad()) {
23
+ onLoadMore();
24
+ }
25
+ }
26
+ }
27
+
28
+ function setupObserver(el: HTMLElement) {
29
+ teardown();
30
+ observer = new IntersectionObserver(handleIntersect, {
31
+ root: options.scrollContainer?.value ?? null,
32
+ rootMargin: `0px 0px ${threshold}px 0px`,
33
+ });
34
+ observer.observe(el);
35
+ }
36
+
37
+ function teardown() {
38
+ if (observer) {
39
+ observer.disconnect();
40
+ observer = null;
41
+ }
42
+ }
43
+
44
+ function check() {
45
+ if (sentinelRef.value && shouldLoad()) {
46
+ onLoadMore();
47
+ }
48
+ }
49
+
50
+ watch(sentinelRef, (el) => {
51
+ if (el) setupObserver(el);
52
+ else teardown();
53
+ });
54
+
55
+ // Re-check when loading finishes (new content may be short enough to need another load)
56
+ watch(
57
+ () => toValue(isLoading),
58
+ (loading) => {
59
+ if (!loading && sentinelRef.value) {
60
+ // Defer to next tick so DOM updates first
61
+ requestAnimationFrame(check);
62
+ }
63
+ },
64
+ );
65
+
66
+ onScopeDispose(teardown);
67
+
68
+ return {
69
+ sentinelRef,
70
+ check,
71
+ stop: teardown,
72
+ };
73
+ }
@@ -0,0 +1 @@
1
+ export { default as InfiniteScroll } from "./InfiniteScroll.vue";
@@ -0,0 +1,29 @@
1
+ <template>
2
+ <IconTooltip :text="tooltip">
3
+ <label :class="labelClass ?? 'font-display text-lg text-muted-foreground cursor-help'">{{ label }}</label>
4
+ </IconTooltip>
5
+ <Input
6
+ :type="type ?? 'string'"
7
+ :class="inputClass ?? 'font-mono-code'"
8
+ :model-value="modelValue"
9
+ @change="(e: Event) => emit('update:modelValue', (e.target as HTMLInputElement).value)"
10
+ />
11
+ </template>
12
+
13
+ <script setup lang="ts">
14
+ import { IconTooltip } from "../icon-tooltip";
15
+ import { Input } from "../../ui/input";
16
+
17
+ defineProps<{
18
+ modelValue: string | number;
19
+ label: string;
20
+ tooltip: string;
21
+ labelClass?: string;
22
+ inputClass?: string;
23
+ type?: string;
24
+ }>();
25
+
26
+ const emit = defineEmits<{
27
+ "update:modelValue": [value: string];
28
+ }>();
29
+ </script>
@@ -0,0 +1,59 @@
1
+ <template>
2
+ <IconTooltip :text="tooltip">
3
+ <label :class="labelClass ?? 'font-display text-lg text-muted-foreground cursor-help'">{{ label }}</label>
4
+ </IconTooltip>
5
+ <Select
6
+ :model-value="modelValue"
7
+ :open="isOpen"
8
+ @update:open="(v: boolean) => emit('update:open', v)"
9
+ @update:model-value="(v: any) => emit('update:modelValue', v)"
10
+ >
11
+ <SelectTrigger class="font-mono-code">
12
+ <SelectValue />
13
+ </SelectTrigger>
14
+ <SelectContent>
15
+ <SelectGroup class="font-mono-code">
16
+ <SelectItem
17
+ v-for="item in items"
18
+ :key="item"
19
+ :value="item"
20
+ >
21
+ {{ item }}
22
+ <template #description>
23
+ <span
24
+ v-if="descriptions?.[item]"
25
+ class="ml-auto pl-2 text-2xs text-muted-foreground whitespace-nowrap"
26
+ >{{ descriptions[item] }}</span>
27
+ </template>
28
+ </SelectItem>
29
+ </SelectGroup>
30
+ </SelectContent>
31
+ </Select>
32
+ </template>
33
+
34
+ <script setup lang="ts">
35
+ import { IconTooltip } from "../icon-tooltip";
36
+ import {
37
+ Select,
38
+ SelectContent,
39
+ SelectGroup,
40
+ SelectItem,
41
+ SelectTrigger,
42
+ SelectValue,
43
+ } from "../../ui/select";
44
+
45
+ defineProps<{
46
+ modelValue: string;
47
+ isOpen: boolean;
48
+ items: readonly string[];
49
+ descriptions?: Record<string, string>;
50
+ label: string;
51
+ tooltip: string;
52
+ labelClass?: string;
53
+ }>();
54
+
55
+ const emit = defineEmits<{
56
+ "update:modelValue": [value: string];
57
+ "update:open": [value: boolean];
58
+ }>();
59
+ </script>
@@ -0,0 +1,32 @@
1
+ <template>
2
+ <IconTooltip :text="tooltip">
3
+ <label :class="labelClass ?? 'font-display text-base text-muted-foreground cursor-help'">{{ label }}</label>
4
+ </IconTooltip>
5
+ <Slider
6
+ class="py-2"
7
+ :min="min"
8
+ :max="max"
9
+ :step="step"
10
+ :model-value="[modelValue]"
11
+ @update:model-value="(v: number[] | undefined) => { if (v) emit('update:modelValue', v[0]!) }"
12
+ />
13
+ </template>
14
+
15
+ <script setup lang="ts">
16
+ import { IconTooltip } from "../icon-tooltip";
17
+ import { Slider } from "../../ui/slider";
18
+
19
+ defineProps<{
20
+ modelValue: number;
21
+ label: string;
22
+ tooltip: string;
23
+ labelClass?: string;
24
+ min: number;
25
+ max: number;
26
+ step: number;
27
+ }>();
28
+
29
+ const emit = defineEmits<{
30
+ "update:modelValue": [value: number];
31
+ }>();
32
+ </script>
@@ -0,0 +1,27 @@
1
+ <template>
2
+ <IconTooltip :text="tooltip">
3
+ <label :class="labelClass ?? 'font-display text-base text-muted-foreground cursor-help'">{{ label }}</label>
4
+ </IconTooltip>
5
+ <div class="flex items-center">
6
+ <Switch
7
+ :checked="checked"
8
+ @update:checked="(v: boolean) => emit('update:checked', v)"
9
+ />
10
+ </div>
11
+ </template>
12
+
13
+ <script setup lang="ts">
14
+ import { IconTooltip } from "../icon-tooltip";
15
+ import { Switch } from "../../ui/switch";
16
+
17
+ defineProps<{
18
+ checked: boolean;
19
+ label: string;
20
+ tooltip: string;
21
+ labelClass?: string;
22
+ }>();
23
+
24
+ const emit = defineEmits<{
25
+ "update:checked": [value: boolean];
26
+ }>();
27
+ </script>
@@ -0,0 +1,4 @@
1
+ export { default as LabeledInput } from "./LabeledInput.vue";
2
+ export { default as LabeledSelect } from "./LabeledSelect.vue";
3
+ export { default as LabeledSlider } from "./LabeledSlider.vue";
4
+ export { default as LabeledSwitch } from "./LabeledSwitch.vue";
@@ -0,0 +1,23 @@
1
+ <script setup lang="ts">
2
+ import { ref } from "vue";
3
+ import { useMetaballs } from "./useMetaballs";
4
+ import type { MetaballConfig } from "./types";
5
+
6
+ const props = defineProps<{
7
+ config?: MetaballConfig;
8
+ }>();
9
+
10
+ const canvasRef = ref<HTMLCanvasElement | null>(null);
11
+ const { isSupported } = useMetaballs(canvasRef, props.config);
12
+
13
+ defineExpose({ isSupported });
14
+ </script>
15
+
16
+ <template>
17
+ <canvas
18
+ v-if="isSupported"
19
+ ref="canvasRef"
20
+ class="pointer-events-none fixed inset-0 -z-10 h-full w-full"
21
+ />
22
+ <slot v-else name="fallback" />
23
+ </template>
@@ -0,0 +1,4 @@
1
+ export { default as MetaballCanvas } from "./MetaballCanvas.vue";
2
+ export { useMetaballs } from "./useMetaballs";
3
+ export type { MetaballConfig } from "./types";
4
+ export { DEFAULT_METABALL_CONFIG } from "./types";
@@ -0,0 +1,63 @@
1
+ export const VERTEX_SHADER = `
2
+ attribute vec2 a_position;
3
+ void main() {
4
+ gl_Position = vec4(a_position, 0.0, 1.0);
5
+ }
6
+ `;
7
+
8
+ /**
9
+ * Metaball fragment shader.
10
+ *
11
+ * Computes a density field per pixel by summing inverse-square
12
+ * contributions from all blobs. Pixels above the threshold
13
+ * render as colored goo with smooth edges.
14
+ */
15
+ export const FRAGMENT_SHADER = `
16
+ precision mediump float;
17
+
18
+ #define MAX_BLOBS 16
19
+
20
+ uniform vec2 u_resolution;
21
+ uniform int u_blobCount;
22
+ uniform vec3 u_positions[MAX_BLOBS];
23
+ uniform vec3 u_colors[MAX_BLOBS];
24
+ uniform float u_threshold;
25
+ uniform float u_edgeSoftness;
26
+ uniform float u_bgAlpha;
27
+
28
+ void main() {
29
+ vec2 uv = gl_FragCoord.xy / u_resolution;
30
+ float aspect = u_resolution.x / u_resolution.y;
31
+ vec2 coord = vec2(uv.x * aspect, uv.y);
32
+
33
+ float density = 0.0;
34
+ vec3 color = vec3(0.0);
35
+
36
+ for (int i = 0; i < MAX_BLOBS; i++) {
37
+ if (i >= u_blobCount) break;
38
+
39
+ vec2 pos = vec2(u_positions[i].x * aspect, u_positions[i].y);
40
+ float radius = u_positions[i].z;
41
+ float dist = distance(coord, pos);
42
+ float contrib = (radius * radius) / (dist * dist + 0.0001);
43
+
44
+ density += contrib;
45
+ color += contrib * u_colors[i];
46
+ }
47
+
48
+ if (density > u_threshold * 0.4) {
49
+ color /= density;
50
+ // Gooey edge: slightly wider smoothstep for organic merge zone
51
+ float edge = smoothstep(
52
+ u_threshold * (1.0 - u_edgeSoftness),
53
+ u_threshold * (1.0 + u_edgeSoftness * 0.3),
54
+ density
55
+ );
56
+ // Solid core with soft goo boundary — full color at core
57
+ gl_FragColor = vec4(color, edge * (1.0 - u_bgAlpha * 0.3));
58
+ } else {
59
+ // Background: transparent (let page bg show through) with optional tint
60
+ gl_FragColor = vec4(0.0, 0.0, 0.0, u_bgAlpha * 0.15);
61
+ }
62
+ }
63
+ `;
@@ -0,0 +1,29 @@
1
+ export interface MetaballConfig {
2
+ /** Number of blobs (default 8, max 16 for shader uniform limit) */
3
+ blobCount?: number;
4
+ /** Animation speed multiplier (default 0.08) */
5
+ speed?: number;
6
+ /** Density threshold for surface rendering (default 1.0, higher = sharper edges) */
7
+ threshold?: number;
8
+ /** Base blob radius as fraction of viewport (default 0.12) */
9
+ baseRadius?: number;
10
+ /** Orbital drift amplitude as fraction of viewport (default 0.3) */
11
+ orbitAmplitude?: number;
12
+ /** CSS color strings for blob colors (cycles if fewer than blobCount) */
13
+ colors?: string[];
14
+ /** Background alpha (0 = fully transparent, default 0) */
15
+ bgAlpha?: number;
16
+ /** Edge softness — smoothstep range as fraction of threshold (default 0.3) */
17
+ edgeSoftness?: number;
18
+ }
19
+
20
+ export const DEFAULT_METABALL_CONFIG: Required<MetaballConfig> = {
21
+ blobCount: 8,
22
+ speed: 0.08,
23
+ threshold: 1.0,
24
+ baseRadius: 0.12,
25
+ orbitAmplitude: 0.3,
26
+ colors: ["#E31937", "#FF6B35", "#FFA726", "#EF5350"],
27
+ bgAlpha: 0,
28
+ edgeSoftness: 0.3,
29
+ };