// AlignUI Tag v0.0.0 import * as React from 'react'; import { tv, type VariantProps } from '@/utils/tv'; import { recursiveCloneChildren } from '@/utils/recursive-clone-children'; import { Slot } from '@radix-ui/react-slot'; import { X } from 'lucide-react'; import { PolymorphicComponentProps } from '@/utils/polymorphic'; const TAG_ROOT_NAME = 'TagRoot'; const TAG_ICON_NAME = 'TagIcon'; const TAG_DISMISS_BUTTON_NAME = 'TagDismissButton'; const TAG_DISMISS_ICON_NAME = 'TagDismissIcon'; export const tagVariants = tv({ slots: { root: [ 'group/tag inline-flex h-6 items-center gap-2 rounded-md px-2 text-label-xs text-text-sub-600', 'transition duration-200 ease-out', 'ring-1 ring-inset', ], icon: [ // base '-mx-1 size-4 shrink-0 text-text-soft-400 transition duration-200 ease-out', // hover 'group-hover/tag:text-text-sub-600', ], dismissButton: [ // base 'group/dismiss-button -ml-1.5 -mr-1 size-4 shrink-0', // focus 'focus:outline-none', ], dismissIcon: 'size-4 text-text-soft-400 transition duration-200 ease-out', }, variants: { variant: { stroke: { root: [ // base 'bg-bg-white-0 ring-stroke-soft-200', // hover 'hover:bg-bg-weak-50 hover:ring-transparent', // focus-within 'focus-within:bg-bg-weak-50 focus-within:ring-transparent', ], dismissIcon: [ // hover 'group-hover/dismiss-button:text-text-sub-600', // focus 'group-focus/dismiss-button:text-text-sub-600', ], }, gray: { root: [ // base 'bg-bg-weak-50 ring-transparent', // hover 'hover:bg-bg-white-0 hover:ring-stroke-soft-200', ], }, }, disabled: { true: { root: 'pointer-events-none bg-bg-weak-50 text-text-disabled-300 ring-transparent', icon: 'text-text-disabled-300 opacity-[.48]', dismissIcon: 'text-text-disabled-300', }, }, }, defaultVariants: { variant: 'stroke', }, }); type TagSharedProps = VariantProps; type TagProps = VariantProps & React.HTMLAttributes & { asChild?: boolean; }; const TagRoot = React.forwardRef( ( { asChild, children, variant, disabled, className, ...rest }, forwardedRef, ) => { const uniqueId = React.useId(); const Component = asChild ? Slot : 'div'; const { root } = tagVariants({ variant, disabled }); const sharedProps: TagSharedProps = { variant, disabled, }; const extendedChildren = recursiveCloneChildren( children as React.ReactElement[], sharedProps, [TAG_ICON_NAME, TAG_DISMISS_BUTTON_NAME, TAG_DISMISS_ICON_NAME], uniqueId, asChild, ); return ( {extendedChildren} ); }, ); TagRoot.displayName = TAG_ROOT_NAME; function TagIcon({ className, variant, disabled, as, ...rest }: PolymorphicComponentProps) { const Component = as || 'div'; const { icon } = tagVariants({ variant, disabled }); return ; } TagIcon.displayName = TAG_ICON_NAME; type TagDismissButtonProps = TagSharedProps & React.ButtonHTMLAttributes & { asChild?: boolean; }; const TagDismissButton = React.forwardRef< HTMLButtonElement, TagDismissButtonProps >( ( { asChild, children, className, variant, disabled, ...rest }, forwardedRef, ) => { const Component = asChild ? Slot : 'button'; const { dismissButton } = tagVariants({ variant, disabled }); return ( {children ?? ( )} ); }, ); TagDismissButton.displayName = TAG_DISMISS_BUTTON_NAME; function TagDismissIcon({ className, variant, disabled, as, ...rest }: PolymorphicComponentProps) { const Component = as || 'div'; const { dismissIcon } = tagVariants({ variant, disabled }); return ; } TagDismissIcon.displayName = TAG_DISMISS_ICON_NAME; export { TagRoot as Root, TagIcon as Icon, TagDismissButton as DismissButton, TagDismissIcon as DismissIcon, };