@docubook/create 1.9.0 → 1.11.2

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 (129) hide show
  1. package/README.md +1 -3
  2. package/package.json +7 -7
  3. package/src/cli/program.js +32 -0
  4. package/src/cli/promptHandler.js +73 -0
  5. package/src/dist/LICENSE +21 -0
  6. package/src/dist/README.md +37 -0
  7. package/src/dist/app/docs/[[...slug]]/page.tsx +105 -0
  8. package/src/dist/app/docs/layout.tsx +16 -0
  9. package/src/dist/app/error.tsx +44 -0
  10. package/src/dist/app/layout.tsx +96 -0
  11. package/src/dist/app/not-found.tsx +19 -0
  12. package/src/dist/app/page.tsx +96 -0
  13. package/src/dist/components/GithubStart.tsx +44 -0
  14. package/src/dist/components/Sponsor.tsx +69 -0
  15. package/src/dist/components/anchor.tsx +84 -0
  16. package/src/dist/components/contexts/theme-provider.tsx +9 -0
  17. package/src/dist/components/docs-breadcrumb.tsx +47 -0
  18. package/src/dist/components/docs-menu.tsx +45 -0
  19. package/src/dist/components/edit-on-github.tsx +33 -0
  20. package/src/dist/components/footer.tsx +85 -0
  21. package/src/dist/components/leftbar.tsx +95 -0
  22. package/src/dist/components/markdown/AccordionMdx.tsx +47 -0
  23. package/src/dist/components/markdown/ButtonMdx.tsx +52 -0
  24. package/src/dist/components/markdown/CardGroupMdx.tsx +28 -0
  25. package/src/dist/components/markdown/CardMdx.tsx +41 -0
  26. package/src/dist/components/markdown/CopyMdx.tsx +33 -0
  27. package/src/dist/components/markdown/ImageMdx.tsx +25 -0
  28. package/src/dist/components/markdown/KeyboardMdx.tsx +102 -0
  29. package/src/dist/components/markdown/LinkMdx.tsx +14 -0
  30. package/src/dist/components/markdown/NoteMdx.tsx +52 -0
  31. package/src/dist/components/markdown/OutletMdx.tsx +29 -0
  32. package/src/dist/components/markdown/PreMdx.tsx +19 -0
  33. package/src/dist/components/markdown/ReleaseMdx.tsx +109 -0
  34. package/src/dist/components/markdown/StepperMdx.tsx +41 -0
  35. package/src/dist/components/markdown/TooltipsMdx.tsx +28 -0
  36. package/src/dist/components/markdown/YoutubeMdx.tsx +22 -0
  37. package/src/dist/components/markdown/mdx-provider.tsx +29 -0
  38. package/src/dist/components/mob-toc.tsx +128 -0
  39. package/src/dist/components/navbar.tsx +87 -0
  40. package/src/dist/components/pagination.tsx +49 -0
  41. package/src/dist/components/scroll-to-top.tsx +86 -0
  42. package/src/dist/components/search.tsx +214 -0
  43. package/src/dist/components/sublink.tsx +133 -0
  44. package/src/dist/components/theme-toggle.tsx +71 -0
  45. package/src/dist/components/toc-observer.tsx +264 -0
  46. package/src/dist/components/toc.tsx +27 -0
  47. package/src/dist/components/typography.tsx +9 -0
  48. package/src/dist/components/ui/accordion.tsx +58 -0
  49. package/src/dist/components/ui/animated-shiny-text.tsx +40 -0
  50. package/src/dist/components/ui/aurora.tsx +45 -0
  51. package/src/dist/components/ui/avatar.tsx +50 -0
  52. package/src/dist/components/ui/badge.tsx +37 -0
  53. package/src/dist/components/ui/breadcrumb.tsx +115 -0
  54. package/src/dist/components/ui/button.tsx +57 -0
  55. package/src/dist/components/ui/card.tsx +76 -0
  56. package/src/dist/components/ui/collapsible.tsx +11 -0
  57. package/src/dist/components/ui/command.tsx +153 -0
  58. package/src/dist/components/ui/dialog.tsx +124 -0
  59. package/src/dist/components/ui/dropdown-menu.tsx +200 -0
  60. package/src/dist/components/ui/icon-cloud.tsx +324 -0
  61. package/src/dist/components/ui/input.tsx +25 -0
  62. package/src/dist/components/ui/interactive-hover-button.tsx +35 -0
  63. package/src/dist/components/ui/popover.tsx +33 -0
  64. package/src/dist/components/ui/scroll-area.tsx +48 -0
  65. package/src/dist/components/ui/separator.tsx +30 -0
  66. package/src/dist/components/ui/sheet.tsx +140 -0
  67. package/src/dist/components/ui/shine-border.tsx +64 -0
  68. package/src/dist/components/ui/skeleton.tsx +15 -0
  69. package/src/dist/components/ui/sonner.tsx +31 -0
  70. package/src/dist/components/ui/table.tsx +117 -0
  71. package/src/dist/components/ui/tabs.tsx +55 -0
  72. package/src/dist/components/ui/toggle-group.tsx +61 -0
  73. package/src/dist/components/ui/toggle.tsx +46 -0
  74. package/src/dist/components.json +17 -0
  75. package/src/dist/contents/docs/getting-started/changelog/index.mdx +512 -0
  76. package/src/dist/contents/docs/getting-started/components/accordion/index.mdx +72 -0
  77. package/src/dist/contents/docs/getting-started/components/button/index.mdx +42 -0
  78. package/src/dist/contents/docs/getting-started/components/card/index.mdx +70 -0
  79. package/src/dist/contents/docs/getting-started/components/card-group/index.mdx +49 -0
  80. package/src/dist/contents/docs/getting-started/components/code-block/index.mdx +41 -0
  81. package/src/dist/contents/docs/getting-started/components/custom/index.mdx +38 -0
  82. package/src/dist/contents/docs/getting-started/components/image/index.mdx +37 -0
  83. package/src/dist/contents/docs/getting-started/components/index.mdx +9 -0
  84. package/src/dist/contents/docs/getting-started/components/keyboard/index.mdx +117 -0
  85. package/src/dist/contents/docs/getting-started/components/link/index.mdx +34 -0
  86. package/src/dist/contents/docs/getting-started/components/note/index.mdx +46 -0
  87. package/src/dist/contents/docs/getting-started/components/release-note/index.mdx +130 -0
  88. package/src/dist/contents/docs/getting-started/components/stepper/index.mdx +47 -0
  89. package/src/dist/contents/docs/getting-started/components/tabs/index.mdx +70 -0
  90. package/src/dist/contents/docs/getting-started/components/tooltips/index.mdx +22 -0
  91. package/src/dist/contents/docs/getting-started/components/youtube/index.mdx +21 -0
  92. package/src/dist/contents/docs/getting-started/customize/index.mdx +94 -0
  93. package/src/dist/contents/docs/getting-started/installation/index.mdx +84 -0
  94. package/src/dist/contents/docs/getting-started/introduction/index.mdx +50 -0
  95. package/src/dist/contents/docs/getting-started/project-structure/index.mdx +87 -0
  96. package/src/dist/contents/docs/getting-started/quick-start-guide/index.mdx +127 -0
  97. package/src/dist/docu.json +100 -0
  98. package/src/dist/hooks/index.ts +2 -0
  99. package/src/dist/hooks/useActiveSection.ts +68 -0
  100. package/src/dist/hooks/useScrollPosition.ts +28 -0
  101. package/src/dist/lib/markdown.ts +244 -0
  102. package/src/dist/lib/routes-config.ts +28 -0
  103. package/src/dist/lib/toc.ts +9 -0
  104. package/src/dist/lib/utils.ts +80 -0
  105. package/src/dist/next-env.d.ts +5 -0
  106. package/src/dist/next.config.mjs +14 -0
  107. package/src/dist/package.json +58 -0
  108. package/src/dist/postcss.config.js +6 -0
  109. package/src/dist/public/favicon.ico +0 -0
  110. package/src/dist/public/images/docu.svg +6 -0
  111. package/src/dist/public/images/example-img.png +0 -0
  112. package/src/dist/public/images/img-playground.png +0 -0
  113. package/src/dist/public/images/new-editor.png +0 -0
  114. package/src/dist/public/images/og-image.png +0 -0
  115. package/src/dist/public/images/release-note.png +0 -0
  116. package/src/dist/public/images/snippet.png +0 -0
  117. package/src/dist/public/images/vercel.png +0 -0
  118. package/src/dist/public/images/view-changelog.png +0 -0
  119. package/src/dist/styles/editor.css +57 -0
  120. package/src/dist/styles/globals.css +156 -0
  121. package/src/dist/styles/syntax.css +100 -0
  122. package/src/dist/tailwind.config.ts +112 -0
  123. package/src/dist/tsconfig.json +26 -0
  124. package/src/index.js +19 -0
  125. package/src/installer/projectInstaller.js +125 -0
  126. package/src/utils/display.js +83 -0
  127. package/src/utils/logger.js +11 -0
  128. package/src/utils/packageManager.js +54 -0
  129. package/create.js +0 -223
