From 9b338aee78dce645ed6fba6f1281a7484af87f89 Mon Sep 17 00:00:00 2001 From: BelkacemYerfa Date: Wed, 27 Mar 2024 20:53:59 +0100 Subject: [PATCH 01/12] fix : the compatibility of file upload component with validation libs --- .gitignore | 1 + content/docs/file-upload.mdx | 14 +- contentlayer.config.js | 5 - src/app/examples/page.tsx | 146 +++++++++++------- .../default/example/file-upload-demo.tsx | 2 + .../file-upload/file-upload-dropzone.tsx | 58 +++++++ .../file-upload/file-upload-reselect.tsx | 98 ++++++++++++ .../default/extension/file-upload.tsx | 72 ++++----- 8 files changed, 302 insertions(+), 94 deletions(-) create mode 100644 src/registry/default/example/file-upload/file-upload-dropzone.tsx create mode 100644 src/registry/default/example/file-upload/file-upload-reselect.tsx diff --git a/.gitignore b/.gitignore index 02cf563..a89e897 100644 --- a/.gitignore +++ b/.gitignore @@ -36,4 +36,5 @@ yarn-error.log* next-env.d.ts .contentlayer +.vscode tsconfig.tsbuildinfo diff --git a/content/docs/file-upload.mdx b/content/docs/file-upload.mdx index e515cc2..26e6516 100644 --- a/content/docs/file-upload.mdx +++ b/content/docs/file-upload.mdx @@ -8,7 +8,7 @@ links: url: https://sonner.emilkowal.ski/ --- - + ## Installation @@ -208,3 +208,15 @@ import { ``` + +## Example + +### reSelect + + + +### dropzoneOptions + +The `dropzoneOptions` prop is an object that can be passed to the `FileUploader` component to customize the useDropzone hook behavior. You can find the full list of options [here](https://react-dropzone.js.org/#src). + + \ No newline at end of file diff --git a/contentlayer.config.js b/contentlayer.config.js index 1ec10a1..efd5301 100644 --- a/contentlayer.config.js +++ b/contentlayer.config.js @@ -61,11 +61,6 @@ export const Doc = defineDocumentType(() => ({ default: true, required: false, }, - state: { - type: "enum", - values: ["deprecated", "new", "updated"], - required: false, - }, }, computedFields, })); diff --git a/src/app/examples/page.tsx b/src/app/examples/page.tsx index 482f067..7244abc 100644 --- a/src/app/examples/page.tsx +++ b/src/app/examples/page.tsx @@ -1,10 +1,23 @@ "use client"; -import { OtpStyledInput } from "@/registry/default/extension/otp-input"; +import { + FileUploader, + FileInput, + FileUploaderContent, + FileUploaderItem, +} from "@/registry/default/extension/file-upload"; +import { useState } from "react"; +import { DropzoneOptions } from "react-dropzone"; +import z from "zod"; +import { zodResolver } from "@hookform/resolvers/zod"; +import { useForm } from "react-hook-form"; +import { Form, FormField, FormItem, FormMessage } from "@/components/ui/form"; import { Button } from "@/components/ui/button"; -import { EyeClosedIcon, EyeOpenIcon } from "@radix-ui/react-icons"; -import { FormEvent, useState } from "react"; import { toast } from "sonner"; +import { Input } from "@/components/ui/input"; +import FileUploaderTest from "@/registry/default/example/file-upload-demo"; +import { AspectRatio } from "@/components/ui/aspect-ratio"; +import Image from "next/image"; export default function PageExample() { return ( @@ -18,64 +31,93 @@ export default function PageExample() { ); } -enum OtpInputType { - password = "password", - text = "text", -} +const CardForm = z.object({ + name: z.string().optional(), + description: z.string().optional(), + files: z + .array( + z.instanceof(File).refine((file) => file.size < 4 * 1024 * 1024, { + message: "File size must be less than 4MB", + }) + ) + .max(5, { + message: "Maximum 5 files are allowed", + }) + .nullable(), +}); + +type CardFormType = z.infer; const ExampleComp = () => { - const [isPassword, setIsPassword] = useState( - OtpInputType.password - ); + const form = useForm({ + resolver: zodResolver(CardForm), + defaultValues: { + name: "", + description: "", + files: null, + }, + }); - const [field, setField] = useState(""); + const dropzone = { + multiple: true, + maxFiles: 5, + maxSize: 4 * 1024 * 1024, + } satisfies DropzoneOptions; - const onChange = (otp: string) => { - setField((prev) => prev + otp); - }; - - const onSubmit = (e: FormEvent) => { - e.preventDefault(); - toast.success("Form submitted : " + field); + const onSubmit = (data: CardFormType) => { + console.log(data); + toast.success(`Files are ${data.files}`); }; return (
-

Carousel

