| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201 |
- import * as React from 'react';
- import { mergeProps } from '@base-ui/react/merge-props';
- import { useRender } from '@base-ui/react/use-render';
- import { cva, type VariantProps } from 'class-variance-authority';
- import { cn } from '@/lib/utils';
- import { Separator } from '@/components/ui/separator';
- function ItemGroup({ className, ...props }: React.ComponentProps<'div'>) {
- return (
- <div
- role="list"
- data-slot="item-group"
- className={cn(
- 'gap-4 has-data-[size=sm]:gap-2.5 has-data-[size=xs]:gap-2 group/item-group flex w-full flex-col',
- className,
- )}
- {...props}
- />
- );
- }
- function ItemSeparator({
- className,
- ...props
- }: React.ComponentProps<typeof Separator>) {
- return (
- <Separator
- data-slot="item-separator"
- orientation="horizontal"
- className={cn('my-2', className)}
- {...props}
- />
- );
- }
- const itemVariants = cva(
- '[a]:hover:bg-muted rounded-lg border text-sm group/item flex w-full flex-wrap items-center transition-colors duration-100 outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 [a]:transition-colors',
- {
- variants: {
- variant: {
- default: 'border-transparent',
- outline: 'border-border',
- muted: 'bg-muted/50 border-transparent',
- },
- size: {
- default: 'gap-2.5 px-3 py-2.5',
- sm: 'gap-2.5 px-3 py-2.5',
- xs: 'gap-2 px-2.5 py-2 in-data-[slot=dropdown-menu-content]:p-0',
- },
- },
- defaultVariants: {
- variant: 'default',
- size: 'default',
- },
- },
- );
- function Item({
- className,
- variant = 'default',
- size = 'default',
- render,
- ...props
- }: useRender.ComponentProps<'div'> & VariantProps<typeof itemVariants>) {
- return useRender({
- defaultTagName: 'div',
- props: mergeProps<'div'>(
- {
- className: cn(itemVariants({ variant, size, className })),
- },
- props,
- ),
- render,
- state: {
- slot: 'item',
- variant,
- size,
- },
- });
- }
- const itemMediaVariants = cva(
- 'gap-2 group-has-data-[slot=item-description]/item:translate-y-0.5 group-has-data-[slot=item-description]/item:self-start flex shrink-0 items-center justify-center [&_svg]:pointer-events-none',
- {
- variants: {
- variant: {
- default: 'bg-transparent',
- icon: "[&_svg:not([class*='size-'])]:size-4",
- image:
- 'size-10 overflow-hidden rounded-sm group-data-[size=sm]/item:size-8 group-data-[size=xs]/item:size-6 [&_img]:size-full [&_img]:object-cover',
- },
- },
- defaultVariants: {
- variant: 'default',
- },
- },
- );
- function ItemMedia({
- className,
- variant = 'default',
- ...props
- }: React.ComponentProps<'div'> & VariantProps<typeof itemMediaVariants>) {
- return (
- <div
- data-slot="item-media"
- data-variant={variant}
- className={cn(itemMediaVariants({ variant, className }))}
- {...props}
- />
- );
- }
- function ItemContent({ className, ...props }: React.ComponentProps<'div'>) {
- return (
- <div
- data-slot="item-content"
- className={cn(
- 'gap-1 group-data-[size=xs]/item:gap-0 flex flex-1 flex-col [&+[data-slot=item-content]]:flex-none',
- className,
- )}
- {...props}
- />
- );
- }
- function ItemTitle({ className, ...props }: React.ComponentProps<'div'>) {
- return (
- <div
- data-slot="item-title"
- className={cn(
- 'gap-2 text-sm leading-snug font-medium underline-offset-4 line-clamp-1 flex w-fit items-center',
- className,
- )}
- {...props}
- />
- );
- }
- function ItemDescription({ className, ...props }: React.ComponentProps<'p'>) {
- return (
- <p
- data-slot="item-description"
- className={cn(
- 'text-muted-foreground text-left text-sm leading-normal group-data-[size=xs]/item:text-xs line-clamp-2 font-normal [&>a]:underline [&>a]:underline-offset-4 [&>a:hover]:text-primary',
- className,
- )}
- {...props}
- />
- );
- }
- function ItemActions({ className, ...props }: React.ComponentProps<'div'>) {
- return (
- <div
- data-slot="item-actions"
- className={cn('gap-2 flex items-center', className)}
- {...props}
- />
- );
- }
- function ItemHeader({ className, ...props }: React.ComponentProps<'div'>) {
- return (
- <div
- data-slot="item-header"
- className={cn(
- 'gap-2 flex basis-full items-center justify-between',
- className,
- )}
- {...props}
- />
- );
- }
- function ItemFooter({ className, ...props }: React.ComponentProps<'div'>) {
- return (
- <div
- data-slot="item-footer"
- className={cn(
- 'gap-2 flex basis-full items-center justify-between',
- className,
- )}
- {...props}
- />
- );
- }
- export {
- Item,
- ItemMedia,
- ItemContent,
- ItemActions,
- ItemGroup,
- ItemSeparator,
- ItemTitle,
- ItemDescription,
- ItemHeader,
- ItemFooter,
- };
|