@glinui/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 (244) hide show
  1. package/dist/components/accordion.d.ts +42 -0
  2. package/dist/components/accordion.d.ts.map +1 -0
  3. package/dist/components/accordion.js +85 -0
  4. package/dist/components/alert-dialog.d.ts +30 -0
  5. package/dist/components/alert-dialog.d.ts.map +1 -0
  6. package/dist/components/alert-dialog.js +53 -0
  7. package/dist/components/alert.d.ts +15 -0
  8. package/dist/components/alert.d.ts.map +1 -0
  9. package/dist/components/alert.js +39 -0
  10. package/dist/components/animated-gradient.d.ts +11 -0
  11. package/dist/components/animated-gradient.d.ts.map +1 -0
  12. package/dist/components/animated-gradient.js +23 -0
  13. package/dist/components/aurora-background.d.ts +15 -0
  14. package/dist/components/aurora-background.d.ts.map +1 -0
  15. package/dist/components/aurora-background.js +26 -0
  16. package/dist/components/avatar.d.ts +54 -0
  17. package/dist/components/avatar.d.ts.map +1 -0
  18. package/dist/components/avatar.js +92 -0
  19. package/dist/components/badge.d.ts +13 -0
  20. package/dist/components/badge.d.ts.map +1 -0
  21. package/dist/components/badge.js +32 -0
  22. package/dist/components/blur-fade.d.ts +17 -0
  23. package/dist/components/blur-fade.d.ts.map +1 -0
  24. package/dist/components/blur-fade.js +48 -0
  25. package/dist/components/blur-spotlight.d.ts +13 -0
  26. package/dist/components/blur-spotlight.d.ts.map +1 -0
  27. package/dist/components/blur-spotlight.js +58 -0
  28. package/dist/components/border-beam.d.ts +11 -0
  29. package/dist/components/border-beam.d.ts.map +1 -0
  30. package/dist/components/border-beam.js +14 -0
  31. package/dist/components/button.d.ts +17 -0
  32. package/dist/components/button.d.ts.map +1 -0
  33. package/dist/components/button.js +33 -0
  34. package/dist/components/card.d.ts +39 -0
  35. package/dist/components/card.d.ts.map +1 -0
  36. package/dist/components/card.js +81 -0
  37. package/dist/components/checkbox.d.ts +14 -0
  38. package/dist/components/checkbox.d.ts.map +1 -0
  39. package/dist/components/checkbox.js +58 -0
  40. package/dist/components/chip.d.ts +15 -0
  41. package/dist/components/chip.d.ts.map +1 -0
  42. package/dist/components/chip.js +35 -0
  43. package/dist/components/chromatic-text.d.ts +11 -0
  44. package/dist/components/chromatic-text.d.ts.map +1 -0
  45. package/dist/components/chromatic-text.js +22 -0
  46. package/dist/components/code.d.ts +13 -0
  47. package/dist/components/code.d.ts.map +1 -0
  48. package/dist/components/code.js +27 -0
  49. package/dist/components/command.d.ts +89 -0
  50. package/dist/components/command.d.ts.map +1 -0
  51. package/dist/components/command.js +123 -0
  52. package/dist/components/counter.d.ts +19 -0
  53. package/dist/components/counter.d.ts.map +1 -0
  54. package/dist/components/counter.js +28 -0
  55. package/dist/components/data-table.d.ts +38 -0
  56. package/dist/components/data-table.d.ts.map +1 -0
  57. package/dist/components/data-table.js +183 -0
  58. package/dist/components/depth-card.d.ts +15 -0
  59. package/dist/components/depth-card.d.ts.map +1 -0
  60. package/dist/components/depth-card.js +52 -0
  61. package/dist/components/dot-pattern.d.ts +10 -0
  62. package/dist/components/dot-pattern.d.ts.map +1 -0
  63. package/dist/components/dot-pattern.js +10 -0
  64. package/dist/components/dropdown-menu.d.ts +74 -0
  65. package/dist/components/dropdown-menu.d.ts.map +1 -0
  66. package/dist/components/dropdown-menu.js +90 -0
  67. package/dist/components/floating-panel.d.ts +17 -0
  68. package/dist/components/floating-panel.d.ts.map +1 -0
  69. package/dist/components/floating-panel.js +57 -0
  70. package/dist/components/glass-breadcrumb.d.ts +17 -0
  71. package/dist/components/glass-breadcrumb.d.ts.map +1 -0
  72. package/dist/components/glass-breadcrumb.js +14 -0
  73. package/dist/components/glass-card.d.ts +20 -0
  74. package/dist/components/glass-card.d.ts.map +1 -0
  75. package/dist/components/glass-card.js +36 -0
  76. package/dist/components/glass-dock.d.ts +21 -0
  77. package/dist/components/glass-dock.d.ts.map +1 -0
  78. package/dist/components/glass-dock.js +54 -0
  79. package/dist/components/glass-navbar.d.ts +21 -0
  80. package/dist/components/glass-navbar.d.ts.map +1 -0
  81. package/dist/components/glass-navbar.js +43 -0
  82. package/dist/components/glass-toggle.d.ts +15 -0
  83. package/dist/components/glass-toggle.d.ts.map +1 -0
  84. package/dist/components/glass-toggle.js +32 -0
  85. package/dist/components/glow-border.d.ts +13 -0
  86. package/dist/components/glow-border.d.ts.map +1 -0
  87. package/dist/components/glow-border.js +10 -0
  88. package/dist/components/gradient-mesh.d.ts +13 -0
  89. package/dist/components/gradient-mesh.d.ts.map +1 -0
  90. package/dist/components/gradient-mesh.js +25 -0
  91. package/dist/components/heading.d.ts +18 -0
  92. package/dist/components/heading.d.ts.map +1 -0
  93. package/dist/components/heading.js +28 -0
  94. package/dist/components/hover-card.d.ts +32 -0
  95. package/dist/components/hover-card.d.ts.map +1 -0
  96. package/dist/components/hover-card.js +28 -0
  97. package/dist/components/icon-frame.d.ts +13 -0
  98. package/dist/components/icon-frame.d.ts.map +1 -0
  99. package/dist/components/icon-frame.js +27 -0
  100. package/dist/components/input.d.ts +13 -0
  101. package/dist/components/input.d.ts.map +1 -0
  102. package/dist/components/input.js +38 -0
  103. package/dist/components/kbd.d.ts +13 -0
  104. package/dist/components/kbd.d.ts.map +1 -0
  105. package/dist/components/kbd.js +27 -0
  106. package/dist/components/label.d.ts +13 -0
  107. package/dist/components/label.d.ts.map +1 -0
  108. package/dist/components/label.js +27 -0
  109. package/dist/components/light-leak.d.ts +15 -0
  110. package/dist/components/light-leak.d.ts.map +1 -0
  111. package/dist/components/light-leak.js +29 -0
  112. package/dist/components/link.d.ts +15 -0
  113. package/dist/components/link.d.ts.map +1 -0
  114. package/dist/components/link.js +32 -0
  115. package/dist/components/liquid-button.d.ts +17 -0
  116. package/dist/components/liquid-button.d.ts.map +1 -0
  117. package/dist/components/liquid-button.js +18 -0
  118. package/dist/components/magnetic-cta.d.ts +18 -0
  119. package/dist/components/magnetic-cta.d.ts.map +1 -0
  120. package/dist/components/magnetic-cta.js +46 -0
  121. package/dist/components/marquee.d.ts +10 -0
  122. package/dist/components/marquee.d.ts.map +1 -0
  123. package/dist/components/marquee.js +16 -0
  124. package/dist/components/meteor-shower.d.ts +11 -0
  125. package/dist/components/meteor-shower.d.ts.map +1 -0
  126. package/dist/components/meteor-shower.js +39 -0
  127. package/dist/components/modal.d.ts +30 -0
  128. package/dist/components/modal.d.ts.map +1 -0
  129. package/dist/components/modal.js +39 -0
  130. package/dist/components/morphing-tabs.d.ts +22 -0
  131. package/dist/components/morphing-tabs.d.ts.map +1 -0
  132. package/dist/components/morphing-tabs.js +72 -0
  133. package/dist/components/number-ticker.d.ts +11 -0
  134. package/dist/components/number-ticker.d.ts.map +1 -0
  135. package/dist/components/number-ticker.js +66 -0
  136. package/dist/components/orbiting-circles.d.ts +21 -0
  137. package/dist/components/orbiting-circles.d.ts.map +1 -0
  138. package/dist/components/orbiting-circles.js +24 -0
  139. package/dist/components/particle-field.d.ts +19 -0
  140. package/dist/components/particle-field.d.ts.map +1 -0
  141. package/dist/components/particle-field.js +41 -0
  142. package/dist/components/popover.d.ts +27 -0
  143. package/dist/components/popover.d.ts.map +1 -0
  144. package/dist/components/popover.js +52 -0
  145. package/dist/components/prism-border.d.ts +13 -0
  146. package/dist/components/prism-border.d.ts.map +1 -0
  147. package/dist/components/prism-border.js +16 -0
  148. package/dist/components/progress.d.ts +58 -0
  149. package/dist/components/progress.d.ts.map +1 -0
  150. package/dist/components/progress.js +108 -0
  151. package/dist/components/pulsating-button.d.ts +13 -0
  152. package/dist/components/pulsating-button.d.ts.map +1 -0
  153. package/dist/components/pulsating-button.js +40 -0
  154. package/dist/components/radio-group.d.ts +27 -0
  155. package/dist/components/radio-group.d.ts.map +1 -0
  156. package/dist/components/radio-group.js +58 -0
  157. package/dist/components/retro-grid.d.ts +13 -0
  158. package/dist/components/retro-grid.d.ts.map +1 -0
  159. package/dist/components/retro-grid.js +17 -0
  160. package/dist/components/reveal-text.d.ts +17 -0
  161. package/dist/components/reveal-text.d.ts.map +1 -0
  162. package/dist/components/reveal-text.js +61 -0
  163. package/dist/components/ripple-button.d.ts +11 -0
  164. package/dist/components/ripple-button.d.ts.map +1 -0
  165. package/dist/components/ripple-button.js +47 -0
  166. package/dist/components/ripple.d.ts +13 -0
  167. package/dist/components/ripple.d.ts.map +1 -0
  168. package/dist/components/ripple.js +24 -0
  169. package/dist/components/select.d.ts +24 -0
  170. package/dist/components/select.d.ts.map +1 -0
  171. package/dist/components/select.js +30 -0
  172. package/dist/components/separator.d.ts +29 -0
  173. package/dist/components/separator.d.ts.map +1 -0
  174. package/dist/components/separator.js +84 -0
  175. package/dist/components/sheet.d.ts +41 -0
  176. package/dist/components/sheet.d.ts.map +1 -0
  177. package/dist/components/sheet.js +85 -0
  178. package/dist/components/shimmer-button.d.ts +13 -0
  179. package/dist/components/shimmer-button.d.ts.map +1 -0
  180. package/dist/components/shimmer-button.js +32 -0
  181. package/dist/components/skeleton.d.ts +17 -0
  182. package/dist/components/skeleton.d.ts.map +1 -0
  183. package/dist/components/skeleton.js +42 -0
  184. package/dist/components/slider.d.ts +14 -0
  185. package/dist/components/slider.d.ts.map +1 -0
  186. package/dist/components/slider.js +89 -0
  187. package/dist/components/sonner.d.ts +14 -0
  188. package/dist/components/sonner.d.ts.map +1 -0
  189. package/dist/components/sonner.js +70 -0
  190. package/dist/components/spotlight-card.d.ts +11 -0
  191. package/dist/components/spotlight-card.d.ts.map +1 -0
  192. package/dist/components/spotlight-card.js +39 -0
  193. package/dist/components/spotlight.d.ts +19 -0
  194. package/dist/components/spotlight.d.ts.map +1 -0
  195. package/dist/components/spotlight.js +23 -0
  196. package/dist/components/status-dot.d.ts +24 -0
  197. package/dist/components/status-dot.d.ts.map +1 -0
  198. package/dist/components/status-dot.js +46 -0
  199. package/dist/components/switch.d.ts +42 -0
  200. package/dist/components/switch.d.ts.map +1 -0
  201. package/dist/components/switch.js +77 -0
  202. package/dist/components/table.d.ts +69 -0
  203. package/dist/components/table.d.ts.map +1 -0
  204. package/dist/components/table.js +176 -0
  205. package/dist/components/tabs.d.ts +34 -0
  206. package/dist/components/tabs.d.ts.map +1 -0
  207. package/dist/components/tabs.js +75 -0
  208. package/dist/components/text-reveal.d.ts +6 -0
  209. package/dist/components/text-reveal.d.ts.map +1 -0
  210. package/dist/components/text-reveal.js +56 -0
  211. package/dist/components/text.d.ts +13 -0
  212. package/dist/components/text.d.ts.map +1 -0
  213. package/dist/components/text.js +27 -0
  214. package/dist/components/textarea.d.ts +13 -0
  215. package/dist/components/textarea.d.ts.map +1 -0
  216. package/dist/components/textarea.js +37 -0
  217. package/dist/components/toast.d.ts +23 -0
  218. package/dist/components/toast.d.ts.map +1 -0
  219. package/dist/components/toast.js +36 -0
  220. package/dist/components/tooltip.d.ts +35 -0
  221. package/dist/components/tooltip.d.ts.map +1 -0
  222. package/dist/components/tooltip.js +34 -0
  223. package/dist/components/tree.d.ts +50 -0
  224. package/dist/components/tree.d.ts.map +1 -0
  225. package/dist/components/tree.js +77 -0
  226. package/dist/components/typewriter.d.ts +25 -0
  227. package/dist/components/typewriter.d.ts.map +1 -0
  228. package/dist/components/typewriter.js +109 -0
  229. package/dist/components/word-rotate.d.ts +11 -0
  230. package/dist/components/word-rotate.d.ts.map +1 -0
  231. package/dist/components/word-rotate.js +29 -0
  232. package/dist/index.d.ts +80 -0
  233. package/dist/index.d.ts.map +1 -0
  234. package/dist/index.js +79 -0
  235. package/dist/lib/cn.d.ts +3 -0
  236. package/dist/lib/cn.d.ts.map +1 -0
  237. package/dist/lib/cn.js +5 -0
  238. package/dist/lib/use-liquid-glass.d.ts +46 -0
  239. package/dist/lib/use-liquid-glass.d.ts.map +1 -0
  240. package/dist/lib/use-liquid-glass.js +144 -0
  241. package/dist/lib/use-prefers-reduced-motion.d.ts +2 -0
  242. package/dist/lib/use-prefers-reduced-motion.d.ts.map +1 -0
  243. package/dist/lib/use-prefers-reduced-motion.js +23 -0
  244. package/package.json +72 -0