-
- -
- - -
- -
+ /> + + +
); }; diff --git a/src/registry/default/example/file-upload-demo.tsx b/src/registry/default/example/file-upload-demo.tsx index 59b3473..dfc6a19 100644 --- a/src/registry/default/example/file-upload-demo.tsx +++ b/src/registry/default/example/file-upload-demo.tsx @@ -40,11 +40,13 @@ const FileSvgDraw = () => { const FileUploaderTest = () => { const [files, setFiles] = useState(null); + const dropZoneConfig = { maxFiles: 5, maxSize: 1024 * 1024 * 4, multiple: true, }; + return ( { + const [files, setFiles] = useState([]); + + const dropzone = { + accept: { + "image/*": [".jpg", ".jpeg", ".png"], + }, + multiple: true, + maxFiles: 5, + maxSize: 5 * 1024 * 1024, + } satisfies DropzoneOptions; + + return ( + + +
+

Drop files here

+
+
+ + {files?.map((file, i) => ( + + {file.name} + + ))} + +
+ ); +}; + +export default FileUploadDropzone; diff --git a/src/registry/default/example/file-upload/file-upload-reselect.tsx b/src/registry/default/example/file-upload/file-upload-reselect.tsx new file mode 100644 index 0000000..49a3443 --- /dev/null +++ b/src/registry/default/example/file-upload/file-upload-reselect.tsx @@ -0,0 +1,98 @@ +"use client"; + +import { + FileUploader, + FileInput, + FileUploaderContent, + FileUploaderItem, +} from "@/registry/default/extension/file-upload"; +import { DropzoneOptions } from "react-dropzone"; +import z from "zod"; +import { zodResolver } from "@hookform/resolvers/zod"; +import { useForm } from "react-hook-form"; +import { Form, FormField, FormItem, FormMessage } from "@/components/ui/form"; +import { Button } from "@/components/ui/button"; +import { toast } from "sonner"; + +const CardForm = z.object({ + name: z.string().optional(), + description: z.string().optional(), + files: z + .array( + z.instanceof(File).refine((file) => file.size < 4 * 1024 * 1024, { + message: "File size must be less than 4MB", + }) + ) + .max(5, { + message: "Maximum 5 files are allowed", + }) + .nullable(), +}); + +type CardFormType = z.infer; + +const FileUploadDropzone = () => { + const form = useForm({ + resolver: zodResolver(CardForm), + defaultValues: { + name: "", + description: "", + files: null, + }, + }); + + const dropzone = { + multiple: true, + maxFiles: 5, + maxSize: 4 * 1024 * 1024, + } satisfies DropzoneOptions; + + const onSubmit = (data: CardFormType) => { + console.log(data); + toast.success(`Files are ${data.files}`); + }; + + return ( +
+ + ( + + + +
+

Drop files here

+
+
+ + {field.value?.map((file, i) => ( + + {file.name} + + ))} + +
+ +
+ )} + /> + + + + ); +}; + +export default FileUploadDropzone; diff --git a/src/registry/default/extension/file-upload.tsx b/src/registry/default/extension/file-upload.tsx index 04ffdeb..0f802f8 100644 --- a/src/registry/default/extension/file-upload.tsx +++ b/src/registry/default/extension/file-upload.tsx @@ -44,9 +44,9 @@ export const useFileUpload = () => { }; type FileUploaderProps = { - reSelect?: boolean; value: File[] | null; - onValueChange: Dispatch>; + reSelect?: boolean; + onValueChange: (value: File[] | null) => void; dropzoneOptions: DropzoneOptions; }; @@ -58,9 +58,9 @@ export const FileUploader = forwardRef< { className, dropzoneOptions, - reSelect, value, onValueChange, + reSelect, children, ...props }, @@ -80,43 +80,36 @@ export const FileUploader = forwardRef< const reSelectAll = maxFiles === 1 ? true : reSelect; - const addFileToSet = useCallback( - (file: File) => { - if (file.size > maxSize) { - toast.error(`File too big , Max size is ${maxSize / 1024 / 1024}MB`); - } - - onValueChange((prev) => { - if (!reSelectAll && prev && prev.length >= maxFiles) { - return prev; - } - return [...(prev || []), file]; - }); + const removeFileFromSet = useCallback( + (i: number) => { + if (!value) return; + const newFiles = value.filter((_, index) => index !== i); + onValueChange(newFiles); }, - [reSelectAll] + [value, onValueChange] ); - const removeFileFromSet = useCallback((index: number) => { - onValueChange((prev) => { - if (!prev) return prev; - const newPreview = [...prev]; - newPreview.splice(index, 1); - return newPreview; - }); - }, []); - const handleKeyDown = useCallback( (e: React.KeyboardEvent) => { e.preventDefault(); e.stopPropagation(); + if (!value) return; - if (e.key === "ArrowDown") { + const moveNext = () => { const nextIndex = activeIndex + 1; setActiveIndex(nextIndex > value.length - 1 ? 0 : nextIndex); - } else if (e.key === "ArrowUp") { + }; + + const movePrev = () => { const nextIndex = activeIndex - 1; setActiveIndex(nextIndex < 0 ? value.length - 1 : nextIndex); + }; + + if (e.key === "ArrowDown") { + moveNext(); + } else if (e.key === "ArrowUp") { + movePrev(); } else if (e.key === "Enter" || e.key === "Space") { if (activeIndex === -1) { dropzoneState.inputRef.current?.click(); @@ -124,30 +117,37 @@ export const FileUploader = forwardRef< } else if (e.key === "Delete" || e.key === "Backspace") { if (activeIndex !== -1) { removeFileFromSet(activeIndex); - const newIndex = activeIndex - 1; - setActiveIndex(newIndex < 0 ? value.length - 1 : newIndex); + movePrev(); } } else if (e.key === "Escape") { setActiveIndex(-1); } }, - [value, activeIndex] + [value, activeIndex, removeFileFromSet] ); const onDrop = useCallback( (acceptedFiles: File[], rejectedFiles: FileRejection[]) => { const files = acceptedFiles; - if (!!reSelectAll) { - onValueChange([]); - } - if (!files) { toast.error("file error , probably too big"); return; } - files.forEach(addFileToSet); + const newValues: File[] = value ? [...value] : []; + + if (reSelectAll) { + newValues.splice(0, newValues.length); + } + + files.forEach((file) => { + if (newValues.length < maxFiles) { + newValues.push(file); + } + }); + + onValueChange(newValues); if (rejectedFiles.length > 0) { for (let i = 0; i < rejectedFiles.length; i++) { @@ -164,7 +164,7 @@ export const FileUploader = forwardRef< } } }, - [reSelectAll] + [reSelectAll, value] ); useEffect(() => { From a85c135f98139091bbe6823a5a815647622dd7f8 Mon Sep 17 00:00:00 2001 From: BelkacemYerfa Date: Wed, 27 Mar 2024 23:29:08 +0100 Subject: [PATCH 02/12] feat : add the file upload doc --- content/docs/file-upload.mdx | 13 +- src/__registry__/index.tsx | 28 +++- src/components/ui/scroll-area.tsx | 2 +- src/registry/components.ts | 25 ++- .../default/example/breadcrumb-demo.tsx | 25 +-- .../file-upload/file-upload-dropzone.tsx | 4 +- .../file-upload/file-upload-reselect.tsx | 98 ------------ .../example/file-upload/file-upload-zod.tsx | 148 ++++++++++++++++++ ....tsx => image-carousel-upload-example.tsx} | 0 .../default/extension/file-upload.tsx | 20 ++- 10 files changed, 210 insertions(+), 153 deletions(-) delete mode 100644 src/registry/default/example/file-upload/file-upload-reselect.tsx create mode 100644 src/registry/default/example/file-upload/file-upload-zod.tsx rename src/registry/default/example/{image-carousel-upload-demo.tsx => image-carousel-upload-example.tsx} (100%) diff --git a/content/docs/file-upload.mdx b/content/docs/file-upload.mdx index 26e6516..84272f6 100644 --- a/content/docs/file-upload.mdx +++ b/content/docs/file-upload.mdx @@ -211,12 +211,15 @@ import { ## Example -### reSelect - - -### dropzoneOptions +### DropzoneOptions The `dropzoneOptions` prop is an object that can be passed to the `FileUploader` component to customize the useDropzone hook behavior. You can find the full list of options [here](https://react-dropzone.js.org/#src). - \ No newline at end of file + + +### Form + +This form uses the reSelect prop to remove all the current selected files when new files are selected. + + diff --git a/src/__registry__/index.tsx b/src/__registry__/index.tsx index c2611b8..46195d9 100644 --- a/src/__registry__/index.tsx +++ b/src/__registry__/index.tsx @@ -103,13 +103,6 @@ export const Index: Record = { component: React.lazy(() => import("@/registry/default/example/breadcrumb-demo.tsx")), files: ["src/registry/default/example/breadcrumb-demo.tsx"], }, - "image-carousel-upload-demo": { - name: "image-carousel-upload-demo", - type: "components:demo", - registryDependencies: ["image-carousel-upload"], - component: React.lazy(() => import("@/registry/default/example/image-carousel-upload-demo.tsx")), - files: ["src/registry/default/example/image-carousel-upload-demo.tsx"], - }, "tree-view-builtin-indicator": { name: "tree-view-builtin-indicator", type: "components:example", @@ -180,5 +173,26 @@ export const Index: Record = { component: React.lazy(() => import("@/registry/default/example/otp-input/otp-input-zod.tsx")), files: ["src/registry/default/example/otp-input/otp-input-zod.tsx"], }, + "file-upload-dropzone": { + name: "file-upload-dropzone", + type: "components:example", + registryDependencies: ["file-upload"], + component: React.lazy(() => import("@/registry/default/example/file-upload/file-upload-dropzone.tsx")), + files: ["src/registry/default/example/file-upload/file-upload-dropzone.tsx"], + }, + "file-upload-zod": { + name: "file-upload-zod", + type: "components:example", + registryDependencies: ["file-upload"], + component: React.lazy(() => import("@/registry/default/example/file-upload/file-upload-zod.tsx")), + files: ["src/registry/default/example/file-upload/file-upload-zod.tsx"], + }, + "image-carousel-upload-example": { + name: "image-carousel-upload-example", + type: "components:example", + registryDependencies: ["image-carousel-upload"], + component: React.lazy(() => import("@/registry/default/example/image-carousel-upload-example.tsx")), + files: ["src/registry/default/example/image-carousel-upload-example.tsx"], + }, }, } diff --git a/src/components/ui/scroll-area.tsx b/src/components/ui/scroll-area.tsx index 32cf968..3e5d5f0 100644 --- a/src/components/ui/scroll-area.tsx +++ b/src/components/ui/scroll-area.tsx @@ -11,7 +11,7 @@ const ScrollArea = React.forwardRef< >(({ className, children, ...props }, ref) => ( diff --git a/src/registry/components.ts b/src/registry/components.ts index 45b922f..182def0 100644 --- a/src/registry/components.ts +++ b/src/registry/components.ts @@ -88,12 +88,6 @@ const demos: Registry = [ registryDependencies: ["breadcrumb"], files: ["example/breadcrumb-demo.tsx"], }, - { - name: "image-carousel-upload-demo", - type: "components:demo", - registryDependencies: ["image-carousel-upload"], - files: ["example/image-carousel-upload-demo.tsx"], - }, ]; const examples: Registry = [ @@ -157,6 +151,25 @@ const examples: Registry = [ registryDependencies: ["otp-input"], files: ["example/otp-input/otp-input-zod.tsx"], }, + { + name: "file-upload-dropzone", + type: "components:example", + registryDependencies: ["file-upload"], + files: ["example/file-upload/file-upload-dropzone.tsx"], + }, + { + name: "file-upload-zod", + type: "components:example", + registryDependencies: ["file-upload"], + files: ["example/file-upload/file-upload-zod.tsx"], + }, + // Under development + { + name: "image-carousel-upload-example", + type: "components:example", + registryDependencies: ["image-carousel-upload"], + files: ["example/image-carousel-upload-example.tsx"], + }, ]; export const registry: Registry = [...extension, ...demos, ...examples]; diff --git a/src/registry/default/example/breadcrumb-demo.tsx b/src/registry/default/example/breadcrumb-demo.tsx index 3f6e063..93d421f 100644 --- a/src/registry/default/example/breadcrumb-demo.tsx +++ b/src/registry/default/example/breadcrumb-demo.tsx @@ -4,18 +4,15 @@ import { BreadCrumb, BreadCrumbItem, BreadCrumbSeparator, - BreadCrumbPopover, - BreadCrumbTrigger, - BreadCrumbContent, - BreadCrumbEllipsis, } from "@/registry/default/extension/breadcrumb"; import Link from "next/link"; + const BreadCrumbTest = () => { return ( Home @@ -25,24 +22,6 @@ const BreadCrumbTest = () => { Settings - - - - open rest links - - - - Account - - - Settings - - - - Account diff --git a/src/registry/default/example/file-upload/file-upload-dropzone.tsx b/src/registry/default/example/file-upload/file-upload-dropzone.tsx index 3629cd0..e465372 100644 --- a/src/registry/default/example/file-upload/file-upload-dropzone.tsx +++ b/src/registry/default/example/file-upload/file-upload-dropzone.tsx @@ -18,8 +18,8 @@ const FileUploadDropzone = () => { "image/*": [".jpg", ".jpeg", ".png"], }, multiple: true, - maxFiles: 5, - maxSize: 5 * 1024 * 1024, + maxFiles: 4, + maxSize: 1 * 1024 * 1024, } satisfies DropzoneOptions; return ( diff --git a/src/registry/default/example/file-upload/file-upload-reselect.tsx b/src/registry/default/example/file-upload/file-upload-reselect.tsx deleted file mode 100644 index 49a3443..0000000 --- a/src/registry/default/example/file-upload/file-upload-reselect.tsx +++ /dev/null @@ -1,98 +0,0 @@ -"use client"; - -import { - FileUploader, - FileInput, - FileUploaderContent, - FileUploaderItem, -} from "@/registry/default/extension/file-upload"; -import { DropzoneOptions } from "react-dropzone"; -import z from "zod"; -import { zodResolver } from "@hookform/resolvers/zod"; -import { useForm } from "react-hook-form"; -import { Form, FormField, FormItem, FormMessage } from "@/components/ui/form"; -import { Button } from "@/components/ui/button"; -import { toast } from "sonner"; - -const CardForm = z.object({ - name: z.string().optional(), - description: z.string().optional(), - files: z - .array( - z.instanceof(File).refine((file) => file.size < 4 * 1024 * 1024, { - message: "File size must be less than 4MB", - }) - ) - .max(5, { - message: "Maximum 5 files are allowed", - }) - .nullable(), -}); - -type CardFormType = z.infer; - -const FileUploadDropzone = () => { - const form = useForm({ - resolver: zodResolver(CardForm), - defaultValues: { - name: "", - description: "", - files: null, - }, - }); - - const dropzone = { - multiple: true, - maxFiles: 5, - maxSize: 4 * 1024 * 1024, - } satisfies DropzoneOptions; - - const onSubmit = (data: CardFormType) => { - console.log(data); - toast.success(`Files are ${data.files}`); - }; - - return ( -
- - ( - - - -
-

Drop files here

-
-
- - {field.value?.map((file, i) => ( - - {file.name} - - ))} - -
- -
- )} - /> - - - - ); -}; - -export default FileUploadDropzone; diff --git a/src/registry/default/example/file-upload/file-upload-zod.tsx b/src/registry/default/example/file-upload/file-upload-zod.tsx new file mode 100644 index 0000000..575cedb --- /dev/null +++ b/src/registry/default/example/file-upload/file-upload-zod.tsx @@ -0,0 +1,148 @@ +"use client"; + +import { + FileUploader, + FileInput, + FileUploaderContent, + FileUploaderItem, +} from "@/registry/default/extension/file-upload"; +import { DropzoneOptions } from "react-dropzone"; +import z from "zod"; +import { zodResolver } from "@hookform/resolvers/zod"; +import { useForm } from "react-hook-form"; +import { Form, FormField, FormItem, FormMessage } from "@/components/ui/form"; +import { Button, buttonVariants } from "@/components/ui/button"; +import { toast } from "sonner"; +import { Input } from "@/components/ui/input"; +import { Paperclip, Send } from "lucide-react"; +import { cn } from "@/lib/utils"; +import { AspectRatio } from "@/components/ui/aspect-ratio"; +import Image from "next/image"; + +const CardForm = z.object({ + message: z.string().min(1), + files: z + .array( + z.instanceof(File).refine((file) => file.size < 4 * 1024 * 1024, { + message: "File size must be less than 4MB", + }) + ) + .max(5, { + message: "Maximum 5 files are allowed", + }) + .nullable(), +}); + +type CardFormType = z.infer; + +const FileUploadDropzone = () => { + const form = useForm({ + resolver: zodResolver(CardForm), + defaultValues: { + message: "", + files: null, + }, + }); + + const dropzone = { + multiple: true, + maxFiles: 3, + maxSize: 4 * 1024 * 1024, + } satisfies DropzoneOptions; + + const onSubmit = (data: CardFormType) => { + toast.success("your message has been sent successfully"); + }; + + console.log(form.getValues("files")); + + return ( +
+ +
+ ( + + + + + Select your files + + {field.value && field.value.length > 0 && ( + + {field.value.map((file, i) => ( + + + {file.name} + + + ))} + + )} + + + )} + /> + ( + + + + )} + /> +
+ {form.formState.errors && ( +
+ {Object.values(form.formState.errors).map((error) => ( +

{error.message}

+ ))} +
+ )} + +
+ + ); +}; + +export default FileUploadDropzone; diff --git a/src/registry/default/example/image-carousel-upload-demo.tsx b/src/registry/default/example/image-carousel-upload-example.tsx similarity index 100% rename from src/registry/default/example/image-carousel-upload-demo.tsx rename to src/registry/default/example/image-carousel-upload-example.tsx diff --git a/src/registry/default/extension/file-upload.tsx b/src/registry/default/extension/file-upload.tsx index 0f802f8..620ab1e 100644 --- a/src/registry/default/extension/file-upload.tsx +++ b/src/registry/default/extension/file-upload.tsx @@ -203,7 +203,7 @@ export const FileUploader = forwardRef< tabIndex={0} onKeyDownCapture={handleKeyDown} className={cn( - "grid w-full relative focus:outline-none overflow-hidden ", + "grid w-full focus:outline-none overflow-hidden ", className, { "gap-2": value && value.length > 0, @@ -228,19 +228,17 @@ export const FileUploaderContent = forwardRef< return (
- -
- {children} -
-
+
+ {children} +
); }); From 0aea08e48aaec6875eacae6205e2720b6dd2df1d Mon Sep 17 00:00:00 2001 From: BelkacemYerfa Date: Thu, 28 Mar 2024 00:35:03 +0100 Subject: [PATCH 03/12] feat : add the section example for breadcrumb component --- content/docs/breadcrumb.mdx | 27 +++++++- src/__registry__/index.tsx | 21 ++++++ src/registry/components.ts | 18 +++++ .../default/example/breadcrumb-demo.tsx | 6 +- .../example/breadcrumb/breadcrumb-popover.tsx | 55 ++++++++++++++++ .../breadcrumb/breadcrumb-separator.tsx | 32 +++++++++ .../breadcrumb/breadcrumb-variants.tsx | 66 +++++++++++++++++++ src/registry/default/extension/breadcrumb.tsx | 2 +- 8 files changed, 222 insertions(+), 5 deletions(-) create mode 100644 src/registry/default/example/breadcrumb/breadcrumb-popover.tsx create mode 100644 src/registry/default/example/breadcrumb/breadcrumb-separator.tsx create mode 100644 src/registry/default/example/breadcrumb/breadcrumb-variants.tsx diff --git a/content/docs/breadcrumb.mdx b/content/docs/breadcrumb.mdx index 79fcfc7..18d3aa9 100644 --- a/content/docs/breadcrumb.mdx +++ b/content/docs/breadcrumb.mdx @@ -6,7 +6,7 @@ links: url: https://ui.shadcn.com/docs/components/popover --- - + ## Installation @@ -217,3 +217,28 @@ import { Link } from "next/link"; ``` ## Examples + +### BreadCrumb Separator + + + +### BreadCrumb variants + +By default, the Breadcrumb component uses the `default` variant for each item. You can change the variant by passing the `variant` prop to the `BreadcrumbItem` component. + + + + + + Good to know + + The `variant` prop is the same as the button variants from shadcn, you can check the + button [documentation](https://ui.shadcn.com/docs/components/popover) for more information. + + + +### BreadCrumb Popover + +This popover can be used to display the full path if it's too long to fit in the screen. + + \ No newline at end of file diff --git a/src/__registry__/index.tsx b/src/__registry__/index.tsx index 46195d9..054e362 100644 --- a/src/__registry__/index.tsx +++ b/src/__registry__/index.tsx @@ -187,6 +187,27 @@ export const Index: Record = { component: React.lazy(() => import("@/registry/default/example/file-upload/file-upload-zod.tsx")), files: ["src/registry/default/example/file-upload/file-upload-zod.tsx"], }, + "breadcrumb-separator": { + name: "breadcrumb-separator", + type: "components:example", + registryDependencies: ["breadcrumb"], + component: React.lazy(() => import("@/registry/default/example/breadcrumb/breadcrumb-separator.tsx")), + files: ["src/registry/default/example/breadcrumb/breadcrumb-separator.tsx"], + }, + "breadcrumb-variants": { + name: "breadcrumb-variants", + type: "components:example", + registryDependencies: ["breadcrumb"], + component: React.lazy(() => import("@/registry/default/example/breadcrumb/breadcrumb-variants.tsx")), + files: ["src/registry/default/example/breadcrumb/breadcrumb-variants.tsx"], + }, + "breadcrumb-popover": { + name: "breadcrumb-popover", + type: "components:example", + registryDependencies: ["breadcrumb"], + component: React.lazy(() => import("@/registry/default/example/breadcrumb/breadcrumb-popover.tsx")), + files: ["src/registry/default/example/breadcrumb/breadcrumb-popover.tsx"], + }, "image-carousel-upload-example": { name: "image-carousel-upload-example", type: "components:example", diff --git a/src/registry/components.ts b/src/registry/components.ts index 182def0..48ad54d 100644 --- a/src/registry/components.ts +++ b/src/registry/components.ts @@ -163,6 +163,24 @@ const examples: Registry = [ registryDependencies: ["file-upload"], files: ["example/file-upload/file-upload-zod.tsx"], }, + { + name: "breadcrumb-separator", + type: "components:example", + registryDependencies: ["breadcrumb"], + files: ["example/breadcrumb/breadcrumb-separator.tsx"], + }, + { + name: "breadcrumb-variants", + type: "components:example", + registryDependencies: ["breadcrumb"], + files: ["example/breadcrumb/breadcrumb-variants.tsx"], + }, + { + name: "breadcrumb-popover", + type: "components:example", + registryDependencies: ["breadcrumb"], + files: ["example/breadcrumb/breadcrumb-popover.tsx"], + }, // Under development { name: "image-carousel-upload-example", diff --git a/src/registry/default/example/breadcrumb-demo.tsx b/src/registry/default/example/breadcrumb-demo.tsx index 93d421f..2166db5 100644 --- a/src/registry/default/example/breadcrumb-demo.tsx +++ b/src/registry/default/example/breadcrumb-demo.tsx @@ -12,17 +12,17 @@ const BreadCrumbTest = () => { Home - + Settings - + Account diff --git a/src/registry/default/example/breadcrumb/breadcrumb-popover.tsx b/src/registry/default/example/breadcrumb/breadcrumb-popover.tsx new file mode 100644 index 0000000..0f0fb08 --- /dev/null +++ b/src/registry/default/example/breadcrumb/breadcrumb-popover.tsx @@ -0,0 +1,55 @@ +"use client"; + +import { + BreadCrumb, + BreadCrumbItem, + BreadCrumbSeparator, + BreadCrumbPopover, + BreadCrumbTrigger, + BreadCrumbContent, + BreadCrumbEllipsis, +} from "@/registry/default/extension/breadcrumb"; +import Link from "next/link"; + +const BreadCrumbTest = () => { + return ( + + + Home + + + + Dashboard + + + + + + + open rest links + + + + Settings + + + Account + + + + + + Payments + + + ); +}; + +export default BreadCrumbTest; diff --git a/src/registry/default/example/breadcrumb/breadcrumb-separator.tsx b/src/registry/default/example/breadcrumb/breadcrumb-separator.tsx new file mode 100644 index 0000000..2166db5 --- /dev/null +++ b/src/registry/default/example/breadcrumb/breadcrumb-separator.tsx @@ -0,0 +1,32 @@ +"use client"; + +import { + BreadCrumb, + BreadCrumbItem, + BreadCrumbSeparator, +} from "@/registry/default/extension/breadcrumb"; +import Link from "next/link"; + +const BreadCrumbTest = () => { + return ( + + + Home + + + + Settings + + + + Account + + + ); +}; + +export default BreadCrumbTest; diff --git a/src/registry/default/example/breadcrumb/breadcrumb-variants.tsx b/src/registry/default/example/breadcrumb/breadcrumb-variants.tsx new file mode 100644 index 0000000..5d3ee92 --- /dev/null +++ b/src/registry/default/example/breadcrumb/breadcrumb-variants.tsx @@ -0,0 +1,66 @@ +"use client"; + +import { Select, SelectContent, SelectItem } from "@/components/ui/select"; +import { + BreadCrumb, + BreadCrumbItem, + BreadCrumbSeparator, +} from "@/registry/default/extension/breadcrumb"; +import { SelectTrigger, SelectValue } from "@radix-ui/react-select"; +import Link from "next/link"; +import { useState } from "react"; + +const OPTIONS = ["ghost", "outline", "link", "default", "destructive"]; + +const BreadCrumbVariantPicker = ({ + variant, + setVariant, +}: { + variant: string; + setVariant: (variant: string) => void; +}) => { + return ( +
+ +
+ ); +}; + +const BreadCrumbTest = () => { + const [variant, setVariant] = useState("ghost"); + return ( + <> + + + Home + + + + Settings + + + + Account + + + + + ); +}; + +export default BreadCrumbTest; diff --git a/src/registry/default/extension/breadcrumb.tsx b/src/registry/default/extension/breadcrumb.tsx index 42f1443..2b94235 100644 --- a/src/registry/default/extension/breadcrumb.tsx +++ b/src/registry/default/extension/breadcrumb.tsx @@ -255,7 +255,7 @@ export const BreadCrumbEllipsis = forwardRef< return prev; } const arr = [...prev, index]; - return arr.toSorted((a, b) => Number(a) - Number(b)); + return arr.sort((a, b) => Number(a) - Number(b)); }); }, [index, onValueChange]); return ( From 3313dfa371cd72e67c485ded2d3b25b69df7fa76 Mon Sep 17 00:00:00 2001 From: BelkacemYerfa Date: Thu, 28 Mar 2024 07:53:38 +0100 Subject: [PATCH 04/12] feat : add the last doc updates for the new launch --- .vscode/settings.json | 31 +++++++++---------- content/docs/changelog.mdx | 14 +++++++++ content/docs/tree-view.mdx | 8 +++-- src/app/globals.css | 9 ++++++ src/components/banner.tsx | 4 +-- src/components/mdx-component.tsx | 2 +- src/components/pager.tsx | 4 ++- .../example/file-upload/file-upload-zod.tsx | 2 +- 8 files changed, 51 insertions(+), 23 deletions(-) create mode 100644 content/docs/changelog.mdx diff --git a/.vscode/settings.json b/.vscode/settings.json index 712023a..35b5d3a 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -69,36 +69,35 @@ // Toggle excluded files "files.exclude": { + "**/.DS_Store": true, + "**/.editorconfig": true, + "**/.env.example": true, + "**/.eslintrc.cjs": true, "**/.git": true, - "**/.svn": true, "**/.hg": true, - "**/CVS": true, - "**/.DS_Store": true, - "**/Thumbs.db": true, - "**/node_modules": true, - "**/.next": true, "**/.husky": true, - "**/drizzle": true, - "**/dist": true, - "**/.todo.md": true, - "**/.vscode": true, - "**/.eslintrc.cjs": true, - "**/.editorconfig": true, "**/.lintstagedrc.mjs": true, "**/.markdownlint.json": true, "**/.markdownlintignore": true, + "**/.next": true, "**/.prettierignore": true, + "**/.svn": true, + "**/.todo.md": true, "**/bun.lockb": true, "**/cspell.json": true, + "**/CVS": true, + "**/dist": true, + "**/drizzle": true, + "**/drizzle.config.ts": true, + "**/migrate.ts": true, + "**/next-env.d.ts": true, + "**/node_modules": true, "**/package-lock.json": true, "**/pnpm-lock.yaml": true, - "**/next-env.d.ts": true, "**/postcss.config.cjs": true, "**/prettier.config.js": true, "**/README.md": true, - "**/drizzle.config.ts": true, - "**/migrate.ts": true, - "**/.env.example": true + "**/Thumbs.db": true }, // Misc diff --git a/content/docs/changelog.mdx b/content/docs/changelog.mdx new file mode 100644 index 0000000..b23cda8 --- /dev/null +++ b/content/docs/changelog.mdx @@ -0,0 +1,14 @@ +--- +title : Changelog +description : All last changes in the project with announcements +--- + + +## March 2024 - New docs + +We are happy to announce that we have updated our documentation. We have added new features. We hope you will find it useful. If you have any questions or suggestions, please let us know. + + + + + diff --git a/content/docs/tree-view.mdx b/content/docs/tree-view.mdx index b5d1eac..3e59331 100644 --- a/content/docs/tree-view.mdx +++ b/content/docs/tree-view.mdx @@ -515,7 +515,9 @@ const elements :TreeViewElement[] = [ - First we create the TOC component + TOC component + +First we create the TOC component. ```tsx showLineNumbers title="components/Table_of_content/tree.tsx" import { Tree , TreeViewElement } from "@/components/extension/tree-view-api"; @@ -539,7 +541,9 @@ return ( } ``` - Then the TreeItem element + TreeItem component + +Then the TreeItem element. ```tsx showLineNumbers title="components/Table_of_content/tree-item.tsx" import { File , Folder , TreeViewElement } from "@/components/extension/tree-view-api"; diff --git a/src/app/globals.css b/src/app/globals.css index 18ad028..e360a3f 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -156,3 +156,12 @@ [data-rehype-pretty-code-figure] [data-chars-id] { @apply border-b-2 p-1 shadow-none; } + +[data-rehype-pretty-code-figure] { + @apply mt-2 text-sm font-medium bg-[#282c34] rounded-lg; +} + +[data-rehype-pretty-code-figure] > figcaption { + background: rgba(200, 200, 255, 0.1); + @apply px-3 text-sm w-full rounded-t-md; +} diff --git a/src/components/banner.tsx b/src/components/banner.tsx index 7c8b6fc..f55b14d 100644 --- a/src/components/banner.tsx +++ b/src/components/banner.tsx @@ -4,7 +4,7 @@ import { cn } from "@/lib/utils"; export const Banner = () => { return ( -
+
🥳 New docs for shadcn extesnion are live. { buttonVariants({ variant: "link", }), - "px-1 text-base" + "px-1 text-sm py-0 h-fit" )} > Check them out diff --git a/src/components/mdx-component.tsx b/src/components/mdx-component.tsx index 1356683..9ed7972 100644 --- a/src/components/mdx-component.tsx +++ b/src/components/mdx-component.tsx @@ -177,7 +177,7 @@ const components = {
 {
             control={form.control}
             name="message"
             render={({ field }) => (
-              
+              
                 
Date: Thu, 28 Mar 2024 10:07:54 +0100
Subject: [PATCH 05/12]  fix : the keyboard func for breadcrumb component

---
 src/app/examples/page.tsx                     | 123 ------------------
 src/components/layouts/toc.tsx                |   4 +-
 src/registry/default/extension/breadcrumb.tsx |   8 +-
 .../default/extension/file-upload.tsx         |   1 -
 4 files changed, 7 insertions(+), 129 deletions(-)
 delete mode 100644 src/app/examples/page.tsx

diff --git a/src/app/examples/page.tsx b/src/app/examples/page.tsx
deleted file mode 100644
index 7244abc..0000000
--- a/src/app/examples/page.tsx
+++ /dev/null
@@ -1,123 +0,0 @@
-"use client";
-
-import {
-  FileUploader,
-  FileInput,
-  FileUploaderContent,
-  FileUploaderItem,
-} from "@/registry/default/extension/file-upload";
-import { useState } from "react";
-import { DropzoneOptions } from "react-dropzone";
-import z from "zod";
-import { zodResolver } from "@hookform/resolvers/zod";
-import { useForm } from "react-hook-form";
-import { Form, FormField, FormItem, FormMessage } from "@/components/ui/form";
-import { Button } from "@/components/ui/button";
-import { toast } from "sonner";
-import { Input } from "@/components/ui/input";
-import FileUploaderTest from "@/registry/default/example/file-upload-demo";
-import { AspectRatio } from "@/components/ui/aspect-ratio";
-import Image from "next/image";
-
-export default function PageExample() {
-  return (
-    
-
-

Page Examples

-

Tree view examples

-
- -
- ); -} - -const CardForm = z.object({ - name: z.string().optional(), - description: z.string().optional(), - files: z - .array( - z.instanceof(File).refine((file) => file.size < 4 * 1024 * 1024, { - message: "File size must be less than 4MB", - }) - ) - .max(5, { - message: "Maximum 5 files are allowed", - }) - .nullable(), -}); - -type CardFormType = z.infer; - -const ExampleComp = () => { - const form = useForm({ - resolver: zodResolver(CardForm), - defaultValues: { - name: "", - description: "", - files: null, - }, - }); - - const dropzone = { - multiple: true, - maxFiles: 5, - maxSize: 4 * 1024 * 1024, - } satisfies DropzoneOptions; - - const onSubmit = (data: CardFormType) => { - console.log(data); - toast.success(`Files are ${data.files}`); - }; - - return ( -
-
- - ( - - - -
-

Drop files here

-
-
- - {field.value?.map((file, i) => ( - - - {file.name} - - - ))} - -
- -
- )} - /> - - - -
- ); -}; diff --git a/src/components/layouts/toc.tsx b/src/components/layouts/toc.tsx index 8356ea6..80beb71 100644 --- a/src/components/layouts/toc.tsx +++ b/src/components/layouts/toc.tsx @@ -31,7 +31,7 @@ export const DocMainTOC = ({ toc, slug }: TocProps) => {
Questions? Give us feedback @@ -39,7 +39,7 @@ export const DocMainTOC = ({ toc, slug }: TocProps) => { Edit this page diff --git a/src/registry/default/extension/breadcrumb.tsx b/src/registry/default/extension/breadcrumb.tsx index 2b94235..d8b8cfa 100644 --- a/src/registry/default/extension/breadcrumb.tsx +++ b/src/registry/default/extension/breadcrumb.tsx @@ -81,6 +81,7 @@ export const BreadCrumb = ({ const prevIndex = currentIndex < 0 ? length : currentIndex; setActiveIndex(value[prevIndex]); }; + console.log("right"); switch (e.key) { case "ArrowDown": @@ -143,12 +144,13 @@ export const BreadCrumb = ({ }} >
{children}
@@ -214,8 +216,8 @@ export const BreadCrumbItem = forwardRef< className, isSelected ? "bg-muted focus-visible:ring-0 ring-0" : "" )} - {...props} onClick={() => setActiveIndex(index)} + {...props} > {children}
diff --git a/src/registry/default/extension/file-upload.tsx b/src/registry/default/extension/file-upload.tsx index 620ab1e..2c3be9a 100644 --- a/src/registry/default/extension/file-upload.tsx +++ b/src/registry/default/extension/file-upload.tsx @@ -22,7 +22,6 @@ import { import { toast } from "sonner"; import { Trash2 as RemoveIcon } from "lucide-react"; import { buttonVariants } from "@/components/ui/button"; -import { ScrollArea } from "@/components/ui/scroll-area"; type FileUploaderContextType = { dropzoneState: DropzoneState; From d348a883648520a28b7c98f3cc5dbafba4ea7aad Mon Sep 17 00:00:00 2001 From: BelkacemYerfa Date: Thu, 28 Mar 2024 14:02:40 +0100 Subject: [PATCH 06/12] fix : tree view guide --- content/docs/tree-view.mdx | 49 ++----------------- package-lock.json | 13 ----- package.json | 1 - src/app/page.tsx | 3 +- src/components/banner.tsx | 4 +- .../playground/playground-preview.tsx | 6 +-- src/components/playground/playground.tsx | 15 +++++- src/lib/element-parser.ts | 2 +- .../example/tree-view/tree-view-guide.tsx | 46 +---------------- .../default/extension/tree-view-api.tsx | 11 +---- 10 files changed, 25 insertions(+), 125 deletions(-) diff --git a/content/docs/tree-view.mdx b/content/docs/tree-view.mdx index 3e59331..69eb892 100644 --- a/content/docs/tree-view.mdx +++ b/content/docs/tree-view.mdx @@ -460,50 +460,6 @@ const elements :TreeViewElement[] = [ }, ], }, - { - id: "9", - name: "registry", - children: [ - { - id: "10", - name: "default", - children: [ - { - id: "11", - name: "extension", - children: [ - { - id: "12", - name: "tree-view.tsx", - }, - { - id: "13", - name: "tree-view-api.tsx", - }, - ], - }, - { - id: "14", - name: "dashboard-tree.tsx", - }, - ], - }, - { - id: "15", - name: "pages", - children: [ - { - id: "16", - name: "page.tsx", - }, - { - id: "17", - name: "page-guide.tsx", - }, - ], - }, - ], - }, { id: "18", name: "env.ts", @@ -520,7 +476,7 @@ const elements :TreeViewElement[] = [ First we create the TOC component. ```tsx showLineNumbers title="components/Table_of_content/tree.tsx" -import { Tree , TreeViewElement } from "@/components/extension/tree-view-api"; +import { Tree , TreeViewElement , CollapseButton } from "@/components/extension/tree-view-api"; import { TreeItem } from "./tree-item.tsx" type TOCProps = { @@ -536,11 +492,14 @@ return ( ) } + ) } ``` +Here we can see that we created a `TOC` component that will be responsible for rendering all the tree , the CollapseButton is used for the expandAll functionality. + TreeItem component Then the TreeItem element. diff --git a/package-lock.json b/package-lock.json index 97bd338..1d06e39 100644 --- a/package-lock.json +++ b/package-lock.json @@ -51,7 +51,6 @@ "react-live": "^4.1.6", "react-otp-input": "^3.1.1", "react-resizable-panels": "^2.0.12", - "react-runner": "^1.0.3", "react-wrap-balancer": "^1.1.0", "rehype-pretty-code": "^0.13.0", "rehype-slug": "^6.0.0", @@ -9088,18 +9087,6 @@ "react-dom": "^16.14.0 || ^17.0.0 || ^18.0.0" } }, - "node_modules/react-runner": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/react-runner/-/react-runner-1.0.3.tgz", - "integrity": "sha512-KyAzNzSVdrBc4A7aGW3FD0wVuujfgcBlyIGF0QVicJu0ucMpLYyTHE+PgBu82Iq698TPKRH+eEi6Mrq/e7OffA==", - "dependencies": { - "sucrase": "^3.21.0" - }, - "peerDependencies": { - "react": "^16.0.0 || ^17 || ^18", - "react-dom": "^16.0.0 || ^17 || ^18" - } - }, "node_modules/react-style-singleton": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.2.1.tgz", diff --git a/package.json b/package.json index 8bc44fb..6d7d71c 100644 --- a/package.json +++ b/package.json @@ -56,7 +56,6 @@ "react-live": "^4.1.6", "react-otp-input": "^3.1.1", "react-resizable-panels": "^2.0.12", - "react-runner": "^1.0.3", "react-wrap-balancer": "^1.1.0", "rehype-pretty-code": "^0.13.0", "rehype-slug": "^6.0.0", diff --git a/src/app/page.tsx b/src/app/page.tsx index 0f17d9f..ffb9b22 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -6,8 +6,7 @@ import { cn } from "@/lib/utils"; import Link from "next/link"; import Balancer from "react-wrap-balancer"; -//provide the set of api to the component that allow to build the ui examples -export default function Home() { +export default async function Home() { return (
diff --git a/src/components/banner.tsx b/src/components/banner.tsx index f55b14d..f3de838 100644 --- a/src/components/banner.tsx +++ b/src/components/banner.tsx @@ -4,7 +4,7 @@ import { cn } from "@/lib/utils"; export const Banner = () => { return ( -
+
🥳 New docs for shadcn extesnion are live. { buttonVariants({ variant: "link", }), - "px-1 text-sm py-0 h-fit" + "px-1 text-sm py-0 h-fit text-white" )} > Check them out diff --git a/src/components/playground/playground-preview.tsx b/src/components/playground/playground-preview.tsx index aa81363..4d9aa88 100644 --- a/src/components/playground/playground-preview.tsx +++ b/src/components/playground/playground-preview.tsx @@ -10,11 +10,7 @@ type LivePlaygroundPreviewProps = { export const LivePlaygroundPreview = memo( ({ code, dependencies, example }: LivePlaygroundPreviewProps) => { return ( - +
diff --git a/src/components/playground/playground.tsx b/src/components/playground/playground.tsx index c959a5d..334ad30 100644 --- a/src/components/playground/playground.tsx +++ b/src/components/playground/playground.tsx @@ -27,6 +27,12 @@ import { PlaygroundSearchSelector } from "@/components/drop-downs/search-selecto import { useSearchParams } from "next/navigation"; import { Skeleton } from "@/components/ui/skeleton"; import Editor, { Monaco, useMonaco } from "@monaco-editor/react"; +import { + Tree, + File, + Folder, + CollapseButton, +} from "@/registry/default/extension/tree-view-api"; type PlaygroundProps = { defaultCode?: string; @@ -654,7 +660,7 @@ const Playground = memo(({ defaultCode, dependencies }: PlaygroundProps) => { ) : ( file.file === chosenFile)?.content @@ -710,7 +716,12 @@ const Playground = memo(({ defaultCode, dependencies }: PlaygroundProps) => { {/*
{defaultCode}
*/}
diff --git a/src/lib/element-parser.ts b/src/lib/element-parser.ts index a75a66b..674a939 100644 --- a/src/lib/element-parser.ts +++ b/src/lib/element-parser.ts @@ -53,7 +53,7 @@ function extractComponentContent(fileContent: string): string { } export const readFieContent = (name: string) => { - const correctName = name.toLowerCase().split(" ").join("-") + "-example"; + const correctName = name.toLowerCase().split(" ").join("-") + "-demo"; const filePath = `src/registry/default/example/${correctName}.tsx`; const file = fs.readFileSync(filePath, "utf-8"); return file; diff --git a/src/registry/default/example/tree-view/tree-view-guide.tsx b/src/registry/default/example/tree-view/tree-view-guide.tsx index 3639213..eadb8db 100644 --- a/src/registry/default/example/tree-view/tree-view-guide.tsx +++ b/src/registry/default/example/tree-view/tree-view-guide.tsx @@ -3,6 +3,7 @@ import { TreeViewElement, File, Folder, + CollapseButton, } from "@/registry/default/extension/tree-view-api"; type TOCProps = { @@ -15,6 +16,7 @@ const TOC = ({ toc }: TOCProps) => { {toc.map((element, _) => ( ))} + ); }; @@ -97,50 +99,6 @@ const TOCWrapper = () => { }, ], }, - { - id: "9", - name: "registry", - children: [ - { - id: "10", - name: "default", - children: [ - { - id: "11", - name: "extension", - children: [ - { - id: "12", - name: "tree-view.tsx", - }, - { - id: "13", - name: "tree-view-api.tsx", - }, - ], - }, - { - id: "14", - name: "dashboard-tree.tsx", - }, - ], - }, - { - id: "15", - name: "pages", - children: [ - { - id: "16", - name: "page.tsx", - }, - { - id: "17", - name: "page-guide.tsx", - }, - ], - }, - ], - }, { id: "18", name: "env.ts", diff --git a/src/registry/default/extension/tree-view-api.tsx b/src/registry/default/extension/tree-view-api.tsx index 3bb3ce4..bcdba8b 100644 --- a/src/registry/default/extension/tree-view-api.tsx +++ b/src/registry/default/extension/tree-view-api.tsx @@ -12,7 +12,6 @@ import React, { useEffect, useState, } from "react"; -import useResizeObserver from "use-resize-observer"; import { Button } from "@/components/ui/button"; type TreeViewElement = { @@ -134,14 +133,6 @@ const Tree = forwardRef( } }, [initialSelectedId, elements]); - const { - ref: containerRef, - height, - width, - } = useResizeObserver({}); - - const style = props.style ?? { height, width }; - return ( ( closeIcon, }} > -
+
Date: Thu, 28 Mar 2024 23:02:45 +0100 Subject: [PATCH 07/12] fix : the banner website naming --- src/components/banner.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/banner.tsx b/src/components/banner.tsx index f3de838..6eceff9 100644 --- a/src/components/banner.tsx +++ b/src/components/banner.tsx @@ -1,11 +1,12 @@ import Link from "next/link"; import { buttonVariants } from "@/components/ui/button"; import { cn } from "@/lib/utils"; +import { siteConfig } from "@/config/site-config"; export const Banner = () => { return (
- 🥳 New docs for shadcn extesnion are live. + 🥳 New docs for {siteConfig.name} are live. Date: Fri, 29 Mar 2024 16:05:51 +0100 Subject: [PATCH 08/12] feat : add the navigation mobile menu , feat : add the breadcrumb active example --- content/docs/breadcrumb.mdx | 8 + content/docs/carousel.mdx | 2 +- content/docs/introduction.mdx | 4 +- src/__registry__/index.tsx | 14 ++ src/app/docs/layout.tsx | 2 +- src/components/component-preview.tsx | 8 +- src/components/layouts/site-header.tsx | 29 +++- src/components/side-bar.tsx | 7 +- src/components/ui/sheet.tsx | 140 ++++++++++++++++++ src/registry/components.ts | 12 ++ .../example/breadcrumb/breadcrumb-active.tsx | 59 ++++++++ .../breadcrumb/breadcrumb-orientation.tsx | 32 ++++ .../example/breadcrumb/breadcrumb-popover.tsx | 3 - .../breadcrumb/breadcrumb-separator.tsx | 11 +- .../breadcrumb/breadcrumb-variants.tsx | 18 ++- src/registry/default/extension/breadcrumb.tsx | 26 +++- 16 files changed, 351 insertions(+), 24 deletions(-) create mode 100644 src/components/ui/sheet.tsx create mode 100644 src/registry/default/example/breadcrumb/breadcrumb-active.tsx create mode 100644 src/registry/default/example/breadcrumb/breadcrumb-orientation.tsx diff --git a/content/docs/breadcrumb.mdx b/content/docs/breadcrumb.mdx index 18d3aa9..59bbf9f 100644 --- a/content/docs/breadcrumb.mdx +++ b/content/docs/breadcrumb.mdx @@ -218,6 +218,10 @@ import { Link } from "next/link"; ## Examples +### Orientation + + + ### BreadCrumb Separator @@ -237,6 +241,10 @@ By default, the Breadcrumb component uses the `default` variant for each item. Y +### Active BreadCrumb + + + ### BreadCrumb Popover This popover can be used to display the full path if it's too long to fit in the screen. diff --git a/content/docs/carousel.mdx b/content/docs/carousel.mdx index 78befa9..901d1d0 100644 --- a/content/docs/carousel.mdx +++ b/content/docs/carousel.mdx @@ -24,7 +24,7 @@ links: Run the following command: ```bash -npm embla-carousel embla-carousel-react +npm i embla-carousel embla-carousel-react ``` Copy and paste the following code into your project. diff --git a/content/docs/introduction.mdx b/content/docs/introduction.mdx index e1f929c..28b5416 100644 --- a/content/docs/introduction.mdx +++ b/content/docs/introduction.mdx @@ -13,7 +13,7 @@ Shadcn extension is a set of components that are built on top of Shadcn-ui . It - **Customizable**: Shadcn extension is designed to be highly customizable. It provides a set of components that can be easily customized to fit your needs. - **Easy to use**: Shadcn extension is designed to be easy to use. It provides a set of components that are easy to use and can be easily integrated into your web application. -- **No need for installation**: Shadcn extension does not require any installation. just copy past the code and install the shadcn/ui component that it uses. +- **No need for installation**: Shadcn extension does not require any installation. just Copy&Paste the code and install the shadcn/ui component that it uses. ## Getting Started @@ -25,7 +25,7 @@ To install shadcn extension, you need to configure the shadcn/ui component that ## Usage -To use Shadcn extension, you need to copy past the components that you want to use from the **shadcn extension** . You can then use these components in your web application. +To use Shadcn extension, you need to Copy&Paste the components that you want to use from the **shadcn extension** . You can then use these components in your web application. Example: diff --git a/src/__registry__/index.tsx b/src/__registry__/index.tsx index 054e362..5316581 100644 --- a/src/__registry__/index.tsx +++ b/src/__registry__/index.tsx @@ -208,6 +208,20 @@ export const Index: Record = { component: React.lazy(() => import("@/registry/default/example/breadcrumb/breadcrumb-popover.tsx")), files: ["src/registry/default/example/breadcrumb/breadcrumb-popover.tsx"], }, + "breadcrumb-orientation": { + name: "breadcrumb-orientation", + type: "components:example", + registryDependencies: ["breadcrumb"], + component: React.lazy(() => import("@/registry/default/example/breadcrumb/breadcrumb-orientation.tsx")), + files: ["src/registry/default/example/breadcrumb/breadcrumb-orientation.tsx"], + }, + "breadcrumb-active": { + name: "breadcrumb-active", + type: "components:example", + registryDependencies: ["breadcrumb"], + component: React.lazy(() => import("@/registry/default/example/breadcrumb/breadcrumb-active.tsx")), + files: ["src/registry/default/example/breadcrumb/breadcrumb-active.tsx"], + }, "image-carousel-upload-example": { name: "image-carousel-upload-example", type: "components:example", diff --git a/src/app/docs/layout.tsx b/src/app/docs/layout.tsx index e309b69..3fff752 100644 --- a/src/app/docs/layout.tsx +++ b/src/app/docs/layout.tsx @@ -43,7 +43,7 @@ export default function DocsLayout({ return ( <>
-
+
diff --git a/src/components/component-preview.tsx b/src/components/component-preview.tsx index f022c7b..ed3f4a9 100644 --- a/src/components/component-preview.tsx +++ b/src/components/component-preview.tsx @@ -83,9 +83,11 @@ export function ComponentPreview({ className="relative rounded-md border bg-muted/50 p-2 data-[state=active]:flex flex-col items-center justify-center w-full min-h-[20rem]" > {codeString && } -
- {Preview} -
+ Loading...
}> +
+ {Preview} +
+
diff --git a/src/components/layouts/site-header.tsx b/src/components/layouts/site-header.tsx index c7138ce..a13c185 100644 --- a/src/components/layouts/site-header.tsx +++ b/src/components/layouts/site-header.tsx @@ -11,6 +11,10 @@ import { Pages } from "@/config/docs-config"; import { usePathname } from "next/navigation"; import { cn } from "@/lib/utils"; import { Banner } from "@/components/banner"; +import { Sheet, SheetContent, SheetTrigger } from "@/components/ui/sheet"; +import { SideBar } from "../side-bar"; +import { Menu } from "lucide-react"; +import { useState } from "react"; export const SiteHeader = () => { const pathname = usePathname(); @@ -20,9 +24,13 @@ export const SiteHeader = () => {