UNPKG

@easy-shadcn/react

Version:

Use shadcn/ui easy&enhance like component library

235 lines (232 loc) 8.21 kB
import { Popover, PopoverTrigger, PopoverContent } from './chunk-SNK5IGUQ.mjs'; import { useLocale_default } from './chunk-35JJS2VW.mjs'; import { Button } from './chunk-P4KSIALF.mjs'; import * as React from 'react'; import React__default, { useEffect } from 'react'; import { MagnifyingGlassIcon, ChevronDownIcon, Cross2Icon, CheckIcon } from '@radix-ui/react-icons'; import { cn } from '@easy-shadcn/utils'; import { Command as Command$1 } from 'cmdk'; import { jsx, jsxs } from 'react/jsx-runtime'; var Command = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx( Command$1, { ref, className: cn( "flex h-full w-full flex-col overflow-hidden rounded-md bg-popover text-popover-foreground", className ), ...props } )); Command.displayName = Command$1.displayName; var CommandInput = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxs("div", { className: "flex items-center border-b px-3", "cmdk-input-wrapper": "", children: [ /* @__PURE__ */ jsx(MagnifyingGlassIcon, { className: "mr-2 size-4 shrink-0 opacity-50" }), /* @__PURE__ */ jsx( Command$1.Input, { ref, className: cn( "flex h-10 w-full rounded-md bg-transparent py-3 text-sm outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50", className ), ...props } ) ] })); CommandInput.displayName = Command$1.Input.displayName; var CommandList = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx( Command$1.List, { ref, className: cn("max-h-[300px] overflow-y-auto overflow-x-hidden", className), ...props } )); CommandList.displayName = Command$1.List.displayName; var CommandEmpty = React.forwardRef((props, ref) => /* @__PURE__ */ jsx( Command$1.Empty, { ref, className: "py-6 text-center text-sm", ...props } )); CommandEmpty.displayName = Command$1.Empty.displayName; var CommandGroup = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx( Command$1.Group, { ref, className: cn( "overflow-hidden p-1 text-foreground [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground", className ), ...props } )); CommandGroup.displayName = Command$1.Group.displayName; var CommandSeparator = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx( Command$1.Separator, { ref, className: cn("-mx-1 h-px bg-border", className), ...props } )); CommandSeparator.displayName = Command$1.Separator.displayName; var CommandItem = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx( Command$1.Item, { ref, className: cn( "relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none data-[disabled=true]:pointer-events-none data-[selected=true]:bg-accent data-[selected=true]:text-accent-foreground data-[disabled=true]:opacity-50 gap-2 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0", className ), ...props } )); CommandItem.displayName = Command$1.Item.displayName; var Select = ({ placeholder, buttonProps, showSearch, searchProps, contentProps, empty, options, value, onChange, width, allowClear, multiple }) => { const [locale] = useLocale_default("Select"); const [open, setOpen] = React__default.useState(false); const [innerValue, setInnerValue] = React__default.useState( value ); const [innerOption, setInnerOption] = React__default.useState( Array.isArray(value) ? options.filter((opt) => value.includes(opt.value)) : options.find((opt) => opt.value === value) ); useEffect(() => { setInnerValue(value); setInnerOption( Array.isArray(value) ? options.filter((opt) => value.includes(opt.value)) : options.find((opt) => opt.value === value) ); }, [value, options]); const selectedLabelNode = React__default.useMemo(() => { if (innerOption) { if (Array.isArray(innerOption)) { if (innerOption.length > 0) { return innerOption.map((opt) => opt.label).join(","); } } else { return innerOption.label; } } return placeholder || null; }, [innerOption, placeholder]); const handleSelect = (opt) => { if (multiple === true) { const newValue = Array.isArray(innerValue) ? innerValue.includes(opt.value) ? innerValue.filter((v) => v !== opt.value) : [...innerValue, opt.value] : [opt.value]; const newOpt = Array.isArray(innerOption) ? innerOption.some((o) => o.value === opt.value) ? innerOption.filter((o) => o.value !== opt.value) : [...innerOption, opt] : [opt]; setInnerValue(newValue); setInnerOption(newOpt); onChange?.(newValue, opt); } else { if (opt.value === innerValue) { return; } setInnerValue(opt.value); setInnerOption(opt); onChange?.(opt.value, opt); setOpen(false); } }; const hasSelected = !!innerValue || Array.isArray(innerValue) && innerValue.length > 0; return /* @__PURE__ */ jsxs(Popover, { open, onOpenChange: setOpen, children: [ /* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsx( Button, { variant: "outline", role: "combobox", "aria-expanded": open, ...buttonProps, className: cn( "group justify-between", buttonProps?.className, hasSelected ? undefined : "text-muted-foreground" ), style: { width, ...buttonProps?.style }, icon: /* @__PURE__ */ jsxs("span", { className: "relative", children: [ /* @__PURE__ */ jsx( ChevronDownIcon, { className: cn( "size-4 shrink-0 text-gray-500 transition-transform duration-100", open ? "rotate-180" : undefined ) } ), allowClear && hasSelected && // eslint-disable-next-line jsx-a11y/click-events-have-key-events /* @__PURE__ */ jsx( "span", { role: "button", tabIndex: -1, onClick: (e) => { e.stopPropagation(); setInnerValue(undefined); setInnerOption(undefined); onChange?.(undefined, undefined); }, className: "absolute left-0 top-0 hidden size-4 items-center justify-center rounded-full bg-slate-400 hover:bg-slate-500 group-hover:flex", children: /* @__PURE__ */ jsx(Cross2Icon, { className: cn("size-3 shrink-0 text-white") }) } ) ] }), iconPosition: "end", children: selectedLabelNode } ) }), /* @__PURE__ */ jsx( PopoverContent, { ...contentProps, style: { minWidth: width }, className: cn("p-0 w-auto", contentProps?.className), children: /* @__PURE__ */ jsxs(Command, { children: [ showSearch && /* @__PURE__ */ jsx(CommandInput, { ...searchProps }), /* @__PURE__ */ jsxs(CommandList, { children: [ /* @__PURE__ */ jsx(CommandEmpty, { children: empty || locale.empty }), /* @__PURE__ */ jsx(CommandGroup, { children: options.map((opt) => /* @__PURE__ */ jsxs( CommandItem, { value: opt.value, onSelect: () => handleSelect(opt), children: [ opt.label, /* @__PURE__ */ jsx( CheckIcon, { className: cn( "ml-auto", (Array.isArray(innerValue) ? innerValue.includes(opt.value) : innerValue === opt.value) ? "opacity-100" : "opacity-0" ) } ) ] }, opt.value )) }) ] }) ] }) } ) ] }); }; export { Select };