@next-degree/pickle-shared-js 0.3.22 → 0.3.23
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/app/layout.css +22 -5
- package/dist/app/layout.css.map +1 -1
- package/dist/app/page.cjs +249 -4
- package/dist/app/page.cjs.map +1 -1
- package/dist/app/page.js +254 -4
- package/dist/app/page.js.map +1 -1
- package/dist/components/demos/SelectDemo.cjs +323 -0
- package/dist/components/demos/SelectDemo.cjs.map +1 -0
- package/dist/components/demos/SelectDemo.d.cts +5 -0
- package/dist/components/demos/SelectDemo.d.ts +5 -0
- package/dist/components/demos/SelectDemo.js +295 -0
- package/dist/components/demos/SelectDemo.js.map +1 -0
- package/dist/components/demos/index.cjs +247 -2
- package/dist/components/demos/index.cjs.map +1 -1
- package/dist/components/demos/index.js +252 -2
- package/dist/components/demos/index.js.map +1 -1
- package/dist/components/ui/ErrorMessage.cjs +41 -0
- package/dist/components/ui/ErrorMessage.cjs.map +1 -0
- package/dist/components/ui/ErrorMessage.d.cts +9 -0
- package/dist/components/ui/ErrorMessage.d.ts +9 -0
- package/dist/components/ui/ErrorMessage.js +18 -0
- package/dist/components/ui/ErrorMessage.js.map +1 -0
- package/dist/components/ui/Select.cjs +124 -105
- package/dist/components/ui/Select.cjs.map +1 -1
- package/dist/components/ui/Select.d.cts +3 -1
- package/dist/components/ui/Select.d.ts +3 -1
- package/dist/components/ui/Select.js +124 -105
- package/dist/components/ui/Select.js.map +1 -1
- package/dist/index.cjs +191 -172
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +177 -158
- package/dist/index.js.map +1 -1
- package/dist/styles/globals.css +22 -5
- package/dist/styles/globals.css.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/components/demos/SelectDemo.tsx","../../../src/components/ui/Select.tsx","../../../src/lib/utils.ts","../../../src/components/ui/ErrorMessage.tsx","../../../src/components/ui/Label.tsx","../../../src/components/ui/Chip.tsx","../../../src/components/primitives/separator.tsx"],"sourcesContent":["import Select from '@/components/ui/Select'\n\nfunction SelectDemo() {\n return (\n <div className='m-4'>\n <h3>Select</h3>\n <div className=\"flex max-w-sm flex-col gap-4 mt-2\">\n <Select\n label=\"Label - Singleselect\"\n placeholder=\"Select an option\"\n options={[\n { id: '1', value: '1', title: 'Option 1' },\n { id: '2', value: '2', title: 'Option 2' },\n { id: '3', value: '3', title: 'Option 3' },\n ]}\n />\n <Select\n multiselect\n label=\"Label - Multiselect\"\n placeholder=\"Select an option\"\n options={[\n { id: '1', value: '1', title: 'Option 1' },\n { id: '2', value: '2', title: 'Option 2' },\n { id: '3', value: '3', title: 'Option 3' },\n { id: '4', value: '4', title: 'Option 4' },\n { id: '5', value: '5', title: 'Option 5' },\n { id: '6', value: '6', title: 'Option 6' },\n { id: '7', value: '7', title: 'Option 7' },\n { id: '8', value: '8', title: 'Option 8' },\n { id: '9', value: '9', title: 'Option 9' },\n { id: '10', value: '10', title: 'Option 10' },\n ]}\n />\n <Select\n disabled\n label=\"Label - Disabled\"\n placeholder=\"Select an option\"\n options={[\n { id: '1', value: '1', title: 'Option 1' },\n { id: '2', value: '2', title: 'Option 2' },\n { id: '3', value: '3', title: 'Option 3' },\n ]}\n />\n </div>\n </div>\n )\n}\n\nexport default SelectDemo","'use client'\n\nimport * as SelectPrimitive from '@radix-ui/react-select'\nimport { CheckIcon, ChevronDownIcon, X } from 'lucide-react'\nimport {\n type ComponentPropsWithoutRef,\n forwardRef,\n type KeyboardEvent,\n useEffect,\n useRef,\n useState,\n} from 'react'\n\nimport ErrorMessage from '@/components/ui/ErrorMessage'\nimport Label from '@/components/ui/Label'\nimport Chip from '@/components/ui/Chip'\nimport { Separator } from '@/components/primitives/separator'\nimport { cn } from '@/lib/utils'\n\n\ninterface Props extends Omit<ComponentPropsWithoutRef<'select'>, 'value' | 'onChange'> {\n label?: string\n value?: string | string[]\n options?: { id: string | number; value: string; title: string }[]\n placeholder?: string\n multiselect?: boolean\n onChange?: (value: string | string[]) => void\n classNames?: { label?: string; trigger?: string }\n error?: string\n}\n\nconst Select = forwardRef<HTMLButtonElement, Props>(\n ({ label, options, placeholder, multiselect, classNames, error, id, ...props }, ref) => {\n const { value, defaultValue, dir, className, onChange, ...rest } = props\n const [selected, setSelected] = useState<string[]>([])\n const [open, setOpen] = useState(false)\n const containerRef = useRef<HTMLDivElement>(null)\n\n\n useEffect(() => {\n if (!value) return setSelected([])\n setSelected(Array.isArray(value) ? value : [value])\n }, [value])\n\n const toggleOpen = () => setOpen((prev) => !prev)\n const closeOnEscape = (event: KeyboardEvent) => event.key === 'Escape' && setOpen(false)\n const setValueOnEnter = (event: KeyboardEvent, value: string) =>\n event.key === 'Enter' && handleChange(value)\n\n const chipLabels = selected\n ?.map((s) => options?.find(({ value }) => value === s))\n .filter(Boolean)\n\n function handleLabels() {\n if (multiselect) {\n return selected.map((o) => options?.find((option) => option.value === o)?.title).join(', ')\n }\n return options?.find((option) => option.value === selected.join())?.title\n }\n\n function handleOnOpenChange(isOpen: boolean) {\n if (!multiselect || isOpen) setOpen(isOpen)\n }\n\n function handleChange(newValue: string) {\n let newSelected: string[] = []\n setSelected((prev) => {\n newSelected = prev.includes(newValue)\n ? prev.filter((item) => item !== newValue)\n : [...prev, newValue]\n return multiselect ? newSelected : [newValue]\n })\n onChange?.(multiselect ? newSelected : newValue)\n }\n\n return (\n <div\n className={cn('flex flex-col space-y-1', className)}\n ref={containerRef}\n data-testid={`${(label ?? id)?.toLowerCase()}-select-element`}\n >\n <Label text={label} className={classNames?.label} />\n\n <SelectPrimitive.Root\n open={open}\n value={selected.join(',')}\n onOpenChange={handleOnOpenChange}\n onValueChange={multiselect ? undefined : handleChange}\n defaultValue={typeof defaultValue === 'string' ? defaultValue : undefined}\n dir={dir === 'rtl' ? 'rtl' : 'ltr'}\n {...rest}\n >\n <SelectPrimitive.Trigger\n ref={ref}\n className={cn(\n 'group flex h-11 min-w-80 flex-row items-center justify-between gap-3 rounded-lg border px-4 py-3 text-sm font-normal focus:outline-purple-100 disabled:bg-grey-5 data-[placeholder]:text-grey-50 data-[placeholder]:disabled:text-grey-40',\n classNames?.trigger\n )}\n >\n <span className=\"truncate\">\n <SelectPrimitive.Value\n placeholder={placeholder ?? 'Select an option'}\n aria-label={handleLabels()}\n >\n {handleLabels()}\n </SelectPrimitive.Value>\n </span>\n\n <ChevronDownIcon\n className=\"transform text-black group-data-[state=open]:rotate-180\"\n size=\"16\"\n />\n </SelectPrimitive.Trigger>\n\n <SelectPrimitive.Portal container={containerRef.current}>\n <SelectPrimitive.Content\n hideWhenDetached\n className=\"z-10 max-h-[var(--radix-select-content-available-height)] w-[var(--radix-select-trigger-width)] overflow-hidden rounded-md bg-white py-2 shadow-lg\"\n position=\"popper\"\n sideOffset={4}\n onPointerDownOutside={toggleOpen}\n onKeyDown={closeOnEscape}\n >\n <SelectPrimitive.Viewport>\n {multiselect && !!chipLabels?.length && (\n <SelectPrimitive.Group\n className=\"mb-2 flex flex-row flex-wrap gap-1 px-2\"\n data-testid=\"selected-labels\"\n >\n {chipLabels?.map(\n (chip) =>\n chip && (\n <Chip key={chip.title} size=\"small\" variant=\"primary\">\n <span>{chip.title}</span>\n <X\n size={18}\n data-testid={`chip-remove-${chip.value}`}\n className=\"cursor-pointer\"\n onClick={() => handleChange(chip.value)}\n />\n </Chip>\n )\n )}\n </SelectPrimitive.Group>\n )}\n <Separator />\n {options?.map(({ id, title, value }) => (\n <SelectPrimitive.Item\n key={id}\n value={value}\n className=\"group relative cursor-pointer px-4 py-2 text-left text-sm hover:bg-purple-50 focus:bg-purple-50 focus:outline-none data-[state=checked]:bg-purple-50 data-[state=checked]:pr-10 data-[state=checked]:text-purple-100\"\n data-state={selected.includes(value) ? 'checked' : 'unchecked'}\n onKeyDown={(e) => setValueOnEnter(e, value)}\n onClick={() => handleChange(value)}\n >\n <SelectPrimitive.ItemText>{title}</SelectPrimitive.ItemText>\n <CheckIcon\n className=\"absolute inset-y-0 right-3 my-auto hidden w-6 text-purple-100 group-data-[state=checked]:block\"\n size={16}\n />\n </SelectPrimitive.Item>\n ))}\n </SelectPrimitive.Viewport>\n </SelectPrimitive.Content>\n </SelectPrimitive.Portal>\n </SelectPrimitive.Root>\n <ErrorMessage message={error} className=\"mt-1\" />\n </div>\n )\n }\n)\n\nSelect.displayName = 'Select'\n\nexport default Select\n","import { type ClassValue, clsx } from 'clsx'\nimport { twMerge } from 'tailwind-merge'\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs))\n}\n","import { type ComponentPropsWithoutRef } from 'react'\n\nimport { cn } from '@/lib/utils'\n\ninterface Props extends ComponentPropsWithoutRef<'p'> {\n message?: string\n}\n\nfunction ErrorMessage({ message, className, ...props }: Readonly<Props>) {\n if (!message) return null\n\n return (\n <p className={cn('px-1 text-xs text-red-600', className)} {...props}>\n {message}\n </p>\n )\n}\n\nexport default ErrorMessage\n","import { type ComponentPropsWithoutRef } from 'react'\n\nimport { cn } from '@/lib/utils'\n\ninterface Props extends ComponentPropsWithoutRef<'label'> {\n text?: string\n}\n\nfunction Label({ text, className, ...props }: Readonly<Props>) {\n if (!text) return null\n\n return (\n <label\n className={cn(\n 'text-xs text-grey-80 peer-disabled:cursor-not-allowed peer-disabled:opacity-70',\n className\n )}\n {...props}\n >\n {text}\n </label>\n )\n}\n\nexport default Label\n","import { cva, type VariantProps } from 'cva'\nimport React from 'react'\nimport { twMerge } from 'tailwind-merge'\n\ninterface ChipProps\n extends React.HTMLAttributes<HTMLDivElement>,\n VariantProps<typeof chipVariants> {}\n\nconst Chip = ({ className, variant, size, ...props }: ChipProps) => (\n <div className={twMerge(chipVariants({ variant, size, className }))} {...props} />\n)\n\nconst chipVariants = cva(['flex', 'items-center', 'rounded-3xl', 'border', 'w-fit'], {\n variants: {\n variant: {\n neutral: ['text-grey-80', 'border-grey-10'],\n primary: ['text-purple-100', 'border-purple-20'],\n danger: ['text-pumpkin-100', 'border-pumpkin-20'],\n onboarding: ['text-green-100', 'bg-green-10', 'cursor-pointer'],\n onboardingSelected: ['text-white', 'bg-green-90', 'cursor-pointer'],\n },\n size: {\n small: ['text-sm', 'leading-5', 'px-2', 'py-1', 'gap-1.5'],\n medium: ['text-base', 'leading-6', 'px-3', 'py-2', 'gap-2'],\n },\n },\n defaultVariants: {\n variant: 'neutral',\n size: 'medium',\n },\n})\n\nexport default Chip\n","'use client'\r\n\r\nimport * as SeparatorPrimitive from '@radix-ui/react-separator'\r\nimport * as React from 'react'\r\n\r\nimport { cn } from '@/lib/utils'\r\n\r\nconst Separator = React.forwardRef<\r\n React.ElementRef<typeof SeparatorPrimitive.Root>,\r\n React.ComponentPropsWithoutRef<typeof SeparatorPrimitive.Root>\r\n>(({ className, orientation = 'horizontal', decorative = true, ...props }, ref) => (\r\n <SeparatorPrimitive.Root\r\n ref={ref}\r\n decorative={decorative}\r\n orientation={orientation}\r\n className={cn(\r\n 'shrink-0 bg-grey-10',\r\n orientation === 'horizontal' ? 'h-[1px] w-full' : 'h-full w-[1px]',\r\n className\r\n )}\r\n {...props}\r\n />\r\n))\r\nSeparator.displayName = SeparatorPrimitive.Root.displayName\r\n\r\nexport { Separator }\r\n"],"mappings":"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","names":["import_jsx_runtime","import_tailwind_merge","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","value","id","import_jsx_runtime"]}
|
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
// src/components/ui/Select.tsx
|
|
2
|
+
import * as SelectPrimitive from "@radix-ui/react-select";
|
|
3
|
+
import { CheckIcon, ChevronDownIcon, X } from "lucide-react";
|
|
4
|
+
import {
|
|
5
|
+
forwardRef as forwardRef2,
|
|
6
|
+
useEffect,
|
|
7
|
+
useRef,
|
|
8
|
+
useState
|
|
9
|
+
} from "react";
|
|
10
|
+
|
|
11
|
+
// src/lib/utils.ts
|
|
12
|
+
import { clsx } from "clsx";
|
|
13
|
+
import { twMerge } from "tailwind-merge";
|
|
14
|
+
function cn(...inputs) {
|
|
15
|
+
return twMerge(clsx(inputs));
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// src/components/ui/ErrorMessage.tsx
|
|
19
|
+
import { jsx } from "react/jsx-runtime";
|
|
20
|
+
function ErrorMessage({ message, className, ...props }) {
|
|
21
|
+
if (!message) return null;
|
|
22
|
+
return /* @__PURE__ */ jsx("p", { className: cn("px-1 text-xs text-red-600", className), ...props, children: message });
|
|
23
|
+
}
|
|
24
|
+
var ErrorMessage_default = ErrorMessage;
|
|
25
|
+
|
|
26
|
+
// src/components/ui/Label.tsx
|
|
27
|
+
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
28
|
+
function Label({ text, className, ...props }) {
|
|
29
|
+
if (!text) return null;
|
|
30
|
+
return /* @__PURE__ */ jsx2(
|
|
31
|
+
"label",
|
|
32
|
+
{
|
|
33
|
+
className: cn(
|
|
34
|
+
"text-xs text-grey-80 peer-disabled:cursor-not-allowed peer-disabled:opacity-70",
|
|
35
|
+
className
|
|
36
|
+
),
|
|
37
|
+
...props,
|
|
38
|
+
children: text
|
|
39
|
+
}
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
var Label_default = Label;
|
|
43
|
+
|
|
44
|
+
// src/components/ui/Chip.tsx
|
|
45
|
+
import { cva } from "cva";
|
|
46
|
+
import { twMerge as twMerge2 } from "tailwind-merge";
|
|
47
|
+
import { jsx as jsx3 } from "react/jsx-runtime";
|
|
48
|
+
var Chip = ({ className, variant, size, ...props }) => /* @__PURE__ */ jsx3("div", { className: twMerge2(chipVariants({ variant, size, className })), ...props });
|
|
49
|
+
var chipVariants = cva(["flex", "items-center", "rounded-3xl", "border", "w-fit"], {
|
|
50
|
+
variants: {
|
|
51
|
+
variant: {
|
|
52
|
+
neutral: ["text-grey-80", "border-grey-10"],
|
|
53
|
+
primary: ["text-purple-100", "border-purple-20"],
|
|
54
|
+
danger: ["text-pumpkin-100", "border-pumpkin-20"],
|
|
55
|
+
onboarding: ["text-green-100", "bg-green-10", "cursor-pointer"],
|
|
56
|
+
onboardingSelected: ["text-white", "bg-green-90", "cursor-pointer"]
|
|
57
|
+
},
|
|
58
|
+
size: {
|
|
59
|
+
small: ["text-sm", "leading-5", "px-2", "py-1", "gap-1.5"],
|
|
60
|
+
medium: ["text-base", "leading-6", "px-3", "py-2", "gap-2"]
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
defaultVariants: {
|
|
64
|
+
variant: "neutral",
|
|
65
|
+
size: "medium"
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
var Chip_default = Chip;
|
|
69
|
+
|
|
70
|
+
// src/components/primitives/separator.tsx
|
|
71
|
+
import * as SeparatorPrimitive from "@radix-ui/react-separator";
|
|
72
|
+
import * as React from "react";
|
|
73
|
+
import { jsx as jsx4 } from "react/jsx-runtime";
|
|
74
|
+
var Separator = React.forwardRef(({ className, orientation = "horizontal", decorative = true, ...props }, ref) => /* @__PURE__ */ jsx4(
|
|
75
|
+
SeparatorPrimitive.Root,
|
|
76
|
+
{
|
|
77
|
+
ref,
|
|
78
|
+
decorative,
|
|
79
|
+
orientation,
|
|
80
|
+
className: cn(
|
|
81
|
+
"shrink-0 bg-grey-10",
|
|
82
|
+
orientation === "horizontal" ? "h-[1px] w-full" : "h-full w-[1px]",
|
|
83
|
+
className
|
|
84
|
+
),
|
|
85
|
+
...props
|
|
86
|
+
}
|
|
87
|
+
));
|
|
88
|
+
Separator.displayName = SeparatorPrimitive.Root.displayName;
|
|
89
|
+
|
|
90
|
+
// src/components/ui/Select.tsx
|
|
91
|
+
import { jsx as jsx5, jsxs } from "react/jsx-runtime";
|
|
92
|
+
var Select = forwardRef2(
|
|
93
|
+
({ label, options, placeholder, multiselect, classNames, error, id, ...props }, ref) => {
|
|
94
|
+
const { value, defaultValue, dir, className, onChange, ...rest } = props;
|
|
95
|
+
const [selected, setSelected] = useState([]);
|
|
96
|
+
const [open, setOpen] = useState(false);
|
|
97
|
+
const containerRef = useRef(null);
|
|
98
|
+
useEffect(() => {
|
|
99
|
+
if (!value) return setSelected([]);
|
|
100
|
+
setSelected(Array.isArray(value) ? value : [value]);
|
|
101
|
+
}, [value]);
|
|
102
|
+
const toggleOpen = () => setOpen((prev) => !prev);
|
|
103
|
+
const closeOnEscape = (event) => event.key === "Escape" && setOpen(false);
|
|
104
|
+
const setValueOnEnter = (event, value2) => event.key === "Enter" && handleChange(value2);
|
|
105
|
+
const chipLabels = selected?.map((s) => options?.find(({ value: value2 }) => value2 === s)).filter(Boolean);
|
|
106
|
+
function handleLabels() {
|
|
107
|
+
if (multiselect) {
|
|
108
|
+
return selected.map((o) => options?.find((option) => option.value === o)?.title).join(", ");
|
|
109
|
+
}
|
|
110
|
+
return options?.find((option) => option.value === selected.join())?.title;
|
|
111
|
+
}
|
|
112
|
+
function handleOnOpenChange(isOpen) {
|
|
113
|
+
if (!multiselect || isOpen) setOpen(isOpen);
|
|
114
|
+
}
|
|
115
|
+
function handleChange(newValue) {
|
|
116
|
+
let newSelected = [];
|
|
117
|
+
setSelected((prev) => {
|
|
118
|
+
newSelected = prev.includes(newValue) ? prev.filter((item) => item !== newValue) : [...prev, newValue];
|
|
119
|
+
return multiselect ? newSelected : [newValue];
|
|
120
|
+
});
|
|
121
|
+
onChange?.(multiselect ? newSelected : newValue);
|
|
122
|
+
}
|
|
123
|
+
return /* @__PURE__ */ jsxs(
|
|
124
|
+
"div",
|
|
125
|
+
{
|
|
126
|
+
className: cn("flex flex-col space-y-1", className),
|
|
127
|
+
ref: containerRef,
|
|
128
|
+
"data-testid": `${(label ?? id)?.toLowerCase()}-select-element`,
|
|
129
|
+
children: [
|
|
130
|
+
/* @__PURE__ */ jsx5(Label_default, { text: label, className: classNames?.label }),
|
|
131
|
+
/* @__PURE__ */ jsxs(
|
|
132
|
+
SelectPrimitive.Root,
|
|
133
|
+
{
|
|
134
|
+
open,
|
|
135
|
+
value: selected.join(","),
|
|
136
|
+
onOpenChange: handleOnOpenChange,
|
|
137
|
+
onValueChange: multiselect ? void 0 : handleChange,
|
|
138
|
+
defaultValue: typeof defaultValue === "string" ? defaultValue : void 0,
|
|
139
|
+
dir: dir === "rtl" ? "rtl" : "ltr",
|
|
140
|
+
...rest,
|
|
141
|
+
children: [
|
|
142
|
+
/* @__PURE__ */ jsxs(
|
|
143
|
+
SelectPrimitive.Trigger,
|
|
144
|
+
{
|
|
145
|
+
ref,
|
|
146
|
+
className: cn(
|
|
147
|
+
"group flex h-11 min-w-80 flex-row items-center justify-between gap-3 rounded-lg border px-4 py-3 text-sm font-normal focus:outline-purple-100 disabled:bg-grey-5 data-[placeholder]:text-grey-50 data-[placeholder]:disabled:text-grey-40",
|
|
148
|
+
classNames?.trigger
|
|
149
|
+
),
|
|
150
|
+
children: [
|
|
151
|
+
/* @__PURE__ */ jsx5("span", { className: "truncate", children: /* @__PURE__ */ jsx5(
|
|
152
|
+
SelectPrimitive.Value,
|
|
153
|
+
{
|
|
154
|
+
placeholder: placeholder ?? "Select an option",
|
|
155
|
+
"aria-label": handleLabels(),
|
|
156
|
+
children: handleLabels()
|
|
157
|
+
}
|
|
158
|
+
) }),
|
|
159
|
+
/* @__PURE__ */ jsx5(
|
|
160
|
+
ChevronDownIcon,
|
|
161
|
+
{
|
|
162
|
+
className: "transform text-black group-data-[state=open]:rotate-180",
|
|
163
|
+
size: "16"
|
|
164
|
+
}
|
|
165
|
+
)
|
|
166
|
+
]
|
|
167
|
+
}
|
|
168
|
+
),
|
|
169
|
+
/* @__PURE__ */ jsx5(SelectPrimitive.Portal, { container: containerRef.current, children: /* @__PURE__ */ jsx5(
|
|
170
|
+
SelectPrimitive.Content,
|
|
171
|
+
{
|
|
172
|
+
hideWhenDetached: true,
|
|
173
|
+
className: "z-10 max-h-[var(--radix-select-content-available-height)] w-[var(--radix-select-trigger-width)] overflow-hidden rounded-md bg-white py-2 shadow-lg",
|
|
174
|
+
position: "popper",
|
|
175
|
+
sideOffset: 4,
|
|
176
|
+
onPointerDownOutside: toggleOpen,
|
|
177
|
+
onKeyDown: closeOnEscape,
|
|
178
|
+
children: /* @__PURE__ */ jsxs(SelectPrimitive.Viewport, { children: [
|
|
179
|
+
multiselect && !!chipLabels?.length && /* @__PURE__ */ jsx5(
|
|
180
|
+
SelectPrimitive.Group,
|
|
181
|
+
{
|
|
182
|
+
className: "mb-2 flex flex-row flex-wrap gap-1 px-2",
|
|
183
|
+
"data-testid": "selected-labels",
|
|
184
|
+
children: chipLabels?.map(
|
|
185
|
+
(chip) => chip && /* @__PURE__ */ jsxs(Chip_default, { size: "small", variant: "primary", children: [
|
|
186
|
+
/* @__PURE__ */ jsx5("span", { children: chip.title }),
|
|
187
|
+
/* @__PURE__ */ jsx5(
|
|
188
|
+
X,
|
|
189
|
+
{
|
|
190
|
+
size: 18,
|
|
191
|
+
"data-testid": `chip-remove-${chip.value}`,
|
|
192
|
+
className: "cursor-pointer",
|
|
193
|
+
onClick: () => handleChange(chip.value)
|
|
194
|
+
}
|
|
195
|
+
)
|
|
196
|
+
] }, chip.title)
|
|
197
|
+
)
|
|
198
|
+
}
|
|
199
|
+
),
|
|
200
|
+
/* @__PURE__ */ jsx5(Separator, {}),
|
|
201
|
+
options?.map(({ id: id2, title, value: value2 }) => /* @__PURE__ */ jsxs(
|
|
202
|
+
SelectPrimitive.Item,
|
|
203
|
+
{
|
|
204
|
+
value: value2,
|
|
205
|
+
className: "group relative cursor-pointer px-4 py-2 text-left text-sm hover:bg-purple-50 focus:bg-purple-50 focus:outline-none data-[state=checked]:bg-purple-50 data-[state=checked]:pr-10 data-[state=checked]:text-purple-100",
|
|
206
|
+
"data-state": selected.includes(value2) ? "checked" : "unchecked",
|
|
207
|
+
onKeyDown: (e) => setValueOnEnter(e, value2),
|
|
208
|
+
onClick: () => handleChange(value2),
|
|
209
|
+
children: [
|
|
210
|
+
/* @__PURE__ */ jsx5(SelectPrimitive.ItemText, { children: title }),
|
|
211
|
+
/* @__PURE__ */ jsx5(
|
|
212
|
+
CheckIcon,
|
|
213
|
+
{
|
|
214
|
+
className: "absolute inset-y-0 right-3 my-auto hidden w-6 text-purple-100 group-data-[state=checked]:block",
|
|
215
|
+
size: 16
|
|
216
|
+
}
|
|
217
|
+
)
|
|
218
|
+
]
|
|
219
|
+
},
|
|
220
|
+
id2
|
|
221
|
+
))
|
|
222
|
+
] })
|
|
223
|
+
}
|
|
224
|
+
) })
|
|
225
|
+
]
|
|
226
|
+
}
|
|
227
|
+
),
|
|
228
|
+
/* @__PURE__ */ jsx5(ErrorMessage_default, { message: error, className: "mt-1" })
|
|
229
|
+
]
|
|
230
|
+
}
|
|
231
|
+
);
|
|
232
|
+
}
|
|
233
|
+
);
|
|
234
|
+
Select.displayName = "Select";
|
|
235
|
+
var Select_default = Select;
|
|
236
|
+
|
|
237
|
+
// src/components/demos/SelectDemo.tsx
|
|
238
|
+
import { jsx as jsx6, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
239
|
+
function SelectDemo() {
|
|
240
|
+
return /* @__PURE__ */ jsxs2("div", { className: "m-4", children: [
|
|
241
|
+
/* @__PURE__ */ jsx6("h3", { children: "Select" }),
|
|
242
|
+
/* @__PURE__ */ jsxs2("div", { className: "flex max-w-sm flex-col gap-4 mt-2", children: [
|
|
243
|
+
/* @__PURE__ */ jsx6(
|
|
244
|
+
Select_default,
|
|
245
|
+
{
|
|
246
|
+
label: "Label - Singleselect",
|
|
247
|
+
placeholder: "Select an option",
|
|
248
|
+
options: [
|
|
249
|
+
{ id: "1", value: "1", title: "Option 1" },
|
|
250
|
+
{ id: "2", value: "2", title: "Option 2" },
|
|
251
|
+
{ id: "3", value: "3", title: "Option 3" }
|
|
252
|
+
]
|
|
253
|
+
}
|
|
254
|
+
),
|
|
255
|
+
/* @__PURE__ */ jsx6(
|
|
256
|
+
Select_default,
|
|
257
|
+
{
|
|
258
|
+
multiselect: true,
|
|
259
|
+
label: "Label - Multiselect",
|
|
260
|
+
placeholder: "Select an option",
|
|
261
|
+
options: [
|
|
262
|
+
{ id: "1", value: "1", title: "Option 1" },
|
|
263
|
+
{ id: "2", value: "2", title: "Option 2" },
|
|
264
|
+
{ id: "3", value: "3", title: "Option 3" },
|
|
265
|
+
{ id: "4", value: "4", title: "Option 4" },
|
|
266
|
+
{ id: "5", value: "5", title: "Option 5" },
|
|
267
|
+
{ id: "6", value: "6", title: "Option 6" },
|
|
268
|
+
{ id: "7", value: "7", title: "Option 7" },
|
|
269
|
+
{ id: "8", value: "8", title: "Option 8" },
|
|
270
|
+
{ id: "9", value: "9", title: "Option 9" },
|
|
271
|
+
{ id: "10", value: "10", title: "Option 10" }
|
|
272
|
+
]
|
|
273
|
+
}
|
|
274
|
+
),
|
|
275
|
+
/* @__PURE__ */ jsx6(
|
|
276
|
+
Select_default,
|
|
277
|
+
{
|
|
278
|
+
disabled: true,
|
|
279
|
+
label: "Label - Disabled",
|
|
280
|
+
placeholder: "Select an option",
|
|
281
|
+
options: [
|
|
282
|
+
{ id: "1", value: "1", title: "Option 1" },
|
|
283
|
+
{ id: "2", value: "2", title: "Option 2" },
|
|
284
|
+
{ id: "3", value: "3", title: "Option 3" }
|
|
285
|
+
]
|
|
286
|
+
}
|
|
287
|
+
)
|
|
288
|
+
] })
|
|
289
|
+
] });
|
|
290
|
+
}
|
|
291
|
+
var SelectDemo_default = SelectDemo;
|
|
292
|
+
export {
|
|
293
|
+
SelectDemo_default as default
|
|
294
|
+
};
|
|
295
|
+
//# sourceMappingURL=SelectDemo.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/components/ui/Select.tsx","../../../src/lib/utils.ts","../../../src/components/ui/ErrorMessage.tsx","../../../src/components/ui/Label.tsx","../../../src/components/ui/Chip.tsx","../../../src/components/primitives/separator.tsx","../../../src/components/demos/SelectDemo.tsx"],"sourcesContent":["'use client'\n\nimport * as SelectPrimitive from '@radix-ui/react-select'\nimport { CheckIcon, ChevronDownIcon, X } from 'lucide-react'\nimport {\n type ComponentPropsWithoutRef,\n forwardRef,\n type KeyboardEvent,\n useEffect,\n useRef,\n useState,\n} from 'react'\n\nimport ErrorMessage from '@/components/ui/ErrorMessage'\nimport Label from '@/components/ui/Label'\nimport Chip from '@/components/ui/Chip'\nimport { Separator } from '@/components/primitives/separator'\nimport { cn } from '@/lib/utils'\n\n\ninterface Props extends Omit<ComponentPropsWithoutRef<'select'>, 'value' | 'onChange'> {\n label?: string\n value?: string | string[]\n options?: { id: string | number; value: string; title: string }[]\n placeholder?: string\n multiselect?: boolean\n onChange?: (value: string | string[]) => void\n classNames?: { label?: string; trigger?: string }\n error?: string\n}\n\nconst Select = forwardRef<HTMLButtonElement, Props>(\n ({ label, options, placeholder, multiselect, classNames, error, id, ...props }, ref) => {\n const { value, defaultValue, dir, className, onChange, ...rest } = props\n const [selected, setSelected] = useState<string[]>([])\n const [open, setOpen] = useState(false)\n const containerRef = useRef<HTMLDivElement>(null)\n\n\n useEffect(() => {\n if (!value) return setSelected([])\n setSelected(Array.isArray(value) ? value : [value])\n }, [value])\n\n const toggleOpen = () => setOpen((prev) => !prev)\n const closeOnEscape = (event: KeyboardEvent) => event.key === 'Escape' && setOpen(false)\n const setValueOnEnter = (event: KeyboardEvent, value: string) =>\n event.key === 'Enter' && handleChange(value)\n\n const chipLabels = selected\n ?.map((s) => options?.find(({ value }) => value === s))\n .filter(Boolean)\n\n function handleLabels() {\n if (multiselect) {\n return selected.map((o) => options?.find((option) => option.value === o)?.title).join(', ')\n }\n return options?.find((option) => option.value === selected.join())?.title\n }\n\n function handleOnOpenChange(isOpen: boolean) {\n if (!multiselect || isOpen) setOpen(isOpen)\n }\n\n function handleChange(newValue: string) {\n let newSelected: string[] = []\n setSelected((prev) => {\n newSelected = prev.includes(newValue)\n ? prev.filter((item) => item !== newValue)\n : [...prev, newValue]\n return multiselect ? newSelected : [newValue]\n })\n onChange?.(multiselect ? newSelected : newValue)\n }\n\n return (\n <div\n className={cn('flex flex-col space-y-1', className)}\n ref={containerRef}\n data-testid={`${(label ?? id)?.toLowerCase()}-select-element`}\n >\n <Label text={label} className={classNames?.label} />\n\n <SelectPrimitive.Root\n open={open}\n value={selected.join(',')}\n onOpenChange={handleOnOpenChange}\n onValueChange={multiselect ? undefined : handleChange}\n defaultValue={typeof defaultValue === 'string' ? defaultValue : undefined}\n dir={dir === 'rtl' ? 'rtl' : 'ltr'}\n {...rest}\n >\n <SelectPrimitive.Trigger\n ref={ref}\n className={cn(\n 'group flex h-11 min-w-80 flex-row items-center justify-between gap-3 rounded-lg border px-4 py-3 text-sm font-normal focus:outline-purple-100 disabled:bg-grey-5 data-[placeholder]:text-grey-50 data-[placeholder]:disabled:text-grey-40',\n classNames?.trigger\n )}\n >\n <span className=\"truncate\">\n <SelectPrimitive.Value\n placeholder={placeholder ?? 'Select an option'}\n aria-label={handleLabels()}\n >\n {handleLabels()}\n </SelectPrimitive.Value>\n </span>\n\n <ChevronDownIcon\n className=\"transform text-black group-data-[state=open]:rotate-180\"\n size=\"16\"\n />\n </SelectPrimitive.Trigger>\n\n <SelectPrimitive.Portal container={containerRef.current}>\n <SelectPrimitive.Content\n hideWhenDetached\n className=\"z-10 max-h-[var(--radix-select-content-available-height)] w-[var(--radix-select-trigger-width)] overflow-hidden rounded-md bg-white py-2 shadow-lg\"\n position=\"popper\"\n sideOffset={4}\n onPointerDownOutside={toggleOpen}\n onKeyDown={closeOnEscape}\n >\n <SelectPrimitive.Viewport>\n {multiselect && !!chipLabels?.length && (\n <SelectPrimitive.Group\n className=\"mb-2 flex flex-row flex-wrap gap-1 px-2\"\n data-testid=\"selected-labels\"\n >\n {chipLabels?.map(\n (chip) =>\n chip && (\n <Chip key={chip.title} size=\"small\" variant=\"primary\">\n <span>{chip.title}</span>\n <X\n size={18}\n data-testid={`chip-remove-${chip.value}`}\n className=\"cursor-pointer\"\n onClick={() => handleChange(chip.value)}\n />\n </Chip>\n )\n )}\n </SelectPrimitive.Group>\n )}\n <Separator />\n {options?.map(({ id, title, value }) => (\n <SelectPrimitive.Item\n key={id}\n value={value}\n className=\"group relative cursor-pointer px-4 py-2 text-left text-sm hover:bg-purple-50 focus:bg-purple-50 focus:outline-none data-[state=checked]:bg-purple-50 data-[state=checked]:pr-10 data-[state=checked]:text-purple-100\"\n data-state={selected.includes(value) ? 'checked' : 'unchecked'}\n onKeyDown={(e) => setValueOnEnter(e, value)}\n onClick={() => handleChange(value)}\n >\n <SelectPrimitive.ItemText>{title}</SelectPrimitive.ItemText>\n <CheckIcon\n className=\"absolute inset-y-0 right-3 my-auto hidden w-6 text-purple-100 group-data-[state=checked]:block\"\n size={16}\n />\n </SelectPrimitive.Item>\n ))}\n </SelectPrimitive.Viewport>\n </SelectPrimitive.Content>\n </SelectPrimitive.Portal>\n </SelectPrimitive.Root>\n <ErrorMessage message={error} className=\"mt-1\" />\n </div>\n )\n }\n)\n\nSelect.displayName = 'Select'\n\nexport default Select\n","import { type ClassValue, clsx } from 'clsx'\nimport { twMerge } from 'tailwind-merge'\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs))\n}\n","import { type ComponentPropsWithoutRef } from 'react'\n\nimport { cn } from '@/lib/utils'\n\ninterface Props extends ComponentPropsWithoutRef<'p'> {\n message?: string\n}\n\nfunction ErrorMessage({ message, className, ...props }: Readonly<Props>) {\n if (!message) return null\n\n return (\n <p className={cn('px-1 text-xs text-red-600', className)} {...props}>\n {message}\n </p>\n )\n}\n\nexport default ErrorMessage\n","import { type ComponentPropsWithoutRef } from 'react'\n\nimport { cn } from '@/lib/utils'\n\ninterface Props extends ComponentPropsWithoutRef<'label'> {\n text?: string\n}\n\nfunction Label({ text, className, ...props }: Readonly<Props>) {\n if (!text) return null\n\n return (\n <label\n className={cn(\n 'text-xs text-grey-80 peer-disabled:cursor-not-allowed peer-disabled:opacity-70',\n className\n )}\n {...props}\n >\n {text}\n </label>\n )\n}\n\nexport default Label\n","import { cva, type VariantProps } from 'cva'\nimport React from 'react'\nimport { twMerge } from 'tailwind-merge'\n\ninterface ChipProps\n extends React.HTMLAttributes<HTMLDivElement>,\n VariantProps<typeof chipVariants> {}\n\nconst Chip = ({ className, variant, size, ...props }: ChipProps) => (\n <div className={twMerge(chipVariants({ variant, size, className }))} {...props} />\n)\n\nconst chipVariants = cva(['flex', 'items-center', 'rounded-3xl', 'border', 'w-fit'], {\n variants: {\n variant: {\n neutral: ['text-grey-80', 'border-grey-10'],\n primary: ['text-purple-100', 'border-purple-20'],\n danger: ['text-pumpkin-100', 'border-pumpkin-20'],\n onboarding: ['text-green-100', 'bg-green-10', 'cursor-pointer'],\n onboardingSelected: ['text-white', 'bg-green-90', 'cursor-pointer'],\n },\n size: {\n small: ['text-sm', 'leading-5', 'px-2', 'py-1', 'gap-1.5'],\n medium: ['text-base', 'leading-6', 'px-3', 'py-2', 'gap-2'],\n },\n },\n defaultVariants: {\n variant: 'neutral',\n size: 'medium',\n },\n})\n\nexport default Chip\n","'use client'\r\n\r\nimport * as SeparatorPrimitive from '@radix-ui/react-separator'\r\nimport * as React from 'react'\r\n\r\nimport { cn } from '@/lib/utils'\r\n\r\nconst Separator = React.forwardRef<\r\n React.ElementRef<typeof SeparatorPrimitive.Root>,\r\n React.ComponentPropsWithoutRef<typeof SeparatorPrimitive.Root>\r\n>(({ className, orientation = 'horizontal', decorative = true, ...props }, ref) => (\r\n <SeparatorPrimitive.Root\r\n ref={ref}\r\n decorative={decorative}\r\n orientation={orientation}\r\n className={cn(\r\n 'shrink-0 bg-grey-10',\r\n orientation === 'horizontal' ? 'h-[1px] w-full' : 'h-full w-[1px]',\r\n className\r\n )}\r\n {...props}\r\n />\r\n))\r\nSeparator.displayName = SeparatorPrimitive.Root.displayName\r\n\r\nexport { Separator }\r\n","import Select from '@/components/ui/Select'\n\nfunction SelectDemo() {\n return (\n <div className='m-4'>\n <h3>Select</h3>\n <div className=\"flex max-w-sm flex-col gap-4 mt-2\">\n <Select\n label=\"Label - Singleselect\"\n placeholder=\"Select an option\"\n options={[\n { id: '1', value: '1', title: 'Option 1' },\n { id: '2', value: '2', title: 'Option 2' },\n { id: '3', value: '3', title: 'Option 3' },\n ]}\n />\n <Select\n multiselect\n label=\"Label - Multiselect\"\n placeholder=\"Select an option\"\n options={[\n { id: '1', value: '1', title: 'Option 1' },\n { id: '2', value: '2', title: 'Option 2' },\n { id: '3', value: '3', title: 'Option 3' },\n { id: '4', value: '4', title: 'Option 4' },\n { id: '5', value: '5', title: 'Option 5' },\n { id: '6', value: '6', title: 'Option 6' },\n { id: '7', value: '7', title: 'Option 7' },\n { id: '8', value: '8', title: 'Option 8' },\n { id: '9', value: '9', title: 'Option 9' },\n { id: '10', value: '10', title: 'Option 10' },\n ]}\n />\n <Select\n disabled\n label=\"Label - Disabled\"\n placeholder=\"Select an option\"\n options={[\n { id: '1', value: '1', title: 'Option 1' },\n { id: '2', value: '2', title: 'Option 2' },\n { id: '3', value: '3', title: 'Option 3' },\n ]}\n />\n </div>\n </div>\n )\n}\n\nexport default SelectDemo"],"mappings":"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","names":["forwardRef","jsx","twMerge","jsx","jsx","jsx","forwardRef","value","id","jsx","jsxs"]}
|
|
@@ -767,10 +767,255 @@ function ComboboxDemo() {
|
|
|
767
767
|
}
|
|
768
768
|
var ComboboxDemo_default = ComboboxDemo;
|
|
769
769
|
|
|
770
|
-
// src/components/
|
|
770
|
+
// src/components/ui/Select.tsx
|
|
771
|
+
var SelectPrimitive = __toESM(require("@radix-ui/react-select"), 1);
|
|
772
|
+
var import_lucide_react7 = require("lucide-react");
|
|
773
|
+
var import_react5 = require("react");
|
|
774
|
+
|
|
775
|
+
// src/components/ui/ErrorMessage.tsx
|
|
771
776
|
var import_jsx_runtime12 = require("react/jsx-runtime");
|
|
777
|
+
function ErrorMessage({ message, className, ...props }) {
|
|
778
|
+
if (!message) return null;
|
|
779
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: cn("px-1 text-xs text-red-600", className), ...props, children: message });
|
|
780
|
+
}
|
|
781
|
+
var ErrorMessage_default = ErrorMessage;
|
|
782
|
+
|
|
783
|
+
// src/components/ui/Chip.tsx
|
|
784
|
+
var import_cva4 = require("cva");
|
|
785
|
+
var import_tailwind_merge2 = require("tailwind-merge");
|
|
786
|
+
var import_jsx_runtime13 = require("react/jsx-runtime");
|
|
787
|
+
var Chip = ({ className, variant, size, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: (0, import_tailwind_merge2.twMerge)(chipVariants({ variant, size, className })), ...props });
|
|
788
|
+
var chipVariants = (0, import_cva4.cva)(["flex", "items-center", "rounded-3xl", "border", "w-fit"], {
|
|
789
|
+
variants: {
|
|
790
|
+
variant: {
|
|
791
|
+
neutral: ["text-grey-80", "border-grey-10"],
|
|
792
|
+
primary: ["text-purple-100", "border-purple-20"],
|
|
793
|
+
danger: ["text-pumpkin-100", "border-pumpkin-20"],
|
|
794
|
+
onboarding: ["text-green-100", "bg-green-10", "cursor-pointer"],
|
|
795
|
+
onboardingSelected: ["text-white", "bg-green-90", "cursor-pointer"]
|
|
796
|
+
},
|
|
797
|
+
size: {
|
|
798
|
+
small: ["text-sm", "leading-5", "px-2", "py-1", "gap-1.5"],
|
|
799
|
+
medium: ["text-base", "leading-6", "px-3", "py-2", "gap-2"]
|
|
800
|
+
}
|
|
801
|
+
},
|
|
802
|
+
defaultVariants: {
|
|
803
|
+
variant: "neutral",
|
|
804
|
+
size: "medium"
|
|
805
|
+
}
|
|
806
|
+
});
|
|
807
|
+
var Chip_default = Chip;
|
|
808
|
+
|
|
809
|
+
// src/components/ui/Select.tsx
|
|
810
|
+
var import_jsx_runtime14 = require("react/jsx-runtime");
|
|
811
|
+
var Select = (0, import_react5.forwardRef)(
|
|
812
|
+
({ label, options, placeholder, multiselect, classNames, error, id, ...props }, ref) => {
|
|
813
|
+
const { value, defaultValue, dir, className, onChange, ...rest } = props;
|
|
814
|
+
const [selected, setSelected] = (0, import_react5.useState)([]);
|
|
815
|
+
const [open, setOpen] = (0, import_react5.useState)(false);
|
|
816
|
+
const containerRef = (0, import_react5.useRef)(null);
|
|
817
|
+
(0, import_react5.useEffect)(() => {
|
|
818
|
+
if (!value) return setSelected([]);
|
|
819
|
+
setSelected(Array.isArray(value) ? value : [value]);
|
|
820
|
+
}, [value]);
|
|
821
|
+
const toggleOpen = () => setOpen((prev) => !prev);
|
|
822
|
+
const closeOnEscape = (event) => event.key === "Escape" && setOpen(false);
|
|
823
|
+
const setValueOnEnter = (event, value2) => event.key === "Enter" && handleChange(value2);
|
|
824
|
+
const chipLabels = selected?.map((s) => options?.find(({ value: value2 }) => value2 === s)).filter(Boolean);
|
|
825
|
+
function handleLabels() {
|
|
826
|
+
if (multiselect) {
|
|
827
|
+
return selected.map((o) => options?.find((option) => option.value === o)?.title).join(", ");
|
|
828
|
+
}
|
|
829
|
+
return options?.find((option) => option.value === selected.join())?.title;
|
|
830
|
+
}
|
|
831
|
+
function handleOnOpenChange(isOpen) {
|
|
832
|
+
if (!multiselect || isOpen) setOpen(isOpen);
|
|
833
|
+
}
|
|
834
|
+
function handleChange(newValue) {
|
|
835
|
+
let newSelected = [];
|
|
836
|
+
setSelected((prev) => {
|
|
837
|
+
newSelected = prev.includes(newValue) ? prev.filter((item) => item !== newValue) : [...prev, newValue];
|
|
838
|
+
return multiselect ? newSelected : [newValue];
|
|
839
|
+
});
|
|
840
|
+
onChange?.(multiselect ? newSelected : newValue);
|
|
841
|
+
}
|
|
842
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
|
|
843
|
+
"div",
|
|
844
|
+
{
|
|
845
|
+
className: cn("flex flex-col space-y-1", className),
|
|
846
|
+
ref: containerRef,
|
|
847
|
+
"data-testid": `${(label ?? id)?.toLowerCase()}-select-element`,
|
|
848
|
+
children: [
|
|
849
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(Label_default, { text: label, className: classNames?.label }),
|
|
850
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
|
|
851
|
+
SelectPrimitive.Root,
|
|
852
|
+
{
|
|
853
|
+
open,
|
|
854
|
+
value: selected.join(","),
|
|
855
|
+
onOpenChange: handleOnOpenChange,
|
|
856
|
+
onValueChange: multiselect ? void 0 : handleChange,
|
|
857
|
+
defaultValue: typeof defaultValue === "string" ? defaultValue : void 0,
|
|
858
|
+
dir: dir === "rtl" ? "rtl" : "ltr",
|
|
859
|
+
...rest,
|
|
860
|
+
children: [
|
|
861
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
|
|
862
|
+
SelectPrimitive.Trigger,
|
|
863
|
+
{
|
|
864
|
+
ref,
|
|
865
|
+
className: cn(
|
|
866
|
+
"group flex h-11 min-w-80 flex-row items-center justify-between gap-3 rounded-lg border px-4 py-3 text-sm font-normal focus:outline-purple-100 disabled:bg-grey-5 data-[placeholder]:text-grey-50 data-[placeholder]:disabled:text-grey-40",
|
|
867
|
+
classNames?.trigger
|
|
868
|
+
),
|
|
869
|
+
children: [
|
|
870
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "truncate", children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
871
|
+
SelectPrimitive.Value,
|
|
872
|
+
{
|
|
873
|
+
placeholder: placeholder ?? "Select an option",
|
|
874
|
+
"aria-label": handleLabels(),
|
|
875
|
+
children: handleLabels()
|
|
876
|
+
}
|
|
877
|
+
) }),
|
|
878
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
879
|
+
import_lucide_react7.ChevronDownIcon,
|
|
880
|
+
{
|
|
881
|
+
className: "transform text-black group-data-[state=open]:rotate-180",
|
|
882
|
+
size: "16"
|
|
883
|
+
}
|
|
884
|
+
)
|
|
885
|
+
]
|
|
886
|
+
}
|
|
887
|
+
),
|
|
888
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(SelectPrimitive.Portal, { container: containerRef.current, children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
889
|
+
SelectPrimitive.Content,
|
|
890
|
+
{
|
|
891
|
+
hideWhenDetached: true,
|
|
892
|
+
className: "z-10 max-h-[var(--radix-select-content-available-height)] w-[var(--radix-select-trigger-width)] overflow-hidden rounded-md bg-white py-2 shadow-lg",
|
|
893
|
+
position: "popper",
|
|
894
|
+
sideOffset: 4,
|
|
895
|
+
onPointerDownOutside: toggleOpen,
|
|
896
|
+
onKeyDown: closeOnEscape,
|
|
897
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(SelectPrimitive.Viewport, { children: [
|
|
898
|
+
multiselect && !!chipLabels?.length && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
899
|
+
SelectPrimitive.Group,
|
|
900
|
+
{
|
|
901
|
+
className: "mb-2 flex flex-row flex-wrap gap-1 px-2",
|
|
902
|
+
"data-testid": "selected-labels",
|
|
903
|
+
children: chipLabels?.map(
|
|
904
|
+
(chip) => chip && /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(Chip_default, { size: "small", variant: "primary", children: [
|
|
905
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { children: chip.title }),
|
|
906
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
907
|
+
import_lucide_react7.X,
|
|
908
|
+
{
|
|
909
|
+
size: 18,
|
|
910
|
+
"data-testid": `chip-remove-${chip.value}`,
|
|
911
|
+
className: "cursor-pointer",
|
|
912
|
+
onClick: () => handleChange(chip.value)
|
|
913
|
+
}
|
|
914
|
+
)
|
|
915
|
+
] }, chip.title)
|
|
916
|
+
)
|
|
917
|
+
}
|
|
918
|
+
),
|
|
919
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(Separator, {}),
|
|
920
|
+
options?.map(({ id: id2, title, value: value2 }) => /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
|
|
921
|
+
SelectPrimitive.Item,
|
|
922
|
+
{
|
|
923
|
+
value: value2,
|
|
924
|
+
className: "group relative cursor-pointer px-4 py-2 text-left text-sm hover:bg-purple-50 focus:bg-purple-50 focus:outline-none data-[state=checked]:bg-purple-50 data-[state=checked]:pr-10 data-[state=checked]:text-purple-100",
|
|
925
|
+
"data-state": selected.includes(value2) ? "checked" : "unchecked",
|
|
926
|
+
onKeyDown: (e) => setValueOnEnter(e, value2),
|
|
927
|
+
onClick: () => handleChange(value2),
|
|
928
|
+
children: [
|
|
929
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(SelectPrimitive.ItemText, { children: title }),
|
|
930
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
931
|
+
import_lucide_react7.CheckIcon,
|
|
932
|
+
{
|
|
933
|
+
className: "absolute inset-y-0 right-3 my-auto hidden w-6 text-purple-100 group-data-[state=checked]:block",
|
|
934
|
+
size: 16
|
|
935
|
+
}
|
|
936
|
+
)
|
|
937
|
+
]
|
|
938
|
+
},
|
|
939
|
+
id2
|
|
940
|
+
))
|
|
941
|
+
] })
|
|
942
|
+
}
|
|
943
|
+
) })
|
|
944
|
+
]
|
|
945
|
+
}
|
|
946
|
+
),
|
|
947
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(ErrorMessage_default, { message: error, className: "mt-1" })
|
|
948
|
+
]
|
|
949
|
+
}
|
|
950
|
+
);
|
|
951
|
+
}
|
|
952
|
+
);
|
|
953
|
+
Select.displayName = "Select";
|
|
954
|
+
var Select_default = Select;
|
|
955
|
+
|
|
956
|
+
// src/components/demos/SelectDemo.tsx
|
|
957
|
+
var import_jsx_runtime15 = require("react/jsx-runtime");
|
|
958
|
+
function SelectDemo() {
|
|
959
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "m-4", children: [
|
|
960
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("h3", { children: "Select" }),
|
|
961
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "flex max-w-sm flex-col gap-4 mt-2", children: [
|
|
962
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
963
|
+
Select_default,
|
|
964
|
+
{
|
|
965
|
+
label: "Label - Singleselect",
|
|
966
|
+
placeholder: "Select an option",
|
|
967
|
+
options: [
|
|
968
|
+
{ id: "1", value: "1", title: "Option 1" },
|
|
969
|
+
{ id: "2", value: "2", title: "Option 2" },
|
|
970
|
+
{ id: "3", value: "3", title: "Option 3" }
|
|
971
|
+
]
|
|
972
|
+
}
|
|
973
|
+
),
|
|
974
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
975
|
+
Select_default,
|
|
976
|
+
{
|
|
977
|
+
multiselect: true,
|
|
978
|
+
label: "Label - Multiselect",
|
|
979
|
+
placeholder: "Select an option",
|
|
980
|
+
options: [
|
|
981
|
+
{ id: "1", value: "1", title: "Option 1" },
|
|
982
|
+
{ id: "2", value: "2", title: "Option 2" },
|
|
983
|
+
{ id: "3", value: "3", title: "Option 3" },
|
|
984
|
+
{ id: "4", value: "4", title: "Option 4" },
|
|
985
|
+
{ id: "5", value: "5", title: "Option 5" },
|
|
986
|
+
{ id: "6", value: "6", title: "Option 6" },
|
|
987
|
+
{ id: "7", value: "7", title: "Option 7" },
|
|
988
|
+
{ id: "8", value: "8", title: "Option 8" },
|
|
989
|
+
{ id: "9", value: "9", title: "Option 9" },
|
|
990
|
+
{ id: "10", value: "10", title: "Option 10" }
|
|
991
|
+
]
|
|
992
|
+
}
|
|
993
|
+
),
|
|
994
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
995
|
+
Select_default,
|
|
996
|
+
{
|
|
997
|
+
disabled: true,
|
|
998
|
+
label: "Label - Disabled",
|
|
999
|
+
placeholder: "Select an option",
|
|
1000
|
+
options: [
|
|
1001
|
+
{ id: "1", value: "1", title: "Option 1" },
|
|
1002
|
+
{ id: "2", value: "2", title: "Option 2" },
|
|
1003
|
+
{ id: "3", value: "3", title: "Option 3" }
|
|
1004
|
+
]
|
|
1005
|
+
}
|
|
1006
|
+
)
|
|
1007
|
+
] })
|
|
1008
|
+
] });
|
|
1009
|
+
}
|
|
1010
|
+
var SelectDemo_default = SelectDemo;
|
|
1011
|
+
|
|
1012
|
+
// src/components/demos/index.tsx
|
|
1013
|
+
var import_jsx_runtime16 = require("react/jsx-runtime");
|
|
772
1014
|
function Demos() {
|
|
773
|
-
return /* @__PURE__ */ (0,
|
|
1015
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { children: [
|
|
1016
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(ComboboxDemo_default, {}),
|
|
1017
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(SelectDemo_default, {})
|
|
1018
|
+
] });
|
|
774
1019
|
}
|
|
775
1020
|
var demos_default = Demos;
|
|
776
1021
|
//# sourceMappingURL=index.cjs.map
|