@@ -0,0 +1,109 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import * as React from "react";
4
+ import { cn } from "../lib/cn";
5
+ import { usePrefersReducedMotion } from "../lib/use-prefers-reduced-motion";
6
+ export const Typewriter = React.forwardRef(({ className, text, words, speed = 50, deleteSpeed = 30, delay = 0, cursor = true, cursorChar = "|", loop = false, pauseDuration = 1500, onComplete, "aria-label": ariaLabel, ...props }, ref) => {
7
+ const prefersReducedMotion = usePrefersReducedMotion();
8
+ const [displayedText, setDisplayedText] = React.useState("");
9
+ const [phase, setPhase] = React.useState("idle");
10
+ // Resolve the word list: words array takes priority, fallback to single text
11
+ const wordList = React.useMemo(() => {
12
+ if (words && words.length > 0)
13
+ return words;
14
+ if (text)
15
+ return [text];
16
+ return [""];
17
+ }, [words, text]);
18
+ const isMultiWord = wordList.length > 1;
19
+ // Stable ref so effect deps stay minimal
20
+ const onCompleteRef = React.useRef(onComplete);
21
+ React.useEffect(() => {
22
+ onCompleteRef.current = onComplete;
23
+ }, [onComplete]);
24
+ React.useEffect(() => {
25
+ // Reduced-motion: show first word immediately with no animation
26
+ if (prefersReducedMotion) {
27
+ setDisplayedText(wordList[0]);
28
+ setPhase("pausing");
29
+ onCompleteRef.current?.();
30
+ return;
31
+ }
32
+ let wordIndex = 0;
33
+ let charIndex = 0;
34
+ let timeoutId;
35
+ let cancelled = false;
36
+ const typeWord = () => {
37
+ if (cancelled)
38
+ return;
39
+ const currentWord = wordList[wordIndex];
40
+ setPhase("typing");
41
+ const typeStep = () => {
42
+ if (cancelled)
43
+ return;
44
+ if (charIndex <= currentWord.length) {
45
+ setDisplayedText(currentWord.slice(0, charIndex));
46
+ charIndex += 1;
47
+ timeoutId = setTimeout(typeStep, speed);
48
+ }
49
+ else {
50
+ // Finished typing current word
51
+ setPhase("pausing");
52
+ onCompleteRef.current?.();
53
+ if (isMultiWord || loop) {
54
+ timeoutId = setTimeout(() => {
55
+ if (cancelled)
56
+ return;
57
+ deleteWord(currentWord);
58
+ }, pauseDuration);
59
+ }
60
+ }
61
+ };
62
+ typeStep();
63
+ };
64
+ const deleteWord = (currentWord) => {
65
+ if (cancelled)
66
+ return;
67
+ setPhase("deleting");
68
+ let delIndex = currentWord.length;
69
+ const deleteStep = () => {
70
+ if (cancelled)
71
+ return;
72
+ if (delIndex >= 0) {
73
+ setDisplayedText(currentWord.slice(0, delIndex));
74
+ delIndex -= 1;
75
+ timeoutId = setTimeout(deleteStep, deleteSpeed);
76
+ }
77
+ else {
78
+ // Finished deleting — move to next word
79
+ wordIndex = (wordIndex + 1) % wordList.length;
80
+ // If not looping and we've cycled through all words, stop
81
+ if (!loop && wordIndex === 0 && !isMultiWord) {
82
+ setPhase("pausing");
83
+ return;
84
+ }
85
+ charIndex = 0;
86
+ timeoutId = setTimeout(typeWord, speed * 2);
87
+ }
88
+ };
89
+ deleteStep();
90
+ };
91
+ setDisplayedText("");
92
+ setPhase("idle");
93
+ charIndex = 0;
94
+ wordIndex = 0;
95
+ timeoutId = setTimeout(typeWord, delay);
96
+ return () => {
97
+ cancelled = true;
98
+ clearTimeout(timeoutId);
99
+ };
100
+ }, [wordList, speed, deleteSpeed, delay, loop, pauseDuration, isMultiWord, prefersReducedMotion]);
101
+ // Cursor blinks when pausing; solid while actively typing/deleting
102
+ const cursorBlinking = phase === "pausing";
103
+ // For aria-label: join all words or use single text
104
+ const fullLabel = ariaLabel ?? wordList.join(", ");
105
+ return (_jsxs("span", { ref: ref, "aria-label": fullLabel, "aria-live": "off", className: cn("inline-flex items-baseline", className), ...props, children: [_jsx("span", { "aria-hidden": "true", children: displayedText }), cursor && (_jsx("span", { "aria-hidden": "true", className: cn("ml-[0.05em] inline-block select-none", cursorBlinking
106
+ ? "animate-blink motion-reduce:[animation:none]"
107
+ : "opacity-100"), children: cursorChar }))] }));
108
+ });
109
+ Typewriter.displayName = "Typewriter";
@@ -0,0 +1,11 @@
1
+ import * as React from "react";
2
+ export interface WordRotateProps extends React.HTMLAttributes<HTMLSpanElement> {
3
+ /** Array of words to cycle through */
4
+ words: string[];
5
+ /** Duration each word is shown (ms) */
6
+ duration?: number;
7
+ /** Animation speed for enter/exit (ms) */
8
+ animationDuration?: number;
9
+ }
10
+ export declare const WordRotate: React.ForwardRefExoticComponent<WordRotateProps & React.RefAttributes<HTMLSpanElement>>;
11
+ //# sourceMappingURL=word-rotate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"word-rotate.d.ts","sourceRoot":"","sources":["../../src/components/word-rotate.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAG9B,MAAM,WAAW,eAAgB,SAAQ,KAAK,CAAC,cAAc,CAAC,eAAe,CAAC;IAC5E,sCAAsC;IACtC,KAAK,EAAE,MAAM,EAAE,CAAA;IACf,uCAAuC;IACvC,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,0CAA0C;IAC1C,iBAAiB,CAAC,EAAE,MAAM,CAAA;CAC3B;AAED,eAAO,MAAM,UAAU,yFA0DtB,CAAA"}
@@ -0,0 +1,29 @@
1
+ "use client";
2
+ import { jsx as _jsx } from "react/jsx-runtime";
3
+ import * as React from "react";
4
+ import { cn } from "../lib/cn";
5
+ export const WordRotate = React.forwardRef(({ className, words, duration = 2500, animationDuration = 300, style, ...props }, ref) => {
6
+ const [currentIndex, setCurrentIndex] = React.useState(0);
7
+ const [animating, setAnimating] = React.useState("idle");
8
+ React.useEffect(() => {
9
+ if (words.length <= 1)
10
+ return;
11
+ const prefersReduced = typeof window !== "undefined" && window.matchMedia("(prefers-reduced-motion: reduce)").matches;
12
+ if (prefersReduced)
13
+ return;
14
+ const timer = setInterval(() => {
15
+ setAnimating("out");
16
+ setTimeout(() => {
17
+ setCurrentIndex((prev) => (prev + 1) % words.length);
18
+ setAnimating("in");
19
+ setTimeout(() => setAnimating("idle"), animationDuration);
20
+ }, animationDuration);
21
+ }, duration);
22
+ return () => clearInterval(timer);
23
+ }, [words, duration, animationDuration]);
24
+ return (_jsx("span", { ref: ref, className: cn("inline-block overflow-hidden", className), style: {
25
+ "--word-rotate-duration": `${animationDuration}ms`,
26
+ ...style,
27
+ }, ...props, children: _jsx("span", { className: cn("inline-block", animating === "in" && "animate-word-rotate-in", animating === "out" && "animate-word-rotate-out", "motion-reduce:[animation:none]"), "aria-live": "polite", children: words[currentIndex] }, currentIndex) }));
28
+ });
29
+ WordRotate.displayName = "WordRotate";
@@ -0,0 +1,80 @@
1
+ export * from "./components/accordion";
2
+ export * from "./components/alert-dialog";
3
+ export * from "./components/animated-gradient";
4
+ export * from "./components/alert";
5
+ export * from "./components/aurora-background";
6
+ export * from "./components/avatar";
7
+ export * from "./components/badge";
8
+ export * from "./components/blur-fade";
9
+ export * from "./components/blur-spotlight";
10
+ export * from "./components/border-beam";
11
+ export * from "./components/button";
12
+ export * from "./components/card";
13
+ export * from "./components/checkbox";
14
+ export * from "./components/chip";
15
+ export * from "./components/chromatic-text";
16
+ export * from "./components/code";
17
+ export * from "./components/command";
18
+ export * from "./components/counter";
19
+ export * from "./components/data-table";
20
+ export * from "./components/depth-card";
21
+ export * from "./components/dot-pattern";
22
+ export * from "./components/dropdown-menu";
23
+ export * from "./components/floating-panel";
24
+ export * from "./components/glass-breadcrumb";
25
+ export * from "./components/glass-card";
26
+ export * from "./components/glass-dock";
27
+ export * from "./components/glow-border";
28
+ export * from "./components/gradient-mesh";
29
+ export * from "./components/glass-navbar";
30
+ export * from "./components/glass-toggle";
31
+ export * from "./components/heading";
32
+ export * from "./components/hover-card";
33
+ export * from "./components/icon-frame";
34
+ export * from "./components/input";
35
+ export * from "./components/kbd";
36
+ export * from "./components/label";
37
+ export * from "./components/light-leak";
38
+ export * from "./components/liquid-button";
39
+ export * from "./components/link";
40
+ export * from "./components/magnetic-cta";
41
+ export * from "./components/marquee";
42
+ export * from "./components/meteor-shower";
43
+ export * from "./components/modal";
44
+ export * from "./components/morphing-tabs";
45
+ export * from "./components/number-ticker";
46
+ export * from "./components/orbiting-circles";
47
+ export * from "./components/particle-field";
48
+ export * from "./components/popover";
49
+ export * from "./components/progress";
50
+ export * from "./components/prism-border";
51
+ export * from "./components/pulsating-button";
52
+ export * from "./components/radio-group";
53
+ export * from "./components/retro-grid";
54
+ export * from "./components/reveal-text";
55
+ export * from "./components/ripple";
56
+ export * from "./components/ripple-button";
57
+ export * from "./components/select";
58
+ export * from "./components/separator";
59
+ export * from "./components/sheet";
60
+ export * from "./components/shimmer-button";
61
+ export * from "./components/skeleton";
62
+ export * from "./components/slider";
63
+ export * from "./components/spotlight-card";
64
+ export * from "./components/spotlight";
65
+ export * from "./components/status-dot";
66
+ export * from "./components/switch";
67
+ export * from "./components/table";
68
+ export * from "./components/tabs";
69
+ export * from "./components/text";
70
+ export * from "./components/text-reveal";
71
+ export * from "./components/textarea";
72
+ export * from "./components/sonner";
73
+ export * from "./components/toast";
74
+ export * from "./components/tree";
75
+ export * from "./components/tooltip";
76
+ export * from "./components/typewriter";
77
+ export * from "./components/word-rotate";
78
+ export * from "./lib/cn";
79
+ export { useLiquidGlass } from "./lib/use-liquid-glass";
80
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,wBAAwB,CAAA;AACtC,cAAc,2BAA2B,CAAA;AACzC,cAAc,gCAAgC,CAAA;AAC9C,cAAc,oBAAoB,CAAA;AAClC,cAAc,gCAAgC,CAAA;AAC9C,cAAc,qBAAqB,CAAA;AACnC,cAAc,oBAAoB,CAAA;AAClC,cAAc,wBAAwB,CAAA;AACtC,cAAc,6BAA6B,CAAA;AAC3C,cAAc,0BAA0B,CAAA;AACxC,cAAc,qBAAqB,CAAA;AACnC,cAAc,mBAAmB,CAAA;AACjC,cAAc,uBAAuB,CAAA;AACrC,cAAc,mBAAmB,CAAA;AACjC,cAAc,6BAA6B,CAAA;AAC3C,cAAc,mBAAmB,CAAA;AACjC,cAAc,sBAAsB,CAAA;AACpC,cAAc,sBAAsB,CAAA;AACpC,cAAc,yBAAyB,CAAA;AACvC,cAAc,yBAAyB,CAAA;AACvC,cAAc,0BAA0B,CAAA;AACxC,cAAc,4BAA4B,CAAA;AAC1C,cAAc,6BAA6B,CAAA;AAC3C,cAAc,+BAA+B,CAAA;AAC7C,cAAc,yBAAyB,CAAA;AACvC,cAAc,yBAAyB,CAAA;AACvC,cAAc,0BAA0B,CAAA;AACxC,cAAc,4BAA4B,CAAA;AAC1C,cAAc,2BAA2B,CAAA;AACzC,cAAc,2BAA2B,CAAA;AACzC,cAAc,sBAAsB,CAAA;AACpC,cAAc,yBAAyB,CAAA;AACvC,cAAc,yBAAyB,CAAA;AACvC,cAAc,oBAAoB,CAAA;AAClC,cAAc,kBAAkB,CAAA;AAChC,cAAc,oBAAoB,CAAA;AAClC,cAAc,yBAAyB,CAAA;AACvC,cAAc,4BAA4B,CAAA;AAC1C,cAAc,mBAAmB,CAAA;AACjC,cAAc,2BAA2B,CAAA;AACzC,cAAc,sBAAsB,CAAA;AACpC,cAAc,4BAA4B,CAAA;AAC1C,cAAc,oBAAoB,CAAA;AAClC,cAAc,4BAA4B,CAAA;AAC1C,cAAc,4BAA4B,CAAA;AAC1C,cAAc,+BAA+B,CAAA;AAC7C,cAAc,6BAA6B,CAAA;AAC3C,cAAc,sBAAsB,CAAA;AACpC,cAAc,uBAAuB,CAAA;AACrC,cAAc,2BAA2B,CAAA;AACzC,cAAc,+BAA+B,CAAA;AAC7C,cAAc,0BAA0B,CAAA;AACxC,cAAc,yBAAyB,CAAA;AACvC,cAAc,0BAA0B,CAAA;AACxC,cAAc,qBAAqB,CAAA;AACnC,cAAc,4BAA4B,CAAA;AAC1C,cAAc,qBAAqB,CAAA;AACnC,cAAc,wBAAwB,CAAA;AACtC,cAAc,oBAAoB,CAAA;AAClC,cAAc,6BAA6B,CAAA;AAC3C,cAAc,uBAAuB,CAAA;AACrC,cAAc,qBAAqB,CAAA;AACnC,cAAc,6BAA6B,CAAA;AAC3C,cAAc,wBAAwB,CAAA;AACtC,cAAc,yBAAyB,CAAA;AACvC,cAAc,qBAAqB,CAAA;AACnC,cAAc,oBAAoB,CAAA;AAClC,cAAc,mBAAmB,CAAA;AACjC,cAAc,mBAAmB,CAAA;AACjC,cAAc,0BAA0B,CAAA;AACxC,cAAc,uBAAuB,CAAA;AACrC,cAAc,qBAAqB,CAAA;AACnC,cAAc,oBAAoB,CAAA;AAClC,cAAc,mBAAmB,CAAA;AACjC,cAAc,sBAAsB,CAAA;AACpC,cAAc,yBAAyB,CAAA;AACvC,cAAc,0BAA0B,CAAA;AACxC,cAAc,UAAU,CAAA;AACxB,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAA"}
package/dist/index.js ADDED
@@ -0,0 +1,79 @@
1
+ export * from "./components/accordion";
2
+ export * from "./components/alert-dialog";
3
+ export * from "./components/animated-gradient";
4
+ export * from "./components/alert";
5
+ export * from "./components/aurora-background";
6
+ export * from "./components/avatar";
7
+ export * from "./components/badge";
8
+ export * from "./components/blur-fade";
9
+ export * from "./components/blur-spotlight";
10
+ export * from "./components/border-beam";
11
+ export * from "./components/button";
12
+ export * from "./components/card";
13
+ export * from "./components/checkbox";
14
+ export * from "./components/chip";
15
+ export * from "./components/chromatic-text";
16
+ export * from "./components/code";
17
+ export * from "./components/command";
18
+ export * from "./components/counter";
19
+ export * from "./components/data-table";
20
+ export * from "./components/depth-card";
21
+ export * from "./components/dot-pattern";
22
+ export * from "./components/dropdown-menu";
23
+ export * from "./components/floating-panel";
24
+ export * from "./components/glass-breadcrumb";
25
+ export * from "./components/glass-card";
26
+ export * from "./components/glass-dock";
27
+ export * from "./components/glow-border";
28
+ export * from "./components/gradient-mesh";
29
+ export * from "./components/glass-navbar";
30
+ export * from "./components/glass-toggle";
31
+ export * from "./components/heading";
32
+ export * from "./components/hover-card";
33
+ export * from "./components/icon-frame";
34
+ export * from "./components/input";
35
+ export * from "./components/kbd";
36
+ export * from "./components/label";
37
+ export * from "./components/light-leak";
38
+ export * from "./components/liquid-button";
39
+ export * from "./components/link";
40
+ export * from "./components/magnetic-cta";
41
+ export * from "./components/marquee";
42
+ export * from "./components/meteor-shower";
43
+ export * from "./components/modal";
44
+ export * from "./components/morphing-tabs";
45
+ export * from "./components/number-ticker";
46
+ export * from "./components/orbiting-circles";
47
+ export * from "./components/particle-field";
48
+ export * from "./components/popover";
49
+ export * from "./components/progress";
50
+ export * from "./components/prism-border";
51
+ export * from "./components/pulsating-button";
52
+ export * from "./components/radio-group";
53
+ export * from "./components/retro-grid";
54
+ export * from "./components/reveal-text";
55
+ export * from "./components/ripple";
56
+ export * from "./components/ripple-button";
57
+ export * from "./components/select";
58
+ export * from "./components/separator";
59
+ export * from "./components/sheet";
60
+ export * from "./components/shimmer-button";
61
+ export * from "./components/skeleton";
62
+ export * from "./components/slider";
63
+ export * from "./components/spotlight-card";
64
+ export * from "./components/spotlight";
65
+ export * from "./components/status-dot";
66
+ export * from "./components/switch";
67
+ export * from "./components/table";
68
+ export * from "./components/tabs";
69
+ export * from "./components/text";
70
+ export * from "./components/text-reveal";
71
+ export * from "./components/textarea";
72
+ export * from "./components/sonner";
73
+ export * from "./components/toast";
74
+ export * from "./components/tree";
75
+ export * from "./components/tooltip";
76
+ export * from "./components/typewriter";
77
+ export * from "./components/word-rotate";
78
+ export * from "./lib/cn";
79
+ export { useLiquidGlass } from "./lib/use-liquid-glass";
@@ -0,0 +1,3 @@
1
+ import { type ClassValue } from "clsx";
2
+ export declare function cn(...inputs: ClassValue[]): string;
3
+ //# sourceMappingURL=cn.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cn.d.ts","sourceRoot":"","sources":["../../src/lib/cn.ts"],"names":[],"mappings":"AAAA,OAAO,EAAQ,KAAK,UAAU,EAAE,MAAM,MAAM,CAAA;AAG5C,wBAAgB,EAAE,CAAC,GAAG,MAAM,EAAE,UAAU,EAAE,UAEzC"}
package/dist/lib/cn.js ADDED
@@ -0,0 +1,5 @@
1
+ import { clsx } from "clsx";
2
+ import { twMerge } from "tailwind-merge";
3
+ export function cn(...inputs) {
4
+ return twMerge(clsx(inputs));
5
+ }
@@ -0,0 +1,46 @@
1
+ import type { CSSProperties, ReactNode } from "react";
2
+ /**
3
+ * Liquid Glass — SVG displacement-map refraction for `backdrop-filter`.
4
+ *
5
+ * Uses `feDisplacementMap` to create real optical refraction through a
6
+ * curved "squircle" surface. The SVG filter handles ONLY the displacement;
7
+ * blur + saturation are chained as separate CSS `backdrop-filter` functions
8
+ * so Chrome processes them correctly.
9
+ *
10
+ * `backdrop-filter: url(#svgFilter) blur(Xpx) saturate(Y)`
11
+ *
12
+ * Browser support (2026):
13
+ * - Chromium (Chrome, Edge, Brave, Arc, Opera) — full refraction
14
+ * - Safari / Firefox — graceful fallback to CSS blur + saturate
15
+ *
16
+ * When Safari / Firefox add `backdrop-filter: url()` support, the
17
+ * effect will automatically upgrade without code changes.
18
+ *
19
+ * Technique credit: https://kube.io/blog/liquid-glass-css-svg
20
+ */
21
+ type LiquidGlassOptions = {
22
+ /** Max pixel displacement for refraction (default: 40) */
23
+ displacement?: number;
24
+ /** Gaussian blur standard-deviation in px (default: 12) */
25
+ blur?: number;
26
+ /** Saturation multiplier — 1.8 = Apple's 180% (default: 1.8) */
27
+ saturate?: number;
28
+ /** Surface profile shape (default: "squircle") */
29
+ profile?: "squircle" | "convex";
30
+ /** Disable the effect entirely (default: false) */
31
+ disabled?: boolean;
32
+ };
33
+ export declare function useLiquidGlass(opts?: LiquidGlassOptions): {
34
+ /** Attach to the glass element */
35
+ ref: import("react").RefObject<HTMLDivElement | null>;
36
+ /** Render this anywhere in the DOM (hidden SVG filter defs) */
37
+ svgFilter: ReactNode;
38
+ /** Apply to the glass element's `style` prop */
39
+ style: CSSProperties;
40
+ /** Filter ID (for manual usage) */
41
+ filterId: string;
42
+ /** True when SVG refraction is active (Chrome only) */
43
+ isSupported: boolean;
44
+ };
45
+ export {};
46
+ //# sourceMappingURL=use-liquid-glass.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-liquid-glass.d.ts","sourceRoot":"","sources":["../../src/lib/use-liquid-glass.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAGrD;;;;;;;;;;;;;;;;;;GAkBG;AAEH,KAAK,kBAAkB,GAAG;IACxB,0DAA0D;IAC1D,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,2DAA2D;IAC3D,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,gEAAgE;IAChE,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,kDAAkD;IAClD,OAAO,CAAC,EAAE,UAAU,GAAG,QAAQ,CAAA;IAC/B,mDAAmD;IACnD,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB,CAAA;AAmGD,wBAAgB,cAAc,CAAC,IAAI,GAAE,kBAAuB;IA0GxD,kCAAkC;;IAElC,+DAA+D;eACvC,SAAS;IACjC,gDAAgD;;IAEhD,mCAAmC;;IAEnC,uDAAuD;;EAG1D"}
@@ -0,0 +1,144 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { useEffect, useId, useRef, useState } from "react";
4
+ // ---------------------------------------------------------------------------
5
+ // Browser detection
6
+ // ---------------------------------------------------------------------------
7
+ /** Only Chromium exposes SVG filters as `backdrop-filter`. */
8
+ function supportsBackdropSvgFilter() {
9
+ if (typeof navigator === "undefined")
10
+ return false;
11
+ return /Chrome|Chromium/.test(navigator.userAgent);
12
+ }
13
+ // ---------------------------------------------------------------------------
14
+ // Displacement map generator
15
+ // ---------------------------------------------------------------------------
16
+ /**
17
+ * Builds a PNG data-URL encoding a displacement map.
18
+ *
19
+ * Red channel → horizontal displacement
20
+ * Green channel → vertical displacement
21
+ * 128 = neutral (no shift), ±127 = max shift.
22
+ *
23
+ * Generated at half resolution for performance — the SVG filter stretches
24
+ * it to the element size via `preserveAspectRatio="none"`.
25
+ */
26
+ function buildDisplacementMap(w, h, profile) {
27
+ const canvas = document.createElement("canvas");
28
+ canvas.width = w;
29
+ canvas.height = h;
30
+ const ctx = canvas.getContext("2d");
31
+ const img = ctx.createImageData(w, h);
32
+ const px = img.data;
33
+ const mx = w / 2;
34
+ const my = h / 2;
35
+ for (let row = 0; row < h; row++) {
36
+ for (let col = 0; col < w; col++) {
37
+ const i = (row * w + col) * 4;
38
+ // Normalized coords [-1, 1]
39
+ const nx = (col - mx) / mx;
40
+ const ny = (row - my) / my;
41
+ // Distance from centre (squircle or circle)
42
+ const dist = profile === "squircle"
43
+ ? (Math.abs(nx) ** 4 + Math.abs(ny) ** 4) ** 0.25
44
+ : Math.hypot(nx, ny);
45
+ // Outside shape or dead-centre → no displacement
46
+ if (dist >= 1 || dist < 0.002) {
47
+ px[i] = 128;
48
+ px[i + 1] = 128;
49
+ px[i + 2] = 128;
50
+ px[i + 3] = 255;
51
+ continue;
52
+ }
53
+ // Surface gradient magnitude (derivative of height function)
54
+ let grad;
55
+ if (profile === "squircle") {
56
+ // h = (1 - d^4)^0.25 → |∇h| ∝ d^3 / (1 - d^4)^0.75
57
+ grad = dist ** 3 / Math.max(1 - dist ** 4, 1e-4) ** 0.75;
58
+ }
59
+ else {
60
+ // h = √(1 - d²) → |∇h| = d / √(1 - d²)
61
+ grad = dist / Math.max(1 - dist * dist, 1e-4) ** 0.5;
62
+ }
63
+ // Smooth falloff near rim so edges don't clip hard
64
+ grad *= (1 - dist) ** 0.5;
65
+ grad = Math.min(grad, 1);
66
+ // Direction: radially outward from centre
67
+ const angle = Math.atan2(ny, nx);
68
+ const dx = Math.cos(angle) * grad;
69
+ const dy = Math.sin(angle) * grad;
70
+ // Encode in R/G channels — FULL range ±127 for maximum refraction
71
+ px[i] = Math.round(Math.max(0, Math.min(255, 128 + dx * 127)));
72
+ px[i + 1] = Math.round(Math.max(0, Math.min(255, 128 + dy * 127)));
73
+ px[i + 2] = 128;
74
+ px[i + 3] = 255;
75
+ }
76
+ }
77
+ ctx.putImageData(img, 0, 0);
78
+ return canvas.toDataURL("image/png");
79
+ }
80
+ // ---------------------------------------------------------------------------
81
+ // Hook
82
+ // ---------------------------------------------------------------------------
83
+ export function useLiquidGlass(opts = {}) {
84
+ const { displacement = 40, blur = 12, saturate = 1.8, profile = "squircle", disabled = false, } = opts;
85
+ const uid = useId().replace(/:/g, "");
86
+ const filterId = `lg-${uid}`;
87
+ const ref = useRef(null);
88
+ const [supported, setSupported] = useState(false);
89
+ const [dim, setDim] = useState({ w: 0, h: 0 });
90
+ const [mapUrl, setMapUrl] = useState(null);
91
+ // Detect Chromium on mount
92
+ useEffect(() => {
93
+ if (!disabled)
94
+ setSupported(supportsBackdropSvgFilter());
95
+ }, [disabled]);
96
+ // Observe element dimensions
97
+ useEffect(() => {
98
+ if (!supported || !ref.current)
99
+ return;
100
+ const el = ref.current;
101
+ const ro = new ResizeObserver(([entry]) => {
102
+ if (!entry)
103
+ return;
104
+ const { width, height } = entry.contentRect;
105
+ setDim({ w: Math.round(width), h: Math.round(height) });
106
+ });
107
+ ro.observe(el);
108
+ return () => ro.disconnect();
109
+ }, [supported]);
110
+ // Generate displacement map at half resolution (better quality than 1/4)
111
+ useEffect(() => {
112
+ if (!supported || dim.w < 16 || dim.h < 16)
113
+ return;
114
+ const scale = 0.5;
115
+ const url = buildDisplacementMap(Math.round(dim.w * scale), Math.round(dim.h * scale), profile);
116
+ setMapUrl(url);
117
+ }, [supported, dim.w, dim.h, profile]);
118
+ const ready = supported && !!mapUrl && dim.w > 0;
119
+ // SVG filter — ONLY displacement, no blur or saturate.
120
+ // Blur + saturate are chained as CSS functions in `backdropFilter`.
121
+ // This is critical: Chrome processes `url()` + CSS functions correctly
122
+ // only when the SVG filter is simple (displacement only).
123
+ const svgFilter = ready ? (_jsx("svg", { width: "0", height: "0", style: { position: "fixed", top: 0, left: 0, pointerEvents: "none" }, "aria-hidden": true, children: _jsx("defs", { children: _jsxs("filter", { id: filterId, x: "0", y: "0", width: dim.w, height: dim.h, filterUnits: "userSpaceOnUse", colorInterpolationFilters: "sRGB", children: [_jsx("feImage", { href: mapUrl, x: "0", y: "0", width: dim.w, height: dim.h, result: "dispMap", preserveAspectRatio: "none" }), _jsx("feDisplacementMap", { in: "SourceGraphic", in2: "dispMap", scale: String(displacement), xChannelSelector: "R", yChannelSelector: "G" })] }) }) })) : null;
124
+ // Style: chain SVG displacement with CSS blur + saturate
125
+ // Chrome processes: url(#filter) → blur → saturate as a pipeline
126
+ const style = ready
127
+ ? {
128
+ backdropFilter: `url(#${filterId}) blur(${blur}px) saturate(${saturate})`,
129
+ WebkitBackdropFilter: `url(#${filterId}) blur(${blur}px) saturate(${saturate})`,
130
+ }
131
+ : {};
132
+ return {
133
+ /** Attach to the glass element */
134
+ ref,
135
+ /** Render this anywhere in the DOM (hidden SVG filter defs) */
136
+ svgFilter: svgFilter,
137
+ /** Apply to the glass element's `style` prop */
138
+ style,
139
+ /** Filter ID (for manual usage) */
140
+ filterId,
141
+ /** True when SVG refraction is active (Chrome only) */
142
+ isSupported: ready,
143
+ };
144
+ }
@@ -0,0 +1,2 @@
1
+ export declare function usePrefersReducedMotion(): boolean;
2
+ //# sourceMappingURL=use-prefers-reduced-motion.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-prefers-reduced-motion.d.ts","sourceRoot":"","sources":["../../src/lib/use-prefers-reduced-motion.ts"],"names":[],"mappings":"AAMA,wBAAgB,uBAAuB,YA0BtC"}
@@ -0,0 +1,23 @@
1
+ "use client";
2
+ import * as React from "react";
3
+ const QUERY = "(prefers-reduced-motion: reduce)";
4
+ export function usePrefersReducedMotion() {
5
+ const [prefersReducedMotion, setPrefersReducedMotion] = React.useState(false);
6
+ React.useEffect(() => {
7
+ if (typeof window === "undefined" || typeof window.matchMedia !== "function") {
8
+ return;
9
+ }
10
+ const mediaQuery = window.matchMedia(QUERY);
11
+ const handleChange = () => {
12
+ setPrefersReducedMotion(mediaQuery.matches);
13
+ };
14
+ handleChange();
15
+ if (typeof mediaQuery.addEventListener === "function") {
16
+ mediaQuery.addEventListener("change", handleChange);
17
+ return () => mediaQuery.removeEventListener("change", handleChange);
18
+ }
19
+ mediaQuery.addListener(handleChange);
20
+ return () => mediaQuery.removeListener(handleChange);
21
+ }, []);
22
+ return prefersReducedMotion;
23
+ }
package/package.json ADDED
@@ -0,0 +1,72 @@
1
+ {
2
+ "name": "@glinui/ui",
3
+ "version": "0.1.0",
4
+ "type": "module",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "exports": {
8
+ ".": {
9
+ "types": "./dist/index.d.ts",
10
+ "default": "./dist/index.js"
11
+ }
12
+ },
13
+ "files": ["dist"],
14
+ "license": "MIT",
15
+ "repository": {
16
+ "type": "git",
17
+ "url": "https://github.com/GLINCKER/glinui",
18
+ "directory": "packages/ui"
19
+ },
20
+ "homepage": "https://glinui.com",
21
+ "bugs": "https://github.com/GLINCKER/glinui/issues",
22
+ "keywords": ["glinui", "glassmorphism", "liquid-glass", "react", "tailwindcss", "ui", "design-system"],
23
+ "publishConfig": {
24
+ "access": "public"
25
+ },
26
+ "scripts": {
27
+ "build": "tsc -p tsconfig.json",
28
+ "typecheck": "tsc -p tsconfig.json --noEmit",
29
+ "lint": "echo 'lint: @glinui/ui (todo)'",
30
+ "test": "vitest run",
31
+ "test:coverage": "vitest run --coverage"
32
+ },
33
+ "peerDependencies": {
34
+ "react": "^18.0.0 || ^19.0.0",
35
+ "react-dom": "^18.0.0 || ^19.0.0"
36
+ },
37
+ "dependencies": {
38
+ "@radix-ui/react-accordion": "^1.2.12",
39
+ "@radix-ui/react-alert-dialog": "^1.1.15",
40
+ "@radix-ui/react-checkbox": "^1.3.3",
41
+ "@radix-ui/react-dialog": "^1.1.15",
42
+ "@radix-ui/react-dropdown-menu": "^2.1.16",
43
+ "@radix-ui/react-hover-card": "^1.1.15",
44
+ "@radix-ui/react-popover": "^1.1.15",
45
+ "@radix-ui/react-progress": "^1.1.8",
46
+ "@radix-ui/react-radio-group": "^1.3.8",
47
+ "@radix-ui/react-select": "^2.2.6",
48
+ "@radix-ui/react-slider": "^1.3.6",
49
+ "@radix-ui/react-slot": "^1.2.4",
50
+ "@radix-ui/react-switch": "^1.2.6",
51
+ "@radix-ui/react-tabs": "^1.1.13",
52
+ "@radix-ui/react-toast": "^1.2.15",
53
+ "@radix-ui/react-tooltip": "^1.2.8",
54
+ "class-variance-authority": "^0.7.1",
55
+ "clsx": "^2.1.1",
56
+ "cmdk": "^1.1.1",
57
+ "lucide-react": "^0.563.0",
58
+ "sonner": "^2.0.7",
59
+ "tailwind-merge": "^3.3.1"
60
+ },
61
+ "devDependencies": {
62
+ "@testing-library/jest-dom": "^6.9.1",
63
+ "@testing-library/react": "^16.3.0",
64
+ "@testing-library/user-event": "^14.6.1",
65
+ "@types/react": "^19.0.6",
66
+ "@types/react-dom": "^19.0.2",
67
+ "@vitest/coverage-v8": "3.2.4",
68
+ "axe-core": "^4.11.1",
69
+ "jsdom": "^26.1.0",
70
+ "vitest": "^3.2.4"
71
+ }
72
+ }