@addsign/moje-agenda-shared-lib 2.0.66 → 2.0.68

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.
Files changed (58) hide show
  1. package/dist/Calendar-DWT4e7Th.js.map +1 -1
  2. package/dist/Combination-DmhTQmbL.js +996 -0
  3. package/dist/Combination-DmhTQmbL.js.map +1 -0
  4. package/dist/Dialog-3u5-ws89.js +424 -0
  5. package/dist/Dialog-3u5-ws89.js.map +1 -0
  6. package/dist/Dialog-CCrUyF91.js.map +1 -1
  7. package/dist/assets/style.css +3 -3
  8. package/dist/components/datatable/DataTableServer.js +349 -252
  9. package/dist/components/datatable/DataTableServer.js.map +1 -1
  10. package/dist/components/form/FileInputForm.d.ts +14 -0
  11. package/dist/components/form/FileInputForm.js +173 -0
  12. package/dist/components/form/FileInputForm.js.map +1 -0
  13. package/dist/components/form/FileInputFormMultiple.d.ts +16 -0
  14. package/dist/components/form/FileInputFormMultiple.js +240 -0
  15. package/dist/components/form/FileInputFormMultiple.js.map +1 -0
  16. package/dist/components/form/FileInputFull.d.ts +17 -0
  17. package/dist/components/form/FileInputFull.js +188 -0
  18. package/dist/components/form/FileInputFull.js.map +1 -0
  19. package/dist/components/form/FileInputFullMultiple.d.ts +19 -0
  20. package/dist/components/form/FileInputFullMultiple.js +226 -0
  21. package/dist/components/form/FileInputFullMultiple.js.map +1 -0
  22. package/dist/components/ui/Combobox.js.map +1 -1
  23. package/dist/components/ui/checkbox.js.map +1 -1
  24. package/dist/components/ui/command.js.map +1 -1
  25. package/dist/components/ui/multi-select.js.map +1 -1
  26. package/dist/components/ui/radioGroup.js.map +1 -1
  27. package/dist/components/ui/toast.js.map +1 -1
  28. package/dist/handleErrors-B2be_Hgy.js +31615 -0
  29. package/dist/handleErrors-B2be_Hgy.js.map +1 -0
  30. package/dist/handleErrors-P52guX3U.js +32 -0
  31. package/dist/handleErrors-P52guX3U.js.map +1 -0
  32. package/dist/index-BikTN7j8.js +2266 -0
  33. package/dist/index-BikTN7j8.js.map +1 -0
  34. package/dist/main.d.ts +2 -0
  35. package/dist/main.js +34 -30
  36. package/dist/main.js.map +1 -1
  37. package/dist/popover-BLI2Jq-c.js +319 -0
  38. package/dist/popover-BLI2Jq-c.js.map +1 -0
  39. package/dist/popover-CcrzvSk7.js.map +1 -1
  40. package/dist/tslib.es6-e8r3nMQ9.js +172 -0
  41. package/dist/tslib.es6-e8r3nMQ9.js.map +1 -0
  42. package/dist/types.d.ts +1 -0
  43. package/dist/types.js.map +1 -1
  44. package/lib/components/datatable/DataTableServer.tsx +165 -42
  45. package/lib/components/form/FileInputForm.tsx +184 -0
  46. package/lib/components/form/FileInputFormMultiple.tsx +220 -0
  47. package/lib/components/ui/Calendar.tsx +0 -2
  48. package/lib/components/ui/Combobox.tsx +0 -2
  49. package/lib/components/ui/Dialog.tsx +0 -2
  50. package/lib/components/ui/checkbox.tsx +0 -2
  51. package/lib/components/ui/command.tsx +0 -2
  52. package/lib/components/ui/multi-select.tsx +387 -387
  53. package/lib/components/ui/popover.tsx +0 -2
  54. package/lib/components/ui/radioGroup.tsx +0 -2
  55. package/lib/components/ui/toast.tsx +0 -1
  56. package/lib/main.ts +2 -0
  57. package/lib/types.ts +1 -0
  58. package/package.json +1 -2
