@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,324 @@
1
+ "use client";
2
+
3
+ import React, { useEffect, useRef, useState } from "react";
4
+ import { renderToString } from "react-dom/server";
5
+
6
+ interface Icon {
7
+ x: number;
8
+ y: number;
9
+ z: number;
10
+ scale: number;
11
+ opacity: number;
12
+ id: number;
13
+ }
14
+
15
+ interface IconCloudProps {
16
+ icons?: React.ReactNode[];
17
+ images?: string[];
18
+ }
19
+
20
+ function easeOutCubic(t: number): number {
21
+ return 1 - Math.pow(1 - t, 3);
22
+ }
23
+
24
+ export function IconCloud({ icons, images }: IconCloudProps) {
25
+ const canvasRef = useRef<HTMLCanvasElement>(null);
26
+ const [iconPositions, setIconPositions] = useState<Icon[]>([]);
27
+ const [rotation, setRotation] = useState({ x: 0, y: 0 });
28
+ const [isDragging, setIsDragging] = useState(false);
29
+ const [lastMousePos, setLastMousePos] = useState({ x: 0, y: 0 });
30
+ const [mousePos, setMousePos] = useState({ x: 0, y: 0 });
31
+ const [targetRotation, setTargetRotation] = useState<{
32
+ x: number;
33
+ y: number;
34
+ startX: number;
35
+ startY: number;
36
+ distance: number;
37
+ startTime: number;
38
+ duration: number;
39
+ } | null>(null);
40
+ const animationFrameRef = useRef<number>();
41
+ const rotationRef = useRef(rotation);
42
+ const iconCanvasesRef = useRef<HTMLCanvasElement[]>([]);
43
+ const imagesLoadedRef = useRef<boolean[]>([]);
44
+
45
+ // Create icon canvases once when icons/images change
46
+ useEffect(() => {
47
+ if (!icons && !images) return;
48
+
49
+ const items = icons || images || [];
50
+ imagesLoadedRef.current = new Array(items.length).fill(false);
51
+
52
+ const newIconCanvases = items.map((item, index) => {
53
+ const offscreen = document.createElement("canvas");
54
+ offscreen.width = 40;
55
+ offscreen.height = 40;
56
+ const offCtx = offscreen.getContext("2d");
57
+
58
+ if (offCtx) {
59
+ if (images) {
60
+ // Handle image URLs directly
61
+ const img = new Image();
62
+ img.crossOrigin = "anonymous";
63
+ img.src = items[index] as string;
64
+ img.onload = () => {
65
+ offCtx.clearRect(0, 0, offscreen.width, offscreen.height);
66
+
67
+ // Create circular clipping path
68
+ offCtx.beginPath();
69
+ offCtx.arc(20, 20, 20, 0, Math.PI * 2);
70
+ offCtx.closePath();
71
+ offCtx.clip();
72
+
73
+ // Draw the image
74
+ offCtx.drawImage(img, 0, 0, 40, 40);
75
+
76
+ imagesLoadedRef.current[index] = true;
77
+ };
78
+ } else {
79
+ // Handle SVG icons
80
+ offCtx.scale(0.4, 0.4);
81
+ const svgString = renderToString(item as React.ReactElement);
82
+ const img = new Image();
83
+ img.src = "data:image/svg+xml;base64," + btoa(svgString);
84
+ img.onload = () => {
85
+ offCtx.clearRect(0, 0, offscreen.width, offscreen.height);
86
+ offCtx.drawImage(img, 0, 0);
87
+ imagesLoadedRef.current[index] = true;
88
+ };
89
+ }
90
+ }
91
+ return offscreen;
92
+ });
93
+
94
+ iconCanvasesRef.current = newIconCanvases;
95
+ }, [icons, images]);
96
+
97
+ // Generate initial icon positions on a sphere
98
+ useEffect(() => {
99
+ const items = icons || images || [];
100
+ const newIcons: Icon[] = [];
101
+ const numIcons = items.length || 20;
102
+
103
+ // Fibonacci sphere parameters
104
+ const offset = 2 / numIcons;
105
+ const increment = Math.PI * (3 - Math.sqrt(5));
106
+
107
+ for (let i = 0; i < numIcons; i++) {
108
+ const y = i * offset - 1 + offset / 2;
109
+ const r = Math.sqrt(1 - y * y);
110
+ const phi = i * increment;
111
+
112
+ const x = Math.cos(phi) * r;
113
+ const z = Math.sin(phi) * r;
114
+
115
+ newIcons.push({
116
+ x: x * 100,
117
+ y: y * 100,
118
+ z: z * 100,
119
+ scale: 1,
120
+ opacity: 1,
121
+ id: i,
122
+ });
123
+ }
124
+ setIconPositions(newIcons);
125
+ }, [icons, images]);
126
+
127
+ // Handle mouse events
128
+ const handleMouseDown = (e: React.MouseEvent<HTMLCanvasElement>) => {
129
+ const rect = canvasRef.current?.getBoundingClientRect();
130
+ if (!rect || !canvasRef.current) return;
131
+
132
+ const x = e.clientX - rect.left;
133
+ const y = e.clientY - rect.top;
134
+
135
+ const ctx = canvasRef.current.getContext("2d");
136
+ if (!ctx) return;
137
+
138
+ iconPositions.forEach((icon) => {
139
+ const cosX = Math.cos(rotationRef.current.x);
140
+ const sinX = Math.sin(rotationRef.current.x);
141
+ const cosY = Math.cos(rotationRef.current.y);
142
+ const sinY = Math.sin(rotationRef.current.y);
143
+
144
+ const rotatedX = icon.x * cosY - icon.z * sinY;
145
+ const rotatedZ = icon.x * sinY + icon.z * cosY;
146
+ const rotatedY = icon.y * cosX + rotatedZ * sinX;
147
+
148
+ const screenX = canvasRef.current!.width / 2 + rotatedX;
149
+ const screenY = canvasRef.current!.height / 2 + rotatedY;
150
+
151
+ const scale = (rotatedZ + 200) / 300;
152
+ const radius = 20 * scale;
153
+ const dx = x - screenX;
154
+ const dy = y - screenY;
155
+
156
+ if (dx * dx + dy * dy < radius * radius) {
157
+ const targetX = -Math.atan2(
158
+ icon.y,
159
+ Math.sqrt(icon.x * icon.x + icon.z * icon.z),
160
+ );
161
+ const targetY = Math.atan2(icon.x, icon.z);
162
+
163
+ const currentX = rotationRef.current.x;
164
+ const currentY = rotationRef.current.y;
165
+ const distance = Math.sqrt(
166
+ Math.pow(targetX - currentX, 2) + Math.pow(targetY - currentY, 2),
167
+ );
168
+
169
+ const duration = Math.min(2000, Math.max(800, distance * 1000));
170
+
171
+ setTargetRotation({
172
+ x: targetX,
173
+ y: targetY,
174
+ startX: currentX,
175
+ startY: currentY,
176
+ distance,
177
+ startTime: performance.now(),
178
+ duration,
179
+ });
180
+ return;
181
+ }
182
+ });
183
+
184
+ setIsDragging(true);
185
+ setLastMousePos({ x: e.clientX, y: e.clientY });
186
+ };
187
+
188
+ const handleMouseMove = (e: React.MouseEvent<HTMLCanvasElement>) => {
189
+ const rect = canvasRef.current?.getBoundingClientRect();
190
+ if (rect) {
191
+ const x = e.clientX - rect.left;
192
+ const y = e.clientY - rect.top;
193
+ setMousePos({ x, y });
194
+ }
195
+
196
+ if (isDragging) {
197
+ const deltaX = e.clientX - lastMousePos.x;
198
+ const deltaY = e.clientY - lastMousePos.y;
199
+
200
+ rotationRef.current = {
201
+ x: rotationRef.current.x + deltaY * 0.002,
202
+ y: rotationRef.current.y + deltaX * 0.002,
203
+ };
204
+
205
+ setLastMousePos({ x: e.clientX, y: e.clientY });
206
+ }
207
+ };
208
+
209
+ const handleMouseUp = () => {
210
+ setIsDragging(false);
211
+ };
212
+
213
+ // Animation and rendering
214
+ useEffect(() => {
215
+ const canvas = canvasRef.current;
216
+ const ctx = canvas?.getContext("2d");
217
+ if (!canvas || !ctx) return;
218
+
219
+ const animate = () => {
220
+ ctx.clearRect(0, 0, canvas.width, canvas.height);
221
+
222
+ const centerX = canvas.width / 2;
223
+ const centerY = canvas.height / 2;
224
+ const maxDistance = Math.sqrt(centerX * centerX + centerY * centerY);
225
+ const dx = mousePos.x - centerX;
226
+ const dy = mousePos.y - centerY;
227
+ const distance = Math.sqrt(dx * dx + dy * dy);
228
+ const speed = 0.003 + (distance / maxDistance) * 0.01;
229
+
230
+ if (targetRotation) {
231
+ const elapsed = performance.now() - targetRotation.startTime;
232
+ const progress = Math.min(1, elapsed / targetRotation.duration);
233
+ const easedProgress = easeOutCubic(progress);
234
+
235
+ rotationRef.current = {
236
+ x:
237
+ targetRotation.startX +
238
+ (targetRotation.x - targetRotation.startX) * easedProgress,
239
+ y:
240
+ targetRotation.startY +
241
+ (targetRotation.y - targetRotation.startY) * easedProgress,
242
+ };
243
+
244
+ if (progress >= 1) {
245
+ setTargetRotation(null);
246
+ }
247
+ } else if (!isDragging) {
248
+ rotationRef.current = {
249
+ x: rotationRef.current.x + (dy / canvas.height) * speed,
250
+ y: rotationRef.current.y + (dx / canvas.width) * speed,
251
+ };
252
+ }
253
+
254
+ iconPositions.forEach((icon, index) => {
255
+ const cosX = Math.cos(rotationRef.current.x);
256
+ const sinX = Math.sin(rotationRef.current.x);
257
+ const cosY = Math.cos(rotationRef.current.y);
258
+ const sinY = Math.sin(rotationRef.current.y);
259
+
260
+ const rotatedX = icon.x * cosY - icon.z * sinY;
261
+ const rotatedZ = icon.x * sinY + icon.z * cosY;
262
+ const rotatedY = icon.y * cosX + rotatedZ * sinX;
263
+
264
+ const scale = (rotatedZ + 200) / 300;
265
+ const opacity = Math.max(0.2, Math.min(1, (rotatedZ + 150) / 200));
266
+
267
+ ctx.save();
268
+ ctx.translate(
269
+ canvas.width / 2 + rotatedX,
270
+ canvas.height / 2 + rotatedY,
271
+ );
272
+ ctx.scale(scale, scale);
273
+ ctx.globalAlpha = opacity;
274
+
275
+ if (icons || images) {
276
+ // Only try to render icons/images if they exist
277
+ if (
278
+ iconCanvasesRef.current[index] &&
279
+ imagesLoadedRef.current[index]
280
+ ) {
281
+ ctx.drawImage(iconCanvasesRef.current[index], -20, -20, 40, 40);
282
+ }
283
+ } else {
284
+ // Show numbered circles if no icons/images are provided
285
+ ctx.beginPath();
286
+ ctx.arc(0, 0, 20, 0, Math.PI * 2);
287
+ ctx.fillStyle = "#4444ff";
288
+ ctx.fill();
289
+ ctx.fillStyle = "white";
290
+ ctx.textAlign = "center";
291
+ ctx.textBaseline = "middle";
292
+ ctx.font = "16px Arial";
293
+ ctx.fillText(`${icon.id + 1}`, 0, 0);
294
+ }
295
+
296
+ ctx.restore();
297
+ });
298
+ animationFrameRef.current = requestAnimationFrame(animate);
299
+ };
300
+
301
+ animate();
302
+
303
+ return () => {
304
+ if (animationFrameRef.current) {
305
+ cancelAnimationFrame(animationFrameRef.current);
306
+ }
307
+ };
308
+ }, [icons, images, iconPositions, isDragging, mousePos, targetRotation]);
309
+
310
+ return (
311
+ <canvas
312
+ ref={canvasRef}
313
+ width={400}
314
+ height={400}
315
+ onMouseDown={handleMouseDown}
316
+ onMouseMove={handleMouseMove}
317
+ onMouseUp={handleMouseUp}
318
+ onMouseLeave={handleMouseUp}
319
+ className="rounded-full"
320
+ aria-label="Interactive 3D Icon Cloud"
321
+ role="img"
322
+ />
323
+ );
324
+ }
@@ -0,0 +1,25 @@
1
+ import * as React from "react"
2
+
3
+ import { cn } from "@/lib/utils"
4
+
5
+ export interface InputProps
6
+ extends React.InputHTMLAttributes<HTMLInputElement> {}
7
+
8
+ const Input = React.forwardRef<HTMLInputElement, InputProps>(
9
+ ({ className, type, ...props }, ref) => {
10
+ return (
11
+ <input
12
+ type={type}
13
+ className={cn(
14
+ "flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
15
+ className
16
+ )}
17
+ ref={ref}
18
+ {...props}
19
+ />
20
+ )
21
+ }
22
+ )
23
+ Input.displayName = "Input"
24
+
25
+ export { Input }
@@ -0,0 +1,35 @@
1
+ import React from "react";
2
+ import { ArrowRight } from "lucide-react";
3
+ import { cn } from "@/lib/utils";
4
+
5
+ interface InteractiveHoverButtonProps
6
+ extends React.ButtonHTMLAttributes<HTMLButtonElement> {}
7
+
8
+ export const InteractiveHoverButton = React.forwardRef<
9
+ HTMLButtonElement,
10
+ InteractiveHoverButtonProps
11
+ >(({ children, className, ...props }, ref) => {
12
+ return (
13
+ <button
14
+ ref={ref}
15
+ className={cn(
16
+ "group relative w-auto cursor-pointer overflow-hidden rounded-full border bg-background p-2 px-6 text-center font-semibold",
17
+ className,
18
+ )}
19
+ {...props}
20
+ >
21
+ <div className="flex items-center gap-2">
22
+ <div className="h-2 w-2 rounded-full bg-primary transition-all duration-300 group-hover:scale-[100.8]"></div>
23
+ <span className="inline-block transition-all duration-300 group-hover:translate-x-12 group-hover:opacity-0">
24
+ {children}
25
+ </span>
26
+ </div>
27
+ <div className="absolute top-0 z-10 flex h-full w-full translate-x-12 items-center justify-center gap-2 text-primary-foreground opacity-0 transition-all duration-300 group-hover:-translate-x-5 group-hover:opacity-100">
28
+ <span>{children}</span>
29
+ <ArrowRight className="w-4 h-4" />
30
+ </div>
31
+ </button>
32
+ );
33
+ });
34
+
35
+ InteractiveHoverButton.displayName = "InteractiveHoverButton";
@@ -0,0 +1,33 @@
1
+ "use client"
2
+
3
+ import * as React from "react"
4
+ import * as PopoverPrimitive from "@radix-ui/react-popover"
5
+
6
+ import { cn } from "@/lib/utils"
7
+
8
+ const Popover = PopoverPrimitive.Root
9
+
10
+ const PopoverTrigger = PopoverPrimitive.Trigger
11
+
12
+ const PopoverAnchor = PopoverPrimitive.Anchor
13
+
14
+ const PopoverContent = React.forwardRef<
15
+ React.ElementRef<typeof PopoverPrimitive.Content>,
16
+ React.ComponentPropsWithoutRef<typeof PopoverPrimitive.Content>
17
+ >(({ className, align = "center", sideOffset = 4, ...props }, ref) => (
18
+ <PopoverPrimitive.Portal>
19
+ <PopoverPrimitive.Content
20
+ ref={ref}
21
+ align={align}
22
+ sideOffset={sideOffset}
23
+ className={cn(
24
+ "z-50 w-72 rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
25
+ className
26
+ )}
27
+ {...props}
28
+ />
29
+ </PopoverPrimitive.Portal>
30
+ ))
31
+ PopoverContent.displayName = PopoverPrimitive.Content.displayName
32
+
33
+ export { Popover, PopoverTrigger, PopoverContent, PopoverAnchor }
@@ -0,0 +1,48 @@
1
+ "use client"
2
+
3
+ import * as React from "react"
4
+ import * as ScrollAreaPrimitive from "@radix-ui/react-scroll-area"
5
+
6
+ import { cn } from "@/lib/utils"
7
+
8
+ const ScrollArea = React.forwardRef<
9
+ React.ElementRef<typeof ScrollAreaPrimitive.Root>,
10
+ React.ComponentPropsWithoutRef<typeof ScrollAreaPrimitive.Root>
11
+ >(({ className, children, ...props }, ref) => (
12
+ <ScrollAreaPrimitive.Root
13
+ ref={ref}
14
+ className={cn("relative overflow-hidden", className)}
15
+ {...props}
16
+ >
17
+ <ScrollAreaPrimitive.Viewport className="h-full w-full rounded-[inherit]">
18
+ {children}
19
+ </ScrollAreaPrimitive.Viewport>
20
+ <ScrollBar />
21
+ <ScrollAreaPrimitive.Corner />
22
+ </ScrollAreaPrimitive.Root>
23
+ ))
24
+ ScrollArea.displayName = ScrollAreaPrimitive.Root.displayName
25
+
26
+ const ScrollBar = React.forwardRef<
27
+ React.ElementRef<typeof ScrollAreaPrimitive.ScrollAreaScrollbar>,
28
+ React.ComponentPropsWithoutRef<typeof ScrollAreaPrimitive.ScrollAreaScrollbar>
29
+ >(({ className, orientation = "vertical", ...props }, ref) => (
30
+ <ScrollAreaPrimitive.ScrollAreaScrollbar
31
+ ref={ref}
32
+ orientation={orientation}
33
+ className={cn(
34
+ "flex touch-none select-none transition-colors",
35
+ orientation === "vertical" &&
36
+ "h-full w-2.5 border-l border-l-transparent p-[1px]",
37
+ orientation === "horizontal" &&
38
+ "h-2.5 flex-col border-t border-t-transparent p-[1px]",
39
+ className
40
+ )}
41
+ {...props}
42
+ >
43
+ <ScrollAreaPrimitive.ScrollAreaThumb className="relative flex-1 rounded-full bg-border" />
44
+ </ScrollAreaPrimitive.ScrollAreaScrollbar>
45
+ ))
46
+ ScrollBar.displayName = ScrollAreaPrimitive.ScrollAreaScrollbar.displayName
47
+
48
+ export { ScrollArea, ScrollBar }
@@ -0,0 +1,30 @@
1
+ "use client";
2
+
3
+ import * as React from "react";
4
+ import * as SeparatorPrimitive from "@radix-ui/react-separator";
5
+ import { cn } from "@/lib/utils";
6
+
7
+ const Separator = React.forwardRef<
8
+ React.ElementRef<typeof SeparatorPrimitive.Root>,
9
+ React.ComponentPropsWithoutRef<typeof SeparatorPrimitive.Root>
10
+ >(
11
+ (
12
+ { className, orientation = "horizontal", decorative = true, ...props },
13
+ ref
14
+ ) => (
15
+ <SeparatorPrimitive.Root
16
+ ref={ref}
17
+ decorative={decorative}
18
+ orientation={orientation}
19
+ className={cn(
20
+ "shrink-0 bg-border",
21
+ orientation === "horizontal" ? "h-[1px] w-full" : "h-full w-[1px]",
22
+ className
23
+ )}
24
+ {...props}
25
+ />
26
+ )
27
+ );
28
+ Separator.displayName = SeparatorPrimitive.Root.displayName;
29
+
30
+ export { Separator };
@@ -0,0 +1,140 @@
1
+ "use client";
2
+
3
+ import * as React from "react";
4
+ import * as SheetPrimitive from "@radix-ui/react-dialog";
5
+ import { cva, type VariantProps } from "class-variance-authority";
6
+ import { X } from "lucide-react";
7
+
8
+ import { cn } from "@/lib/utils";
9
+
10
+ const Sheet = SheetPrimitive.Root;
11
+
12
+ const SheetTrigger = SheetPrimitive.Trigger;
13
+
14
+ const SheetClose = SheetPrimitive.Close;
15
+
16
+ const SheetPortal = SheetPrimitive.Portal;
17
+
18
+ const SheetOverlay = React.forwardRef<
19
+ React.ElementRef<typeof SheetPrimitive.Overlay>,
20
+ React.ComponentPropsWithoutRef<typeof SheetPrimitive.Overlay>
21
+ >(({ className, ...props }, ref) => (
22
+ <SheetPrimitive.Overlay
23
+ className={cn(
24
+ "fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
25
+ className
26
+ )}
27
+ {...props}
28
+ ref={ref}
29
+ />
30
+ ));
31
+ SheetOverlay.displayName = SheetPrimitive.Overlay.displayName;
32
+
33
+ const sheetVariants = cva(
34
+ "fixed z-50 gap-4 bg-background p-6 shadow-lg transition ease-in-out data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:duration-300 data-[state=open]:duration-500",
35
+ {
36
+ variants: {
37
+ side: {
38
+ top: "inset-x-0 top-0 border-b data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top",
39
+ bottom:
40
+ "inset-x-0 bottom-0 border-t data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom",
41
+ left: "inset-y-0 left-0 h-full w-3/4 border-r data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left sm:max-w-sm",
42
+ right:
43
+ "inset-y-0 right-0 h-full w-3/4 border-l data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right sm:max-w-sm",
44
+ },
45
+ },
46
+ defaultVariants: {
47
+ side: "right",
48
+ },
49
+ }
50
+ );
51
+
52
+ interface SheetContentProps
53
+ extends React.ComponentPropsWithoutRef<typeof SheetPrimitive.Content>,
54
+ VariantProps<typeof sheetVariants> {}
55
+
56
+ const SheetContent = React.forwardRef<
57
+ React.ElementRef<typeof SheetPrimitive.Content>,
58
+ SheetContentProps
59
+ >(({ side = "right", className, children, ...props }, ref) => (
60
+ <SheetPortal>
61
+ <SheetOverlay />
62
+ <SheetPrimitive.Content
63
+ ref={ref}
64
+ className={cn(sheetVariants({ side }), className)}
65
+ {...props}
66
+ >
67
+ {children}
68
+ <SheetPrimitive.Close className="absolute right-4 top-7 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-secondary">
69
+ <X className="h-4 w-4" />
70
+ <span className="sr-only">Close</span>
71
+ </SheetPrimitive.Close>
72
+ </SheetPrimitive.Content>
73
+ </SheetPortal>
74
+ ));
75
+ SheetContent.displayName = SheetPrimitive.Content.displayName;
76
+
77
+ const SheetHeader = ({
78
+ className,
79
+ ...props
80
+ }: React.HTMLAttributes<HTMLDivElement>) => (
81
+ <div
82
+ className={cn(
83
+ "flex flex-col space-y-2 text-center sm:text-left",
84
+ className
85
+ )}
86
+ {...props}
87
+ />
88
+ );
89
+ SheetHeader.displayName = "SheetHeader";
90
+
91
+ const SheetFooter = ({
92
+ className,
93
+ ...props
94
+ }: React.HTMLAttributes<HTMLDivElement>) => (
95
+ <div
96
+ className={cn(
97
+ "flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2",
98
+ className
99
+ )}
100
+ {...props}
101
+ />
102
+ );
103
+ SheetFooter.displayName = "SheetFooter";
104
+
105
+ const SheetTitle = React.forwardRef<
106
+ React.ElementRef<typeof SheetPrimitive.Title>,
107
+ React.ComponentPropsWithoutRef<typeof SheetPrimitive.Title>
108
+ >(({ className, ...props }, ref) => (
109
+ <SheetPrimitive.Title
110
+ ref={ref}
111
+ className={cn("text-lg font-semibold text-foreground", className)}
112
+ {...props}
113
+ />
114
+ ));
115
+ SheetTitle.displayName = SheetPrimitive.Title.displayName;
116
+
117
+ const SheetDescription = React.forwardRef<
118
+ React.ElementRef<typeof SheetPrimitive.Description>,
119
+ React.ComponentPropsWithoutRef<typeof SheetPrimitive.Description>
120
+ >(({ className, ...props }, ref) => (
121
+ <SheetPrimitive.Description
122
+ ref={ref}
123
+ className={cn("text-sm text-muted-foreground", className)}
124
+ {...props}
125
+ />
126
+ ));
127
+ SheetDescription.displayName = SheetPrimitive.Description.displayName;
128
+
129
+ export {
130
+ Sheet,
131
+ SheetPortal,
132
+ SheetOverlay,
133
+ SheetTrigger,
134
+ SheetClose,
135
+ SheetContent,
136
+ SheetHeader,
137
+ SheetFooter,
138
+ SheetTitle,
139
+ SheetDescription,
140
+ };
@@ -0,0 +1,64 @@
1
+ "use client";
2
+
3
+ import * as React from "react";
4
+
5
+ import { cn } from "@/lib/utils";
6
+
7
+ interface ShineBorderProps extends React.HTMLAttributes<HTMLDivElement> {
8
+ /**
9
+ * Width of the border in pixels
10
+ * @default 1
11
+ */
12
+ borderWidth?: number;
13
+ /**
14
+ * Duration of the animation in seconds
15
+ * @default 14
16
+ */
17
+ duration?: number;
18
+ /**
19
+ * Color of the border, can be a single color or an array of colors
20
+ * @default "#000000"
21
+ */
22
+ shineColor?: string | string[];
23
+ }
24
+
25
+ /**
26
+ * Shine Border
27
+ *
28
+ * An animated background border effect component with configurable properties.
29
+ */
30
+ export function ShineBorder({
31
+ borderWidth = 1,
32
+ duration = 14,
33
+ shineColor = "#000000",
34
+ className,
35
+ style,
36
+ ...props
37
+ }: ShineBorderProps) {
38
+ return (
39
+ <div
40
+ style={
41
+ {
42
+ "--border-width": `${borderWidth}px`,
43
+ "--duration": `${duration}s`,
44
+ backgroundImage: `radial-gradient(transparent,transparent, ${
45
+ Array.isArray(shineColor) ? shineColor.join(",") : shineColor
46
+ },transparent,transparent)`,
47
+ backgroundSize: "300% 300%",
48
+ mask: `linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0)`,
49
+ WebkitMask: `linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0)`,
50
+ WebkitMaskComposite: "xor",
51
+ maskComposite: "exclude",
52
+ padding: "var(--border-width)",
53
+ ...style,
54
+ } as React.CSSProperties
55
+ }
56
+ className={cn(
57
+ "pointer-events-none absolute inset-0 size-full rounded-[inherit] will-change-[background-position] motion-safe:animate-shine",
58
+ className,
59
+ )}
60
+ {...props}
61
+ />
62
+ );
63
+ }
64
+ export default ShineBorder;