diff --git a/src/components/ui/alert-dialog.tsx b/src/components/ui/alert-dialog.tsx deleted file mode 100644 index a6f8177..0000000 --- a/src/components/ui/alert-dialog.tsx +++ /dev/null @@ -1,157 +0,0 @@ -"use client" - -import { ComponentProps } from "react" -import * as AlertDialogPrimitive from "@radix-ui/react-alert-dialog" - -import { cn } from "@/lib/utils" -import { buttonVariants } from "@/components/ui/button" - -function AlertDialog({ - ...props -}: ComponentProps) { - return -} - -function AlertDialogTrigger({ - ...props -}: ComponentProps) { - return ( - - ) -} - -function AlertDialogPortal({ - ...props -}: ComponentProps) { - return ( - - ) -} - -function AlertDialogOverlay({ - className, - ...props -}: ComponentProps) { - return ( - - ) -} - -function AlertDialogContent({ - className, - ...props -}: ComponentProps) { - return ( - - - - - ) -} - -function AlertDialogHeader({ - className, - ...props -}: ComponentProps<"div">) { - return ( -
- ) -} - -function AlertDialogFooter({ - className, - ...props -}: ComponentProps<"div">) { - return ( -
- ) -} - -function AlertDialogTitle({ - className, - ...props -}: ComponentProps) { - return ( - - ) -} - -function AlertDialogDescription({ - className, - ...props -}: ComponentProps) { - return ( - - ) -} - -function AlertDialogAction({ - className, - ...props -}: ComponentProps) { - return ( - - ) -} - -function AlertDialogCancel({ - className, - ...props -}: ComponentProps) { - return ( - - ) -} - -export { - AlertDialog, - AlertDialogPortal, - AlertDialogOverlay, - AlertDialogTrigger, - AlertDialogContent, - AlertDialogHeader, - AlertDialogFooter, - AlertDialogTitle, - AlertDialogDescription, - AlertDialogAction, - AlertDialogCancel, -} diff --git a/src/components/ui/alert-dialog/alert-dialog-action.tsx b/src/components/ui/alert-dialog/alert-dialog-action.tsx new file mode 100644 index 0000000..7a94842 --- /dev/null +++ b/src/components/ui/alert-dialog/alert-dialog-action.tsx @@ -0,0 +1,21 @@ +"use client" + +import { ComponentProps } from "react" +import * as AlertDialogPrimitive from "@radix-ui/react-alert-dialog" + +import { cn } from "@/lib/utils" +import { buttonVariants } from "@/components/ui/button" + +function AlertDialogAction({ + className, + ...props +}: ComponentProps) { + return ( + + ) +} + +export { AlertDialogAction } diff --git a/src/components/ui/alert-dialog/alert-dialog-cancel.tsx b/src/components/ui/alert-dialog/alert-dialog-cancel.tsx new file mode 100644 index 0000000..83e28e4 --- /dev/null +++ b/src/components/ui/alert-dialog/alert-dialog-cancel.tsx @@ -0,0 +1,21 @@ +"use client" + +import { ComponentProps } from "react" +import * as AlertDialogPrimitive from "@radix-ui/react-alert-dialog" + +import { cn } from "@/lib/utils" +import { buttonVariants } from "@/components/ui/button" + +function AlertDialogCancel({ + className, + ...props +}: ComponentProps) { + return ( + + ) +} + +export { AlertDialogCancel } diff --git a/src/components/ui/alert-dialog/alert-dialog-content.tsx b/src/components/ui/alert-dialog/alert-dialog-content.tsx new file mode 100644 index 0000000..9dbc22d --- /dev/null +++ b/src/components/ui/alert-dialog/alert-dialog-content.tsx @@ -0,0 +1,30 @@ +"use client" + +import { ComponentProps } from "react" +import * as AlertDialogPrimitive from "@radix-ui/react-alert-dialog" + +import { cn } from "@/lib/utils" + +import { AlertDialogOverlay } from "./alert-dialog-overlay" +import { AlertDialogPortal } from "./alert-dialog-portal" + +function AlertDialogContent({ + className, + ...props +}: ComponentProps) { + return ( + + + + + ) +} + +export { AlertDialogContent } diff --git a/src/components/ui/alert-dialog/alert-dialog-description.tsx b/src/components/ui/alert-dialog/alert-dialog-description.tsx new file mode 100644 index 0000000..496e4c9 --- /dev/null +++ b/src/components/ui/alert-dialog/alert-dialog-description.tsx @@ -0,0 +1,21 @@ +"use client" + +import { ComponentProps } from "react" +import * as AlertDialogPrimitive from "@radix-ui/react-alert-dialog" + +import { cn } from "@/lib/utils" + +function AlertDialogDescription({ + className, + ...props +}: ComponentProps) { + return ( + + ) +} + +export { AlertDialogDescription } diff --git a/src/components/ui/alert-dialog/alert-dialog-footer.tsx b/src/components/ui/alert-dialog/alert-dialog-footer.tsx new file mode 100644 index 0000000..1f77db3 --- /dev/null +++ b/src/components/ui/alert-dialog/alert-dialog-footer.tsx @@ -0,0 +1,23 @@ +"use client" + +import { ComponentProps } from "react" + +import { cn } from "@/lib/utils" + +function AlertDialogFooter({ + className, + ...props +}: ComponentProps<"div">) { + return ( +
+ ) +} + +export { AlertDialogFooter } diff --git a/src/components/ui/alert-dialog/alert-dialog-header.tsx b/src/components/ui/alert-dialog/alert-dialog-header.tsx new file mode 100644 index 0000000..25829a4 --- /dev/null +++ b/src/components/ui/alert-dialog/alert-dialog-header.tsx @@ -0,0 +1,20 @@ +"use client" + +import { ComponentProps } from "react" + +import { cn } from "@/lib/utils" + +function AlertDialogHeader({ + className, + ...props +}: ComponentProps<"div">) { + return ( +
+ ) +} + +export { AlertDialogHeader } diff --git a/src/components/ui/alert-dialog/alert-dialog-overlay.tsx b/src/components/ui/alert-dialog/alert-dialog-overlay.tsx new file mode 100644 index 0000000..bed50cf --- /dev/null +++ b/src/components/ui/alert-dialog/alert-dialog-overlay.tsx @@ -0,0 +1,24 @@ +"use client" + +import { ComponentProps } from "react" +import * as AlertDialogPrimitive from "@radix-ui/react-alert-dialog" + +import { cn } from "@/lib/utils" + +function AlertDialogOverlay({ + className, + ...props +}: ComponentProps) { + return ( + + ) +} + +export { AlertDialogOverlay } diff --git a/src/components/ui/alert-dialog/alert-dialog-portal.tsx b/src/components/ui/alert-dialog/alert-dialog-portal.tsx new file mode 100644 index 0000000..087d522 --- /dev/null +++ b/src/components/ui/alert-dialog/alert-dialog-portal.tsx @@ -0,0 +1,14 @@ +"use client" + +import { ComponentProps } from "react" +import * as AlertDialogPrimitive from "@radix-ui/react-alert-dialog" + +function AlertDialogPortal({ + ...props +}: ComponentProps) { + return ( + + ) +} + +export { AlertDialogPortal } diff --git a/src/components/ui/alert-dialog/alert-dialog-title.tsx b/src/components/ui/alert-dialog/alert-dialog-title.tsx new file mode 100644 index 0000000..e4bf00d --- /dev/null +++ b/src/components/ui/alert-dialog/alert-dialog-title.tsx @@ -0,0 +1,21 @@ +"use client" + +import { ComponentProps } from "react" +import * as AlertDialogPrimitive from "@radix-ui/react-alert-dialog" + +import { cn } from "@/lib/utils" + +function AlertDialogTitle({ + className, + ...props +}: ComponentProps) { + return ( + + ) +} + +export { AlertDialogTitle } diff --git a/src/components/ui/alert-dialog/alert-dialog-trigger.tsx b/src/components/ui/alert-dialog/alert-dialog-trigger.tsx new file mode 100644 index 0000000..d5fba4f --- /dev/null +++ b/src/components/ui/alert-dialog/alert-dialog-trigger.tsx @@ -0,0 +1,14 @@ +"use client" + +import { ComponentProps } from "react" +import * as AlertDialogPrimitive from "@radix-ui/react-alert-dialog" + +function AlertDialogTrigger({ + ...props +}: ComponentProps) { + return ( + + ) +} + +export { AlertDialogTrigger } diff --git a/src/components/ui/alert-dialog/alert-dialog.tsx b/src/components/ui/alert-dialog/alert-dialog.tsx new file mode 100644 index 0000000..100afa5 --- /dev/null +++ b/src/components/ui/alert-dialog/alert-dialog.tsx @@ -0,0 +1,12 @@ +"use client" + +import { ComponentProps } from "react" +import * as AlertDialogPrimitive from "@radix-ui/react-alert-dialog" + +function AlertDialog({ + ...props +}: ComponentProps) { + return +} + +export { AlertDialog } diff --git a/src/components/ui/alert-dialog/index.tsx b/src/components/ui/alert-dialog/index.tsx new file mode 100644 index 0000000..46c9341 --- /dev/null +++ b/src/components/ui/alert-dialog/index.tsx @@ -0,0 +1,11 @@ +export { AlertDialog } from "./alert-dialog" +export { AlertDialogAction } from "./alert-dialog-action" +export { AlertDialogCancel } from "./alert-dialog-cancel" +export { AlertDialogContent } from "./alert-dialog-content" +export { AlertDialogDescription } from "./alert-dialog-description" +export { AlertDialogFooter } from "./alert-dialog-footer" +export { AlertDialogHeader } from "./alert-dialog-header" +export { AlertDialogOverlay } from "./alert-dialog-overlay" +export { AlertDialogPortal } from "./alert-dialog-portal" +export { AlertDialogTitle } from "./alert-dialog-title" +export { AlertDialogTrigger } from "./alert-dialog-trigger" diff --git a/src/components/ui/carousel.tsx b/src/components/ui/carousel.tsx deleted file mode 100644 index 0e76744..0000000 --- a/src/components/ui/carousel.tsx +++ /dev/null @@ -1,242 +0,0 @@ -"use client" - -import { ComponentProps, createContext, useCallback, useContext, useEffect, useState, KeyboardEvent } from "react" -import useEmblaCarousel, { - type UseEmblaCarouselType, -} from "embla-carousel-react" -import ArrowLeft from "lucide-react/dist/esm/icons/arrow-left" -import ArrowRight from "lucide-react/dist/esm/icons/arrow-right" - -import { cn } from "@/lib/utils" -import { Button } from "@/components/ui/button" - -type CarouselApi = UseEmblaCarouselType[1] -type UseCarouselParameters = Parameters -type CarouselOptions = UseCarouselParameters[0] -type CarouselPlugin = UseCarouselParameters[1] - -type CarouselProps = { - opts?: CarouselOptions - plugins?: CarouselPlugin - orientation?: "horizontal" | "vertical" - setApi?: (api: CarouselApi) => void -} - -type CarouselContextProps = { - carouselRef: ReturnType[0] - api: ReturnType[1] - scrollPrev: () => void - scrollNext: () => void - canScrollPrev: boolean - canScrollNext: boolean -} & CarouselProps - -const CarouselContext = createContext(null) - -function useCarousel() { - const context = useContext(CarouselContext) - - if (!context) { - throw new Error("useCarousel must be used within a ") - } - - return context -} - -function Carousel({ - orientation = "horizontal", - opts, - setApi, - plugins, - className, - children, - ...props -}: ComponentProps<"div"> & CarouselProps) { - const [carouselRef, api] = useEmblaCarousel( - { - ...opts, - axis: orientation === "horizontal" ? "x" : "y", - }, - plugins - ) - const [canScrollPrev, setCanScrollPrev] = useState(false) - const [canScrollNext, setCanScrollNext] = useState(false) - - const onSelect = useCallback((api: CarouselApi) => { - if (!api) return - setCanScrollPrev(api.canScrollPrev()) - setCanScrollNext(api.canScrollNext()) - }, []) - - const scrollPrev = useCallback(() => { - api?.scrollPrev() - }, [api]) - - const scrollNext = useCallback(() => { - api?.scrollNext() - }, [api]) - - const handleKeyDown = useCallback( - (event: KeyboardEvent) => { - if (event.key === "ArrowLeft") { - event.preventDefault() - scrollPrev() - } else if (event.key === "ArrowRight") { - event.preventDefault() - scrollNext() - } - }, - [scrollPrev, scrollNext] - ) - - useEffect(() => { - if (!api || !setApi) return - setApi(api) - }, [api, setApi]) - - useEffect(() => { - if (!api) return - onSelect(api) - api.on("reInit", onSelect) - api.on("select", onSelect) - - return () => { - api?.off("select", onSelect) - } - }, [api, onSelect]) - - return ( - -
- {children} -
-
- ) -} - -function CarouselContent({ className, ...props }: ComponentProps<"div">) { - const { carouselRef, orientation } = useCarousel() - - return ( -
-
-
- ) -} - -function CarouselItem({ className, ...props }: ComponentProps<"div">) { - const { orientation } = useCarousel() - - return ( -
- ) -} - -function CarouselPrevious({ - className, - variant = "outline", - size = "icon", - ...props -}: ComponentProps) { - const { orientation, scrollPrev, canScrollPrev } = useCarousel() - - return ( - - ) -} - -function CarouselNext({ - className, - variant = "outline", - size = "icon", - ...props -}: ComponentProps) { - const { orientation, scrollNext, canScrollNext } = useCarousel() - - return ( - - ) -} - -export { - type CarouselApi, - Carousel, - CarouselContent, - CarouselItem, - CarouselPrevious, - CarouselNext, -} diff --git a/src/components/ui/carousel/carousel-content.tsx b/src/components/ui/carousel/carousel-content.tsx new file mode 100644 index 0000000..81ebcd3 --- /dev/null +++ b/src/components/ui/carousel/carousel-content.tsx @@ -0,0 +1,30 @@ +"use client" + +import { ComponentProps } from "react" + +import { cn } from "@/lib/utils" + +import { useCarousel } from "./use-carousel" + +function CarouselContent({ className, ...props }: ComponentProps<"div">) { + const { carouselRef, orientation } = useCarousel() + + return ( +
+
+
+ ) +} + +export { CarouselContent } diff --git a/src/components/ui/carousel/carousel-context.ts b/src/components/ui/carousel/carousel-context.ts new file mode 100644 index 0000000..7ffcd86 --- /dev/null +++ b/src/components/ui/carousel/carousel-context.ts @@ -0,0 +1,18 @@ +import { createContext } from "react" +import type { UseEmblaCarouselType } from "embla-carousel-react" + +import type { CarouselProps } from "./carousel-types" + +type CarouselContextProps = { + carouselRef: UseEmblaCarouselType[0] + api: UseEmblaCarouselType[1] + scrollPrev: () => void + scrollNext: () => void + canScrollPrev: boolean + canScrollNext: boolean +} & CarouselProps + +const CarouselContext = createContext(null) + +export type { CarouselContextProps } +export { CarouselContext } diff --git a/src/components/ui/carousel/carousel-item.tsx b/src/components/ui/carousel/carousel-item.tsx new file mode 100644 index 0000000..112d8fe --- /dev/null +++ b/src/components/ui/carousel/carousel-item.tsx @@ -0,0 +1,27 @@ +"use client" + +import { ComponentProps } from "react" + +import { cn } from "@/lib/utils" + +import { useCarousel } from "./use-carousel" + +function CarouselItem({ className, ...props }: ComponentProps<"div">) { + const { orientation } = useCarousel() + + return ( +
+ ) +} + +export { CarouselItem } diff --git a/src/components/ui/carousel/carousel-next.tsx b/src/components/ui/carousel/carousel-next.tsx new file mode 100644 index 0000000..52cb2f8 --- /dev/null +++ b/src/components/ui/carousel/carousel-next.tsx @@ -0,0 +1,41 @@ +"use client" + +import { ComponentProps } from "react" +import ArrowRight from "lucide-react/dist/esm/icons/arrow-right" + +import { cn } from "@/lib/utils" +import { Button } from "@/components/ui/button" + +import { useCarousel } from "./use-carousel" + +function CarouselNext({ + className, + variant = "outline", + size = "icon", + ...props +}: ComponentProps) { + const { orientation, scrollNext, canScrollNext } = useCarousel() + + return ( + + ) +} + +export { CarouselNext } diff --git a/src/components/ui/carousel/carousel-previous.tsx b/src/components/ui/carousel/carousel-previous.tsx new file mode 100644 index 0000000..1b4f9af --- /dev/null +++ b/src/components/ui/carousel/carousel-previous.tsx @@ -0,0 +1,41 @@ +"use client" + +import { ComponentProps } from "react" +import ArrowLeft from "lucide-react/dist/esm/icons/arrow-left" + +import { cn } from "@/lib/utils" +import { Button } from "@/components/ui/button" + +import { useCarousel } from "./use-carousel" + +function CarouselPrevious({ + className, + variant = "outline", + size = "icon", + ...props +}: ComponentProps) { + const { orientation, scrollPrev, canScrollPrev } = useCarousel() + + return ( + + ) +} + +export { CarouselPrevious } diff --git a/src/components/ui/carousel/carousel-types.ts b/src/components/ui/carousel/carousel-types.ts new file mode 100644 index 0000000..d9a413f --- /dev/null +++ b/src/components/ui/carousel/carousel-types.ts @@ -0,0 +1,18 @@ +import type { UseEmblaCarouselType } from "embla-carousel-react" + +type CarouselApi = UseEmblaCarouselType[1] + +type UseCarouselParameters = Parameters + +type CarouselOptions = UseCarouselParameters[0] + +type CarouselPlugin = UseCarouselParameters[1] + +type CarouselProps = { + opts?: CarouselOptions + plugins?: CarouselPlugin + orientation?: "horizontal" | "vertical" + setApi?: (api: CarouselApi) => void +} + +export type { CarouselApi, CarouselOptions, CarouselPlugin, CarouselProps } diff --git a/src/components/ui/carousel/carousel.tsx b/src/components/ui/carousel/carousel.tsx new file mode 100644 index 0000000..faa6a5a --- /dev/null +++ b/src/components/ui/carousel/carousel.tsx @@ -0,0 +1,109 @@ +"use client" + +import { + ComponentProps, + KeyboardEvent, + useCallback, + useEffect, + useState, +} from "react" +import useEmblaCarousel from "embla-carousel-react" + +import { cn } from "@/lib/utils" + +import { CarouselContext, type CarouselContextProps } from "./carousel-context" +import type { CarouselApi, CarouselProps } from "./carousel-types" + +function Carousel({ + orientation = "horizontal", + opts, + setApi, + plugins, + className, + children, + ...props +}: ComponentProps<"div"> & CarouselProps) { + const [carouselRef, api] = useEmblaCarousel( + { + ...opts, + axis: orientation === "horizontal" ? "x" : "y", + }, + plugins + ) + const [canScrollPrev, setCanScrollPrev] = useState(false) + const [canScrollNext, setCanScrollNext] = useState(false) + + const onSelect = useCallback((api: CarouselApi) => { + if (!api) return + setCanScrollPrev(api.canScrollPrev()) + setCanScrollNext(api.canScrollNext()) + }, []) + + const scrollPrev = useCallback(() => { + api?.scrollPrev() + }, [api]) + + const scrollNext = useCallback(() => { + api?.scrollNext() + }, [api]) + + const handleKeyDown = useCallback( + (event: KeyboardEvent) => { + if (event.key === "ArrowLeft") { + event.preventDefault() + scrollPrev() + } else if (event.key === "ArrowRight") { + event.preventDefault() + scrollNext() + } + }, + [scrollPrev, scrollNext] + ) + + useEffect(() => { + if (!api || !setApi) return + setApi(api) + }, [api, setApi]) + + useEffect(() => { + if (!api) return + onSelect(api) + api.on("reInit", onSelect) + api.on("select", onSelect) + + return () => { + api?.off("select", onSelect) + } + }, [api, onSelect]) + + return ( + +
+ {children} +
+
+ ) +} + +export { Carousel } diff --git a/src/components/ui/carousel/index.tsx b/src/components/ui/carousel/index.tsx new file mode 100644 index 0000000..2d03e62 --- /dev/null +++ b/src/components/ui/carousel/index.tsx @@ -0,0 +1,6 @@ +export { Carousel } from "./carousel" +export { CarouselContent } from "./carousel-content" +export { CarouselItem } from "./carousel-item" +export { CarouselNext } from "./carousel-next" +export { CarouselPrevious } from "./carousel-previous" +export { type CarouselApi } from "./carousel-types" diff --git a/src/components/ui/carousel/use-carousel.tsx b/src/components/ui/carousel/use-carousel.tsx new file mode 100644 index 0000000..c9edf29 --- /dev/null +++ b/src/components/ui/carousel/use-carousel.tsx @@ -0,0 +1,17 @@ +"use client" + +import { useContext } from "react" + +import { CarouselContext } from "./carousel-context" + +function useCarousel() { + const context = useContext(CarouselContext) + + if (!context) { + throw new Error("useCarousel must be used within a ") + } + + return context +} + +export { useCarousel } diff --git a/src/components/ui/chart.tsx b/src/components/ui/chart.tsx deleted file mode 100644 index 101c153..0000000 --- a/src/components/ui/chart.tsx +++ /dev/null @@ -1,351 +0,0 @@ -import { ComponentProps, ComponentType, createContext, CSSProperties, ReactNode, useContext, useId, useMemo } from "react" -import * as RechartsPrimitive from "recharts" - -import { cn } from "@/lib/utils" - -// Format: { THEME_NAME: CSS_SELECTOR } -const THEMES = { light: "", dark: ".dark" } as const - -export type ChartConfig = { - [k in string]: { - label?: ReactNode - icon?: ComponentType - } & ( - | { color?: string; theme?: never } - | { color?: never; theme: Record } - ) -} - -type ChartContextProps = { - config: ChartConfig -} - -const ChartContext = createContext(null) - -function useChart() { - const context = useContext(ChartContext) - - if (!context) { - throw new Error("useChart must be used within a ") - } - - return context -} - -function ChartContainer({ - id, - className, - children, - config, - ...props -}: ComponentProps<"div"> & { - config: ChartConfig - children: ComponentProps< - typeof RechartsPrimitive.ResponsiveContainer - >["children"] -}) { - const uniqueId = useId() - const chartId = `chart-${id || uniqueId.replace(/:/g, "")}` - - return ( - -
- - - {children} - -
-
- ) -} - -const ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => { - const colorConfig = Object.entries(config).filter( - ([, config]) => config.theme || config.color - ) - - if (!colorConfig.length) { - return null - } - - return ( -