@easy-shadcn/react
Version:
Use shadcn/ui easy&enhance like component library
235 lines (232 loc) • 8.21 kB
JavaScript
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 };