@@ -0,0 +1,264 @@
1
+ "use client";
2
+
3
+ import { getDocsTocs } from "@/lib/markdown";
4
+ import clsx from "clsx";
5
+ import Link from "next/link";
6
+ import { useState, useRef, useEffect, useCallback } from "react";
7
+ import { motion } from "framer-motion";
8
+ import { ScrollToTop } from "./scroll-to-top";
9
+ import { TocItem } from "@/lib/toc";
10
+
11
+ interface TocObserverProps {
12
+ data: TocItem[];
13
+ activeId?: string | null;
14
+ onActiveIdChange?: (id: string | null) => void;
15
+ }
16
+
17
+ export default function TocObserver({
18
+ data,
19
+ activeId: externalActiveId,
20
+ onActiveIdChange
21
+ }: TocObserverProps) {
22
+ const [internalActiveId, setInternalActiveId] = useState<string | null>(null);
23
+ const observer = useRef<IntersectionObserver | null>(null);
24
+ const [clickedId, setClickedId] = useState<string | null>(null);
25
+ const itemRefs = useRef<Map<string, HTMLAnchorElement>>(new Map());
26
+
27
+ // Use external activeId if provided, otherwise use internal state
28
+ const activeId = externalActiveId !== undefined ? externalActiveId : internalActiveId;
29
+ const setActiveId = onActiveIdChange || setInternalActiveId;
30
+
31
+ // Handle intersection observer for auto-highlighting
32
+ useEffect(() => {
33
+ const handleIntersect = (entries: IntersectionObserverEntry[]) => {
34
+ const visibleEntries = entries.filter(entry => entry.isIntersecting);
35
+
36
+ // Find the most recently scrolled-into-view element
37
+ const mostVisibleEntry = visibleEntries.reduce((prev, current) => {
38
+ // Prefer the entry that's more visible or higher on the page
39
+ const prevRatio = prev?.intersectionRatio || 0;
40
+ const currentRatio = current.intersectionRatio;
41
+
42
+ if (currentRatio > prevRatio) return current;
43
+ if (currentRatio === prevRatio &&
44
+ current.boundingClientRect.top < prev.boundingClientRect.top) {
45
+ return current;
46
+ }
47
+ return prev;
48
+ }, visibleEntries[0]);
49
+
50
+ if (mostVisibleEntry && !clickedId) {
51
+ const newActiveId = mostVisibleEntry.target.id;
52
+ if (newActiveId !== activeId) {
53
+ setActiveId(newActiveId);
54
+ }
55
+ }
56
+ };
57
+
58
+ observer.current = new IntersectionObserver(handleIntersect, {
59
+ root: null,
60
+ rootMargin: "-20% 0px -70% 0px", // Adjusted margins for better section detection
61
+ threshold: [0, 0.1, 0.5, 0.9, 1], // Multiple thresholds for better accuracy
62
+ });
63
+
64
+ const elements = data.map((item) =>
65
+ document.getElementById(item.href.slice(1))
66
+ );
67
+
68
+ elements.forEach((el) => {
69
+ if (el && observer.current) {
70
+ observer.current.observe(el);
71
+ }
72
+ });
73
+
74
+ // Set initial active ID if none is set
75
+ if (!activeId && elements[0]) {
76
+ setActiveId(elements[0].id);
77
+ }
78
+
79
+ return () => {
80
+ if (observer.current) {
81
+ elements.forEach((el) => {
82
+ if (el) {
83
+ observer.current!.unobserve(el);
84
+ }
85
+ });
86
+ }
87
+ };
88
+ }, [data, clickedId, activeId, setActiveId]);
89
+
90
+ const handleLinkClick = useCallback((id: string) => {
91
+ setClickedId(id);
92
+ setActiveId(id);
93
+
94
+ // Reset the clicked state after a delay to allow for smooth scrolling
95
+ const timer = setTimeout(() => {
96
+ setClickedId(null);
97
+ }, 1000);
98
+
99
+ return () => clearTimeout(timer);
100
+ }, [setActiveId]);
101
+
102
+ // Function to check if an item has children
103
+ const hasChildren = (currentId: string, currentLevel: number) => {
104
+ const currentIndex = data.findIndex(item => item.href.slice(1) === currentId);
105
+ if (currentIndex === -1 || currentIndex === data.length - 1) return false;
106
+
107
+ const nextItem = data[currentIndex + 1];
108
+ return nextItem.level > currentLevel;
109
+ };
110
+
111
+ // Calculate scroll progress for the active section
112
+ const [scrollProgress, setScrollProgress] = useState(0);
113
+ const [activeSectionIndex, setActiveSectionIndex] = useState(0);
114
+
115
+ useEffect(() => {
116
+ const handleScroll = () => {
117
+ if (!activeId) return;
118
+
119
+ const activeElement = document.getElementById(activeId);
120
+ if (!activeElement) return;
121
+
122
+ const rect = activeElement.getBoundingClientRect();
123
+ const windowHeight = window.innerHeight;
124
+ const elementTop = rect.top;
125
+ const elementHeight = rect.height;
126
+
127
+ // Calculate how much of the element is visible
128
+ let progress = 0;
129
+ if (elementTop < windowHeight) {
130
+ progress = Math.min(1, (windowHeight - elementTop) / (windowHeight + elementHeight));
131
+ }
132
+
133
+ setScrollProgress(progress);
134
+ };
135
+
136
+ window.addEventListener('scroll', handleScroll, { passive: true });
137
+ return () => window.removeEventListener('scroll', handleScroll);
138
+ }, [activeId]);
139
+
140
+ // Update active section index when activeId changes
141
+ useEffect(() => {
142
+ if (activeId) {
143
+ const index = data.findIndex(item => item.href.slice(1) === activeId);
144
+ if (index !== -1) {
145
+ setActiveSectionIndex(index);
146
+ }
147
+ }
148
+ }, [activeId, data]);
149
+
150
+ return (
151
+ <div className="relative">
152
+ <div className="relative text-sm text-stone-600 dark:text-stone-400">
153
+ <div className="flex flex-col gap-0">
154
+ {data.map(({ href, level, text }, index) => {
155
+ const id = href.slice(1);
156
+ const isActive = activeId === id;
157
+ const indent = level > 1 ? (level - 1) * 20 : 0;
158
+ const isParent = hasChildren(id, level);
159
+ const isLastInLevel = index === data.length - 1 || data[index + 1].level <= level;
160
+
161
+ return (
162
+ <div key={href} className="relative">
163
+ {/* Simple L-shaped connector */}
164
+ {level > 1 && (
165
+ <div
166
+ className={clsx("absolute top-0 h-full w-6", {
167
+ "left-[6px]": indent === 20, // Level 2
168
+ "left-[22px]": indent === 40, // Level 3
169
+ "left-[38px]": indent === 60, // Level 4
170
+ })}
171
+ >
172
+ {/* Vertical line */}
173
+ <div className={clsx(
174
+ "absolute left-0 top-0 h-full w-px",
175
+ isActive ? "bg-primary/20" : "bg-stone-300 dark:bg-stone-600"
176
+ )}>
177
+ {isActive && (
178
+ <motion.div
179
+ className="absolute left-0 top-0 w-full h-full bg-primary origin-top"
180
+ initial={{ scaleY: 0 }}
181
+ animate={{ scaleY: scrollProgress }}
182
+ transition={{ duration: 0.3 }}
183
+ />
184
+ )}
185
+ </div>
186
+
187
+ {/* Horizontal line */}
188
+ <div className={clsx(
189
+ "absolute left-0 top-1/2 h-px w-6",
190
+ isActive ? "bg-primary/20" : "bg-stone-300 dark:bg-stone-600"
191
+ )}>
192
+ {isActive && (
193
+ <motion.div
194
+ className="absolute left-0 top-0 h-full w-full bg-primary origin-left"
195
+ initial={{ scaleX: 0 }}
196
+ animate={{ scaleX: scrollProgress }}
197
+ transition={{ duration: 0.3, delay: 0.1 }}
198
+ />
199
+ )}
200
+ </div>
201
+ </div>
202
+ )}
203
+
204
+ <Link
205
+ href={href}
206
+ onClick={() => handleLinkClick(id)}
207
+ className={clsx(
208
+ "relative flex items-center py-2 transition-colors",
209
+ {
210
+ "text-primary dark:text-primary-400 font-medium": isActive,
211
+ "text-stone-600 dark:text-stone-400 hover:text-stone-900 dark:hover:text-stone-200": !isActive,
212
+ }
213
+ )}
214
+ style={{
215
+ paddingLeft: `${indent}px`,
216
+ marginLeft: level > 1 ? '12px' : '0',
217
+ }}
218
+ ref={(el) => {
219
+ const map = itemRefs.current;
220
+ if (el) {
221
+ map.set(id, el);
222
+ } else {
223
+ map.delete(id);
224
+ }
225
+ }}
226
+ >
227
+ {/* Circle indicator */}
228
+ <div className="relative w-4 h-4 flex items-center justify-center flex-shrink-0">
229
+ <div className={clsx(
230
+ "w-1.5 h-1.5 rounded-full transition-all duration-300 relative z-10",
231
+ {
232
+ "bg-primary scale-100": isActive,
233
+ "bg-stone-300 dark:bg-stone-600 scale-75 group-hover:scale-100 group-hover:bg-primary/50": !isActive,
234
+ }
235
+ )}>
236
+ {isActive && (
237
+ <motion.div
238
+ className="absolute inset-0 rounded-full bg-primary/20"
239
+ initial={{ scale: 1 }}
240
+ animate={{ scale: 1.8 }}
241
+ transition={{
242
+ duration: 2,
243
+ repeat: Infinity,
244
+ repeatType: "reverse"
245
+ }}
246
+ />
247
+ )}
248
+ </div>
249
+ </div>
250
+
251
+ <span className="truncate text-sm">
252
+ {text}
253
+ </span>
254
+ </Link>
255
+ </div>
256
+ );
257
+ })}
258
+ </div>
259
+ </div>
260
+ {/* Add scroll to top link at the bottom of TOC */}
261
+ <ScrollToTop className="mt-6" />
262
+ </div>
263
+ );
264
+ }
@@ -0,0 +1,27 @@
1
+ import { getDocsTocs } from "@/lib/markdown";
2
+ import TocObserver from "./toc-observer";
3
+ import { ScrollArea } from "@/components/ui/scroll-area";
4
+ import { ListIcon } from "lucide-react";
5
+ import Sponsor from "./Sponsor";
6
+
7
+
8
+ export default async function Toc({ path }: { path: string }) {
9
+ const tocs = await getDocsTocs(path);
10
+
11
+ return (
12
+ <div className="lg:flex hidden toc flex-[1.5] min-w-[238px] py-5 sticky top-16 h-[calc(100vh-4rem)]">
13
+ <div className="flex flex-col h-full w-full px-2 gap-2 mb-auto">
14
+ <div className="flex items-center gap-2">
15
+ <ListIcon className="w-4 h-4" />
16
+ <h3 className="font-medium text-sm">On this page</h3>
17
+ </div>
18
+ <div className="flex-shrink-0 min-h-0 max-h-[calc(70vh-4rem)]">
19
+ <ScrollArea className="h-full">
20
+ <TocObserver data={tocs} />
21
+ </ScrollArea>
22
+ </div>
23
+ <Sponsor />
24
+ </div>
25
+ </div>
26
+ );
27
+ }
@@ -0,0 +1,9 @@
1
+ import { PropsWithChildren } from "react";
2
+
3
+ export function Typography({ children }: PropsWithChildren) {
4
+ return (
5
+ <div className="prose prose-zinc dark:prose-invert prose-code:font-code dark:prose-code:bg-stone-900/25 prose-code:bg-stone-50 prose-pre:bg-background prose-headings:scroll-m-20 w-[85vw] sm:w-full sm:mx-auto prose-code:text-sm prose-code:leading-6 dark:prose-code:text-white prose-code:text-stone-800 prose-code:p-1 prose-code:rounded-md prose-code:border pt-2 !min-w-full prose-img:rounded-md prose-img:border prose-code:before:content-none prose-code:after:content-none prose-code:px-1.5 prose-code:overflow-x-auto !max-w-[500px] prose-img:my-3 prose-h2:my-4 prose-h2:mt-8">
6
+ {children}
7
+ </div>
8
+ );
9
+ }
@@ -0,0 +1,58 @@
1
+ "use client"
2
+
3
+ import * as React from "react"
4
+ import * as AccordionPrimitive from "@radix-ui/react-accordion"
5
+ import { ChevronDown } from "lucide-react"
6
+
7
+ import { cn } from "@/lib/utils"
8
+
9
+ const Accordion = AccordionPrimitive.Root
10
+
11
+ const AccordionItem = React.forwardRef<
12
+ React.ElementRef<typeof AccordionPrimitive.Item>,
13
+ React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Item>
14
+ >(({ className, ...props }, ref) => (
15
+ <AccordionPrimitive.Item
16
+ ref={ref}
17
+ className={cn("border-b", className)}
18
+ {...props}
19
+ />
20
+ ))
21
+ AccordionItem.displayName = "AccordionItem"
22
+
23
+ const AccordionTrigger = React.forwardRef<
24
+ React.ElementRef<typeof AccordionPrimitive.Trigger>,
25
+ React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Trigger>
26
+ >(({ className, children, ...props }, ref) => (
27
+ <AccordionPrimitive.Header className="flex">
28
+ <AccordionPrimitive.Trigger
29
+ ref={ref}
30
+ className={cn(
31
+ "flex flex-1 items-center justify-between py-4 font-medium transition-all hover:underline [&[data-state=open]>svg]:rotate-180",
32
+ className
33
+ )}
34
+ {...props}
35
+ >
36
+ {children}
37
+ <ChevronDown className="h-4 w-4 shrink-0 transition-transform duration-200" />
38
+ </AccordionPrimitive.Trigger>
39
+ </AccordionPrimitive.Header>
40
+ ))
41
+ AccordionTrigger.displayName = AccordionPrimitive.Trigger.displayName
42
+
43
+ const AccordionContent = React.forwardRef<
44
+ React.ElementRef<typeof AccordionPrimitive.Content>,
45
+ React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Content>
46
+ >(({ className, children, ...props }, ref) => (
47
+ <AccordionPrimitive.Content
48
+ ref={ref}
49
+ className="overflow-hidden text-sm transition-all data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down"
50
+ {...props}
51
+ >
52
+ <div className={cn("pb-4 pt-0", className)}>{children}</div>
53
+ </AccordionPrimitive.Content>
54
+ ))
55
+
56
+ AccordionContent.displayName = AccordionPrimitive.Content.displayName
57
+
58
+ export { Accordion, AccordionItem, AccordionTrigger, AccordionContent }
@@ -0,0 +1,40 @@
1
+ import { CSSProperties, FC, ReactNode } from "react";
2
+
3
+ import { cn } from "@/lib/utils";
4
+
5
+ interface AnimatedShinyTextProps {
6
+ children: ReactNode;
7
+ className?: string;
8
+ shimmerWidth?: number;
9
+ }
10
+
11
+ const AnimatedShinyText: FC<AnimatedShinyTextProps> = ({
12
+ children,
13
+ className,
14
+ shimmerWidth = 100,
15
+ }) => {
16
+ return (
17
+ <p
18
+ style={
19
+ {
20
+ "--shiny-width": `${shimmerWidth}px`,
21
+ } as CSSProperties
22
+ }
23
+ className={cn(
24
+ "mx-auto max-w-md text-neutral-600/70 dark:text-neutral-400/70",
25
+
26
+ // Shine effect
27
+ "animate-shiny-text bg-clip-text bg-no-repeat [background-position:0_0] [background-size:var(--shiny-width)_100%] [transition:background-position_1s_cubic-bezier(.6,.6,0,1)_infinite]",
28
+
29
+ // Shine gradient
30
+ "bg-gradient-to-r from-transparent via-black/80 via-50% to-transparent dark:via-white/80",
31
+
32
+ className,
33
+ )}
34
+ >
35
+ {children}
36
+ </p>
37
+ );
38
+ };
39
+
40
+ export default AnimatedShinyText;
@@ -0,0 +1,45 @@
1
+ "use client";
2
+
3
+ import React, { memo } from "react";
4
+
5
+ interface AuroraTextProps {
6
+ children: React.ReactNode;
7
+ className?: string;
8
+ colors?: string[];
9
+ speed?: number;
10
+ }
11
+
12
+ export const AuroraText = memo(
13
+ ({
14
+ children,
15
+ className = "",
16
+ colors = ["#FF0080", "#7928CA", "#0070F3", "#38bdf8"],
17
+ speed = 1,
18
+ }: AuroraTextProps) => {
19
+ const gradientStyle = {
20
+ backgroundImage: `linear-gradient(135deg, ${colors.join(", ")}, ${
21
+ colors[0]
22
+ })`,
23
+ WebkitBackgroundClip: "text",
24
+ WebkitTextFillColor: "transparent",
25
+ animationDuration: `${10 / speed}s`,
26
+ };
27
+
28
+ return (
29
+ <span className={`relative inline-block ${className}`}>
30
+ <span className="sr-only">{children}</span>
31
+ <span
32
+ className="relative animate-aurora bg-[length:200%_auto] bg-clip-text text-transparent"
33
+ style={gradientStyle}
34
+ aria-hidden="true"
35
+ >
36
+ {children}
37
+ </span>
38
+ </span>
39
+ );
40
+ },
41
+ );
42
+
43
+ AuroraText.displayName = "AuroraText";
44
+
45
+ export default AuroraText;
@@ -0,0 +1,50 @@
1
+ "use client"
2
+
3
+ import * as React from "react"
4
+ import * as AvatarPrimitive from "@radix-ui/react-avatar"
5
+
6
+ import { cn } from "@/lib/utils"
7
+
8
+ const Avatar = React.forwardRef<
9
+ React.ElementRef<typeof AvatarPrimitive.Root>,
10
+ React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Root>
11
+ >(({ className, ...props }, ref) => (
12
+ <AvatarPrimitive.Root
13
+ ref={ref}
14
+ className={cn(
15
+ "relative flex h-10 w-10 shrink-0 overflow-hidden rounded-full",
16
+ className
17
+ )}
18
+ {...props}
19
+ />
20
+ ))
21
+ Avatar.displayName = AvatarPrimitive.Root.displayName
22
+
23
+ const AvatarImage = React.forwardRef<
24
+ React.ElementRef<typeof AvatarPrimitive.Image>,
25
+ React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Image>
26
+ >(({ className, ...props }, ref) => (
27
+ <AvatarPrimitive.Image
28
+ ref={ref}
29
+ className={cn("aspect-square h-full w-full", className)}
30
+ {...props}
31
+ />
32
+ ))
33
+ AvatarImage.displayName = AvatarPrimitive.Image.displayName
34
+
35
+ const AvatarFallback = React.forwardRef<
36
+ React.ElementRef<typeof AvatarPrimitive.Fallback>,
37
+ React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Fallback>
38
+ >(({ className, ...props }, ref) => (
39
+ <AvatarPrimitive.Fallback
40
+ ref={ref}
41
+ className={cn(
42
+ "flex h-full w-full items-center justify-center rounded-full bg-muted",
43
+ className
44
+ )}
45
+ {...props}
46
+ />
47
+ ))
48
+ AvatarFallback.displayName = AvatarPrimitive.Fallback.displayName
49
+
50
+ export { Avatar, AvatarImage, AvatarFallback }
@@ -0,0 +1,37 @@
1
+ "use client";
2
+
3
+ import * as React from "react";
4
+ import { cva, type VariantProps } from "class-variance-authority";
5
+ import { cn } from "@/lib/utils";
6
+
7
+ const badgeVariants = cva(
8
+ "inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
9
+ {
10
+ variants: {
11
+ variant: {
12
+ default:
13
+ "border-transparent bg-primary text-primary-foreground hover:bg-primary/80",
14
+ secondary:
15
+ "border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80",
16
+ destructive:
17
+ "border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80",
18
+ outline: "text-foreground",
19
+ },
20
+ },
21
+ defaultVariants: {
22
+ variant: "default",
23
+ },
24
+ }
25
+ );
26
+
27
+ export interface BadgeProps
28
+ extends React.HTMLAttributes<HTMLDivElement>,
29
+ VariantProps<typeof badgeVariants> {}
30
+
31
+ function Badge({ className, variant, ...props }: BadgeProps) {
32
+ return (
33
+ <div className={cn(badgeVariants({ variant }), className)} {...props} />
34
+ );
35
+ }
36
+
37
+ export { Badge, badgeVariants };
@@ -0,0 +1,115 @@
1
+ import * as React from "react"
2
+ import { Slot } from "@radix-ui/react-slot"
3
+ import { ChevronRight, MoreHorizontal } from "lucide-react"
4
+
5
+ import { cn } from "@/lib/utils"
6
+
7
+ const Breadcrumb = React.forwardRef<
8
+ HTMLElement,
9
+ React.ComponentPropsWithoutRef<"nav"> & {
10
+ separator?: React.ReactNode
11
+ }
12
+ >(({ ...props }, ref) => <nav ref={ref} aria-label="breadcrumb" {...props} />)
13
+ Breadcrumb.displayName = "Breadcrumb"
14
+
15
+ const BreadcrumbList = React.forwardRef<
16
+ HTMLOListElement,
17
+ React.ComponentPropsWithoutRef<"ol">
18
+ >(({ className, ...props }, ref) => (
19
+ <ol
20
+ ref={ref}
21
+ className={cn(
22
+ "flex flex-wrap items-center gap-1.5 break-words text-sm text-muted-foreground sm:gap-2.5",
23
+ className
24
+ )}
25
+ {...props}
26
+ />
27
+ ))
28
+ BreadcrumbList.displayName = "BreadcrumbList"
29
+
30
+ const BreadcrumbItem = React.forwardRef<
31
+ HTMLLIElement,
32
+ React.ComponentPropsWithoutRef<"li">
33
+ >(({ className, ...props }, ref) => (
34
+ <li
35
+ ref={ref}
36
+ className={cn("inline-flex items-center gap-1.5", className)}
37
+ {...props}
38
+ />
39
+ ))
40
+ BreadcrumbItem.displayName = "BreadcrumbItem"
41
+
42
+ const BreadcrumbLink = React.forwardRef<
43
+ HTMLAnchorElement,
44
+ React.ComponentPropsWithoutRef<"a"> & {
45
+ asChild?: boolean
46
+ }
47
+ >(({ asChild, className, ...props }, ref) => {
48
+ const Comp = asChild ? Slot : "a"
49
+
50
+ return (
51
+ <Comp
52
+ ref={ref}
53
+ className={cn("transition-colors hover:text-foreground", className)}
54
+ {...props}
55
+ />
56
+ )
57
+ })
58
+ BreadcrumbLink.displayName = "BreadcrumbLink"
59
+
60
+ const BreadcrumbPage = React.forwardRef<
61
+ HTMLSpanElement,
62
+ React.ComponentPropsWithoutRef<"span">
63
+ >(({ className, ...props }, ref) => (
64
+ <span
65
+ ref={ref}
66
+ role="link"
67
+ aria-disabled="true"
68
+ aria-current="page"
69
+ className={cn("font-normal text-foreground", className)}
70
+ {...props}
71
+ />
72
+ ))
73
+ BreadcrumbPage.displayName = "BreadcrumbPage"
74
+
75
+ const BreadcrumbSeparator = ({
76
+ children,
77
+ className,
78
+ ...props
79
+ }: React.ComponentProps<"li">) => (
80
+ <li
81
+ role="presentation"
82
+ aria-hidden="true"
83
+ className={cn("[&>svg]:size-3.5", className)}
84
+ {...props}
85
+ >
86
+ {children ?? <ChevronRight />}
87
+ </li>
88
+ )
89
+ BreadcrumbSeparator.displayName = "BreadcrumbSeparator"
90
+
91
+ const BreadcrumbEllipsis = ({
92
+ className,
93
+ ...props
94
+ }: React.ComponentProps<"span">) => (
95
+ <span
96
+ role="presentation"
97
+ aria-hidden="true"
98
+ className={cn("flex h-9 w-9 items-center justify-center", className)}
99
+ {...props}
100
+ >
101
+ <MoreHorizontal className="h-4 w-4" />
102
+ <span className="sr-only">More</span>
103
+ </span>
104
+ )
105
+ BreadcrumbEllipsis.displayName = "BreadcrumbElipssis"
106
+
107
+ export {
108
+ Breadcrumb,
109
+ BreadcrumbList,
110
+ BreadcrumbItem,
111
+ BreadcrumbLink,
112
+ BreadcrumbPage,
113
+ BreadcrumbSeparator,
114
+ BreadcrumbEllipsis,
115
+ }