@@ -1,387 +1,387 @@
1
- // src/components/multi-select.tsx
2
-
3
- import * as React from "react";
4
- import { cva, type VariantProps } from "class-variance-authority";
5
- import { CheckIcon, XCircle, ChevronDown, XIcon } from "lucide-react";
6
-
7
- import { cn } from "../../utils/utils";
8
- import { Separator } from "./separator";
9
- import { Button } from "./button";
10
- import { Badge } from "./badge";
11
- import { Popover, PopoverContent, PopoverTrigger } from "./popover";
12
- import {
13
- Command,
14
- CommandEmpty,
15
- CommandGroup,
16
- CommandInput,
17
- CommandItem,
18
- CommandList,
19
- CommandSeparator,
20
- } from "./command";
21
- import { IOptionItem } from "../../types";
22
-
23
- /**
24
- * Variants for the multi-select component to handle different styles.
25
- * Uses class-variance-authority (cva) to define different styles based on "variant" prop.
26
- */
27
- const multiSelectVariants = cva("m-1 transition ease-in-out delay-150 ", {
28
- variants: {
29
- variant: {
30
- default:
31
- "border-foreground/10 text-foreground bg-card hover:bg-card/80 font-normal",
32
- secondary:
33
- "border-foreground/10 bg-secondary text-secondary-foreground hover:bg-secondary/80 font-normal",
34
- destructive:
35
- "border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80 font-normal",
36
- inverted: "inverted",
37
- },
38
- },
39
- defaultVariants: {
40
- variant: "default",
41
- },
42
- });
43
-
44
- /**
45
- * Props for MultiSelect component
46
- */
47
- interface MultiSelectProps
48
- extends Omit<
49
- React.ButtonHTMLAttributes<HTMLButtonElement>,
50
- "onChange" | "value"
51
- >,
52
- VariantProps<typeof multiSelectVariants> {
53
- /**
54
- * An array of option objects to be displayed in the multi-select component.
55
- * Each option object has a label, value, and an optional icon.
56
- */
57
- options: IOptionItem[];
58
-
59
- /**
60
- * Callback function triggered when the selected values change.
61
- * Receives an array of the new selected values.
62
- */
63
- onChange: (value: string[]) => void;
64
-
65
- /** The controlled value of the component */
66
- value?: string[];
67
-
68
- /** The default selected values when the component mounts (uncontrolled mode) */
69
- defaultValue?: string[];
70
-
71
- /**
72
- * Placeholder text to be displayed when no values are selected.
73
- * Optional, defaults to "Select options".
74
- */
75
- placeholder?: string;
76
-
77
- /**
78
- * Placeholder text to be displayed when no values are selected.
79
- * Optional, defaults to "Select options".
80
- */
81
- placeholderSearch?: string;
82
-
83
- /**
84
- * Maximum number of items to display. Extra selected items will be summarized.
85
- * Optional, defaults to 3.
86
- */
87
- maxCount?: number;
88
-
89
- /**
90
- * The modality of the popover. When set to true, interaction with outside elements
91
- * will be disabled and only popover content will be visible to screen readers.
92
- * Optional, defaults to false.
93
- */
94
- modalPopover?: boolean;
95
-
96
- /**
97
- * If true, renders the multi-select component as a child of another component.
98
- * Optional, defaults to false.
99
- */
100
- asChild?: boolean;
101
-
102
- /**
103
- * Additional class names to apply custom styles to the multi-select component.
104
- * Optional, can be used to add custom styles.
105
- */
106
- className?: string;
107
-
108
- /**
109
- * If true, the multi-select component will be disabled.
110
- * Optional, defaults to false.
111
- */
112
- disabled?: boolean;
113
-
114
- /**
115
- * value?: string;
116
- onChange?: (value: string | undefined) => void;
117
- */
118
- }
119
-
120
- export const MultiSelect = React.forwardRef<
121
- HTMLButtonElement,
122
- MultiSelectProps
123
- >(
124
- (
125
- {
126
- options,
127
- onChange,
128
- value: propValue,
129
- variant,
130
- defaultValue = [],
131
- placeholder = "Vyberte možnosti",
132
- placeholderSearch = "Vyhledejte",
133
- maxCount = 3,
134
- modalPopover = false,
135
- asChild = false,
136
- className,
137
- ...props
138
- },
139
- ref
140
- ) => {
141
- const [selectedValues, setSelectedValues] = React.useState<string[]>(
142
- Array.isArray(propValue) ? propValue : defaultValue || []
143
- );
144
- const [isPopoverOpen, setIsPopoverOpen] = React.useState(false);
145
-
146
- // Update internal state when controlled value changes
147
- React.useEffect(() => {
148
- if (
149
- propValue !== undefined &&
150
- propValue !== null &&
151
- Array.isArray(propValue)
152
- ) {
153
- setSelectedValues(propValue || []);
154
- } else {
155
- setSelectedValues([]);
156
- }
157
- }, [propValue]);
158
-
159
- const handleValueChange = (newValues: string[]) => {
160
- setSelectedValues(newValues ?? []);
161
- onChange(newValues ?? []);
162
- };
163
-
164
- const handleTogglePopover = () => {
165
- setIsPopoverOpen((prev) => !prev);
166
- };
167
-
168
- const toggleOption = (option: string | number | null) => {
169
- if (option === null) return;
170
- const optionStr = String(option);
171
- const newSelectedValues = selectedValues.includes(optionStr)
172
- ? selectedValues.filter((value) => value !== optionStr)
173
- : [...selectedValues, optionStr];
174
- handleValueChange(newSelectedValues);
175
- };
176
-
177
- const handleClear = () => {
178
- handleValueChange([]);
179
- };
180
-
181
- const clearExtraOptions = () => {
182
- const newSelectedValues = selectedValues.slice(0, maxCount);
183
- handleValueChange(newSelectedValues);
184
- };
185
-
186
- const toggleAll = () => {
187
- if (selectedValues.length === options.length) {
188
- handleClear();
189
- } else {
190
- const allValues = options.map((option) => option.value as string);
191
- handleValueChange(allValues);
192
- }
193
- };
194
- console.log("selectedValues", "color: #007acc;", selectedValues);
195
- return (
196
- <Popover
197
- open={isPopoverOpen}
198
- onOpenChange={setIsPopoverOpen}
199
- modal={modalPopover}
200
- >
201
- <PopoverTrigger asChild>
202
- <Button
203
- ref={ref}
204
- {...props}
205
- onClick={handleTogglePopover}
206
- className={cn(
207
- "flex w-full p-1 rounded-md border min-h-10 h-auto items-center justify-between hover:bg-inherit [&_svg]:pointer-events-auto font-normal bg-background text-muted-foreground",
208
- className
209
- )}
210
- >
211
- {selectedValues.length > 0 ? (
212
- <div className="flex justify-between items-center w-full">
213
- <div className="flex flex-wrap items-center">
214
- {maxCount === 0 && selectedValues.length == 1 && (
215
- <span className="px-2">
216
- {
217
- options.find((o) => o.value === selectedValues[0])
218
- ?.label
219
- }
220
- </span>
221
- )}
222
- {maxCount === 0 && selectedValues.length > 1 && (
223
- <span className="px-2">
224
- {`Více (${selectedValues.length})`}
225
- </span>
226
- )}
227
- {maxCount > 0 &&
228
- selectedValues.slice(0, maxCount).map((value) => {
229
- const option = options.find((o) => o.value === value);
230
- return (
231
- <Badge
232
- key={value}
233
- className={cn(multiSelectVariants({ variant }))}
234
- >
235
- {option?.label}
236
- <XCircle
237
- className="ml-2 h-4 w-4 cursor-pointer text-muted-foreground"
238
- onClick={(event) => {
239
- event.stopPropagation();
240
- toggleOption(value);
241
- }}
242
- />
243
- </Badge>
244
- );
245
- })}
246
-
247
- {maxCount > 0 && selectedValues.length > maxCount && (
248
- <Badge
249
- className={cn(
250
- "bg-transparent text-foreground border-foreground/1 hover:bg-transparent",
251
- multiSelectVariants({ variant })
252
- )}
253
- >
254
- {`Více (${selectedValues.length - maxCount})`}
255
- <XCircle
256
- className="ml-2 h-4 w-4 cursor-pointer text-muted-foreground"
257
- onClick={(event) => {
258
- event.stopPropagation();
259
- clearExtraOptions();
260
- }}
261
- />
262
- </Badge>
263
- )}
264
- </div>
265
- <div className="flex items-center justify-between">
266
- <XIcon
267
- className="h-4 mx-2 cursor-pointer text-muted-foreground"
268
- onClick={(event) => {
269
- event.stopPropagation();
270
- handleClear();
271
- }}
272
- />
273
- <Separator
274
- orientation="vertical"
275
- className="flex min-h-6 h-full"
276
- />
277
- <ChevronDown className="h-4 mx-2 cursor-pointer text-muted-foreground" />
278
- </div>
279
- </div>
280
- ) : (
281
- <div className="flex items-center justify-between w-full mx-auto">
282
- <span className="text-sm text-muted-foreground mx-3">
283
- {placeholder}
284
- </span>
285
- <ChevronDown className="h-4 cursor-pointer text-muted-foreground mx-2" />
286
- </div>
287
- )}
288
- </Button>
289
- </PopoverTrigger>
290
- <PopoverContent
291
- className="w-auto p-0"
292
- align="start"
293
- onEscapeKeyDown={() => setIsPopoverOpen(false)}
294
- >
295
- <Command>
296
- <CommandInput
297
- placeholder={placeholderSearch}
298
- onKeyDown={(e: React.KeyboardEvent<HTMLInputElement>) => {
299
- if (e.key === "Enter") {
300
- setIsPopoverOpen(true);
301
- } else if (e.key === "Backspace" && !e.currentTarget.value) {
302
- const newSelectedValues = [...selectedValues];
303
- newSelectedValues.pop();
304
- handleValueChange(newSelectedValues);
305
- }
306
- }}
307
- />
308
- <CommandList>
309
- <CommandEmpty>No results found.</CommandEmpty>
310
- <CommandGroup>
311
- <CommandItem
312
- key="all"
313
- onSelect={toggleAll}
314
- className="cursor-pointer"
315
- >
316
- <div
317
- className={cn(
318
- "mr-2 flex h-4 w-4 items-center justify-center rounded-sm border border-primary",
319
- selectedValues && selectedValues.length === options.length
320
- ? "bg-primary text-primary-foreground"
321
- : "opacity-50 [&_svg]:invisible"
322
- )}
323
- >
324
- <CheckIcon className="h-4 w-4" />
325
- </div>
326
- <span>(Vyberte vše)</span>
327
- </CommandItem>
328
- {options.map((option) => {
329
- const optionStr = String(option.value);
330
- const isSelected =
331
- selectedValues?.includes(optionStr) || false;
332
- return (
333
- <CommandItem
334
- key={optionStr}
335
- onSelect={() => toggleOption(option.value)}
336
- className="cursor-pointer"
337
- >
338
- <div
339
- className={cn(
340
- "mr-2 flex h-4 w-4 items-center justify-center rounded-sm border border-primary",
341
- isSelected
342
- ? "bg-primary text-primary-foreground"
343
- : "opacity-50 [&_svg]:invisible"
344
- )}
345
- >
346
- <CheckIcon className="h-4 w-4" />
347
- </div>
348
-
349
- <span>{option.label}</span>
350
- </CommandItem>
351
- );
352
- })}
353
- </CommandGroup>
354
- <CommandSeparator />
355
- <CommandGroup>
356
- <div className="flex items-center justify-between">
357
- {selectedValues.length > 0 && (
358
- <>
359
- <CommandItem
360
- onSelect={handleClear}
361
- className="flex-1 justify-center cursor-pointer"
362
- >
363
- Odebrat vše
364
- </CommandItem>
365
- <Separator
366
- orientation="vertical"
367
- className="flex min-h-6 h-full"
368
- />
369
- </>
370
- )}
371
- <CommandItem
372
- onSelect={() => setIsPopoverOpen(false)}
373
- className="flex-1 justify-center cursor-pointer max-w-full"
374
- >
375
- Zavřít
376
- </CommandItem>
377
- </div>
378
- </CommandGroup>
379
- </CommandList>
380
- </Command>
381
- </PopoverContent>
382
- </Popover>
383
- );
384
- }
385
- );
386
-
387
- MultiSelect.displayName = "MultiSelect";
1
+ // src/components/multi-select.tsx
2
+
3
+ import * as React from "react";
4
+ import { cva, type VariantProps } from "class-variance-authority";
5
+ import { CheckIcon, XCircle, ChevronDown, XIcon } from "lucide-react";
6
+
7
+ import { cn } from "../../utils/utils";
8
+ import { Separator } from "./separator";
9
+ import { Button } from "./button";
10
+ import { Badge } from "./badge";
11
+ import { Popover, PopoverContent, PopoverTrigger } from "./popover";
12
+ import {
13
+ Command,
14
+ CommandEmpty,
15
+ CommandGroup,
16
+ CommandInput,
17
+ CommandItem,
18
+ CommandList,
19
+ CommandSeparator,
20
+ } from "./command";
21
+ import { IOptionItem } from "../../types";
22
+
23
+ /**
24
+ * Variants for the multi-select component to handle different styles.
25
+ * Uses class-variance-authority (cva) to define different styles based on "variant" prop.
26
+ */
27
+ const multiSelectVariants = cva("m-1 transition ease-in-out delay-150 ", {
28
+ variants: {
29
+ variant: {
30
+ default:
31
+ "border-foreground/10 text-foreground bg-card hover:bg-card/80 font-normal",
32
+ secondary:
33
+ "border-foreground/10 bg-secondary text-secondary-foreground hover:bg-secondary/80 font-normal",
34
+ destructive:
35
+ "border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80 font-normal",
36
+ inverted: "inverted",
37
+ },
38
+ },
39
+ defaultVariants: {
40
+ variant: "default",
41
+ },
42
+ });
43
+
44
+ /**
45
+ * Props for MultiSelect component
46
+ */
47
+ interface MultiSelectProps
48
+ extends Omit<
49
+ React.ButtonHTMLAttributes<HTMLButtonElement>,
50
+ "onChange" | "value"
51
+ >,
52
+ VariantProps<typeof multiSelectVariants> {
53
+ /**
54
+ * An array of option objects to be displayed in the multi-select component.
55
+ * Each option object has a label, value, and an optional icon.
56
+ */
57
+ options: IOptionItem[];
58
+
59
+ /**
60
+ * Callback function triggered when the selected values change.
61
+ * Receives an array of the new selected values.
62
+ */
63
+ onChange: (value: string[]) => void;
64
+
65
+ /** The controlled value of the component */
66
+ value?: string[];
67
+
68
+ /** The default selected values when the component mounts (uncontrolled mode) */
69
+ defaultValue?: string[];
70
+
71
+ /**
72
+ * Placeholder text to be displayed when no values are selected.
73
+ * Optional, defaults to "Select options".
74
+ */
75
+ placeholder?: string;
76
+
77
+ /**
78
+ * Placeholder text to be displayed when no values are selected.
79
+ * Optional, defaults to "Select options".
80
+ */
81
+ placeholderSearch?: string;
82
+
83
+ /**
84
+ * Maximum number of items to display. Extra selected items will be summarized.
85
+ * Optional, defaults to 3.
86
+ */
87
+ maxCount?: number;
88
+
89
+ /**
90
+ * The modality of the popover. When set to true, interaction with outside elements
91
+ * will be disabled and only popover content will be visible to screen readers.
92
+ * Optional, defaults to false.
93
+ */
94
+ modalPopover?: boolean;
95
+
96
+ /**
97
+ * If true, renders the multi-select component as a child of another component.
98
+ * Optional, defaults to false.
99
+ */
100
+ asChild?: boolean;
101
+
102
+ /**
103
+ * Additional class names to apply custom styles to the multi-select component.
104
+ * Optional, can be used to add custom styles.
105
+ */
106
+ className?: string;
107
+
108
+ /**
109
+ * If true, the multi-select component will be disabled.
110
+ * Optional, defaults to false.
111
+ */
112
+ disabled?: boolean;
113
+
114
+ /**
115
+ * value?: string;
116
+ onChange?: (value: string | undefined) => void;
117
+ */
118
+ }
119
+
120
+ export const MultiSelect = React.forwardRef<
121
+ HTMLButtonElement,
122
+ MultiSelectProps
123
+ >(
124
+ (
125
+ {
126
+ options,
127
+ onChange,
128
+ value: propValue,
129
+ variant,
130
+ defaultValue = [],
131
+ placeholder = "Vyberte možnosti",
132
+ placeholderSearch = "Vyhledejte",
133
+ maxCount = 3,
134
+ modalPopover = false,
135
+ asChild = false,
136
+ className,
137
+ ...props
138
+ },
139
+ ref
140
+ ) => {
141
+ const [selectedValues, setSelectedValues] = React.useState<string[]>(
142
+ Array.isArray(propValue) ? propValue : defaultValue || []
143
+ );
144
+ const [isPopoverOpen, setIsPopoverOpen] = React.useState(false);
145
+
146
+ // Update internal state when controlled value changes
147
+ React.useEffect(() => {
148
+ if (
149
+ propValue !== undefined &&
150
+ propValue !== null &&
151
+ Array.isArray(propValue)
152
+ ) {
153
+ setSelectedValues(propValue || []);
154
+ } else {
155
+ setSelectedValues([]);
156
+ }
157
+ }, [propValue]);
158
+
159
+ const handleValueChange = (newValues: string[]) => {
160
+ setSelectedValues(newValues ?? []);
161
+ onChange(newValues ?? []);
162
+ };
163
+
164
+ const handleTogglePopover = () => {
165
+ setIsPopoverOpen((prev) => !prev);
166
+ };
167
+
168
+ const toggleOption = (option: string | number | null) => {
169
+ if (option === null) return;
170
+ const optionStr = String(option);
171
+ const newSelectedValues = selectedValues.includes(optionStr)
172
+ ? selectedValues.filter((value) => value !== optionStr)
173
+ : [...selectedValues, optionStr];
174
+ handleValueChange(newSelectedValues);
175
+ };
176
+
177
+ const handleClear = () => {
178
+ handleValueChange([]);
179
+ };
180
+
181
+ const clearExtraOptions = () => {
182
+ const newSelectedValues = selectedValues.slice(0, maxCount);
183
+ handleValueChange(newSelectedValues);
184
+ };
185
+
186
+ const toggleAll = () => {
187
+ if (selectedValues.length === options.length) {
188
+ handleClear();
189
+ } else {
190
+ const allValues = options.map((option) => option.value as string);
191
+ handleValueChange(allValues);
192
+ }
193
+ };
194
+ console.log("selectedValues", "color: #007acc;", selectedValues);
195
+ return (
196
+ <Popover
197
+ open={isPopoverOpen}
198
+ onOpenChange={setIsPopoverOpen}
199
+ modal={modalPopover}
200
+ >
201
+ <PopoverTrigger asChild>
202
+ <Button
203
+ ref={ref}
204
+ {...props}
205
+ onClick={handleTogglePopover}
206
+ className={cn(
207
+ "flex w-full p-1 rounded-md border min-h-10 h-auto items-center justify-between hover:bg-inherit [&_svg]:pointer-events-auto font-normal bg-background text-muted-foreground",
208
+ className
209
+ )}
210
+ >
211
+ {selectedValues.length > 0 ? (
212
+ <div className="flex justify-between items-center w-full">
213
+ <div className="flex flex-wrap items-center">
214
+ {maxCount === 0 && selectedValues.length == 1 && (
215
+ <span className="px-2">
216
+ {
217
+ options.find((o) => o.value === selectedValues[0])
218
+ ?.label
219
+ }
220
+ </span>
221
+ )}
222
+ {maxCount === 0 && selectedValues.length > 1 && (
223
+ <span className="px-2">
224
+ {`Více (${selectedValues.length})`}
225
+ </span>
226
+ )}
227
+ {maxCount > 0 &&
228
+ selectedValues.slice(0, maxCount).map((value) => {
229
+ const option = options.find((o) => o.value === value);
230
+ return (
231
+ <Badge
232
+ key={value}
233
+ className={cn(multiSelectVariants({ variant }))}
234
+ >
235
+ {option?.label}
236
+ <XCircle
237
+ className="ml-2 h-4 w-4 cursor-pointer text-muted-foreground"
238
+ onClick={(event) => {
239
+ event.stopPropagation();
240
+ toggleOption(value);
241
+ }}
242
+ />
243
+ </Badge>
244
+ );
245
+ })}
246
+
247
+ {maxCount > 0 && selectedValues.length > maxCount && (
248
+ <Badge
249
+ className={cn(
250
+ "bg-transparent text-foreground border-foreground/1 hover:bg-transparent",
251
+ multiSelectVariants({ variant })
252
+ )}
253
+ >
254
+ {`Více (${selectedValues.length - maxCount})`}
255
+ <XCircle
256
+ className="ml-2 h-4 w-4 cursor-pointer text-muted-foreground"
257
+ onClick={(event) => {
258
+ event.stopPropagation();
259
+ clearExtraOptions();
260
+ }}
261
+ />
262
+ </Badge>
263
+ )}
264
+ </div>
265
+ <div className="flex items-center justify-between">
266
+ <XIcon
267
+ className="h-4 mx-2 cursor-pointer text-muted-foreground"
268
+ onClick={(event) => {
269
+ event.stopPropagation();
270
+ handleClear();
271
+ }}
272
+ />
273
+ <Separator
274
+ orientation="vertical"
275
+ className="flex min-h-6 h-full"
276
+ />
277
+ <ChevronDown className="h-4 mx-2 cursor-pointer text-muted-foreground" />
278
+ </div>
279
+ </div>
280
+ ) : (
281
+ <div className="flex items-center justify-between w-full mx-auto">
282
+ <span className="text-sm text-muted-foreground mx-3">
283
+ {placeholder}
284
+ </span>
285
+ <ChevronDown className="h-4 cursor-pointer text-muted-foreground mx-2" />
286
+ </div>
287
+ )}
288
+ </Button>
289
+ </PopoverTrigger>
290
+ <PopoverContent
291
+ className="w-auto p-0"
292
+ align="start"
293
+ onEscapeKeyDown={() => setIsPopoverOpen(false)}
294
+ >
295
+ <Command>
296
+ <CommandInput
297
+ placeholder={placeholderSearch}
298
+ onKeyDown={(e: React.KeyboardEvent<HTMLInputElement>) => {
299
+ if (e.key === "Enter") {
300
+ setIsPopoverOpen(true);
301
+ } else if (e.key === "Backspace" && !e.currentTarget.value) {
302
+ const newSelectedValues = [...selectedValues];
303
+ newSelectedValues.pop();
304
+ handleValueChange(newSelectedValues);
305
+ }
306
+ }}
307
+ />
308
+ <CommandList>
309
+ <CommandEmpty>No results found.</CommandEmpty>
310
+ <CommandGroup>
311
+ <CommandItem
312
+ key="all"
313
+ onSelect={toggleAll}
314
+ className="cursor-pointer"
315
+ >
316
+ <div
317
+ className={cn(
318
+ "mr-2 flex h-4 w-4 items-center justify-center rounded-sm border border-primary",
319
+ selectedValues && selectedValues.length === options.length
320
+ ? "bg-primary text-primary-foreground"
321
+ : "opacity-50 [&_svg]:invisible"
322
+ )}
323
+ >
324
+ <CheckIcon className="h-4 w-4" />
325
+ </div>
326
+ <span>(Vyberte vše)</span>
327
+ </CommandItem>
328
+ {options.map((option) => {
329
+ const optionStr = String(option.value);
330
+ const isSelected =
331
+ selectedValues?.includes(optionStr) || false;
332
+ return (
333
+ <CommandItem
334
+ key={optionStr}
335
+ onSelect={() => toggleOption(option.value)}
336
+ className="cursor-pointer"
337
+ >
338
+ <div
339
+ className={cn(
340
+ "mr-2 flex h-4 w-4 items-center justify-center rounded-sm border border-primary",
341
+ isSelected
342
+ ? "bg-primary text-primary-foreground"
343
+ : "opacity-50 [&_svg]:invisible"
344
+ )}
345
+ >
346
+ <CheckIcon className="h-4 w-4" />
347
+ </div>
348
+
349
+ <span>{option.label}</span>
350
+ </CommandItem>
351
+ );
352
+ })}
353
+ </CommandGroup>
354
+ <CommandSeparator />
355
+ <CommandGroup>
356
+ <div className="flex items-center justify-between">
357
+ {selectedValues.length > 0 && (
358
+ <>
359
+ <CommandItem
360
+ onSelect={handleClear}
361
+ className="flex-1 justify-center cursor-pointer"
362
+ >
363
+ Odebrat vše
364
+ </CommandItem>
365
+ <Separator
366
+ orientation="vertical"
367
+ className="flex min-h-6 h-full"
368
+ />
369
+ </>
370
+ )}
371
+ <CommandItem
372
+ onSelect={() => setIsPopoverOpen(false)}
373
+ className="flex-1 justify-center cursor-pointer max-w-full"
374
+ >
375
+ Zavřít
376
+ </CommandItem>
377
+ </div>
378
+ </CommandGroup>
379
+ </CommandList>
380
+ </Command>
381
+ </PopoverContent>
382
+ </Popover>
383
+ );
384
+ }
385
+ );
386
+
387
+ MultiSelect.displayName = "MultiSelect";