@ghatak/slash-ui 1.0.0 → 1.0.3

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 (155) hide show
  1. package/dist/.next/dev/types/validator.d.ts +1 -0
  2. package/dist/.next/dev/types/validator.js +44 -0
  3. package/dist/__registry__/index.d.ts +1 -0
  4. package/dist/__registry__/index.js +492 -0
  5. package/dist/app/(auth)/layout.d.ts +5 -0
  6. package/dist/app/(auth)/layout.js +8 -0
  7. package/dist/app/(auth)/login/page.d.ts +1 -0
  8. package/dist/app/(auth)/login/page.js +45 -0
  9. package/dist/app/(protected)/component/[id]/page.d.ts +5 -0
  10. package/dist/app/(protected)/component/[id]/page.js +13 -0
  11. package/dist/app/(protected)/component/page.d.ts +2 -0
  12. package/dist/app/(protected)/component/page.js +26 -0
  13. package/dist/app/(protected)/docs/page.d.ts +2 -0
  14. package/dist/app/(protected)/docs/page.js +43 -0
  15. package/dist/app/account/page.d.ts +1 -0
  16. package/dist/app/account/page.js +38 -0
  17. package/dist/app/api/me/route.d.ts +8 -0
  18. package/dist/app/api/me/route.js +20 -0
  19. package/dist/app/layout.d.ts +6 -0
  20. package/dist/app/layout.js +21 -0
  21. package/dist/app/page.d.ts +2 -0
  22. package/{app/page.tsx → dist/app/page.js} +2 -13
  23. package/dist/app/pricing/page.d.ts +2 -0
  24. package/dist/app/pricing/page.js +5 -0
  25. package/dist/bin/intex.d.ts +2 -0
  26. package/dist/bin/intex.js +14 -0
  27. package/dist/components/smooth-scroll.d.ts +4 -0
  28. package/dist/components/smooth-scroll.js +21 -0
  29. package/dist/components/toast.d.ts +11 -0
  30. package/dist/components/toast.js +39 -0
  31. package/dist/components/ui/IndustryProof.d.ts +1 -0
  32. package/dist/components/ui/IndustryProof.js +55 -0
  33. package/dist/components/ui/ShowcaseContainer.d.ts +8 -0
  34. package/dist/components/ui/ShowcaseContainer.js +139 -0
  35. package/dist/components/ui/dot-cursor.d.ts +2 -0
  36. package/dist/components/ui/dot-cursor.js +70 -0
  37. package/dist/components/ui/featuredComponents.d.ts +2 -0
  38. package/dist/components/ui/featuredComponents.js +14 -0
  39. package/dist/components/ui/footer.d.ts +2 -0
  40. package/dist/components/ui/footer.js +5 -0
  41. package/dist/components/ui/hero.d.ts +3 -0
  42. package/dist/components/ui/hero.js +21 -0
  43. package/dist/components/ui/navbar.d.ts +3 -0
  44. package/dist/components/ui/navbar.js +102 -0
  45. package/dist/components/ui/pricing.d.ts +2 -0
  46. package/dist/components/ui/pricing.js +26 -0
  47. package/dist/hooks/use-component-search.d.ts +5 -0
  48. package/dist/hooks/use-component-search.js +37 -0
  49. package/dist/lib/actions/auth.action.d.ts +8 -0
  50. package/dist/lib/actions/auth.action.js +66 -0
  51. package/dist/lib/auth.d.ts +1 -0
  52. package/dist/lib/auth.js +15 -0
  53. package/dist/lib/email.d.ts +1 -0
  54. package/{lib/email.ts → dist/lib/email.js} +18 -22
  55. package/dist/lib/prisma.d.ts +2 -0
  56. package/dist/lib/prisma.js +8 -0
  57. package/dist/lib/registry.d.ts +1 -0
  58. package/{lib/registry.ts → dist/lib/registry.js} +16 -17
  59. package/dist/lib/utils.d.ts +2 -0
  60. package/dist/lib/utils.js +5 -0
  61. package/dist/middleware/middleware.d.ts +5 -0
  62. package/dist/middleware/middleware.js +19 -0
  63. package/{next.config.ts → dist/next.config.d.ts} +1 -5
  64. package/dist/next.config.js +4 -0
  65. package/dist/prisma.config.d.ts +3 -0
  66. package/{prisma.config.ts → dist/prisma.config.js} +7 -8
  67. package/dist/registry/details/buttons/neubrutal-button-details.d.ts +2 -0
  68. package/dist/registry/details/buttons/neubrutal-button-details.js +25 -0
  69. package/dist/registry/details/cursor/dot-cursor-details.d.ts +2 -0
  70. package/dist/registry/details/cursor/dot-cursor-details.js +5 -0
  71. package/dist/registry/details/navbar/floating-navbar-details.d.ts +2 -0
  72. package/dist/registry/details/navbar/floating-navbar-details.js +5 -0
  73. package/dist/registry/details/scrollbars/minimal-scrollbar-details.js +1 -0
  74. package/dist/registry/index.d.ts +7 -0
  75. package/dist/registry/index.js +31 -0
  76. package/dist/registry/ui/buttons/neubrutal-button.d.ts +6 -0
  77. package/dist/registry/ui/buttons/neubrutal-button.js +18 -0
  78. package/dist/registry/ui/cursors/dot-cursor.d.ts +2 -0
  79. package/dist/registry/ui/cursors/dot-cursor.js +70 -0
  80. package/dist/registry/ui/navbars/floating-navbar.d.ts +2 -0
  81. package/dist/registry/ui/navbars/floating-navbar.js +35 -0
  82. package/dist/registry/ui/scrollbars/minimal-scrollbar.d.ts +2 -0
  83. package/dist/registry/ui/scrollbars/minimal-scrollbar.js +171 -0
  84. package/dist/scripts/build-registry.d.ts +1 -0
  85. package/dist/scripts/build-registry.js +47 -0
  86. package/dist/src/commands/add.d.ts +1 -0
  87. package/dist/src/commands/add.js +34 -0
  88. package/dist/src/commands/init.d.ts +1 -0
  89. package/dist/src/commands/init.js +63 -0
  90. package/dist/src/commands/list.d.ts +1 -0
  91. package/dist/src/commands/list.js +37 -0
  92. package/dist/src/index.d.ts +2 -0
  93. package/dist/src/index.js +28 -0
  94. package/dist/src/utils/get-pkg-manager.d.ts +1 -0
  95. package/dist/src/utils/get-pkg-manager.js +10 -0
  96. package/dist/tsconfig.tsbuildinfo +1 -0
  97. package/package.json +11 -2
  98. package/app/(auth)/layout.tsx +0 -18
  99. package/app/(auth)/login/page.tsx +0 -152
  100. package/app/(protected)/component/[id]/page.tsx +0 -48
  101. package/app/(protected)/component/page.tsx +0 -151
  102. package/app/(protected)/docs/page.tsx +0 -222
  103. package/app/account/page.tsx +0 -109
  104. package/app/api/me/route.ts +0 -24
  105. package/app/globals.css +0 -68
  106. package/app/icon.png +0 -0
  107. package/app/layout.tsx +0 -43
  108. package/app/pricing/page.tsx +0 -12
  109. package/bin/intex.ts +0 -19
  110. package/components/smooth-scroll.tsx +0 -26
  111. package/components/toast.tsx +0 -101
  112. package/components/ui/IndustryProof.tsx +0 -159
  113. package/components/ui/ShowcaseContainer.tsx +0 -497
  114. package/components/ui/dot-cursor.tsx +0 -108
  115. package/components/ui/featuredComponents.tsx +0 -126
  116. package/components/ui/footer.tsx +0 -59
  117. package/components/ui/hero.tsx +0 -85
  118. package/components/ui/navbar.tsx +0 -337
  119. package/components/ui/pricing.tsx +0 -163
  120. package/eslint.config.mjs +0 -18
  121. package/hooks/use-component-search.tsx +0 -52
  122. package/lib/actions/auth.action.ts +0 -88
  123. package/lib/auth.ts +0 -18
  124. package/lib/prisma.ts +0 -14
  125. package/lib/utils.ts +0 -6
  126. package/middleware/middleware.ts +0 -21
  127. package/postcss.config.mjs +0 -7
  128. package/prisma/migrations/20260303172729_init/migration.sql +0 -21
  129. package/prisma/migrations/migration_lock.toml +0 -3
  130. package/prisma/schema.prisma +0 -22
  131. package/public/compVideos/neubrutal-button.mp4 +0 -0
  132. package/public/fonts/BeVietnamPro-ExtraBold.otf +0 -0
  133. package/public/fonts/CartographCF-Regular.ttf +0 -0
  134. package/public/fonts/Hoshiko-Satsuki.ttf +0 -0
  135. package/public/fonts/Switzer-Regular.otf +0 -0
  136. package/public/images/PricingSlash.svg +0 -58
  137. package/public/images/slash_1.svg +0 -59
  138. package/public/images/slash_2.svg +0 -18
  139. package/public/video/hero_video.mp4 +0 -0
  140. package/registry/details/buttons/neubrutal-button-details.tsx +0 -146
  141. package/registry/details/cursor/dot-cursor-details.tsx +0 -11
  142. package/registry/details/navbar/floating-navbar-details.tsx +0 -11
  143. package/registry/index.ts +0 -35
  144. package/registry/ui/buttons/neubrutal-button.tsx +0 -33
  145. package/registry/ui/cursors/dot-cursor.tsx +0 -108
  146. package/registry/ui/navbars/floating-navbar.tsx +0 -99
  147. package/registry/ui/scrollbars/minimal-scrollbar.tsx +0 -203
  148. package/scripts/build-registry.ts +0 -60
  149. package/src/commands/add.ts +0 -40
  150. package/src/commands/init.ts +0 -75
  151. package/src/commands/list.ts +0 -44
  152. package/src/index.ts +0 -35
  153. package/src/utils/get-pkg-manager.ts +0 -7
  154. package/tsconfig.json +0 -34
  155. /package/{registry/details/scrollbars/minimal-scrollbar-details.tsx → dist/registry/details/scrollbars/minimal-scrollbar-details.d.ts} +0 -0
