build and format
This commit is contained in:
@@ -16,9 +16,9 @@
|
||||
"main_title_line2": "سریع و مطمئن",
|
||||
"contact_us": "تماس با ما"
|
||||
},
|
||||
"Categories" : {
|
||||
"title" : "دسته بندی ها",
|
||||
"description" : "از بین صدها مرکز زیبایی، دقیقا همونی که میخای رو پیدا کن."
|
||||
"Categories": {
|
||||
"title": "دسته بندی ها",
|
||||
"description": "از بین صدها مرکز زیبایی، دقیقا همونی که میخای رو پیدا کن."
|
||||
},
|
||||
"Application": {
|
||||
"title": "دانلود نرم افزار تلفن همراه 141",
|
||||
|
||||
23041
pnpm-lock.yaml
generated
23041
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@@ -1,21 +1,15 @@
|
||||
"use client"
|
||||
"use client";
|
||||
|
||||
import { Card, CardContent } from "@/components/UI/card"
|
||||
import {
|
||||
Carousel,
|
||||
CarouselContent,
|
||||
CarouselItem,
|
||||
CarouselNext,
|
||||
CarouselPrevious,
|
||||
} from "@/components/UI/Carousel"
|
||||
import { categories } from "@/data/mockCategories"
|
||||
import Image from "next/image"
|
||||
import {easeOut, motion} from "framer-motion"
|
||||
import { Card, CardContent } from "@/components/UI/card";
|
||||
import { Carousel, CarouselContent, CarouselItem, CarouselNext, CarouselPrevious } from "@/components/UI/Carousel";
|
||||
import { categories } from "@/data/mockCategories";
|
||||
import Image from "next/image";
|
||||
import { easeOut, motion } from "framer-motion";
|
||||
|
||||
type Props = {
|
||||
title: string
|
||||
description: string
|
||||
}
|
||||
title: string;
|
||||
description: string;
|
||||
};
|
||||
|
||||
const containerVariants = {
|
||||
hidden: {},
|
||||
@@ -24,7 +18,7 @@ const containerVariants = {
|
||||
staggerChildren: 0.08,
|
||||
},
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
const itemVariants = {
|
||||
hidden: {
|
||||
@@ -41,59 +35,40 @@ const itemVariants = {
|
||||
ease: easeOut,
|
||||
},
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
export function CarouselComponent({ title, description }: Props) {
|
||||
return (
|
||||
<div className="relative w-full">
|
||||
|
||||
<Carousel dir="rtl" className="w-full" opts={{ direction: "rtl" }}>
|
||||
|
||||
{/* 🔥 Animated Header */}
|
||||
<motion.div
|
||||
initial={{ opacity: 0, x: 40 }}
|
||||
animate={{ opacity: 1, x: 0 }}
|
||||
transition={{ duration: 0.6 }}
|
||||
className="flex items-center justify-between w-full h-full my-5"
|
||||
className="my-5 flex h-full w-full items-center justify-between"
|
||||
>
|
||||
<span className="flex items-center justify-center gap-x-2">
|
||||
<motion.div
|
||||
initial={{ height: 0 }}
|
||||
animate={{ height: 64 }}
|
||||
transition={{ duration: 0.5 }}
|
||||
className="bg-primary-100 w-4 rounded-2xl rounded-tr-none"
|
||||
/>
|
||||
<div>
|
||||
<p className="text-lg font-semibold">{title}</p>
|
||||
<p className="text-muted-foreground">{description}</p>
|
||||
</div>
|
||||
</span>
|
||||
<span className="flex items-center justify-center gap-x-2">
|
||||
<motion.div
|
||||
initial={{ height: 0 }}
|
||||
animate={{ height: 64 }}
|
||||
transition={{ duration: 0.5 }}
|
||||
className="bg-primary-100 w-4 rounded-2xl rounded-tr-none"
|
||||
/>
|
||||
<div>
|
||||
<p className="text-lg font-semibold">{title}</p>
|
||||
<p className="text-muted-foreground">{description}</p>
|
||||
</div>
|
||||
</span>
|
||||
</motion.div>
|
||||
|
||||
{/* 🔥 Animated Carousel Items */}
|
||||
<motion.div
|
||||
variants={containerVariants}
|
||||
initial="hidden"
|
||||
animate="show"
|
||||
>
|
||||
<motion.div variants={containerVariants} initial="hidden" animate="show">
|
||||
<CarouselContent>
|
||||
{categories.map((category) => (
|
||||
<CarouselItem
|
||||
key={category.id}
|
||||
className="
|
||||
md:basis-1/5
|
||||
lg:basis-1/7
|
||||
relative
|
||||
after:content-['']
|
||||
after:absolute
|
||||
after:top-1/2
|
||||
after:-translate-y-1/2
|
||||
after:left-2
|
||||
after:w-px
|
||||
after:h-[50%]
|
||||
after:bg-border
|
||||
last:after:hidden
|
||||
"
|
||||
className="after:bg-border relative after:absolute after:top-1/2 after:left-2 after:h-[50%] after:w-px after:-translate-y-1/2 after:content-[''] last:after:hidden md:basis-1/5 lg:basis-1/7"
|
||||
>
|
||||
<motion.div variants={itemVariants} className="p-1">
|
||||
<motion.div
|
||||
@@ -103,8 +78,8 @@ export function CarouselComponent({ title, description }: Props) {
|
||||
}}
|
||||
transition={{ type: "spring", stiffness: 300 }}
|
||||
>
|
||||
<Card dir="rtl" className="transition-shadow hover:shadow-xl cursor-pointer">
|
||||
<CardContent className="flex flex-col gap-3 h-30 items-center justify-center p-6">
|
||||
<Card dir="rtl" className="cursor-pointer transition-shadow hover:shadow-xl">
|
||||
<CardContent className="flex h-30 flex-col items-center justify-center gap-3 p-6">
|
||||
<motion.div
|
||||
whileHover={{ rotate: 5 }}
|
||||
transition={{ type: "spring", stiffness: 200 }}
|
||||
@@ -118,9 +93,7 @@ export function CarouselComponent({ title, description }: Props) {
|
||||
/>
|
||||
</motion.div>
|
||||
|
||||
<p className="font-semibold text-text-muted">
|
||||
{category.title}
|
||||
</p>
|
||||
<p className="text-text-muted font-semibold">{category.title}</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</motion.div>
|
||||
@@ -144,8 +117,7 @@ export function CarouselComponent({ title, description }: Props) {
|
||||
<CarouselNext />
|
||||
</motion.div>
|
||||
</motion.div>
|
||||
|
||||
</Carousel>
|
||||
</div>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,17 +1,14 @@
|
||||
import { CarouselComponent } from "./CarouselComponent"
|
||||
import { useTranslations } from "next-intl"
|
||||
import { CarouselComponent } from "./CarouselComponent";
|
||||
import { useTranslations } from "next-intl";
|
||||
|
||||
const Categories = () => {
|
||||
const t = useTranslations("Categories")
|
||||
const t = useTranslations("Categories");
|
||||
|
||||
return (
|
||||
<div className="container mx-auto my-16">
|
||||
<CarouselComponent
|
||||
title={t("title")}
|
||||
description={t("description")}
|
||||
/>
|
||||
<CarouselComponent title={t("title")} description={t("description")} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
export default Categories
|
||||
export default Categories;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
"use client"
|
||||
"use client";
|
||||
import { MarkerIcon, MarkerPreviewIcon } from "@/assets";
|
||||
import { useMap } from "@vis.gl/react-maplibre";
|
||||
import maplibregl from "maplibre-gl";
|
||||
@@ -20,7 +20,7 @@ type Props = {
|
||||
};
|
||||
|
||||
const MarkerPosition = ({ preview = false, onChange }: Props) => {
|
||||
const { current : homePageMap} = useMap();
|
||||
const { current: homePageMap } = useMap();
|
||||
const markerRef = useRef<maplibregl.Marker | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
@@ -1,108 +1,106 @@
|
||||
"use client"
|
||||
"use client";
|
||||
|
||||
import * as React from "react"
|
||||
import useEmblaCarousel, {
|
||||
type UseEmblaCarouselType,
|
||||
} from "embla-carousel-react"
|
||||
import * as React from "react";
|
||||
import useEmblaCarousel, { type UseEmblaCarouselType } from "embla-carousel-react";
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
import { Button } from "@/components/UI/button"
|
||||
import {ArrowLeft, ArrowRight, ChevronIcon} from "@/assets";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { Button } from "@/components/UI/button";
|
||||
import { ArrowLeft, ArrowRight, ChevronIcon } from "@/assets";
|
||||
|
||||
type CarouselApi = UseEmblaCarouselType[1]
|
||||
type UseCarouselParameters = Parameters<typeof useEmblaCarousel>
|
||||
type CarouselOptions = UseCarouselParameters[0]
|
||||
type CarouselPlugin = UseCarouselParameters[1]
|
||||
type CarouselApi = UseEmblaCarouselType[1];
|
||||
type UseCarouselParameters = Parameters<typeof useEmblaCarousel>;
|
||||
type CarouselOptions = UseCarouselParameters[0];
|
||||
type CarouselPlugin = UseCarouselParameters[1];
|
||||
|
||||
type CarouselProps = {
|
||||
opts?: CarouselOptions
|
||||
plugins?: CarouselPlugin
|
||||
orientation?: "horizontal" | "vertical"
|
||||
setApi?: (api: CarouselApi) => void
|
||||
}
|
||||
opts?: CarouselOptions;
|
||||
plugins?: CarouselPlugin;
|
||||
orientation?: "horizontal" | "vertical";
|
||||
setApi?: (api: CarouselApi) => void;
|
||||
};
|
||||
|
||||
type CarouselContextProps = {
|
||||
carouselRef: ReturnType<typeof useEmblaCarousel>[0]
|
||||
api: ReturnType<typeof useEmblaCarousel>[1]
|
||||
scrollPrev: () => void
|
||||
scrollNext: () => void
|
||||
canScrollPrev: boolean
|
||||
canScrollNext: boolean
|
||||
} & CarouselProps
|
||||
carouselRef: ReturnType<typeof useEmblaCarousel>[0];
|
||||
api: ReturnType<typeof useEmblaCarousel>[1];
|
||||
scrollPrev: () => void;
|
||||
scrollNext: () => void;
|
||||
canScrollPrev: boolean;
|
||||
canScrollNext: boolean;
|
||||
} & CarouselProps;
|
||||
|
||||
const CarouselContext = React.createContext<CarouselContextProps | null>(null)
|
||||
const CarouselContext = React.createContext<CarouselContextProps | null>(null);
|
||||
|
||||
function useCarousel() {
|
||||
const context = React.useContext(CarouselContext)
|
||||
const context = React.useContext(CarouselContext);
|
||||
|
||||
if (!context) {
|
||||
throw new Error("useCarousel must be used within a <Carousel />")
|
||||
throw new Error("useCarousel must be used within a <Carousel />");
|
||||
}
|
||||
|
||||
return context
|
||||
return context;
|
||||
}
|
||||
|
||||
function Carousel({
|
||||
orientation = "horizontal",
|
||||
opts,
|
||||
setApi,
|
||||
plugins,
|
||||
className,
|
||||
children,
|
||||
...props
|
||||
}: React.ComponentProps<"div"> & CarouselProps) {
|
||||
orientation = "horizontal",
|
||||
opts,
|
||||
setApi,
|
||||
plugins,
|
||||
className,
|
||||
children,
|
||||
...props
|
||||
}: React.ComponentProps<"div"> & CarouselProps) {
|
||||
const [carouselRef, api] = useEmblaCarousel(
|
||||
{
|
||||
...opts,
|
||||
axis: orientation === "horizontal" ? "x" : "y",
|
||||
},
|
||||
plugins
|
||||
)
|
||||
const [canScrollPrev, setCanScrollPrev] = React.useState(false)
|
||||
const [canScrollNext, setCanScrollNext] = React.useState(false)
|
||||
);
|
||||
const [canScrollPrev, setCanScrollPrev] = React.useState(false);
|
||||
const [canScrollNext, setCanScrollNext] = React.useState(false);
|
||||
|
||||
const onSelect = React.useCallback((api: CarouselApi) => {
|
||||
if (!api) return
|
||||
setCanScrollPrev(api.canScrollPrev())
|
||||
setCanScrollNext(api.canScrollNext())
|
||||
}, [])
|
||||
if (!api) return;
|
||||
setCanScrollPrev(api.canScrollPrev());
|
||||
setCanScrollNext(api.canScrollNext());
|
||||
}, []);
|
||||
|
||||
const scrollPrev = React.useCallback(() => {
|
||||
api?.scrollPrev()
|
||||
}, [api])
|
||||
api?.scrollPrev();
|
||||
}, [api]);
|
||||
|
||||
const scrollNext = React.useCallback(() => {
|
||||
api?.scrollNext()
|
||||
}, [api])
|
||||
api?.scrollNext();
|
||||
}, [api]);
|
||||
|
||||
const handleKeyDown = React.useCallback(
|
||||
(event: React.KeyboardEvent<HTMLDivElement>) => {
|
||||
if (event.key === "ArrowLeft") {
|
||||
event.preventDefault()
|
||||
scrollPrev()
|
||||
event.preventDefault();
|
||||
scrollPrev();
|
||||
} else if (event.key === "ArrowRight") {
|
||||
event.preventDefault()
|
||||
scrollNext()
|
||||
event.preventDefault();
|
||||
scrollNext();
|
||||
}
|
||||
},
|
||||
[scrollPrev, scrollNext]
|
||||
)
|
||||
);
|
||||
|
||||
React.useEffect(() => {
|
||||
if (!api || !setApi) return
|
||||
setApi(api)
|
||||
}, [api, setApi])
|
||||
if (!api || !setApi) return;
|
||||
setApi(api);
|
||||
}, [api, setApi]);
|
||||
|
||||
React.useEffect(() => {
|
||||
if (!api) return
|
||||
onSelect(api)
|
||||
api.on("reInit", onSelect)
|
||||
api.on("select", onSelect)
|
||||
if (!api) return;
|
||||
onSelect(api);
|
||||
api.on("reInit", onSelect);
|
||||
api.on("select", onSelect);
|
||||
|
||||
return () => {
|
||||
api?.off("select", onSelect)
|
||||
}
|
||||
}, [api, onSelect])
|
||||
api?.off("select", onSelect);
|
||||
};
|
||||
}, [api, onSelect]);
|
||||
|
||||
return (
|
||||
<CarouselContext.Provider
|
||||
@@ -110,8 +108,7 @@ function Carousel({
|
||||
carouselRef,
|
||||
api: api,
|
||||
opts,
|
||||
orientation:
|
||||
orientation || (opts?.axis === "y" ? "vertical" : "horizontal"),
|
||||
orientation: orientation || (opts?.axis === "y" ? "vertical" : "horizontal"),
|
||||
scrollPrev,
|
||||
scrollNext,
|
||||
canScrollPrev,
|
||||
@@ -129,32 +126,28 @@ function Carousel({
|
||||
{children}
|
||||
</div>
|
||||
</CarouselContext.Provider>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
function CarouselContent({ className, ...props }: React.ComponentProps<"div">) {
|
||||
const { carouselRef, orientation } = useCarousel()
|
||||
const { carouselRef, orientation } = useCarousel();
|
||||
|
||||
return (
|
||||
<div
|
||||
ref={carouselRef}
|
||||
className="overflow-hidden border border-text-primary/10 p-1 rounded-2xl"
|
||||
className="border-text-primary/10 overflow-hidden rounded-2xl border p-1"
|
||||
data-slot="carousel-content"
|
||||
>
|
||||
<div
|
||||
className={cn(
|
||||
"flex",
|
||||
orientation === "horizontal" ? "-ml-4" : "-mt-4 flex-col",
|
||||
className
|
||||
)}
|
||||
className={cn("flex", orientation === "horizontal" ? "-ml-4" : "-mt-4 flex-col", className)}
|
||||
{...props}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
function CarouselItem({ className, ...props }: React.ComponentProps<"div">) {
|
||||
const { orientation } = useCarousel()
|
||||
const { orientation } = useCarousel();
|
||||
|
||||
return (
|
||||
<div
|
||||
@@ -168,16 +161,16 @@ function CarouselItem({ className, ...props }: React.ComponentProps<"div">) {
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
function CarouselPrevious({
|
||||
className,
|
||||
variant = "outline",
|
||||
size = "icon-sm",
|
||||
...props
|
||||
}: React.ComponentProps<typeof Button>) {
|
||||
const { orientation, scrollPrev, canScrollPrev } = useCarousel()
|
||||
className,
|
||||
variant = "outline",
|
||||
size = "icon-sm",
|
||||
...props
|
||||
}: React.ComponentProps<typeof Button>) {
|
||||
const { orientation, scrollPrev, canScrollPrev } = useCarousel();
|
||||
|
||||
return (
|
||||
<Button
|
||||
@@ -185,7 +178,7 @@ function CarouselPrevious({
|
||||
variant={variant}
|
||||
size={size}
|
||||
className={cn(
|
||||
"rounded-xl p-5 absolute touch-manipulation bg-card border border-primary-300",
|
||||
"bg-card border-primary-300 absolute touch-manipulation rounded-xl border p-5",
|
||||
orientation === "horizontal"
|
||||
? "top-1/2 -left-12 -translate-y-1/2"
|
||||
: "-top-12 left-1/2 -translate-x-1/2 rotate-90",
|
||||
@@ -198,16 +191,16 @@ function CarouselPrevious({
|
||||
<ArrowLeft className="text-text-primary" />
|
||||
<span className="sr-only">Previous slide</span>
|
||||
</Button>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
function CarouselNext({
|
||||
className,
|
||||
variant = "outline",
|
||||
size = "icon-sm",
|
||||
...props
|
||||
}: React.ComponentProps<typeof Button>) {
|
||||
const { orientation, scrollNext, canScrollNext } = useCarousel()
|
||||
className,
|
||||
variant = "outline",
|
||||
size = "icon-sm",
|
||||
...props
|
||||
}: React.ComponentProps<typeof Button>) {
|
||||
const { orientation, scrollNext, canScrollNext } = useCarousel();
|
||||
|
||||
return (
|
||||
<Button
|
||||
@@ -215,7 +208,7 @@ function CarouselNext({
|
||||
variant={variant}
|
||||
size={size}
|
||||
className={cn(
|
||||
"rounded-xl p-5 absolute touch-manipulation bg-card border-primary-300",
|
||||
"bg-card border-primary-300 absolute touch-manipulation rounded-xl p-5",
|
||||
orientation === "horizontal"
|
||||
? "top-1/2 -right-12 -translate-y-1/2"
|
||||
: "-bottom-12 left-1/2 -translate-x-1/2 rotate-90",
|
||||
@@ -228,15 +221,7 @@ function CarouselNext({
|
||||
<ArrowRight className="text-text-primary size-5" />
|
||||
<span className="sr-only">Next slide</span>
|
||||
</Button>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
export {
|
||||
type CarouselApi,
|
||||
Carousel,
|
||||
CarouselContent,
|
||||
CarouselItem,
|
||||
CarouselPrevious,
|
||||
CarouselNext,
|
||||
useCarousel,
|
||||
}
|
||||
export { type CarouselApi, Carousel, CarouselContent, CarouselItem, CarouselPrevious, CarouselNext, useCarousel };
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import * as React from "react"
|
||||
import { cva, type VariantProps } from "class-variance-authority"
|
||||
import { Slot } from "radix-ui"
|
||||
import * as React from "react";
|
||||
import { cva, type VariantProps } from "class-variance-authority";
|
||||
import { Slot } from "radix-ui";
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
const buttonVariants = cva(
|
||||
"focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 rounded-lg border border-transparent bg-clip-padding text-sm font-medium focus-visible:ring-3 aria-invalid:ring-3 [&_svg:not([class*='size-'])]:size-4 inline-flex items-center justify-center whitespace-nowrap transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none shrink-0 [&_svg]:shrink-0 outline-none group/button select-none",
|
||||
@@ -10,10 +10,13 @@ const buttonVariants = cva(
|
||||
variants: {
|
||||
variant: {
|
||||
default: "bg-primary text-primary-foreground [a]:hover:bg-primary/80",
|
||||
outline: "border-border bg-background hover:bg-muted hover:text-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50 aria-expanded:bg-muted aria-expanded:text-foreground",
|
||||
secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80 aria-expanded:bg-secondary aria-expanded:text-secondary-foreground",
|
||||
outline:
|
||||
"border-border bg-background hover:bg-muted hover:text-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50 aria-expanded:bg-muted aria-expanded:text-foreground",
|
||||
secondary:
|
||||
"bg-secondary text-secondary-foreground hover:bg-secondary/80 aria-expanded:bg-secondary aria-expanded:text-secondary-foreground",
|
||||
ghost: "hover:bg-muted hover:text-foreground dark:hover:bg-muted/50 aria-expanded:bg-muted aria-expanded:text-foreground",
|
||||
destructive: "bg-destructive/10 hover:bg-destructive/20 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/20 text-destructive focus-visible:border-destructive/40 dark:hover:bg-destructive/30",
|
||||
destructive:
|
||||
"bg-destructive/10 hover:bg-destructive/20 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/20 text-destructive focus-visible:border-destructive/40 dark:hover:bg-destructive/30",
|
||||
link: "text-primary underline-offset-4 hover:underline",
|
||||
},
|
||||
size: {
|
||||
@@ -22,7 +25,8 @@ const buttonVariants = cva(
|
||||
sm: "h-7 gap-1 rounded-[min(var(--radius-md),12px)] px-2.5 text-[0.8rem] in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3.5",
|
||||
lg: "h-9 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-3 has-data-[icon=inline-start]:pl-3",
|
||||
icon: "size-8",
|
||||
"icon-xs": "size-6 rounded-[min(var(--radius-md),10px)] in-data-[slot=button-group]:rounded-lg [&_svg:not([class*='size-'])]:size-3",
|
||||
"icon-xs":
|
||||
"size-6 rounded-[min(var(--radius-md),10px)] in-data-[slot=button-group]:rounded-lg [&_svg:not([class*='size-'])]:size-3",
|
||||
"icon-sm": "size-7 rounded-[min(var(--radius-md),12px)] in-data-[slot=button-group]:rounded-lg",
|
||||
"icon-lg": "size-9",
|
||||
},
|
||||
@@ -32,19 +36,19 @@ const buttonVariants = cva(
|
||||
size: "default",
|
||||
},
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
function Button({
|
||||
className,
|
||||
variant = "default",
|
||||
size = "default",
|
||||
asChild = false,
|
||||
...props
|
||||
}: React.ComponentProps<"button"> &
|
||||
className,
|
||||
variant = "default",
|
||||
size = "default",
|
||||
asChild = false,
|
||||
...props
|
||||
}: React.ComponentProps<"button"> &
|
||||
VariantProps<typeof buttonVariants> & {
|
||||
asChild?: boolean
|
||||
}) {
|
||||
const Comp = asChild ? Slot.Root : "button"
|
||||
asChild?: boolean;
|
||||
}) {
|
||||
const Comp = asChild ? Slot.Root : "button";
|
||||
|
||||
return (
|
||||
<Comp
|
||||
@@ -54,7 +58,7 @@ function Button({
|
||||
className={cn(buttonVariants({ variant, size, className }))}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
export { Button, buttonVariants }
|
||||
export { Button, buttonVariants };
|
||||
|
||||
@@ -1,20 +1,19 @@
|
||||
import * as React from "react"
|
||||
import * as React from "react";
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
function Card({
|
||||
className,
|
||||
size = "default",
|
||||
...props
|
||||
}: React.ComponentProps<"div"> & { size?: "default" | "sm" }) {
|
||||
function Card({ className, size = "default", ...props }: React.ComponentProps<"div"> & { size?: "default" | "sm" }) {
|
||||
return (
|
||||
<div
|
||||
data-slot="card"
|
||||
data-size={size}
|
||||
className={cn("ring-foreground/10 text-card-foreground gap-4 overflow-hidden rounded-xl py-4 text-sm has-data-[slot=card-footer]:pb-0 has-[>img:first-child]:pt-0 data-[size=sm]:gap-3 data-[size=sm]:py-3 data-[size=sm]:has-data-[slot=card-footer]:pb-0 *:[img:first-child]:rounded-t-xl *:[img:last-child]:rounded-b-xl group/card flex flex-col", className)}
|
||||
className={cn(
|
||||
"ring-foreground/10 text-card-foreground group/card flex flex-col gap-4 overflow-hidden rounded-xl py-4 text-sm has-data-[slot=card-footer]:pb-0 has-[>img:first-child]:pt-0 data-[size=sm]:gap-3 data-[size=sm]:py-3 data-[size=sm]:has-data-[slot=card-footer]:pb-0 *:[img:first-child]:rounded-t-xl *:[img:last-child]:rounded-b-xl",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
function CardHeader({ className, ...props }: React.ComponentProps<"div">) {
|
||||
@@ -22,12 +21,12 @@ function CardHeader({ className, ...props }: React.ComponentProps<"div">) {
|
||||
<div
|
||||
data-slot="card-header"
|
||||
className={cn(
|
||||
"gap-1 rounded-t-xl px-4 group-data-[size=sm]/card:px-3 [.border-b]:pb-4 group-data-[size=sm]/card:[.border-b]:pb-3 group/card-header @container/card-header grid auto-rows-min items-start has-data-[slot=card-action]:grid-cols-[1fr_auto] has-data-[slot=card-description]:grid-rows-[auto_auto]",
|
||||
"group/card-header @container/card-header grid auto-rows-min items-start gap-1 rounded-t-xl px-4 group-data-[size=sm]/card:px-3 has-data-[slot=card-action]:grid-cols-[1fr_auto] has-data-[slot=card-description]:grid-rows-[auto_auto] [.border-b]:pb-4 group-data-[size=sm]/card:[.border-b]:pb-3",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
function CardTitle({ className, ...props }: React.ComponentProps<"div">) {
|
||||
@@ -37,58 +36,38 @@ function CardTitle({ className, ...props }: React.ComponentProps<"div">) {
|
||||
className={cn("text-base leading-snug font-medium group-data-[size=sm]/card:text-sm", className)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
function CardDescription({ className, ...props }: React.ComponentProps<"div">) {
|
||||
return (
|
||||
<div
|
||||
data-slot="card-description"
|
||||
className={cn("text-muted-foreground text-sm", className)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
return <div data-slot="card-description" className={cn("text-muted-foreground text-sm", className)} {...props} />;
|
||||
}
|
||||
|
||||
function CardAction({ className, ...props }: React.ComponentProps<"div">) {
|
||||
return (
|
||||
<div
|
||||
data-slot="card-action"
|
||||
className={cn(
|
||||
"col-start-2 row-span-2 row-start-1 self-start justify-self-end",
|
||||
className
|
||||
)}
|
||||
className={cn("col-start-2 row-span-2 row-start-1 self-start justify-self-end", className)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
function CardContent({ className, ...props }: React.ComponentProps<"div">) {
|
||||
return (
|
||||
<div
|
||||
data-slot="card-content"
|
||||
className={cn("px-4 group-data-[size=sm]/card:px-3", className)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
return <div data-slot="card-content" className={cn("px-4 group-data-[size=sm]/card:px-3", className)} {...props} />;
|
||||
}
|
||||
|
||||
function CardFooter({ className, ...props }: React.ComponentProps<"div">) {
|
||||
return (
|
||||
<div
|
||||
data-slot="card-footer"
|
||||
className={cn("bg-muted/50 rounded-b-xl border-t p-4 group-data-[size=sm]/card:p-3 flex items-center", className)}
|
||||
className={cn(
|
||||
"bg-muted/50 flex items-center rounded-b-xl border-t p-4 group-data-[size=sm]/card:p-3",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
export {
|
||||
Card,
|
||||
CardHeader,
|
||||
CardFooter,
|
||||
CardTitle,
|
||||
CardAction,
|
||||
CardDescription,
|
||||
CardContent,
|
||||
}
|
||||
export { Card, CardHeader, CardFooter, CardTitle, CardAction, CardDescription, CardContent };
|
||||
|
||||
@@ -44,4 +44,4 @@ export const categories = [
|
||||
title: "ژل و بوتاکس",
|
||||
image: "/images/categories/ژل.jpg",
|
||||
},
|
||||
]
|
||||
];
|
||||
|
||||
Reference in New Issue
Block a user