@@ -0,0 +1,7 @@
1
+ export declare const Index: {
2
+ name: string;
3
+ type: string;
4
+ files: string[];
5
+ category: string;
6
+ install: string;
7
+ }[];
@@ -0,0 +1,31 @@
1
+ // registry/index.ts
2
+ export const Index = [
3
+ {
4
+ name: 'neubrutal-button',
5
+ type: 'ui',
6
+ files: ['ui/buttons/neubrutal-button.tsx'],
7
+ category: 'buttons',
8
+ install: 'npm install framer-motion lucide-react',
9
+ },
10
+ {
11
+ name: 'dot-cursor',
12
+ type: 'ui',
13
+ files: ['ui/cursors/dot-cursor.tsx'],
14
+ category: 'cursors',
15
+ install: 'npm install framer-motion',
16
+ },
17
+ {
18
+ name: 'flaoting-navbar',
19
+ type: 'ui',
20
+ files: ['ui/navbars/floating-navbar.tsx'],
21
+ category: 'navbars',
22
+ install: 'npm install lucide-react framer-motion gsap',
23
+ },
24
+ {
25
+ name: 'minimal-scrollbar',
26
+ type: 'ui',
27
+ files: ['ui/scrollbars/minimal-scrollbar.tsx'],
28
+ category: 'scrollbars',
29
+ install: '',
30
+ }
31
+ ];
@@ -0,0 +1,6 @@
1
+ import React from 'react';
2
+ interface NeubrutalButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
3
+ children: React.ReactNode;
4
+ }
5
+ export default function NeubrutalButton({ children, className, ...props }: NeubrutalButtonProps): import("react/jsx-runtime").JSX.Element;
6
+ export {};
@@ -0,0 +1,18 @@
1
+ var __rest = (this && this.__rest) || function (s, e) {
2
+ var t = {};
3
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
4
+ t[p] = s[p];
5
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
6
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
7
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
8
+ t[p[i]] = s[p[i]];
9
+ }
10
+ return t;
11
+ };
12
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
13
+ import { cn } from '@/lib/utils';
14
+ // 1. CHANGE THIS TO DEFAULT EXPORT
15
+ export default function NeubrutalButton(_a) {
16
+ var { children = 'Click Me!', className } = _a, props = __rest(_a, ["children", "className"]);
17
+ return (_jsxs("button", Object.assign({}, props, { className: cn('group relative w-[140px] h-[50px] bg-none outline-none border-none p-0 cursor-pointer active:translate-y-[2px] transition-transform', className), children: [_jsx("div", { className: 'absolute top-[14px] -left-[1px] w-[calc(100%+2px)] h-full bg-[#8c8c8c] rounded-[7mm] outline outline-2 outline-[#242622] -z-10' }), _jsxs("div", { className: 'absolute top-[10px] left-0 w-full h-full bg-[#e5e5c7] rounded-[7mm] outline outline-2 outline-[#242622] -z-10', children: [_jsx("div", { className: 'absolute bottom-0 left-[15%] w-[2px] h-[9px] bg-[#242622]' }), _jsx("div", { className: 'absolute bottom-0 left-[85%] w-[2px] h-[9px] bg-[#242622]' })] }), _jsxs("div", { className: 'relative w-full h-full flex items-center justify-center bg-[#ffffee] rounded-[7mm] outline outline-2 outline-[#242622] text-[#242622] font-semibold text-base overflow-hidden transition-all duration-200 group-active:translate-y-[10px]', children: [_jsx("div", { className: 'absolute top-0 -left-[20px] w-[15px] h-full bg-black/10 skew-x-[30deg] transition-all duration-300 group-active:left-[calc(100%+20px)]' }), children] })] })));
18
+ }
@@ -0,0 +1,2 @@
1
+ declare const CustomCursor: () => import("react/jsx-runtime").JSX.Element;
2
+ export default CustomCursor;
@@ -0,0 +1,70 @@
1
+ 'use client';
2
+ import { jsx as _jsx } from "react/jsx-runtime";
3
+ import { useState, useEffect } from 'react';
4
+ const CustomCursor = () => {
5
+ const [position, setPosition] = useState({ x: 0, y: 0 });
6
+ const [isHovering, setIsHovering] = useState(false);
7
+ const [isDarkBackground, setIsDarkBackground] = useState(false);
8
+ useEffect(() => {
9
+ // document.body.style.cursor = 'none';
10
+ const updatePosition = (e) => {
11
+ setPosition({ x: e.clientX, y: e.clientY });
12
+ const element = document.elementFromPoint(e.clientX, e.clientY);
13
+ if (element) {
14
+ const bgColor = window.getComputedStyle(element).backgroundColor;
15
+ const brightness = getBrightness(bgColor);
16
+ setIsDarkBackground(brightness < 128);
17
+ }
18
+ };
19
+ const handleMouseOver = (e) => {
20
+ const target = e.target;
21
+ if (target.tagName === 'A' ||
22
+ target.tagName === 'BUTTON' ||
23
+ target.onclick !== null ||
24
+ window.getComputedStyle(target).cursor === 'pointer') {
25
+ setIsHovering(true);
26
+ }
27
+ };
28
+ const handleMouseOut = () => {
29
+ setIsHovering(false);
30
+ };
31
+ window.addEventListener('mousemove', updatePosition);
32
+ document.addEventListener('mouseover', handleMouseOver);
33
+ document.addEventListener('mouseout', handleMouseOut);
34
+ return () => {
35
+ window.removeEventListener('mousemove', updatePosition);
36
+ document.removeEventListener('mouseover', handleMouseOver);
37
+ document.removeEventListener('mouseout', handleMouseOut);
38
+ };
39
+ }, []);
40
+ const getBrightness = (color) => {
41
+ const rgb = color.match(/\d+/g);
42
+ if (!rgb)
43
+ return 255;
44
+ const r = parseInt(rgb[0]);
45
+ const g = parseInt(rgb[1]);
46
+ const b = parseInt(rgb[2]);
47
+ return (r * 299 + g * 587 + b * 114) / 1000;
48
+ };
49
+ return (_jsx("div", { style: {
50
+ cursor: 'none',
51
+ width: '100vw',
52
+ height: '100vh',
53
+ position: 'fixed',
54
+ top: 0,
55
+ left: 0,
56
+ pointerEvents: 'none'
57
+ }, children: _jsx("div", { style: {
58
+ position: 'fixed',
59
+ left: `${position.x}px`,
60
+ top: `${position.y}px`,
61
+ pointerEvents: 'none',
62
+ transform: `translate(-50%, -50%) scale(${isHovering ? 1.5 : 1})`,
63
+ transition: 'transform 0.2s ease',
64
+ zIndex: 9999,
65
+ }, children: _jsx("svg", { xmlns: "http://www.w3.org/2000/svg", width: "24", height: "24", viewBox: "0 0 24 24", style: {
66
+ display: 'block',
67
+ transition: 'all 0.2s ease',
68
+ }, children: _jsx("path", { fill: isDarkBackground ? '#ffffff' : '#000000', stroke: isDarkBackground ? '#000000' : '#ffffff', strokeWidth: "2", d: "M5.5 3.21V20.8c0 .45.54.67.85.35l4.86-4.86a.5.5 0 0 1 .35-.15h6.87a.5.5 0 0 0 .35-.85L6.35 2.85a.5.5 0 0 0-.85.35Z" }) }) }) }));
69
+ };
70
+ export default CustomCursor;
@@ -0,0 +1,2 @@
1
+ declare const Navbar: () => import("react/jsx-runtime").JSX.Element | null;
2
+ export default Navbar;
@@ -0,0 +1,35 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { useState, useEffect } from 'react';
4
+ import Link from 'next/link';
5
+ import { motion, AnimatePresence } from 'framer-motion';
6
+ import { Sun, Moon } from 'lucide-react';
7
+ const Navbar = () => {
8
+ const [mounted, setMounted] = useState(false);
9
+ const [isDark, setIsDark] = useState(true);
10
+ const [scrolled, setScrolled] = useState(false);
11
+ useEffect(() => {
12
+ setMounted(true);
13
+ const handleScroll = () => setScrolled(window.scrollY > 20);
14
+ window.addEventListener('scroll', handleScroll);
15
+ return () => window.removeEventListener('scroll', handleScroll);
16
+ }, []);
17
+ const toggleTheme = () => {
18
+ setIsDark(!isDark);
19
+ document.documentElement.classList.toggle('dark');
20
+ };
21
+ const navLinks = [
22
+ { name: 'Archives', slug: 'work' },
23
+ { name: 'Capabilities', slug: 'service' },
24
+ { name: 'Ethos', slug: 'about' },
25
+ ];
26
+ if (!mounted)
27
+ return null;
28
+ return (_jsx("nav", { className: 'fixed top-0 left-0 w-full z-[100] flex justify-center pt-6 px-6 pointer-events-none mt-10', children: _jsxs(motion.div, { initial: { y: -100 }, animate: { y: 0 }, className: `
29
+ flex items-center justify-between px-6 transition-all duration-500 pointer-events-auto
30
+ ${scrolled
31
+ ? 'w-full md:w-[800px] h-14 bg-white/5 backdrop-blur-md border border-white/10 rounded-full shadow-2xl'
32
+ : 'w-full h-20 bg-transparent border-transparent'}
33
+ `, children: [_jsx(Link, { href: '/', className: 'group flex items-center', children: _jsx("span", { className: ' text-3xl uppercase tracking-wide font-bold', children: "Renoh" }) }), _jsx("div", { className: 'hidden md:flex items-center space-x-8', children: navLinks.map((link) => (_jsxs(Link, { href: `/${link.slug}`, className: 'text-[10px] font-plex uppercase tracking-[0.2em] text-zinc-400 hover:text-white transition-colors relative group', children: [link.name, _jsx("span", { className: 'absolute -bottom-1 left-0 w-0 h-px bg-white transition-all duration-500 group-hover:w-full' })] }, link.slug))) }), _jsxs("div", { className: 'flex items-center space-x-4', children: [_jsx("button", { onClick: toggleTheme, className: 'p-2 hover:bg-white/10 rounded-full transition-colors text-white', children: _jsx(AnimatePresence, { mode: 'wait', children: _jsx(motion.div, { initial: { opacity: 0, rotate: -90 }, animate: { opacity: 1, rotate: 0 }, exit: { opacity: 0, rotate: 90 }, transition: { duration: 0.2 }, children: isDark ? _jsx(Sun, { size: 16 }) : _jsx(Moon, { size: 16 }) }, isDark ? 'dark' : 'light') }) }), _jsx(Link, { href: '/contact', children: _jsx(motion.div, { whileHover: { scale: 1.05 }, whileTap: { scale: 0.95 }, className: 'px-4 py-2 bg-white text-black text-[10px] font-plex uppercase tracking-widest rounded-full', children: "Inquire" }) })] })] }) }));
34
+ };
35
+ export default Navbar;
@@ -0,0 +1,2 @@
1
+ declare const VisualScrollbar: () => import("react/jsx-runtime").JSX.Element | null;
2
+ export default VisualScrollbar;
@@ -0,0 +1,171 @@
1
+ 'use client';
2
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { useState, useEffect, useRef, useCallback } from 'react';
4
+ import { usePathname } from 'next/navigation';
5
+ const VisualScrollbar = () => {
6
+ const [thumbTop, setThumbTop] = useState(0);
7
+ const channelRef = useRef(null);
8
+ const thumbRef = useRef(null);
9
+ const tickingRef = useRef(false);
10
+ const measurementsRef = useRef({
11
+ height: 0,
12
+ thumbH: 0,
13
+ paddingTop: 0,
14
+ paddingBottom: 0,
15
+ available: 0,
16
+ });
17
+ // Hide scrollbar on contact page
18
+ const pathname = usePathname();
19
+ const shouldHide = pathname === '/contact';
20
+ const measure = useCallback(() => {
21
+ if (!channelRef.current || !thumbRef.current)
22
+ return;
23
+ const chRect = channelRef.current.getBoundingClientRect();
24
+ const thumbRect = thumbRef.current.getBoundingClientRect();
25
+ const style = window.getComputedStyle(channelRef.current);
26
+ const height = chRect.height;
27
+ const thumbH = thumbRect.height;
28
+ const paddingTop = parseFloat(style.paddingTop) || 0;
29
+ const paddingBottom = parseFloat(style.paddingBottom) || 0;
30
+ const available = Math.max(height - thumbH - (paddingTop + paddingBottom), 0);
31
+ measurementsRef.current = {
32
+ height,
33
+ thumbH,
34
+ paddingTop,
35
+ paddingBottom,
36
+ available,
37
+ };
38
+ }, []);
39
+ const updateThumb = useCallback(() => {
40
+ const scrollTop = window.scrollY;
41
+ const scrollHeight = document.documentElement.scrollHeight;
42
+ const clientHeight = document.documentElement.clientHeight;
43
+ const maxScroll = Math.max(scrollHeight - clientHeight, 1);
44
+ const scrollPercent = Math.min(Math.max(scrollTop / maxScroll, 0), 1);
45
+ const topPx = measurementsRef.current.paddingTop +
46
+ scrollPercent * measurementsRef.current.available;
47
+ setThumbTop(topPx);
48
+ }, []);
49
+ useEffect(() => {
50
+ const handleScroll = () => {
51
+ if (!tickingRef.current) {
52
+ tickingRef.current = true;
53
+ requestAnimationFrame(() => {
54
+ updateThumb();
55
+ tickingRef.current = false;
56
+ });
57
+ }
58
+ };
59
+ let resizeTimeout = null;
60
+ const handleResize = () => {
61
+ if (resizeTimeout)
62
+ clearTimeout(resizeTimeout);
63
+ resizeTimeout = setTimeout(() => {
64
+ measure();
65
+ updateThumb();
66
+ }, 150);
67
+ };
68
+ // Initial setup with small delay to ensure DOM is ready
69
+ const initTimeout = setTimeout(() => {
70
+ measure();
71
+ updateThumb();
72
+ }, 100);
73
+ window.addEventListener('scroll', handleScroll, { passive: true });
74
+ window.addEventListener('resize', handleResize, { passive: true });
75
+ return () => {
76
+ clearTimeout(initTimeout);
77
+ if (resizeTimeout)
78
+ clearTimeout(resizeTimeout);
79
+ window.removeEventListener('scroll', handleScroll);
80
+ window.removeEventListener('resize', handleResize);
81
+ };
82
+ }, [measure, updateThumb]);
83
+ // Return null if on contact page
84
+ if (shouldHide)
85
+ return null;
86
+ return (_jsxs(_Fragment, { children: [_jsx("style", { children: `
87
+ :root {
88
+ --left-offset: 20px;
89
+ --track-h: 50vh;
90
+ --track-w: 3px;
91
+ --thumb-w: 2px;
92
+ --thumb-h: 50px;
93
+ --track-bg: #212121;
94
+ --channel-bg: rgba(255,255,255,0.15);
95
+ --thumb-gradient: linear-gradient(180deg,#ffffff,#d7d7d7);
96
+ --track-radius: 0px;
97
+ --thumb-radius: 0px;
98
+ --transition-speed: 1ms;
99
+ }
100
+
101
+ * {
102
+ box-sizing: border-box;
103
+ }
104
+
105
+ body {
106
+ background: #0a0a0a;
107
+ color: #e6e6e6;
108
+ margin: 0;
109
+ padding: 0;
110
+ }
111
+
112
+ .vs {
113
+ position: fixed;
114
+ left: var(--left-offset);
115
+ top: 50%;
116
+ transform: translateY(-50%);
117
+ width: var(--track-w);
118
+ height: var(--track-h);
119
+ background: var(--track-bg);
120
+ border-radius: var(--track-radius);
121
+ overflow: hidden;
122
+ box-shadow:
123
+ inset 0 1px 0 rgba(255,255,255,0.08),
124
+ 0 10px 24px rgba(0,0,0,0.6);
125
+ backdrop-filter: blur(6px);
126
+ pointer-events: none;
127
+ z-index: 9999;
128
+ display: flex;
129
+ justify-content: center;
130
+ will-change: transform;
131
+ }
132
+
133
+ .vs__channel {
134
+ position: relative;
135
+ width: 100%;
136
+ height: 100%;
137
+ background: var(--channel-bg);
138
+ border-radius: var(--track-radius);
139
+ overflow: hidden;
140
+ }
141
+
142
+ .vs__thumb {
143
+ position: absolute;
144
+ left: 50%;
145
+ transform: translateX(-50%) translateZ(0);
146
+ width: var(--thumb-w);
147
+ height: var(--thumb-h);
148
+ border-radius: var(--thumb-radius);
149
+ background: var(--thumb-gradient);
150
+ box-shadow:
151
+ 0 4px 14px rgba(0,0,0,0.6),
152
+ inset 0 1px 0 rgba(255,255,255,0.4);
153
+ will-change: top;
154
+ }
155
+
156
+ .vs:hover .vs__thumb {
157
+ transform: translateX(-50%) translateZ(0) scaleY(1.05);
158
+ transition: transform 180ms ease;
159
+ }
160
+
161
+ @media (max-width:720px) {
162
+ :root {
163
+ --left-offset: 10px;
164
+ --thumb-h: 30px;
165
+ --track-w: 3px;
166
+ --track-h: 30vh;
167
+ }
168
+ }
169
+ ` }), _jsx("div", { className: 'vs', children: _jsx("div", { className: 'vs__channel', ref: channelRef, children: _jsx("div", { className: 'vs__thumb', ref: thumbRef, style: { top: `${thumbTop}px` }, "aria-hidden": 'true' }) }) })] }));
170
+ };
171
+ export default VisualScrollbar;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,47 @@
1
+ import { writeFileSync, existsSync, mkdirSync, readFileSync } from 'fs';
2
+ import path from 'path';
3
+ import { Index } from '../registry/index';
4
+ const OUTPUT_DIR = path.join(process.cwd(), '__registry__');
5
+ const OUTPUT_PATH = path.join(OUTPUT_DIR, 'index.ts');
6
+ async function buildRegistry() {
7
+ if (!existsSync(OUTPUT_DIR)) {
8
+ mkdirSync(OUTPUT_DIR);
9
+ }
10
+ let indexContent = `// @ts-nocheck
11
+ // This file is autogenerated by scripts/build-registry.ts
12
+ import * as React from "react"
13
+
14
+ export const Index: Record<string, any> = {
15
+ "default": {
16
+ `;
17
+ Index.forEach((item) => {
18
+ const componentPath = item.files[0].replace(/\.tsx?$/, '');
19
+ const sourceFilePath = path.join(process.cwd(), 'registry', item.files[0]);
20
+ const detailsFilePath = path.join(process.cwd(), 'registry', `details/${item.name}.tsx`);
21
+ const hasDetails = existsSync(detailsFilePath);
22
+ const rawContent = existsSync(sourceFilePath)
23
+ ? readFileSync(sourceFilePath, 'utf8')
24
+ : '';
25
+ const safeContent = rawContent.replace(/`/g, '\\`').replace(/\$/g, '\\$');
26
+ const safeDescription = (item.description || '')
27
+ .replace(/`/g, '\\`')
28
+ .replace(/\$/g, '\\$');
29
+ indexContent += ` "${item.name}": {
30
+ name: "${item.name}",
31
+ type: "${item.type}",
32
+ component: React.lazy(() => import("../registry/${componentPath}")),
33
+ details: ${hasDetails ? `React.lazy(() => import("../registry/details/${item.name}"))` : 'null'},
34
+ files: ${JSON.stringify(item.files)},
35
+ category: "${item.category || 'undefined'}",
36
+ content: \`${safeContent}\`,
37
+ description: \`${safeDescription}\`,
38
+ install: "${item.install || ''}",
39
+ },
40
+ `;
41
+ });
42
+ indexContent += ` }
43
+ };`;
44
+ writeFileSync(OUTPUT_PATH, indexContent);
45
+ console.log('✅ Slash UI Registry updated!');
46
+ }
47
+ buildRegistry();
@@ -0,0 +1 @@
1
+ export declare const addCommand: (componentName: string) => Promise<void>;
@@ -0,0 +1,34 @@
1
+ import fs from "fs-extra";
2
+ import path from "path";
3
+ import chalk from "chalk";
4
+ // Import the Index that YOUR script just generated
5
+ import { Index } from "../../__registry__/index";
6
+ export const addCommand = async (componentName) => {
7
+ try {
8
+ // Access the 'default' key from your generated file
9
+ const component = Index.default[componentName];
10
+ if (!component) {
11
+ console.error(chalk.red(`\nError: Component "${componentName}" not found in registry.`));
12
+ return;
13
+ }
14
+ // Determine target directory (e.g., components/ui)
15
+ const targetDir = path.join(process.cwd(), "components", "ui");
16
+ await fs.ensureDir(targetDir);
17
+ // Use the first filename from your registry item
18
+ const fileName = component.files[0] ? path.basename(component.files[0]) : `${componentName}.tsx`;
19
+ const filePath = path.join(targetDir, fileName);
20
+ // Write the 'content' string that your build script saved
21
+ await fs.writeFile(filePath, component.content);
22
+ // --- Premium Success Message ---
23
+ console.log(`\n${chalk.bgCyan.black(" DONE ")} ${chalk.green(`Component ${chalk.bold(componentName)} has been added.`)}`);
24
+ console.log(`${chalk.dim("Location:")} ${chalk.cyan(filePath)}`);
25
+ // -------------------------------
26
+ if (component.install) {
27
+ console.log(chalk.yellow(`\nNote: This component requires dependencies: `) + chalk.cyan(component.install));
28
+ console.log(chalk.dim(`Run: npm install ${component.install}`));
29
+ }
30
+ }
31
+ catch (error) {
32
+ console.error(chalk.red("\nFailed to add component:"), error);
33
+ }
34
+ };
@@ -0,0 +1 @@
1
+ export declare const initCommand: () => Promise<void>;
@@ -0,0 +1,63 @@
1
+ import fs from 'fs-extra';
2
+ import path from 'path';
3
+ import chalk from 'chalk';
4
+ import prompts from 'prompts';
5
+ export const initCommand = async () => {
6
+ try {
7
+ console.log(chalk.bold.blue('\n🚀 Initializing Slash UI...\n'));
8
+ // 1. Ask user for preferred configuration
9
+ const response = await prompts([
10
+ {
11
+ type: 'text',
12
+ name: 'componentsPath',
13
+ message: 'Where would you like to install your components?',
14
+ initial: 'components/ui',
15
+ },
16
+ {
17
+ type: 'confirm',
18
+ name: 'proceed',
19
+ message: 'This will create necessary directories and configuration files. Proceed?',
20
+ initial: true,
21
+ },
22
+ ]);
23
+ if (!response.proceed) {
24
+ console.log(chalk.yellow('Aborted initialization.'));
25
+ return;
26
+ }
27
+ // 2. Create the components directory
28
+ const targetDir = path.join(process.cwd(), response.componentsPath);
29
+ await fs.ensureDir(targetDir);
30
+ console.log(chalk.green(`✔ Created directory: ${response.componentsPath}`));
31
+ // 3. Create a components.json for your CLI to remember settings
32
+ const config = {
33
+ style: 'default',
34
+ tailwind: {
35
+ config: 'tailwind.config.js',
36
+ css: 'app/globals.css',
37
+ baseColor: 'zinc',
38
+ },
39
+ paths: {
40
+ components: response.componentsPath,
41
+ utils: 'lib/utils',
42
+ },
43
+ };
44
+ await fs.writeJSON(path.join(process.cwd(), 'components.json'), config, {
45
+ spaces: 2,
46
+ });
47
+ console.log(chalk.green('✔ Created components.json configuration'));
48
+ // 4. Check for Tailwind Config
49
+ const tailwindConfigPath = path.join(process.cwd(), 'tailwind.config.ts');
50
+ if (fs.existsSync(tailwindConfigPath)) {
51
+ let content = fs.readFileSync(tailwindConfigPath, 'utf-8');
52
+ // Automatically add the components directory to Tailwind's content array
53
+ if (!content.includes(response.componentsPath)) {
54
+ content = content.replace(/content: \[([\s\S]*?)\]/, `content: [$1, "./${response.componentsPath}/**/*.{ts,tsx}"]`);
55
+ fs.writeFileSync(tailwindConfigPath, content);
56
+ console.log(chalk.dim('✔ Updated tailwind.config.ts content paths.'));
57
+ }
58
+ }
59
+ }
60
+ catch (error) {
61
+ console.error(chalk.red('\nFailed to initialize project:'), error);
62
+ }
63
+ };
@@ -0,0 +1 @@
1
+ export declare const listCommand: () => Promise<void>;
@@ -0,0 +1,37 @@
1
+ import chalk from "chalk";
2
+ import prompts from "prompts";
3
+ import { Index } from "../../__registry__/index";
4
+ import { addCommand } from "./add";
5
+ export const listCommand = async () => {
6
+ try {
7
+ const registryData = Index.default;
8
+ const components = Object.keys(registryData);
9
+ if (components.length === 0) {
10
+ console.log(chalk.red("\n✖ No components found. Run 'npm run build:registry' first."));
11
+ return;
12
+ }
13
+ // 1. Create the interactive menu choices
14
+ const choices = components.map((name) => ({
15
+ title: name,
16
+ value: name,
17
+ description: chalk.dim(registryData[name].category || "ui"),
18
+ }));
19
+ console.log(chalk.bold.cyan("\n─── Slash UI Explorer ───"));
20
+ // 2. Launch the autocomplete search menu
21
+ const response = await prompts({
22
+ type: "autocomplete",
23
+ name: "selected",
24
+ message: "Search components",
25
+ choices: choices,
26
+ // This allows filtering as you type
27
+ suggest: (input, choices) => Promise.resolve(choices.filter(i => i.title.toLowerCase().includes(input.toLowerCase()))),
28
+ });
29
+ // 3. If they select one, run the add command immediately
30
+ if (response.selected) {
31
+ await addCommand(response.selected);
32
+ }
33
+ }
34
+ catch (error) {
35
+ console.error(chalk.red("\nFailed to display component list:"), error);
36
+ }
37
+ };
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
@@ -0,0 +1,28 @@
1
+ #!/usr/bin/env node
2
+ import { Command } from 'commander';
3
+ import { addCommand } from './commands/add';
4
+ import { initCommand } from './commands/init';
5
+ import { listCommand } from './commands/list';
6
+ const program = new Command();
7
+ program
8
+ .name('slash-ui')
9
+ .description('CLI for Slash UI components')
10
+ .version('1.0.0');
11
+ // 1. Init
12
+ program
13
+ .command('init')
14
+ .description('Initialize your project for Slash UI')
15
+ .action(initCommand);
16
+ // 2. List
17
+ program
18
+ .command('list')
19
+ .description('List all available components')
20
+ .action(listCommand);
21
+ // 3. Add
22
+ program
23
+ .command('add')
24
+ .description('Add a component to your project')
25
+ .argument('<component>', 'the component name to add')
26
+ .action(addCommand);
27
+ // ONLY ONE PARSE CALL AT THE VERY END
28
+ program.parse();
@@ -0,0 +1 @@
1
+ export declare function getPkgManager(): "yarn" | "pnpm" | "bun" | "npm";
@@ -0,0 +1,10 @@
1
+ export function getPkgManager() {
2
+ const userAgent = process.env.npm_config_user_agent || "";
3
+ if (userAgent.includes("yarn"))
4
+ return "yarn";
5
+ if (userAgent.includes("pnpm"))
6
+ return "pnpm";
7
+ if (userAgent.includes("bun"))
8
+ return "bun";
9
+ return "npm";
10
+ }