@page-speed/forms 0.4.4 → 0.4.6
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/README.md +158 -616
- package/dist/core.cjs +103 -10
- package/dist/core.cjs.map +1 -1
- package/dist/core.d.cts +15 -4
- package/dist/core.d.ts +15 -4
- package/dist/core.js +104 -12
- package/dist/core.js.map +1 -1
- package/dist/index.cjs +103 -10
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +104 -12
- package/dist/index.js.map +1 -1
- package/dist/inputs.cjs +582 -189
- package/dist/inputs.cjs.map +1 -1
- package/dist/inputs.d.cts +143 -2
- package/dist/inputs.d.ts +143 -2
- package/dist/inputs.js +581 -189
- package/dist/inputs.js.map +1 -1
- package/dist/{types-BBif0kuP.d.cts → types-4ppM117e.d.cts} +53 -1
- package/dist/{types-BBif0kuP.d.ts → types-4ppM117e.d.ts} +53 -1
- package/dist/validation-rules.d.cts +1 -1
- package/dist/validation-rules.d.ts +1 -1
- package/dist/validation-utils.d.cts +1 -1
- package/dist/validation-utils.d.ts +1 -1
- package/dist/validation-valibot.d.cts +1 -1
- package/dist/validation-valibot.d.ts +1 -1
- package/dist/validation.d.cts +1 -1
- package/dist/validation.d.ts +1 -1
- package/package.json +2 -2
package/dist/inputs.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as React9 from 'react';
|
|
2
2
|
import { clsx } from 'clsx';
|
|
3
3
|
import { twMerge } from 'tailwind-merge';
|
|
4
4
|
import { useOnClickOutside } from '@opensite/hooks/useOnClickOutside';
|
|
@@ -40,7 +40,7 @@ function TextInput({
|
|
|
40
40
|
error && "border-destructive ring-1 ring-destructive",
|
|
41
41
|
className
|
|
42
42
|
);
|
|
43
|
-
return /* @__PURE__ */
|
|
43
|
+
return /* @__PURE__ */ React9.createElement(
|
|
44
44
|
"input",
|
|
45
45
|
{
|
|
46
46
|
type,
|
|
@@ -94,7 +94,7 @@ function TextArea({
|
|
|
94
94
|
error && "border-destructive ring-1 ring-destructive",
|
|
95
95
|
className
|
|
96
96
|
);
|
|
97
|
-
return /* @__PURE__ */
|
|
97
|
+
return /* @__PURE__ */ React9.createElement(
|
|
98
98
|
"textarea",
|
|
99
99
|
{
|
|
100
100
|
name,
|
|
@@ -133,11 +133,11 @@ var LabelGroup = ({
|
|
|
133
133
|
variant === "legend" ? "mb-1.5" : "mb-1 block",
|
|
134
134
|
primaryClassName
|
|
135
135
|
);
|
|
136
|
-
const requiredIndicator = required ? /* @__PURE__ */
|
|
136
|
+
const requiredIndicator = required ? /* @__PURE__ */ React9.createElement("span", { className: "text-destructive pl-0.5", "aria-label": "required" }, "*") : null;
|
|
137
137
|
let primaryElement = null;
|
|
138
138
|
if (primary) {
|
|
139
139
|
if (variant === "label") {
|
|
140
|
-
primaryElement = /* @__PURE__ */
|
|
140
|
+
primaryElement = /* @__PURE__ */ React9.createElement(
|
|
141
141
|
"label",
|
|
142
142
|
{
|
|
143
143
|
htmlFor: labelHtmlFor,
|
|
@@ -148,12 +148,12 @@ var LabelGroup = ({
|
|
|
148
148
|
requiredIndicator
|
|
149
149
|
);
|
|
150
150
|
} else if (variant === "legend") {
|
|
151
|
-
primaryElement = /* @__PURE__ */
|
|
151
|
+
primaryElement = /* @__PURE__ */ React9.createElement("legend", { "data-slot": "field-legend", className: primaryClasses }, primary, requiredIndicator);
|
|
152
152
|
} else {
|
|
153
|
-
primaryElement = /* @__PURE__ */
|
|
153
|
+
primaryElement = /* @__PURE__ */ React9.createElement("div", { "data-slot": "field-label", className: primaryClasses }, primary, requiredIndicator);
|
|
154
154
|
}
|
|
155
155
|
}
|
|
156
|
-
const secondaryElement = secondary ? /* @__PURE__ */
|
|
156
|
+
const secondaryElement = secondary ? /* @__PURE__ */ React9.createElement(
|
|
157
157
|
"p",
|
|
158
158
|
{
|
|
159
159
|
"data-slot": "field-description",
|
|
@@ -163,7 +163,10 @@ var LabelGroup = ({
|
|
|
163
163
|
secondary
|
|
164
164
|
) : null;
|
|
165
165
|
if (!primaryElement && !secondaryElement) return null;
|
|
166
|
-
|
|
166
|
+
if (variant === "legend") {
|
|
167
|
+
return /* @__PURE__ */ React9.createElement(React9.Fragment, null, primaryElement, secondaryElement);
|
|
168
|
+
}
|
|
169
|
+
return /* @__PURE__ */ React9.createElement("div", { className: "flex flex-1 flex-col gap-0.5" }, primaryElement, secondaryElement);
|
|
167
170
|
};
|
|
168
171
|
|
|
169
172
|
// src/inputs/Checkbox.tsx
|
|
@@ -182,9 +185,9 @@ function Checkbox({
|
|
|
182
185
|
useChoiceCard = false,
|
|
183
186
|
...props
|
|
184
187
|
}) {
|
|
185
|
-
const inputRef =
|
|
188
|
+
const inputRef = React9.useRef(null);
|
|
186
189
|
const checkboxId = props.id || `checkbox-${name}`;
|
|
187
|
-
|
|
190
|
+
React9.useEffect(() => {
|
|
188
191
|
if (inputRef.current) {
|
|
189
192
|
inputRef.current.indeterminate = indeterminate;
|
|
190
193
|
}
|
|
@@ -196,7 +199,7 @@ function Checkbox({
|
|
|
196
199
|
onBlur?.();
|
|
197
200
|
};
|
|
198
201
|
const isActive = value || indeterminate && !value;
|
|
199
|
-
const checkbox = /* @__PURE__ */
|
|
202
|
+
const checkbox = /* @__PURE__ */ React9.createElement(
|
|
200
203
|
"div",
|
|
201
204
|
{
|
|
202
205
|
className: cn(
|
|
@@ -204,7 +207,7 @@ function Checkbox({
|
|
|
204
207
|
!label && className
|
|
205
208
|
)
|
|
206
209
|
},
|
|
207
|
-
/* @__PURE__ */
|
|
210
|
+
/* @__PURE__ */ React9.createElement(
|
|
208
211
|
"input",
|
|
209
212
|
{
|
|
210
213
|
ref: inputRef,
|
|
@@ -223,7 +226,7 @@ function Checkbox({
|
|
|
223
226
|
...props
|
|
224
227
|
}
|
|
225
228
|
),
|
|
226
|
-
/* @__PURE__ */
|
|
229
|
+
/* @__PURE__ */ React9.createElement(
|
|
227
230
|
"div",
|
|
228
231
|
{
|
|
229
232
|
className: cn(
|
|
@@ -236,7 +239,7 @@ function Checkbox({
|
|
|
236
239
|
"peer-focus-visible:ring-2 peer-focus-visible:ring-ring/50 peer-focus-visible:ring-offset-1"
|
|
237
240
|
)
|
|
238
241
|
},
|
|
239
|
-
value && /* @__PURE__ */
|
|
242
|
+
value && /* @__PURE__ */ React9.createElement(
|
|
240
243
|
"svg",
|
|
241
244
|
{
|
|
242
245
|
className: "size-3.5",
|
|
@@ -247,9 +250,9 @@ function Checkbox({
|
|
|
247
250
|
strokeLinecap: "round",
|
|
248
251
|
strokeLinejoin: "round"
|
|
249
252
|
},
|
|
250
|
-
/* @__PURE__ */
|
|
253
|
+
/* @__PURE__ */ React9.createElement("polyline", { points: "20 6 9 17 4 12" })
|
|
251
254
|
),
|
|
252
|
-
indeterminate && !value && /* @__PURE__ */
|
|
255
|
+
indeterminate && !value && /* @__PURE__ */ React9.createElement(
|
|
253
256
|
"svg",
|
|
254
257
|
{
|
|
255
258
|
className: "size-3.5",
|
|
@@ -260,12 +263,12 @@ function Checkbox({
|
|
|
260
263
|
strokeLinecap: "round",
|
|
261
264
|
strokeLinejoin: "round"
|
|
262
265
|
},
|
|
263
|
-
/* @__PURE__ */
|
|
266
|
+
/* @__PURE__ */ React9.createElement("line", { x1: "5", y1: "12", x2: "19", y2: "12" })
|
|
264
267
|
)
|
|
265
268
|
)
|
|
266
269
|
);
|
|
267
270
|
if (label) {
|
|
268
|
-
return /* @__PURE__ */
|
|
271
|
+
return /* @__PURE__ */ React9.createElement(
|
|
269
272
|
"label",
|
|
270
273
|
{
|
|
271
274
|
className: cn(
|
|
@@ -277,7 +280,7 @@ function Checkbox({
|
|
|
277
280
|
),
|
|
278
281
|
htmlFor: checkboxId
|
|
279
282
|
},
|
|
280
|
-
/* @__PURE__ */
|
|
283
|
+
/* @__PURE__ */ React9.createElement(
|
|
281
284
|
"div",
|
|
282
285
|
{
|
|
283
286
|
className: cn(
|
|
@@ -286,7 +289,7 @@ function Checkbox({
|
|
|
286
289
|
)
|
|
287
290
|
},
|
|
288
291
|
checkbox,
|
|
289
|
-
/* @__PURE__ */
|
|
292
|
+
/* @__PURE__ */ React9.createElement(
|
|
290
293
|
LabelGroup,
|
|
291
294
|
{
|
|
292
295
|
variant: "text",
|
|
@@ -331,11 +334,11 @@ function CheckboxGroup({
|
|
|
331
334
|
).length;
|
|
332
335
|
const allSelected = selectedEnabledCount === enabledOptions.length;
|
|
333
336
|
const someSelected = selectedEnabledCount > 0 && !allSelected;
|
|
334
|
-
const useChoiceCard =
|
|
337
|
+
const useChoiceCard = React9.useMemo(() => {
|
|
335
338
|
if (!options) return false;
|
|
336
339
|
return options?.some((opt) => opt.description);
|
|
337
340
|
}, [options]);
|
|
338
|
-
const countableValue =
|
|
341
|
+
const countableValue = React9.useMemo(() => {
|
|
339
342
|
if (value?.length > 0) {
|
|
340
343
|
return value.length;
|
|
341
344
|
}
|
|
@@ -360,7 +363,7 @@ function CheckboxGroup({
|
|
|
360
363
|
onBlur?.();
|
|
361
364
|
};
|
|
362
365
|
const maxReached = Boolean(maxSelections && countableValue >= maxSelections);
|
|
363
|
-
const containerClass =
|
|
366
|
+
const containerClass = React9.useMemo(() => {
|
|
364
367
|
return cn(
|
|
365
368
|
"w-full gap-3 grid grid-cols-1 border-0 m-0 p-0 min-w-0",
|
|
366
369
|
(layout === "grid" || layout === "inline") && "md:grid-cols-2",
|
|
@@ -369,7 +372,7 @@ function CheckboxGroup({
|
|
|
369
372
|
}, [layout, className]);
|
|
370
373
|
const groupDescriptionId = description ? `${name}-description` : void 0;
|
|
371
374
|
const groupAriaDescribedBy = [props["aria-describedby"], groupDescriptionId].filter(Boolean).join(" ") || void 0;
|
|
372
|
-
return /* @__PURE__ */
|
|
375
|
+
return /* @__PURE__ */ React9.createElement(
|
|
373
376
|
"fieldset",
|
|
374
377
|
{
|
|
375
378
|
className: containerClass,
|
|
@@ -379,7 +382,7 @@ function CheckboxGroup({
|
|
|
379
382
|
"aria-required": required || props["aria-required"],
|
|
380
383
|
"aria-label": typeof label === "string" ? label : props["aria-label"]
|
|
381
384
|
},
|
|
382
|
-
/* @__PURE__ */
|
|
385
|
+
/* @__PURE__ */ React9.createElement(
|
|
383
386
|
LabelGroup,
|
|
384
387
|
{
|
|
385
388
|
labelHtmlFor: name,
|
|
@@ -390,7 +393,7 @@ function CheckboxGroup({
|
|
|
390
393
|
primary: label
|
|
391
394
|
}
|
|
392
395
|
),
|
|
393
|
-
showSelectAll && enabledOptions.length > 0 && /* @__PURE__ */
|
|
396
|
+
showSelectAll && enabledOptions.length > 0 && /* @__PURE__ */ React9.createElement(
|
|
394
397
|
Checkbox,
|
|
395
398
|
{
|
|
396
399
|
name: `${name}-select-all`,
|
|
@@ -408,7 +411,7 @@ function CheckboxGroup({
|
|
|
408
411
|
options.map((option) => {
|
|
409
412
|
const isChecked = value.includes(option.value);
|
|
410
413
|
const isDisabled = disabled || option.disabled || maxReached && !isChecked;
|
|
411
|
-
return /* @__PURE__ */
|
|
414
|
+
return /* @__PURE__ */ React9.createElement(
|
|
412
415
|
Checkbox,
|
|
413
416
|
{
|
|
414
417
|
key: option.value,
|
|
@@ -426,7 +429,7 @@ function CheckboxGroup({
|
|
|
426
429
|
}
|
|
427
430
|
);
|
|
428
431
|
}),
|
|
429
|
-
(minSelections || maxSelections) && /* @__PURE__ */
|
|
432
|
+
(minSelections || maxSelections) && /* @__PURE__ */ React9.createElement(
|
|
430
433
|
"div",
|
|
431
434
|
{
|
|
432
435
|
className: cn(
|
|
@@ -435,8 +438,8 @@ function CheckboxGroup({
|
|
|
435
438
|
),
|
|
436
439
|
"aria-live": "polite"
|
|
437
440
|
},
|
|
438
|
-
minSelections && countableValue < minSelections && /* @__PURE__ */
|
|
439
|
-
maxSelections && /* @__PURE__ */
|
|
441
|
+
minSelections && countableValue < minSelections && /* @__PURE__ */ React9.createElement("span", null, "Select at least ", minSelections, " option", minSelections !== 1 ? "s" : ""),
|
|
442
|
+
maxSelections && /* @__PURE__ */ React9.createElement("span", null, countableValue, "/", maxSelections, " selected")
|
|
440
443
|
)
|
|
441
444
|
);
|
|
442
445
|
}
|
|
@@ -487,10 +490,10 @@ function Radio({
|
|
|
487
490
|
const handleBlur = () => {
|
|
488
491
|
onBlur?.();
|
|
489
492
|
};
|
|
490
|
-
const useChoiceCard =
|
|
493
|
+
const useChoiceCard = React9.useMemo(() => {
|
|
491
494
|
return options.some((option) => option.description);
|
|
492
495
|
}, [options]);
|
|
493
|
-
const containerClass =
|
|
496
|
+
const containerClass = React9.useMemo(() => {
|
|
494
497
|
return cn(
|
|
495
498
|
"w-full gap-3 grid grid-cols-1 border-0 m-0 p-0 min-w-0",
|
|
496
499
|
(layout === "grid" || layout === "inline") && "md:grid-cols-2",
|
|
@@ -499,7 +502,7 @@ function Radio({
|
|
|
499
502
|
}, [layout, className]);
|
|
500
503
|
const groupDescriptionId = description ? `${name}-description` : void 0;
|
|
501
504
|
const groupAriaDescribedBy = [props["aria-describedby"], groupDescriptionId].filter(Boolean).join(" ") || void 0;
|
|
502
|
-
return /* @__PURE__ */
|
|
505
|
+
return /* @__PURE__ */ React9.createElement(
|
|
503
506
|
"fieldset",
|
|
504
507
|
{
|
|
505
508
|
className: containerClass,
|
|
@@ -509,7 +512,7 @@ function Radio({
|
|
|
509
512
|
"aria-required": required || props["aria-required"],
|
|
510
513
|
"aria-label": typeof label === "string" ? label : props["aria-label"]
|
|
511
514
|
},
|
|
512
|
-
/* @__PURE__ */
|
|
515
|
+
/* @__PURE__ */ React9.createElement(
|
|
513
516
|
LabelGroup,
|
|
514
517
|
{
|
|
515
518
|
variant: "legend",
|
|
@@ -523,7 +526,7 @@ function Radio({
|
|
|
523
526
|
const isDisabled = disabled || option.disabled;
|
|
524
527
|
const radioId = `${name}-${option.value}`;
|
|
525
528
|
const hasDescription = option.description != null && option.description !== "";
|
|
526
|
-
const radioIndicator = /* @__PURE__ */
|
|
529
|
+
const radioIndicator = /* @__PURE__ */ React9.createElement("div", { className: "relative inline-flex items-center justify-center" }, /* @__PURE__ */ React9.createElement(
|
|
527
530
|
"input",
|
|
528
531
|
{
|
|
529
532
|
type: "radio",
|
|
@@ -538,7 +541,7 @@ function Radio({
|
|
|
538
541
|
className: "peer sr-only",
|
|
539
542
|
"aria-describedby": hasDescription ? `${radioId}-description` : props["aria-describedby"]
|
|
540
543
|
}
|
|
541
|
-
), /* @__PURE__ */
|
|
544
|
+
), /* @__PURE__ */ React9.createElement(
|
|
542
545
|
"div",
|
|
543
546
|
{
|
|
544
547
|
className: cn(
|
|
@@ -551,9 +554,9 @@ function Radio({
|
|
|
551
554
|
"peer-focus-visible:ring-2 peer-focus-visible:ring-ring/50 peer-focus-visible:ring-offset-1"
|
|
552
555
|
)
|
|
553
556
|
},
|
|
554
|
-
isChecked && /* @__PURE__ */
|
|
557
|
+
isChecked && /* @__PURE__ */ React9.createElement("div", { className: "size-3 rounded-full bg-primary" })
|
|
555
558
|
));
|
|
556
|
-
const labelContent = /* @__PURE__ */
|
|
559
|
+
const labelContent = /* @__PURE__ */ React9.createElement(
|
|
557
560
|
LabelGroup,
|
|
558
561
|
{
|
|
559
562
|
variant: "text",
|
|
@@ -564,7 +567,7 @@ function Radio({
|
|
|
564
567
|
secondaryClassName: "text-xs opacity-75"
|
|
565
568
|
}
|
|
566
569
|
);
|
|
567
|
-
return /* @__PURE__ */
|
|
570
|
+
return /* @__PURE__ */ React9.createElement(
|
|
568
571
|
"label",
|
|
569
572
|
{
|
|
570
573
|
key: option.value,
|
|
@@ -578,7 +581,7 @@ function Radio({
|
|
|
578
581
|
onKeyDown: (e) => handleKeyDown(e, index),
|
|
579
582
|
tabIndex: isDisabled ? -1 : 0
|
|
580
583
|
},
|
|
581
|
-
/* @__PURE__ */
|
|
584
|
+
/* @__PURE__ */ React9.createElement(
|
|
582
585
|
"div",
|
|
583
586
|
{
|
|
584
587
|
className: cn(
|
|
@@ -587,7 +590,7 @@ function Radio({
|
|
|
587
590
|
)
|
|
588
591
|
},
|
|
589
592
|
!useChoiceCard && radioIndicator,
|
|
590
|
-
|
|
593
|
+
labelContent,
|
|
591
594
|
useChoiceCard && radioIndicator
|
|
592
595
|
)
|
|
593
596
|
);
|
|
@@ -614,19 +617,20 @@ function Select({
|
|
|
614
617
|
renderOption,
|
|
615
618
|
...props
|
|
616
619
|
}) {
|
|
617
|
-
const [isOpen, setIsOpen] =
|
|
618
|
-
const [searchQuery, setSearchQuery] =
|
|
619
|
-
const [focusedIndex, setFocusedIndex] =
|
|
620
|
-
const
|
|
621
|
-
const
|
|
620
|
+
const [isOpen, setIsOpen] = React9.useState(false);
|
|
621
|
+
const [searchQuery, setSearchQuery] = React9.useState("");
|
|
622
|
+
const [focusedIndex, setFocusedIndex] = React9.useState(-1);
|
|
623
|
+
const triggerRef = React9.useRef(null);
|
|
624
|
+
const dropdownRef = React9.useRef(null);
|
|
625
|
+
const searchInputRef = React9.useRef(null);
|
|
622
626
|
const dropdownId = `${name}-dropdown`;
|
|
623
|
-
const allOptions =
|
|
627
|
+
const allOptions = React9.useMemo(() => {
|
|
624
628
|
if (optionGroups.length > 0) {
|
|
625
629
|
return optionGroups.flatMap((group) => group.options);
|
|
626
630
|
}
|
|
627
631
|
return options;
|
|
628
632
|
}, [options, optionGroups]);
|
|
629
|
-
const filteredOptions =
|
|
633
|
+
const filteredOptions = React9.useMemo(() => {
|
|
630
634
|
if (!searchQuery.trim()) {
|
|
631
635
|
return allOptions;
|
|
632
636
|
}
|
|
@@ -636,7 +640,7 @@ function Select({
|
|
|
636
640
|
return label.toLowerCase().includes(query);
|
|
637
641
|
});
|
|
638
642
|
}, [allOptions, searchQuery]);
|
|
639
|
-
const selectedOption =
|
|
643
|
+
const selectedOption = React9.useMemo(() => {
|
|
640
644
|
return allOptions.find((opt) => opt.value === value);
|
|
641
645
|
}, [allOptions, value]);
|
|
642
646
|
const hasValue = Boolean(value);
|
|
@@ -736,28 +740,29 @@ function Select({
|
|
|
736
740
|
};
|
|
737
741
|
const handleBlur = (event) => {
|
|
738
742
|
const nextTarget = event?.relatedTarget;
|
|
739
|
-
|
|
743
|
+
const focusStayedInside = !!triggerRef.current && triggerRef.current.contains(nextTarget) || !!dropdownRef.current && dropdownRef.current.contains(nextTarget);
|
|
744
|
+
if (!nextTarget || !focusStayedInside) {
|
|
740
745
|
onBlur?.();
|
|
741
746
|
}
|
|
742
747
|
};
|
|
743
|
-
const closeDropdown =
|
|
744
|
-
if (!isOpen) return;
|
|
748
|
+
const closeDropdown = React9.useCallback(() => {
|
|
745
749
|
setIsOpen(false);
|
|
746
750
|
setSearchQuery("");
|
|
747
751
|
setFocusedIndex(-1);
|
|
748
752
|
onBlur?.();
|
|
749
|
-
}, [
|
|
750
|
-
useOnClickOutside(
|
|
753
|
+
}, [onBlur]);
|
|
754
|
+
useOnClickOutside([triggerRef, dropdownRef], closeDropdown, void 0, {
|
|
755
|
+
capture: true
|
|
756
|
+
});
|
|
751
757
|
const combinedClassName = cn("relative w-full", className);
|
|
752
|
-
return /* @__PURE__ */
|
|
758
|
+
return /* @__PURE__ */ React9.createElement(
|
|
753
759
|
"div",
|
|
754
760
|
{
|
|
755
|
-
ref: selectRef,
|
|
756
761
|
className: combinedClassName,
|
|
757
762
|
onKeyDown: handleKeyDown,
|
|
758
763
|
onBlur: handleBlur
|
|
759
764
|
},
|
|
760
|
-
/* @__PURE__ */
|
|
765
|
+
/* @__PURE__ */ React9.createElement(
|
|
761
766
|
"select",
|
|
762
767
|
{
|
|
763
768
|
name,
|
|
@@ -770,12 +775,13 @@ function Select({
|
|
|
770
775
|
tabIndex: -1,
|
|
771
776
|
style: { display: "none" }
|
|
772
777
|
},
|
|
773
|
-
/* @__PURE__ */
|
|
774
|
-
allOptions.map((option) => /* @__PURE__ */
|
|
778
|
+
/* @__PURE__ */ React9.createElement("option", { value: "" }, "Select..."),
|
|
779
|
+
allOptions.map((option) => /* @__PURE__ */ React9.createElement("option", { key: option.value, value: option.value }, typeof option.label === "string" ? option.label : option.value))
|
|
775
780
|
),
|
|
776
|
-
/* @__PURE__ */
|
|
781
|
+
/* @__PURE__ */ React9.createElement(
|
|
777
782
|
"div",
|
|
778
783
|
{
|
|
784
|
+
ref: triggerRef,
|
|
779
785
|
className: cn(
|
|
780
786
|
"flex h-9 w-full items-center justify-between whitespace-nowrap rounded-md border border-input bg-transparent px-3 py-2 text-sm shadow-sm",
|
|
781
787
|
"cursor-pointer transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring",
|
|
@@ -793,8 +799,8 @@ function Select({
|
|
|
793
799
|
"aria-disabled": disabled,
|
|
794
800
|
tabIndex: disabled ? -1 : 0
|
|
795
801
|
},
|
|
796
|
-
/* @__PURE__ */
|
|
797
|
-
/* @__PURE__ */
|
|
802
|
+
/* @__PURE__ */ React9.createElement("span", { className: "flex items-center flex-1 overflow-hidden text-ellipsis" }, selectedOption ? renderOption ? renderOption(selectedOption) : selectedOption.label : /* @__PURE__ */ React9.createElement("span", { className: "relative" }, placeholder)),
|
|
803
|
+
/* @__PURE__ */ React9.createElement("div", { className: "flex items-center gap-1 ml-2" }, loading && /* @__PURE__ */ React9.createElement("span", { className: "text-xs" }, "\u23F3"), clearable && value && !disabled && !loading && /* @__PURE__ */ React9.createElement(
|
|
798
804
|
"button",
|
|
799
805
|
{
|
|
800
806
|
type: "button",
|
|
@@ -804,16 +810,17 @@ function Select({
|
|
|
804
810
|
tabIndex: -1
|
|
805
811
|
},
|
|
806
812
|
"\u2715"
|
|
807
|
-
), /* @__PURE__ */
|
|
813
|
+
), /* @__PURE__ */ React9.createElement("span", { className: "text-xs leading-none", "aria-hidden": "true" }, isOpen ? "\u25B2" : "\u25BC"))
|
|
808
814
|
),
|
|
809
|
-
isOpen && /* @__PURE__ */
|
|
815
|
+
isOpen && /* @__PURE__ */ React9.createElement(
|
|
810
816
|
"div",
|
|
811
817
|
{
|
|
818
|
+
ref: dropdownRef,
|
|
812
819
|
id: dropdownId,
|
|
813
820
|
className: "absolute z-50 top-full mt-1 min-w-full overflow-hidden rounded-md border border-border bg-popover text-popover-foreground shadow-md",
|
|
814
821
|
role: "listbox"
|
|
815
822
|
},
|
|
816
|
-
searchable && /* @__PURE__ */
|
|
823
|
+
searchable && /* @__PURE__ */ React9.createElement("div", { className: "p-2 border-b border-border" }, /* @__PURE__ */ React9.createElement(
|
|
817
824
|
"input",
|
|
818
825
|
{
|
|
819
826
|
ref: searchInputRef,
|
|
@@ -829,19 +836,19 @@ function Select({
|
|
|
829
836
|
"aria-label": "Search options"
|
|
830
837
|
}
|
|
831
838
|
)),
|
|
832
|
-
/* @__PURE__ */
|
|
839
|
+
/* @__PURE__ */ React9.createElement("div", { className: "max-h-64 overflow-y-auto p-1" }, filteredOptions.length === 0 ? /* @__PURE__ */ React9.createElement("div", { className: "py-2 px-3 text-center text-sm " }, "No options found") : optionGroups.length > 0 ? (
|
|
833
840
|
// Render grouped options
|
|
834
841
|
optionGroups.map((group, groupIndex) => {
|
|
835
842
|
const groupOptions = group.options.filter(
|
|
836
843
|
(opt) => filteredOptions.includes(opt)
|
|
837
844
|
);
|
|
838
845
|
if (groupOptions.length === 0) return null;
|
|
839
|
-
return /* @__PURE__ */
|
|
846
|
+
return /* @__PURE__ */ React9.createElement("div", { key: groupIndex, className: "py-1" }, /* @__PURE__ */ React9.createElement("div", { className: "py-1.5 px-2 text-xs font-semibold " }, group.label), groupOptions.map((option) => {
|
|
840
847
|
const globalIndex = filteredOptions.indexOf(option);
|
|
841
848
|
const isSelected = value === option.value;
|
|
842
849
|
const isFocused = globalIndex === focusedIndex;
|
|
843
850
|
const isDisabled = option.disabled;
|
|
844
|
-
return /* @__PURE__ */
|
|
851
|
+
return /* @__PURE__ */ React9.createElement(
|
|
845
852
|
"div",
|
|
846
853
|
{
|
|
847
854
|
key: option.value,
|
|
@@ -861,7 +868,7 @@ function Select({
|
|
|
861
868
|
const isSelected = value === option.value;
|
|
862
869
|
const isFocused = index === focusedIndex;
|
|
863
870
|
const isDisabled = option.disabled;
|
|
864
|
-
return /* @__PURE__ */
|
|
871
|
+
return /* @__PURE__ */ React9.createElement(
|
|
865
872
|
"div",
|
|
866
873
|
{
|
|
867
874
|
key: option.value,
|
|
@@ -879,6 +886,360 @@ function Select({
|
|
|
879
886
|
);
|
|
880
887
|
}
|
|
881
888
|
Select.displayName = "Select";
|
|
889
|
+
function MultiSelect({
|
|
890
|
+
name,
|
|
891
|
+
value = [],
|
|
892
|
+
onChange,
|
|
893
|
+
onBlur,
|
|
894
|
+
onFocus,
|
|
895
|
+
disabled = false,
|
|
896
|
+
required = false,
|
|
897
|
+
error = false,
|
|
898
|
+
className = "",
|
|
899
|
+
placeholder = "Select...",
|
|
900
|
+
searchable = true,
|
|
901
|
+
clearable = true,
|
|
902
|
+
loading = false,
|
|
903
|
+
maxSelections,
|
|
904
|
+
showSelectAll = false,
|
|
905
|
+
options = [],
|
|
906
|
+
optionGroups = [],
|
|
907
|
+
renderOption,
|
|
908
|
+
renderValue,
|
|
909
|
+
...props
|
|
910
|
+
}) {
|
|
911
|
+
const [isOpen, setIsOpen] = React9.useState(false);
|
|
912
|
+
const [searchQuery, setSearchQuery] = React9.useState("");
|
|
913
|
+
const [focusedIndex, setFocusedIndex] = React9.useState(-1);
|
|
914
|
+
const triggerRef = React9.useRef(null);
|
|
915
|
+
const dropdownRef = React9.useRef(null);
|
|
916
|
+
const searchInputRef = React9.useRef(null);
|
|
917
|
+
const dropdownId = `${name}-dropdown`;
|
|
918
|
+
const allOptions = React9.useMemo(() => {
|
|
919
|
+
if (optionGroups.length > 0) {
|
|
920
|
+
return optionGroups.flatMap((group) => group.options);
|
|
921
|
+
}
|
|
922
|
+
return options;
|
|
923
|
+
}, [options, optionGroups]);
|
|
924
|
+
const filteredOptions = React9.useMemo(() => {
|
|
925
|
+
if (!searchQuery.trim()) {
|
|
926
|
+
return allOptions;
|
|
927
|
+
}
|
|
928
|
+
const query = searchQuery.toLowerCase();
|
|
929
|
+
return allOptions.filter((option) => {
|
|
930
|
+
const label = typeof option.label === "string" ? option.label : String(option.label);
|
|
931
|
+
return label.toLowerCase().includes(query);
|
|
932
|
+
});
|
|
933
|
+
}, [allOptions, searchQuery]);
|
|
934
|
+
const selectedOptions = React9.useMemo(() => {
|
|
935
|
+
return allOptions.filter((opt) => value.includes(opt.value));
|
|
936
|
+
}, [allOptions, value]);
|
|
937
|
+
const hasValue = value.length > 0;
|
|
938
|
+
const isMaxReached = React9.useMemo(() => {
|
|
939
|
+
return maxSelections !== void 0 && value.length >= maxSelections;
|
|
940
|
+
}, [maxSelections, value.length]);
|
|
941
|
+
const handleToggleOption = (optionValue) => {
|
|
942
|
+
const isSelected = value.includes(optionValue);
|
|
943
|
+
if (isSelected) {
|
|
944
|
+
onChange(value.filter((v) => v !== optionValue));
|
|
945
|
+
} else {
|
|
946
|
+
if (!isMaxReached) {
|
|
947
|
+
onChange([...value, optionValue]);
|
|
948
|
+
}
|
|
949
|
+
}
|
|
950
|
+
setSearchQuery("");
|
|
951
|
+
};
|
|
952
|
+
const handleSelectAll = () => {
|
|
953
|
+
const enabledOptions = filteredOptions.filter((opt) => !opt.disabled);
|
|
954
|
+
const allValues = enabledOptions.map((opt) => opt.value);
|
|
955
|
+
onChange(allValues);
|
|
956
|
+
setSearchQuery("");
|
|
957
|
+
};
|
|
958
|
+
const handleClearAll = (e) => {
|
|
959
|
+
e.stopPropagation();
|
|
960
|
+
onChange([]);
|
|
961
|
+
setSearchQuery("");
|
|
962
|
+
setFocusedIndex(-1);
|
|
963
|
+
};
|
|
964
|
+
const handleRemoveValue = (optionValue, e) => {
|
|
965
|
+
e.stopPropagation();
|
|
966
|
+
onChange(value.filter((v) => v !== optionValue));
|
|
967
|
+
};
|
|
968
|
+
const handleToggle = () => {
|
|
969
|
+
if (disabled) return;
|
|
970
|
+
const newIsOpen = !isOpen;
|
|
971
|
+
setIsOpen(newIsOpen);
|
|
972
|
+
if (newIsOpen && searchable && searchInputRef.current) {
|
|
973
|
+
setTimeout(() => searchInputRef.current?.focus(), 0);
|
|
974
|
+
}
|
|
975
|
+
if (newIsOpen) {
|
|
976
|
+
onFocus?.();
|
|
977
|
+
}
|
|
978
|
+
};
|
|
979
|
+
const handleSearchChange = (e) => {
|
|
980
|
+
setSearchQuery(e.target.value);
|
|
981
|
+
setFocusedIndex(0);
|
|
982
|
+
};
|
|
983
|
+
const handleKeyDown = (e) => {
|
|
984
|
+
if (disabled) return;
|
|
985
|
+
switch (e.key) {
|
|
986
|
+
case "ArrowDown":
|
|
987
|
+
e.preventDefault();
|
|
988
|
+
if (!isOpen) {
|
|
989
|
+
setIsOpen(true);
|
|
990
|
+
setFocusedIndex(0);
|
|
991
|
+
} else {
|
|
992
|
+
const enabledOptions = filteredOptions.filter((opt) => !opt.disabled);
|
|
993
|
+
if (enabledOptions.length > 0) {
|
|
994
|
+
const currentIndexInFiltered = focusedIndex;
|
|
995
|
+
const nextIndex = (currentIndexInFiltered + 1) % enabledOptions.length;
|
|
996
|
+
setFocusedIndex(filteredOptions.indexOf(enabledOptions[nextIndex]));
|
|
997
|
+
}
|
|
998
|
+
}
|
|
999
|
+
break;
|
|
1000
|
+
case "ArrowUp":
|
|
1001
|
+
e.preventDefault();
|
|
1002
|
+
if (isOpen) {
|
|
1003
|
+
const enabledOptions = filteredOptions.filter((opt) => !opt.disabled);
|
|
1004
|
+
if (enabledOptions.length > 0) {
|
|
1005
|
+
const currentIndexInFiltered = focusedIndex;
|
|
1006
|
+
const prevIndex = (currentIndexInFiltered - 1 + enabledOptions.length) % enabledOptions.length;
|
|
1007
|
+
setFocusedIndex(filteredOptions.indexOf(enabledOptions[prevIndex]));
|
|
1008
|
+
}
|
|
1009
|
+
}
|
|
1010
|
+
break;
|
|
1011
|
+
case "Enter":
|
|
1012
|
+
e.preventDefault();
|
|
1013
|
+
if (isOpen && focusedIndex >= 0 && focusedIndex < filteredOptions.length) {
|
|
1014
|
+
const focusedOption = filteredOptions[focusedIndex];
|
|
1015
|
+
if (!focusedOption.disabled) {
|
|
1016
|
+
handleToggleOption(focusedOption.value);
|
|
1017
|
+
}
|
|
1018
|
+
} else if (!isOpen) {
|
|
1019
|
+
setIsOpen(true);
|
|
1020
|
+
}
|
|
1021
|
+
break;
|
|
1022
|
+
case "Escape":
|
|
1023
|
+
e.preventDefault();
|
|
1024
|
+
if (isOpen) {
|
|
1025
|
+
setIsOpen(false);
|
|
1026
|
+
setSearchQuery("");
|
|
1027
|
+
setFocusedIndex(-1);
|
|
1028
|
+
}
|
|
1029
|
+
break;
|
|
1030
|
+
case " ":
|
|
1031
|
+
if (isOpen && focusedIndex >= 0 && focusedIndex < filteredOptions.length) {
|
|
1032
|
+
e.preventDefault();
|
|
1033
|
+
const focusedOption = filteredOptions[focusedIndex];
|
|
1034
|
+
if (!focusedOption.disabled) {
|
|
1035
|
+
handleToggleOption(focusedOption.value);
|
|
1036
|
+
}
|
|
1037
|
+
} else if (!isOpen && !searchable) {
|
|
1038
|
+
e.preventDefault();
|
|
1039
|
+
setIsOpen(true);
|
|
1040
|
+
}
|
|
1041
|
+
break;
|
|
1042
|
+
}
|
|
1043
|
+
};
|
|
1044
|
+
const handleBlur = (event) => {
|
|
1045
|
+
const nextTarget = event?.relatedTarget;
|
|
1046
|
+
const focusStayedInside = !!triggerRef.current && triggerRef.current.contains(nextTarget) || !!dropdownRef.current && dropdownRef.current.contains(nextTarget);
|
|
1047
|
+
if (!nextTarget || !focusStayedInside) {
|
|
1048
|
+
onBlur?.();
|
|
1049
|
+
}
|
|
1050
|
+
};
|
|
1051
|
+
const closeDropdown = React9.useCallback(() => {
|
|
1052
|
+
setIsOpen(false);
|
|
1053
|
+
setSearchQuery("");
|
|
1054
|
+
setFocusedIndex(-1);
|
|
1055
|
+
onBlur?.();
|
|
1056
|
+
}, [onBlur]);
|
|
1057
|
+
useOnClickOutside([triggerRef, dropdownRef], closeDropdown, void 0, {
|
|
1058
|
+
capture: true
|
|
1059
|
+
});
|
|
1060
|
+
const combinedClassName = cn("relative w-full", className);
|
|
1061
|
+
return /* @__PURE__ */ React9.createElement(
|
|
1062
|
+
"div",
|
|
1063
|
+
{
|
|
1064
|
+
className: combinedClassName,
|
|
1065
|
+
onKeyDown: handleKeyDown,
|
|
1066
|
+
onBlur: handleBlur
|
|
1067
|
+
},
|
|
1068
|
+
/* @__PURE__ */ React9.createElement(
|
|
1069
|
+
"select",
|
|
1070
|
+
{
|
|
1071
|
+
name,
|
|
1072
|
+
value,
|
|
1073
|
+
onChange: () => {
|
|
1074
|
+
},
|
|
1075
|
+
disabled,
|
|
1076
|
+
required,
|
|
1077
|
+
"aria-hidden": "true",
|
|
1078
|
+
tabIndex: -1,
|
|
1079
|
+
style: { display: "none" },
|
|
1080
|
+
multiple: true
|
|
1081
|
+
},
|
|
1082
|
+
/* @__PURE__ */ React9.createElement("option", { value: "" }, "Select..."),
|
|
1083
|
+
allOptions.map((option) => /* @__PURE__ */ React9.createElement("option", { key: option.value, value: option.value }, typeof option.label === "string" ? option.label : option.value))
|
|
1084
|
+
),
|
|
1085
|
+
/* @__PURE__ */ React9.createElement(
|
|
1086
|
+
"div",
|
|
1087
|
+
{
|
|
1088
|
+
ref: triggerRef,
|
|
1089
|
+
className: cn(
|
|
1090
|
+
"flex min-h-9 w-full items-center justify-between rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-sm",
|
|
1091
|
+
"cursor-pointer transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring",
|
|
1092
|
+
!error && hasValue && "ring-2 ring-ring",
|
|
1093
|
+
disabled && "cursor-not-allowed opacity-50 pointer-events-none",
|
|
1094
|
+
error && "border-destructive ring-1 ring-destructive"
|
|
1095
|
+
),
|
|
1096
|
+
onClick: handleToggle,
|
|
1097
|
+
role: "combobox",
|
|
1098
|
+
"aria-expanded": isOpen,
|
|
1099
|
+
"aria-controls": dropdownId,
|
|
1100
|
+
"aria-invalid": error || props["aria-invalid"],
|
|
1101
|
+
"aria-describedby": props["aria-describedby"],
|
|
1102
|
+
"aria-required": required || props["aria-required"],
|
|
1103
|
+
"aria-disabled": disabled,
|
|
1104
|
+
tabIndex: disabled ? -1 : 0
|
|
1105
|
+
},
|
|
1106
|
+
/* @__PURE__ */ React9.createElement("div", { className: "flex items-center flex-1 overflow-hidden" }, selectedOptions.length > 0 ? /* @__PURE__ */ React9.createElement("div", { className: "flex flex-wrap gap-1" }, selectedOptions.map((option) => /* @__PURE__ */ React9.createElement(
|
|
1107
|
+
"span",
|
|
1108
|
+
{
|
|
1109
|
+
key: option.value,
|
|
1110
|
+
className: "inline-flex items-center gap-1 rounded px-2 py-0.5 text-xs font-medium"
|
|
1111
|
+
},
|
|
1112
|
+
renderValue ? renderValue(option) : /* @__PURE__ */ React9.createElement(React9.Fragment, null, /* @__PURE__ */ React9.createElement("span", { className: "max-w-40 overflow-hidden text-ellipsis whitespace-nowrap" }, option.label), !disabled && /* @__PURE__ */ React9.createElement(
|
|
1113
|
+
"button",
|
|
1114
|
+
{
|
|
1115
|
+
type: "button",
|
|
1116
|
+
className: "flex items-center justify-center h-3.5 w-3.5 rounded-sm border-none bg-transparent cursor-pointer text-[0.625rem] p-0 transition-opacity hover:opacity-70",
|
|
1117
|
+
onClick: (e) => handleRemoveValue(option.value, e),
|
|
1118
|
+
"aria-label": `Remove ${option.label}`,
|
|
1119
|
+
tabIndex: -1
|
|
1120
|
+
},
|
|
1121
|
+
"\u2715"
|
|
1122
|
+
))
|
|
1123
|
+
))) : /* @__PURE__ */ React9.createElement("span", { className: "relative" }, placeholder)),
|
|
1124
|
+
/* @__PURE__ */ React9.createElement("div", { className: "flex items-center gap-1 ml-2" }, loading && /* @__PURE__ */ React9.createElement("span", { className: "text-xs" }, "\u23F3"), clearable && value.length > 0 && !disabled && !loading && /* @__PURE__ */ React9.createElement(
|
|
1125
|
+
"button",
|
|
1126
|
+
{
|
|
1127
|
+
type: "button",
|
|
1128
|
+
className: "flex items-center justify-center h-4 w-4 rounded-sm border-none bg-transparent cursor-pointer text-xs p-0 transition-opacity hover:opacity-70",
|
|
1129
|
+
onClick: handleClearAll,
|
|
1130
|
+
"aria-label": "Clear all selections",
|
|
1131
|
+
tabIndex: -1
|
|
1132
|
+
},
|
|
1133
|
+
"\u2715"
|
|
1134
|
+
), /* @__PURE__ */ React9.createElement("span", { className: "text-xs leading-none", "aria-hidden": "true" }, isOpen ? "\u25B2" : "\u25BC"))
|
|
1135
|
+
),
|
|
1136
|
+
isOpen && /* @__PURE__ */ React9.createElement(
|
|
1137
|
+
"div",
|
|
1138
|
+
{
|
|
1139
|
+
ref: dropdownRef,
|
|
1140
|
+
id: dropdownId,
|
|
1141
|
+
className: "absolute z-50 top-full mt-1 w-full overflow-hidden rounded-md border border-border bg-popover text-popover-foreground shadow-md",
|
|
1142
|
+
role: "listbox",
|
|
1143
|
+
"aria-multiselectable": "true"
|
|
1144
|
+
},
|
|
1145
|
+
searchable && /* @__PURE__ */ React9.createElement("div", { className: "p-2 border-b border-border" }, /* @__PURE__ */ React9.createElement(
|
|
1146
|
+
"input",
|
|
1147
|
+
{
|
|
1148
|
+
ref: searchInputRef,
|
|
1149
|
+
type: "text",
|
|
1150
|
+
className: cn(
|
|
1151
|
+
"w-full border border-input rounded px-2 py-1 text-sm bg-transparent outline-none focus:ring-1 focus:ring-ring",
|
|
1152
|
+
INPUT_AUTOFILL_RESET_CLASSES
|
|
1153
|
+
),
|
|
1154
|
+
placeholder: "Search...",
|
|
1155
|
+
value: searchQuery,
|
|
1156
|
+
onChange: handleSearchChange,
|
|
1157
|
+
onClick: (e) => e.stopPropagation(),
|
|
1158
|
+
"aria-label": "Search options"
|
|
1159
|
+
}
|
|
1160
|
+
)),
|
|
1161
|
+
showSelectAll && filteredOptions.length > 0 && /* @__PURE__ */ React9.createElement("div", { className: "flex gap-2 p-2 border-b border-border" }, /* @__PURE__ */ React9.createElement(
|
|
1162
|
+
"button",
|
|
1163
|
+
{
|
|
1164
|
+
type: "button",
|
|
1165
|
+
className: "flex-1 px-3 py-1.5 text-xs font-medium rounded border border-input bg-transparent hover:bg-muted transition-colors disabled:opacity-50 disabled:cursor-not-allowed",
|
|
1166
|
+
onClick: handleSelectAll,
|
|
1167
|
+
disabled
|
|
1168
|
+
},
|
|
1169
|
+
"Select All"
|
|
1170
|
+
), value.length > 0 && /* @__PURE__ */ React9.createElement(
|
|
1171
|
+
"button",
|
|
1172
|
+
{
|
|
1173
|
+
type: "button",
|
|
1174
|
+
className: "flex-1 px-3 py-1.5 text-xs font-medium rounded border border-input bg-transparent hover:bg-muted transition-colors disabled:opacity-50 disabled:cursor-not-allowed",
|
|
1175
|
+
onClick: handleClearAll,
|
|
1176
|
+
disabled
|
|
1177
|
+
},
|
|
1178
|
+
"Clear All"
|
|
1179
|
+
)),
|
|
1180
|
+
isMaxReached && /* @__PURE__ */ React9.createElement("div", { className: "px-2 py-1 text-xs font-medium text-amber-600 bg-destructive/80 text-destructive-foreground border-b border-destructive" }, "Maximum ", maxSelections, " selection", maxSelections !== 1 ? "s" : "", " ", "reached"),
|
|
1181
|
+
/* @__PURE__ */ React9.createElement("div", { className: "max-h-64 overflow-y-auto p-1" }, filteredOptions.length === 0 ? /* @__PURE__ */ React9.createElement("div", { className: "px-2 py-1 text-center text-sm" }, "No options found") : optionGroups.length > 0 ? (
|
|
1182
|
+
// Render grouped options
|
|
1183
|
+
optionGroups.map((group, groupIndex) => {
|
|
1184
|
+
const groupOptions = group.options.filter(
|
|
1185
|
+
(opt) => filteredOptions.includes(opt)
|
|
1186
|
+
);
|
|
1187
|
+
if (groupOptions.length === 0) return null;
|
|
1188
|
+
return /* @__PURE__ */ React9.createElement("div", { key: groupIndex, className: "py-1" }, /* @__PURE__ */ React9.createElement("div", { className: "py-1.5 px-2 text-xs font-semibold " }, group.label), groupOptions.map((option) => {
|
|
1189
|
+
const globalIndex = filteredOptions.indexOf(option);
|
|
1190
|
+
const isSelected = value.includes(option.value);
|
|
1191
|
+
const isFocused = globalIndex === focusedIndex;
|
|
1192
|
+
const isDisabled = option.disabled || isMaxReached && !isSelected;
|
|
1193
|
+
return /* @__PURE__ */ React9.createElement(
|
|
1194
|
+
"div",
|
|
1195
|
+
{
|
|
1196
|
+
key: option.value,
|
|
1197
|
+
className: cn(
|
|
1198
|
+
"relative flex w-full cursor-pointer items-center gap-2 rounded-sm py-1.5 px-2 text-sm outline-none transition-colors hover:bg-muted",
|
|
1199
|
+
isFocused && "bg-muted",
|
|
1200
|
+
isSelected && "font-medium",
|
|
1201
|
+
isDisabled && "pointer-events-none opacity-50"
|
|
1202
|
+
),
|
|
1203
|
+
onClick: () => !isDisabled && handleToggleOption(option.value),
|
|
1204
|
+
role: "option",
|
|
1205
|
+
"aria-selected": isSelected,
|
|
1206
|
+
"aria-disabled": isDisabled
|
|
1207
|
+
},
|
|
1208
|
+
/* @__PURE__ */ React9.createElement("span", { className: "text-base leading-none" }, isSelected ? "\u2611" : "\u2610"),
|
|
1209
|
+
/* @__PURE__ */ React9.createElement("span", { className: "flex-1" }, renderOption ? renderOption(option) : option.label)
|
|
1210
|
+
);
|
|
1211
|
+
}));
|
|
1212
|
+
})
|
|
1213
|
+
) : (
|
|
1214
|
+
// Render flat options
|
|
1215
|
+
filteredOptions.map((option, index) => {
|
|
1216
|
+
const isSelected = value.includes(option.value);
|
|
1217
|
+
const isFocused = index === focusedIndex;
|
|
1218
|
+
const isDisabled = option.disabled || isMaxReached && !isSelected;
|
|
1219
|
+
return /* @__PURE__ */ React9.createElement(
|
|
1220
|
+
"div",
|
|
1221
|
+
{
|
|
1222
|
+
key: option.value,
|
|
1223
|
+
className: cn(
|
|
1224
|
+
"relative flex w-full cursor-pointer items-center gap-2 rounded-sm py-1.5 px-2 text-sm outline-none transition-colors hover:bg-muted",
|
|
1225
|
+
isFocused && "bg-muted",
|
|
1226
|
+
isSelected && "font-medium bg-muted",
|
|
1227
|
+
isDisabled && "pointer-events-none opacity-50"
|
|
1228
|
+
),
|
|
1229
|
+
onClick: () => !isDisabled && handleToggleOption(option.value),
|
|
1230
|
+
role: "option",
|
|
1231
|
+
"aria-selected": isSelected,
|
|
1232
|
+
"aria-disabled": isDisabled
|
|
1233
|
+
},
|
|
1234
|
+
/* @__PURE__ */ React9.createElement("span", { className: "text-base leading-none" }, isSelected ? "\u2611" : "\u2610"),
|
|
1235
|
+
/* @__PURE__ */ React9.createElement("span", { className: "flex-1" }, renderOption ? renderOption(option) : option.label)
|
|
1236
|
+
);
|
|
1237
|
+
})
|
|
1238
|
+
))
|
|
1239
|
+
)
|
|
1240
|
+
);
|
|
1241
|
+
}
|
|
1242
|
+
MultiSelect.displayName = "MultiSelect";
|
|
882
1243
|
function FileInput({
|
|
883
1244
|
name,
|
|
884
1245
|
value = [],
|
|
@@ -904,14 +1265,14 @@ function FileInput({
|
|
|
904
1265
|
onFileRemove,
|
|
905
1266
|
...props
|
|
906
1267
|
}) {
|
|
907
|
-
const inputRef =
|
|
908
|
-
const [dragActive, setDragActive] =
|
|
909
|
-
const [cropperOpen, setCropperOpen] =
|
|
910
|
-
const [imageToCrop, setImageToCrop] =
|
|
911
|
-
const [crop, setCrop] =
|
|
912
|
-
const [zoom, setZoom] =
|
|
913
|
-
const [croppedAreaPixels, setCroppedAreaPixels] =
|
|
914
|
-
const validateFile =
|
|
1268
|
+
const inputRef = React9.useRef(null);
|
|
1269
|
+
const [dragActive, setDragActive] = React9.useState(false);
|
|
1270
|
+
const [cropperOpen, setCropperOpen] = React9.useState(false);
|
|
1271
|
+
const [imageToCrop, setImageToCrop] = React9.useState(null);
|
|
1272
|
+
const [crop, setCrop] = React9.useState({ x: 0, y: 0 });
|
|
1273
|
+
const [zoom, setZoom] = React9.useState(1);
|
|
1274
|
+
const [croppedAreaPixels, setCroppedAreaPixels] = React9.useState(null);
|
|
1275
|
+
const validateFile = React9.useCallback(
|
|
915
1276
|
(file) => {
|
|
916
1277
|
if (accept) {
|
|
917
1278
|
const acceptedTypes = accept.split(",").map((t) => t.trim());
|
|
@@ -946,7 +1307,7 @@ function FileInput({
|
|
|
946
1307
|
},
|
|
947
1308
|
[accept, maxSize]
|
|
948
1309
|
);
|
|
949
|
-
const handleFiles =
|
|
1310
|
+
const handleFiles = React9.useCallback(
|
|
950
1311
|
(fileList) => {
|
|
951
1312
|
if (!fileList || fileList.length === 0) return;
|
|
952
1313
|
const newFiles = Array.from(fileList);
|
|
@@ -997,7 +1358,7 @@ function FileInput({
|
|
|
997
1358
|
onValidationError
|
|
998
1359
|
]
|
|
999
1360
|
);
|
|
1000
|
-
const createCroppedImage =
|
|
1361
|
+
const createCroppedImage = React9.useCallback(
|
|
1001
1362
|
async (imageUrl, cropArea) => {
|
|
1002
1363
|
return new Promise((resolve, reject) => {
|
|
1003
1364
|
const image = new Image();
|
|
@@ -1041,7 +1402,7 @@ function FileInput({
|
|
|
1041
1402
|
},
|
|
1042
1403
|
[]
|
|
1043
1404
|
);
|
|
1044
|
-
const handleCropSave =
|
|
1405
|
+
const handleCropSave = React9.useCallback(async () => {
|
|
1045
1406
|
if (!imageToCrop || !croppedAreaPixels) return;
|
|
1046
1407
|
try {
|
|
1047
1408
|
const croppedBlob = await createCroppedImage(
|
|
@@ -1074,7 +1435,7 @@ function FileInput({
|
|
|
1074
1435
|
onChange,
|
|
1075
1436
|
multiple
|
|
1076
1437
|
]);
|
|
1077
|
-
const handleCropCancel =
|
|
1438
|
+
const handleCropCancel = React9.useCallback(() => {
|
|
1078
1439
|
if (imageToCrop) {
|
|
1079
1440
|
URL.revokeObjectURL(imageToCrop.url);
|
|
1080
1441
|
}
|
|
@@ -1084,13 +1445,13 @@ function FileInput({
|
|
|
1084
1445
|
setZoom(1);
|
|
1085
1446
|
setCroppedAreaPixels(null);
|
|
1086
1447
|
}, [imageToCrop]);
|
|
1087
|
-
const onCropChange =
|
|
1448
|
+
const onCropChange = React9.useCallback((crop2) => {
|
|
1088
1449
|
setCrop(crop2);
|
|
1089
1450
|
}, []);
|
|
1090
|
-
const onZoomChange =
|
|
1451
|
+
const onZoomChange = React9.useCallback((zoom2) => {
|
|
1091
1452
|
setZoom(zoom2);
|
|
1092
1453
|
}, []);
|
|
1093
|
-
const onCropCompleteInternal =
|
|
1454
|
+
const onCropCompleteInternal = React9.useCallback(
|
|
1094
1455
|
(_, croppedAreaPixels2) => {
|
|
1095
1456
|
setCroppedAreaPixels(croppedAreaPixels2);
|
|
1096
1457
|
},
|
|
@@ -1151,7 +1512,7 @@ function FileInput({
|
|
|
1151
1512
|
}
|
|
1152
1513
|
return null;
|
|
1153
1514
|
};
|
|
1154
|
-
|
|
1515
|
+
React9.useEffect(() => {
|
|
1155
1516
|
return () => {
|
|
1156
1517
|
value.forEach((file) => {
|
|
1157
1518
|
const previewUrl = getPreviewUrl(file);
|
|
@@ -1165,7 +1526,7 @@ function FileInput({
|
|
|
1165
1526
|
};
|
|
1166
1527
|
}, [value, imageToCrop]);
|
|
1167
1528
|
const combinedClassName = `${className}`.trim();
|
|
1168
|
-
return /* @__PURE__ */
|
|
1529
|
+
return /* @__PURE__ */ React9.createElement("div", { className: combinedClassName }, /* @__PURE__ */ React9.createElement(
|
|
1169
1530
|
"input",
|
|
1170
1531
|
{
|
|
1171
1532
|
ref: inputRef,
|
|
@@ -1182,7 +1543,7 @@ function FileInput({
|
|
|
1182
1543
|
"aria-required": required || props["aria-required"],
|
|
1183
1544
|
style: { display: "none" }
|
|
1184
1545
|
}
|
|
1185
|
-
), /* @__PURE__ */
|
|
1546
|
+
), /* @__PURE__ */ React9.createElement(
|
|
1186
1547
|
"div",
|
|
1187
1548
|
{
|
|
1188
1549
|
className: `flex min-h-32 w-full cursor-pointer items-center justify-center rounded-md border-2 border-dashed border-input bg-transparent p-6 transition-colors hover:bg-primary/50 hover:border-ring ${dragActive ? "bg-primary text-primary-foreground border-ring" : ""} ${disabled ? "cursor-not-allowed opacity-50" : ""} ${error ? "border-destructive" : ""}`,
|
|
@@ -1197,7 +1558,7 @@ function FileInput({
|
|
|
1197
1558
|
"aria-label": placeholder,
|
|
1198
1559
|
"aria-disabled": disabled
|
|
1199
1560
|
},
|
|
1200
|
-
/* @__PURE__ */
|
|
1561
|
+
/* @__PURE__ */ React9.createElement("div", { className: "flex flex-col items-center gap-2 text-center" }, /* @__PURE__ */ React9.createElement(
|
|
1201
1562
|
"svg",
|
|
1202
1563
|
{
|
|
1203
1564
|
width: "48",
|
|
@@ -1210,19 +1571,19 @@ function FileInput({
|
|
|
1210
1571
|
strokeLinejoin: "round",
|
|
1211
1572
|
"aria-hidden": "true"
|
|
1212
1573
|
},
|
|
1213
|
-
/* @__PURE__ */
|
|
1214
|
-
/* @__PURE__ */
|
|
1215
|
-
/* @__PURE__ */
|
|
1216
|
-
), /* @__PURE__ */
|
|
1217
|
-
), value.length > 0 && /* @__PURE__ */
|
|
1574
|
+
/* @__PURE__ */ React9.createElement("path", { d: "M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" }),
|
|
1575
|
+
/* @__PURE__ */ React9.createElement("polyline", { points: "17 8 12 3 7 8" }),
|
|
1576
|
+
/* @__PURE__ */ React9.createElement("line", { x1: "12", y1: "3", x2: "12", y2: "15" })
|
|
1577
|
+
), /* @__PURE__ */ React9.createElement("p", { className: "text-sm font-medium" }, value.length > 0 ? `${value.length} file(s) selected` : placeholder), accept && /* @__PURE__ */ React9.createElement("p", { className: "text-xs" }, "Accepted: ", accept), maxSize && /* @__PURE__ */ React9.createElement("p", { className: "text-xs " }, "Max size: ", formatFileSize(maxSize)))
|
|
1578
|
+
), value.length > 0 && /* @__PURE__ */ React9.createElement("ul", { className: "flex flex-col gap-2 mt-4", role: "list" }, value.map((file, index) => {
|
|
1218
1579
|
const previewUrl = showPreview ? getPreviewUrl(file) : null;
|
|
1219
|
-
return /* @__PURE__ */
|
|
1580
|
+
return /* @__PURE__ */ React9.createElement(
|
|
1220
1581
|
"li",
|
|
1221
1582
|
{
|
|
1222
1583
|
key: `${file.name}-${index}`,
|
|
1223
1584
|
className: "flex items-center gap-3 p-3 rounded-md border border-border bg-card text-card-foreground hover:bg-primary/50 transition-colors"
|
|
1224
1585
|
},
|
|
1225
|
-
previewUrl && /* @__PURE__ */
|
|
1586
|
+
previewUrl && /* @__PURE__ */ React9.createElement(
|
|
1226
1587
|
"img",
|
|
1227
1588
|
{
|
|
1228
1589
|
src: previewUrl,
|
|
@@ -1232,7 +1593,7 @@ function FileInput({
|
|
|
1232
1593
|
height: "48"
|
|
1233
1594
|
}
|
|
1234
1595
|
),
|
|
1235
|
-
/* @__PURE__ */
|
|
1596
|
+
/* @__PURE__ */ React9.createElement("div", { className: "flex flex-col flex-1 min-w-0" }, /* @__PURE__ */ React9.createElement("span", { className: "text-sm font-medium truncate" }, file.name), /* @__PURE__ */ React9.createElement("span", { className: "text-xs" }, formatFileSize(file.size)), showProgress && uploadProgress[file.name] !== void 0 && /* @__PURE__ */ React9.createElement("div", { className: "flex items-center gap-2 mt-1" }, /* @__PURE__ */ React9.createElement(
|
|
1236
1597
|
"div",
|
|
1237
1598
|
{
|
|
1238
1599
|
className: "h-1.5 bg-muted rounded-full overflow-hidden flex-1",
|
|
@@ -1242,15 +1603,15 @@ function FileInput({
|
|
|
1242
1603
|
"aria-valuemax": 100,
|
|
1243
1604
|
"aria-label": `Upload progress: ${uploadProgress[file.name]}%`
|
|
1244
1605
|
},
|
|
1245
|
-
/* @__PURE__ */
|
|
1606
|
+
/* @__PURE__ */ React9.createElement(
|
|
1246
1607
|
"div",
|
|
1247
1608
|
{
|
|
1248
1609
|
className: "h-full bg-primary transition-all",
|
|
1249
1610
|
style: { width: `${uploadProgress[file.name]}%` }
|
|
1250
1611
|
}
|
|
1251
1612
|
)
|
|
1252
|
-
), /* @__PURE__ */
|
|
1253
|
-
enableCropping && file.type.startsWith("image/") && /* @__PURE__ */
|
|
1613
|
+
), /* @__PURE__ */ React9.createElement("span", { className: "text-xs " }, uploadProgress[file.name], "%"))),
|
|
1614
|
+
enableCropping && file.type.startsWith("image/") && /* @__PURE__ */ React9.createElement(
|
|
1254
1615
|
"button",
|
|
1255
1616
|
{
|
|
1256
1617
|
type: "button",
|
|
@@ -1262,7 +1623,7 @@ function FileInput({
|
|
|
1262
1623
|
className: "flex items-center justify-center h-8 w-8 rounded border-none bg-transparent hover:bg-primary hover:text-primary-foreground transition-colors",
|
|
1263
1624
|
"aria-label": `Crop ${file.name}`
|
|
1264
1625
|
},
|
|
1265
|
-
/* @__PURE__ */
|
|
1626
|
+
/* @__PURE__ */ React9.createElement(
|
|
1266
1627
|
"svg",
|
|
1267
1628
|
{
|
|
1268
1629
|
width: "20",
|
|
@@ -1275,11 +1636,11 @@ function FileInput({
|
|
|
1275
1636
|
strokeLinejoin: "round",
|
|
1276
1637
|
"aria-hidden": "true"
|
|
1277
1638
|
},
|
|
1278
|
-
/* @__PURE__ */
|
|
1279
|
-
/* @__PURE__ */
|
|
1639
|
+
/* @__PURE__ */ React9.createElement("path", { d: "M6.13 1L6 16a2 2 0 0 0 2 2h15" }),
|
|
1640
|
+
/* @__PURE__ */ React9.createElement("path", { d: "M1 6.13L16 6a2 2 0 0 1 2 2v15" })
|
|
1280
1641
|
)
|
|
1281
1642
|
),
|
|
1282
|
-
/* @__PURE__ */
|
|
1643
|
+
/* @__PURE__ */ React9.createElement(
|
|
1283
1644
|
"button",
|
|
1284
1645
|
{
|
|
1285
1646
|
type: "button",
|
|
@@ -1291,7 +1652,7 @@ function FileInput({
|
|
|
1291
1652
|
className: "flex items-center justify-center h-8 w-8 rounded border-none bg-transparent hover:bg-primary hover:text-primary-foreground transition-colors",
|
|
1292
1653
|
"aria-label": `Remove ${file.name}`
|
|
1293
1654
|
},
|
|
1294
|
-
/* @__PURE__ */
|
|
1655
|
+
/* @__PURE__ */ React9.createElement(
|
|
1295
1656
|
"svg",
|
|
1296
1657
|
{
|
|
1297
1658
|
width: "20",
|
|
@@ -1304,19 +1665,19 @@ function FileInput({
|
|
|
1304
1665
|
strokeLinejoin: "round",
|
|
1305
1666
|
"aria-hidden": "true"
|
|
1306
1667
|
},
|
|
1307
|
-
/* @__PURE__ */
|
|
1308
|
-
/* @__PURE__ */
|
|
1668
|
+
/* @__PURE__ */ React9.createElement("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
|
|
1669
|
+
/* @__PURE__ */ React9.createElement("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
|
|
1309
1670
|
)
|
|
1310
1671
|
)
|
|
1311
1672
|
);
|
|
1312
|
-
})), cropperOpen && imageToCrop && /* @__PURE__ */
|
|
1673
|
+
})), cropperOpen && imageToCrop && /* @__PURE__ */ React9.createElement("div", { className: "fixed inset-0 z-50 flex items-center justify-center" }, /* @__PURE__ */ React9.createElement(
|
|
1313
1674
|
"div",
|
|
1314
1675
|
{
|
|
1315
1676
|
className: "absolute inset-0 bg-black/50",
|
|
1316
1677
|
onClick: handleCropCancel,
|
|
1317
1678
|
"aria-label": "Close cropper"
|
|
1318
1679
|
}
|
|
1319
|
-
), /* @__PURE__ */
|
|
1680
|
+
), /* @__PURE__ */ React9.createElement("div", { className: "relative bg-popover border border-border rounded-lg shadow-lg max-w-3xl w-full mx-4" }, /* @__PURE__ */ React9.createElement("div", { className: "flex items-center justify-between p-4 border-b border-border" }, /* @__PURE__ */ React9.createElement("h3", { className: "text-lg font-semibold" }, "Crop Image"), /* @__PURE__ */ React9.createElement(
|
|
1320
1681
|
"button",
|
|
1321
1682
|
{
|
|
1322
1683
|
type: "button",
|
|
@@ -1325,7 +1686,7 @@ function FileInput({
|
|
|
1325
1686
|
"aria-label": "Close"
|
|
1326
1687
|
},
|
|
1327
1688
|
"\u2715"
|
|
1328
|
-
)), /* @__PURE__ */
|
|
1689
|
+
)), /* @__PURE__ */ React9.createElement("div", { className: "p-4" }, /* @__PURE__ */ React9.createElement(
|
|
1329
1690
|
"div",
|
|
1330
1691
|
{
|
|
1331
1692
|
className: "relative w-full h-96 bg-muted rounded-md overflow-hidden",
|
|
@@ -1347,7 +1708,7 @@ function FileInput({
|
|
|
1347
1708
|
document.addEventListener("mouseup", handleMouseUp);
|
|
1348
1709
|
}
|
|
1349
1710
|
},
|
|
1350
|
-
/* @__PURE__ */
|
|
1711
|
+
/* @__PURE__ */ React9.createElement(
|
|
1351
1712
|
"img",
|
|
1352
1713
|
{
|
|
1353
1714
|
src: imageToCrop.url,
|
|
@@ -1382,7 +1743,7 @@ function FileInput({
|
|
|
1382
1743
|
}
|
|
1383
1744
|
}
|
|
1384
1745
|
),
|
|
1385
|
-
/* @__PURE__ */
|
|
1746
|
+
/* @__PURE__ */ React9.createElement(
|
|
1386
1747
|
"div",
|
|
1387
1748
|
{
|
|
1388
1749
|
className: "absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 border-2 border-primary rounded pointer-events-none",
|
|
@@ -1391,9 +1752,9 @@ function FileInput({
|
|
|
1391
1752
|
aspectRatio: cropAspectRatio ? String(cropAspectRatio) : void 0
|
|
1392
1753
|
}
|
|
1393
1754
|
},
|
|
1394
|
-
/* @__PURE__ */
|
|
1755
|
+
/* @__PURE__ */ React9.createElement("div", { className: "absolute inset-0 grid grid-cols-3 grid-rows-3" }, /* @__PURE__ */ React9.createElement("div", { className: "border-r border-b border-primary/30" }), /* @__PURE__ */ React9.createElement("div", { className: "border-r border-b border-primary/30" }), /* @__PURE__ */ React9.createElement("div", { className: "border-b border-primary/30" }), /* @__PURE__ */ React9.createElement("div", { className: "border-r border-b border-primary/30" }), /* @__PURE__ */ React9.createElement("div", { className: "border-r border-b border-primary/30" }), /* @__PURE__ */ React9.createElement("div", { className: "border-b border-primary/30" }), /* @__PURE__ */ React9.createElement("div", { className: "border-r border-primary/30" }), /* @__PURE__ */ React9.createElement("div", { className: "border-r border-primary/30" }), /* @__PURE__ */ React9.createElement("div", null))
|
|
1395
1756
|
)
|
|
1396
|
-
), /* @__PURE__ */
|
|
1757
|
+
), /* @__PURE__ */ React9.createElement("div", { className: "flex items-center gap-3 mt-4" }, /* @__PURE__ */ React9.createElement(
|
|
1397
1758
|
"label",
|
|
1398
1759
|
{
|
|
1399
1760
|
htmlFor: "zoom-slider",
|
|
@@ -1402,7 +1763,7 @@ function FileInput({
|
|
|
1402
1763
|
"Zoom: ",
|
|
1403
1764
|
zoom.toFixed(1),
|
|
1404
1765
|
"x"
|
|
1405
|
-
), /* @__PURE__ */
|
|
1766
|
+
), /* @__PURE__ */ React9.createElement(
|
|
1406
1767
|
"input",
|
|
1407
1768
|
{
|
|
1408
1769
|
id: "zoom-slider",
|
|
@@ -1415,7 +1776,7 @@ function FileInput({
|
|
|
1415
1776
|
className: "flex-1 h-2 bg-muted rounded-lg appearance-none cursor-pointer",
|
|
1416
1777
|
"aria-label": "Zoom level"
|
|
1417
1778
|
}
|
|
1418
|
-
))), /* @__PURE__ */
|
|
1779
|
+
))), /* @__PURE__ */ React9.createElement("div", { className: "flex items-center justify-end gap-2 p-4 border-t border-border" }, /* @__PURE__ */ React9.createElement(
|
|
1419
1780
|
"button",
|
|
1420
1781
|
{
|
|
1421
1782
|
type: "button",
|
|
@@ -1423,7 +1784,7 @@ function FileInput({
|
|
|
1423
1784
|
onClick: handleCropCancel
|
|
1424
1785
|
},
|
|
1425
1786
|
"Cancel"
|
|
1426
|
-
), /* @__PURE__ */
|
|
1787
|
+
), /* @__PURE__ */ React9.createElement(
|
|
1427
1788
|
"button",
|
|
1428
1789
|
{
|
|
1429
1790
|
type: "button",
|
|
@@ -1465,13 +1826,13 @@ function DatePicker({
|
|
|
1465
1826
|
showIcon = true,
|
|
1466
1827
|
...props
|
|
1467
1828
|
}) {
|
|
1468
|
-
const [isOpen, setIsOpen] =
|
|
1469
|
-
const [selectedMonth, setSelectedMonth] =
|
|
1829
|
+
const [isOpen, setIsOpen] = React9.useState(false);
|
|
1830
|
+
const [selectedMonth, setSelectedMonth] = React9.useState(
|
|
1470
1831
|
value || /* @__PURE__ */ new Date()
|
|
1471
1832
|
);
|
|
1472
|
-
const
|
|
1473
|
-
const
|
|
1474
|
-
|
|
1833
|
+
const inputRef = React9.useRef(null);
|
|
1834
|
+
const dropdownRef = React9.useRef(null);
|
|
1835
|
+
React9.useEffect(() => {
|
|
1475
1836
|
if (value) {
|
|
1476
1837
|
setSelectedMonth(value);
|
|
1477
1838
|
}
|
|
@@ -1497,12 +1858,20 @@ function DatePicker({
|
|
|
1497
1858
|
if (isDateDisabled && isDateDisabled(date)) return true;
|
|
1498
1859
|
return false;
|
|
1499
1860
|
};
|
|
1500
|
-
const closeCalendar =
|
|
1501
|
-
if (!isOpen) return;
|
|
1861
|
+
const closeCalendar = React9.useCallback(() => {
|
|
1502
1862
|
setIsOpen(false);
|
|
1503
1863
|
onBlur?.();
|
|
1504
|
-
}, [
|
|
1505
|
-
useOnClickOutside(
|
|
1864
|
+
}, [onBlur]);
|
|
1865
|
+
useOnClickOutside([inputRef, dropdownRef], closeCalendar, void 0, {
|
|
1866
|
+
capture: true
|
|
1867
|
+
});
|
|
1868
|
+
const handleBlur = (event) => {
|
|
1869
|
+
const nextTarget = event?.relatedTarget;
|
|
1870
|
+
const focusStayedInside = !!inputRef.current && inputRef.current.contains(nextTarget) || !!dropdownRef.current && dropdownRef.current.contains(nextTarget);
|
|
1871
|
+
if (!nextTarget || !focusStayedInside) {
|
|
1872
|
+
onBlur?.();
|
|
1873
|
+
}
|
|
1874
|
+
};
|
|
1506
1875
|
const dayGridStyle = {
|
|
1507
1876
|
gridTemplateColumns: "repeat(7, minmax(0, 1fr))"
|
|
1508
1877
|
};
|
|
@@ -1540,7 +1909,7 @@ function DatePicker({
|
|
|
1540
1909
|
const handleNextMonth = () => {
|
|
1541
1910
|
setSelectedMonth(new Date(year, month + 1, 1));
|
|
1542
1911
|
};
|
|
1543
|
-
return /* @__PURE__ */
|
|
1912
|
+
return /* @__PURE__ */ React9.createElement("div", { role: "grid", "aria-label": "Calendar", className: "w-[248px] max-w-full" }, /* @__PURE__ */ React9.createElement("div", { className: "flex items-center justify-between pb-3" }, /* @__PURE__ */ React9.createElement(
|
|
1544
1913
|
"button",
|
|
1545
1914
|
{
|
|
1546
1915
|
type: "button",
|
|
@@ -1549,7 +1918,7 @@ function DatePicker({
|
|
|
1549
1918
|
"aria-label": "Previous month"
|
|
1550
1919
|
},
|
|
1551
1920
|
"\u2039"
|
|
1552
|
-
), /* @__PURE__ */
|
|
1921
|
+
), /* @__PURE__ */ React9.createElement("div", { className: "font-medium text-sm" }, `${monthNames[month]} ${year}`), /* @__PURE__ */ React9.createElement(
|
|
1553
1922
|
"button",
|
|
1554
1923
|
{
|
|
1555
1924
|
type: "button",
|
|
@@ -1558,13 +1927,13 @@ function DatePicker({
|
|
|
1558
1927
|
"aria-label": "Next month"
|
|
1559
1928
|
},
|
|
1560
1929
|
"\u203A"
|
|
1561
|
-
)), /* @__PURE__ */
|
|
1930
|
+
)), /* @__PURE__ */ React9.createElement(
|
|
1562
1931
|
"div",
|
|
1563
1932
|
{
|
|
1564
1933
|
className: "grid gap-1 text-xs text-muted-foreground",
|
|
1565
1934
|
style: dayGridStyle
|
|
1566
1935
|
},
|
|
1567
|
-
["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"].map((day) => /* @__PURE__ */
|
|
1936
|
+
["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"].map((day) => /* @__PURE__ */ React9.createElement(
|
|
1568
1937
|
"div",
|
|
1569
1938
|
{
|
|
1570
1939
|
key: day,
|
|
@@ -1572,14 +1941,14 @@ function DatePicker({
|
|
|
1572
1941
|
},
|
|
1573
1942
|
day
|
|
1574
1943
|
))
|
|
1575
|
-
), /* @__PURE__ */
|
|
1944
|
+
), /* @__PURE__ */ React9.createElement("div", { className: "grid gap-1", style: dayGridStyle }, days.map((date, index) => {
|
|
1576
1945
|
if (!date) {
|
|
1577
|
-
return /* @__PURE__ */
|
|
1946
|
+
return /* @__PURE__ */ React9.createElement("div", { key: `empty-${index}`, className: "h-8 w-8" });
|
|
1578
1947
|
}
|
|
1579
1948
|
const isSelected = value && date.toDateString() === value.toDateString();
|
|
1580
1949
|
const isToday = date.toDateString() === (/* @__PURE__ */ new Date()).toDateString();
|
|
1581
1950
|
const disabled2 = isDisabled(date);
|
|
1582
|
-
return /* @__PURE__ */
|
|
1951
|
+
return /* @__PURE__ */ React9.createElement(
|
|
1583
1952
|
"button",
|
|
1584
1953
|
{
|
|
1585
1954
|
key: date.toISOString(),
|
|
@@ -1600,20 +1969,20 @@ function DatePicker({
|
|
|
1600
1969
|
})));
|
|
1601
1970
|
};
|
|
1602
1971
|
const combinedClassName = cn("relative", className);
|
|
1603
|
-
return /* @__PURE__ */
|
|
1972
|
+
return /* @__PURE__ */ React9.createElement("div", { className: combinedClassName, onBlur: handleBlur }, /* @__PURE__ */ React9.createElement(
|
|
1604
1973
|
"input",
|
|
1605
1974
|
{
|
|
1606
1975
|
type: "hidden",
|
|
1607
1976
|
name,
|
|
1608
1977
|
value: value ? value.toISOString() : ""
|
|
1609
1978
|
}
|
|
1610
|
-
), /* @__PURE__ */
|
|
1979
|
+
), /* @__PURE__ */ React9.createElement("div", { className: "relative" }, showIcon && /* @__PURE__ */ React9.createElement(
|
|
1611
1980
|
"span",
|
|
1612
1981
|
{
|
|
1613
1982
|
className: "absolute left-3 top-1/2 -translate-y-1/2 pointer-events-none",
|
|
1614
1983
|
"aria-hidden": "true"
|
|
1615
1984
|
},
|
|
1616
|
-
/* @__PURE__ */
|
|
1985
|
+
/* @__PURE__ */ React9.createElement(
|
|
1617
1986
|
"svg",
|
|
1618
1987
|
{
|
|
1619
1988
|
xmlns: "http://www.w3.org/2000/svg",
|
|
@@ -1626,9 +1995,9 @@ function DatePicker({
|
|
|
1626
1995
|
strokeLinejoin: "round",
|
|
1627
1996
|
strokeWidth: "2"
|
|
1628
1997
|
},
|
|
1629
|
-
/* @__PURE__ */
|
|
1998
|
+
/* @__PURE__ */ React9.createElement("path", { d: "M8 2v4m8-4v4m5 8V6a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h8M3 10h18m-5 10l2 2l4-4" })
|
|
1630
1999
|
)
|
|
1631
|
-
), /* @__PURE__ */
|
|
2000
|
+
), /* @__PURE__ */ React9.createElement(
|
|
1632
2001
|
"input",
|
|
1633
2002
|
{
|
|
1634
2003
|
ref: inputRef,
|
|
@@ -1645,7 +2014,6 @@ function DatePicker({
|
|
|
1645
2014
|
),
|
|
1646
2015
|
value: displayValue,
|
|
1647
2016
|
onClick: handleToggle,
|
|
1648
|
-
onBlur,
|
|
1649
2017
|
disabled,
|
|
1650
2018
|
required,
|
|
1651
2019
|
placeholder,
|
|
@@ -1654,7 +2022,7 @@ function DatePicker({
|
|
|
1654
2022
|
"aria-required": required || props["aria-required"],
|
|
1655
2023
|
readOnly: true
|
|
1656
2024
|
}
|
|
1657
|
-
), clearable && value && !disabled && /* @__PURE__ */
|
|
2025
|
+
), clearable && value && !disabled && /* @__PURE__ */ React9.createElement(
|
|
1658
2026
|
"button",
|
|
1659
2027
|
{
|
|
1660
2028
|
type: "button",
|
|
@@ -1664,7 +2032,14 @@ function DatePicker({
|
|
|
1664
2032
|
tabIndex: -1
|
|
1665
2033
|
},
|
|
1666
2034
|
"\u2715"
|
|
1667
|
-
)), isOpen && !disabled && /* @__PURE__ */
|
|
2035
|
+
)), isOpen && !disabled && /* @__PURE__ */ React9.createElement(
|
|
2036
|
+
"div",
|
|
2037
|
+
{
|
|
2038
|
+
ref: dropdownRef,
|
|
2039
|
+
className: "absolute z-50 top-full mt-1 w-fit rounded-md border border-border bg-popover text-popover-foreground shadow-md p-3"
|
|
2040
|
+
},
|
|
2041
|
+
renderCalendar()
|
|
2042
|
+
));
|
|
1668
2043
|
}
|
|
1669
2044
|
DatePicker.displayName = "DatePicker";
|
|
1670
2045
|
function normalizeToNativeTime(value) {
|
|
@@ -1724,11 +2099,11 @@ function TimePicker({
|
|
|
1724
2099
|
showIcon = true,
|
|
1725
2100
|
...props
|
|
1726
2101
|
}) {
|
|
1727
|
-
const inputRef =
|
|
1728
|
-
const [nativeValue, setNativeValue] =
|
|
2102
|
+
const inputRef = React9.useRef(null);
|
|
2103
|
+
const [nativeValue, setNativeValue] = React9.useState(
|
|
1729
2104
|
normalizeToNativeTime(value)
|
|
1730
2105
|
);
|
|
1731
|
-
|
|
2106
|
+
React9.useEffect(() => {
|
|
1732
2107
|
setNativeValue(normalizeToNativeTime(value));
|
|
1733
2108
|
}, [value]);
|
|
1734
2109
|
const handleChange = (e) => {
|
|
@@ -1744,13 +2119,13 @@ function TimePicker({
|
|
|
1744
2119
|
};
|
|
1745
2120
|
const hasValue = Boolean(value);
|
|
1746
2121
|
const stepInSeconds = Math.max(1, minuteStep * 60);
|
|
1747
|
-
return /* @__PURE__ */
|
|
2122
|
+
return /* @__PURE__ */ React9.createElement("div", { className: cn("relative", className) }, /* @__PURE__ */ React9.createElement("input", { type: "hidden", name, value }), /* @__PURE__ */ React9.createElement("div", { className: "relative" }, showIcon && /* @__PURE__ */ React9.createElement(
|
|
1748
2123
|
"span",
|
|
1749
2124
|
{
|
|
1750
2125
|
className: "absolute left-3 top-1/2 -translate-y-1/2 pointer-events-none",
|
|
1751
2126
|
"aria-hidden": "true"
|
|
1752
2127
|
},
|
|
1753
|
-
/* @__PURE__ */
|
|
2128
|
+
/* @__PURE__ */ React9.createElement(
|
|
1754
2129
|
"svg",
|
|
1755
2130
|
{
|
|
1756
2131
|
xmlns: "http://www.w3.org/2000/svg",
|
|
@@ -1763,10 +2138,10 @@ function TimePicker({
|
|
|
1763
2138
|
strokeLinejoin: "round",
|
|
1764
2139
|
strokeWidth: "2"
|
|
1765
2140
|
},
|
|
1766
|
-
/* @__PURE__ */
|
|
1767
|
-
/* @__PURE__ */
|
|
2141
|
+
/* @__PURE__ */ React9.createElement("circle", { cx: "12", cy: "12", r: "10" }),
|
|
2142
|
+
/* @__PURE__ */ React9.createElement("path", { d: "M12 6v6l4 2" })
|
|
1768
2143
|
)
|
|
1769
|
-
), /* @__PURE__ */
|
|
2144
|
+
), /* @__PURE__ */ React9.createElement(
|
|
1770
2145
|
"input",
|
|
1771
2146
|
{
|
|
1772
2147
|
ref: inputRef,
|
|
@@ -1794,7 +2169,7 @@ function TimePicker({
|
|
|
1794
2169
|
"aria-required": required || props["aria-required"],
|
|
1795
2170
|
...props
|
|
1796
2171
|
}
|
|
1797
|
-
), clearable && value && !disabled && /* @__PURE__ */
|
|
2172
|
+
), clearable && value && !disabled && /* @__PURE__ */ React9.createElement(
|
|
1798
2173
|
"button",
|
|
1799
2174
|
{
|
|
1800
2175
|
type: "button",
|
|
@@ -1847,15 +2222,16 @@ function DateRangePicker({
|
|
|
1847
2222
|
separator = " - ",
|
|
1848
2223
|
...props
|
|
1849
2224
|
}) {
|
|
1850
|
-
const [isOpen, setIsOpen] =
|
|
1851
|
-
const [selectedMonth, setSelectedMonth] =
|
|
2225
|
+
const [isOpen, setIsOpen] = React9.useState(false);
|
|
2226
|
+
const [selectedMonth, setSelectedMonth] = React9.useState(
|
|
1852
2227
|
value.start || /* @__PURE__ */ new Date()
|
|
1853
2228
|
);
|
|
1854
|
-
const [rangeStart, setRangeStart] =
|
|
1855
|
-
const [rangeEnd, setRangeEnd] =
|
|
1856
|
-
const [hoverDate, setHoverDate] =
|
|
1857
|
-
const
|
|
1858
|
-
|
|
2229
|
+
const [rangeStart, setRangeStart] = React9.useState(value.start);
|
|
2230
|
+
const [rangeEnd, setRangeEnd] = React9.useState(value.end);
|
|
2231
|
+
const [hoverDate, setHoverDate] = React9.useState(null);
|
|
2232
|
+
const triggerRef = React9.useRef(null);
|
|
2233
|
+
const dropdownRef = React9.useRef(null);
|
|
2234
|
+
React9.useEffect(() => {
|
|
1859
2235
|
setRangeStart(value.start);
|
|
1860
2236
|
setRangeEnd(value.end);
|
|
1861
2237
|
if (value.start) {
|
|
@@ -1898,12 +2274,20 @@ function DateRangePicker({
|
|
|
1898
2274
|
if (isDateDisabled && isDateDisabled(date)) return true;
|
|
1899
2275
|
return false;
|
|
1900
2276
|
};
|
|
1901
|
-
const closeCalendar =
|
|
1902
|
-
if (!isOpen) return;
|
|
2277
|
+
const closeCalendar = React9.useCallback(() => {
|
|
1903
2278
|
setIsOpen(false);
|
|
1904
2279
|
onBlur?.();
|
|
1905
|
-
}, [
|
|
1906
|
-
useOnClickOutside(
|
|
2280
|
+
}, [onBlur]);
|
|
2281
|
+
useOnClickOutside([triggerRef, dropdownRef], closeCalendar, void 0, {
|
|
2282
|
+
capture: true
|
|
2283
|
+
});
|
|
2284
|
+
const handleBlur = (event) => {
|
|
2285
|
+
const nextTarget = event?.relatedTarget;
|
|
2286
|
+
const focusStayedInside = !!triggerRef.current && triggerRef.current.contains(nextTarget) || !!dropdownRef.current && dropdownRef.current.contains(nextTarget);
|
|
2287
|
+
if (!nextTarget || !focusStayedInside) {
|
|
2288
|
+
onBlur?.();
|
|
2289
|
+
}
|
|
2290
|
+
};
|
|
1907
2291
|
const dayGridStyle = {
|
|
1908
2292
|
gridTemplateColumns: "repeat(7, minmax(0, 1fr))"
|
|
1909
2293
|
};
|
|
@@ -1937,7 +2321,7 @@ function DateRangePicker({
|
|
|
1937
2321
|
for (let day = 1; day <= daysInMonth; day++) {
|
|
1938
2322
|
days.push(new Date(year, month, day));
|
|
1939
2323
|
}
|
|
1940
|
-
return /* @__PURE__ */
|
|
2324
|
+
return /* @__PURE__ */ React9.createElement("div", { className: "w-[240px] max-w-full" }, /* @__PURE__ */ React9.createElement("div", { className: "flex items-center justify-between pb-3" }, controls?.prev ? /* @__PURE__ */ React9.createElement(
|
|
1941
2325
|
"button",
|
|
1942
2326
|
{
|
|
1943
2327
|
type: "button",
|
|
@@ -1946,7 +2330,7 @@ function DateRangePicker({
|
|
|
1946
2330
|
"aria-label": "Previous month"
|
|
1947
2331
|
},
|
|
1948
2332
|
"\u2039"
|
|
1949
|
-
) : /* @__PURE__ */
|
|
2333
|
+
) : /* @__PURE__ */ React9.createElement("div", { className: "h-8 w-8", "aria-hidden": "true" }), /* @__PURE__ */ React9.createElement("div", { className: "font-medium text-sm" }, `${monthNames[month]} ${year}`), controls?.next ? /* @__PURE__ */ React9.createElement(
|
|
1950
2334
|
"button",
|
|
1951
2335
|
{
|
|
1952
2336
|
type: "button",
|
|
@@ -1955,13 +2339,13 @@ function DateRangePicker({
|
|
|
1955
2339
|
"aria-label": "Next month"
|
|
1956
2340
|
},
|
|
1957
2341
|
"\u203A"
|
|
1958
|
-
) : /* @__PURE__ */
|
|
2342
|
+
) : /* @__PURE__ */ React9.createElement("div", { className: "h-8 w-8", "aria-hidden": "true" })), /* @__PURE__ */ React9.createElement(
|
|
1959
2343
|
"div",
|
|
1960
2344
|
{
|
|
1961
2345
|
className: "grid gap-1 text-xs text-muted-foreground",
|
|
1962
2346
|
style: dayGridStyle
|
|
1963
2347
|
},
|
|
1964
|
-
["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"].map((day) => /* @__PURE__ */
|
|
2348
|
+
["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"].map((day) => /* @__PURE__ */ React9.createElement(
|
|
1965
2349
|
"div",
|
|
1966
2350
|
{
|
|
1967
2351
|
key: `${month}-${day}`,
|
|
@@ -1969,9 +2353,9 @@ function DateRangePicker({
|
|
|
1969
2353
|
},
|
|
1970
2354
|
day
|
|
1971
2355
|
))
|
|
1972
|
-
), /* @__PURE__ */
|
|
2356
|
+
), /* @__PURE__ */ React9.createElement("div", { className: "grid gap-1", style: dayGridStyle }, days.map((date, index) => {
|
|
1973
2357
|
if (!date) {
|
|
1974
|
-
return /* @__PURE__ */
|
|
2358
|
+
return /* @__PURE__ */ React9.createElement("div", { key: `empty-${month}-${index}`, className: "h-8 w-8" });
|
|
1975
2359
|
}
|
|
1976
2360
|
const isStart = rangeStart && date.toDateString() === rangeStart.toDateString();
|
|
1977
2361
|
const isEnd = rangeEnd && date.toDateString() === rangeEnd.toDateString();
|
|
@@ -1983,7 +2367,7 @@ function DateRangePicker({
|
|
|
1983
2367
|
);
|
|
1984
2368
|
const isToday = date.toDateString() === (/* @__PURE__ */ new Date()).toDateString();
|
|
1985
2369
|
const disabled2 = isDisabled(date);
|
|
1986
|
-
return /* @__PURE__ */
|
|
2370
|
+
return /* @__PURE__ */ React9.createElement(
|
|
1987
2371
|
"button",
|
|
1988
2372
|
{
|
|
1989
2373
|
key: date.toISOString(),
|
|
@@ -2008,27 +2392,27 @@ function DateRangePicker({
|
|
|
2008
2392
|
};
|
|
2009
2393
|
const combinedClassName = cn("relative", className);
|
|
2010
2394
|
const displayValue = rangeStart && rangeEnd ? `${formatDate2(rangeStart, format)}${separator}${formatDate2(rangeEnd, format)}` : rangeStart ? formatDate2(rangeStart, format) : "";
|
|
2011
|
-
return /* @__PURE__ */
|
|
2395
|
+
return /* @__PURE__ */ React9.createElement("div", { className: combinedClassName, onBlur: handleBlur }, /* @__PURE__ */ React9.createElement(
|
|
2012
2396
|
"input",
|
|
2013
2397
|
{
|
|
2014
2398
|
type: "hidden",
|
|
2015
2399
|
name: `${name}[start]`,
|
|
2016
2400
|
value: rangeStart ? rangeStart.toISOString() : ""
|
|
2017
2401
|
}
|
|
2018
|
-
), /* @__PURE__ */
|
|
2402
|
+
), /* @__PURE__ */ React9.createElement(
|
|
2019
2403
|
"input",
|
|
2020
2404
|
{
|
|
2021
2405
|
type: "hidden",
|
|
2022
2406
|
name: `${name}[end]`,
|
|
2023
2407
|
value: rangeEnd ? rangeEnd.toISOString() : ""
|
|
2024
2408
|
}
|
|
2025
|
-
), /* @__PURE__ */
|
|
2409
|
+
), /* @__PURE__ */ React9.createElement("div", { className: "relative" }, showIcon && /* @__PURE__ */ React9.createElement(
|
|
2026
2410
|
"span",
|
|
2027
2411
|
{
|
|
2028
2412
|
className: "absolute left-3 top-1/2 -translate-y-1/2 pointer-events-none",
|
|
2029
2413
|
"aria-hidden": "true"
|
|
2030
2414
|
},
|
|
2031
|
-
/* @__PURE__ */
|
|
2415
|
+
/* @__PURE__ */ React9.createElement(
|
|
2032
2416
|
"svg",
|
|
2033
2417
|
{
|
|
2034
2418
|
xmlns: "http://www.w3.org/2000/svg",
|
|
@@ -2041,11 +2425,12 @@ function DateRangePicker({
|
|
|
2041
2425
|
strokeLinejoin: "round",
|
|
2042
2426
|
strokeWidth: "2"
|
|
2043
2427
|
},
|
|
2044
|
-
/* @__PURE__ */
|
|
2428
|
+
/* @__PURE__ */ React9.createElement("path", { d: "M8 2v4m8-4v4m5 8V6a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h8M3 10h18m-5 10l2 2l4-4" })
|
|
2045
2429
|
)
|
|
2046
|
-
), /* @__PURE__ */
|
|
2430
|
+
), /* @__PURE__ */ React9.createElement(
|
|
2047
2431
|
"input",
|
|
2048
2432
|
{
|
|
2433
|
+
ref: triggerRef,
|
|
2049
2434
|
type: "text",
|
|
2050
2435
|
className: cn(
|
|
2051
2436
|
"flex h-9 w-full rounded-md border border-input bg-transparent py-1 text-base shadow-sm transition-colors",
|
|
@@ -2059,7 +2444,6 @@ function DateRangePicker({
|
|
|
2059
2444
|
),
|
|
2060
2445
|
value: displayValue,
|
|
2061
2446
|
onClick: handleToggle,
|
|
2062
|
-
onBlur,
|
|
2063
2447
|
disabled,
|
|
2064
2448
|
required,
|
|
2065
2449
|
placeholder,
|
|
@@ -2068,7 +2452,7 @@ function DateRangePicker({
|
|
|
2068
2452
|
"aria-required": required || props["aria-required"],
|
|
2069
2453
|
readOnly: true
|
|
2070
2454
|
}
|
|
2071
|
-
), clearable && (rangeStart || rangeEnd) && !disabled && /* @__PURE__ */
|
|
2455
|
+
), clearable && (rangeStart || rangeEnd) && !disabled && /* @__PURE__ */ React9.createElement(
|
|
2072
2456
|
"button",
|
|
2073
2457
|
{
|
|
2074
2458
|
type: "button",
|
|
@@ -2078,7 +2462,15 @@ function DateRangePicker({
|
|
|
2078
2462
|
tabIndex: -1
|
|
2079
2463
|
},
|
|
2080
2464
|
"\u2715"
|
|
2081
|
-
)), isOpen && !disabled && /* @__PURE__ */
|
|
2465
|
+
)), isOpen && !disabled && /* @__PURE__ */ React9.createElement(
|
|
2466
|
+
"div",
|
|
2467
|
+
{
|
|
2468
|
+
ref: dropdownRef,
|
|
2469
|
+
className: "absolute z-50 top-full mt-1 w-fit rounded-md border border-border bg-popover text-popover-foreground shadow-md p-3"
|
|
2470
|
+
},
|
|
2471
|
+
/* @__PURE__ */ React9.createElement("div", { role: "grid", "aria-label": "Calendar" }, /* @__PURE__ */ React9.createElement("div", { className: "grid gap-4", style: monthsGridStyle }, renderMonth(selectedMonth, { prev: true }), renderMonth(addMonths(selectedMonth, 1), { next: true }))),
|
|
2472
|
+
rangeStart && !rangeEnd && /* @__PURE__ */ React9.createElement("div", { className: "text-xs text-center pt-2 border-t border-border mt-2" }, "Select end date")
|
|
2473
|
+
));
|
|
2082
2474
|
}
|
|
2083
2475
|
DateRangePicker.displayName = "DateRangePicker";
|
|
2084
2476
|
function htmlToMarkdown(html) {
|
|
@@ -2149,11 +2541,11 @@ function RichTextEditor({
|
|
|
2149
2541
|
],
|
|
2150
2542
|
...props
|
|
2151
2543
|
}) {
|
|
2152
|
-
const [currentMode, setCurrentMode] =
|
|
2153
|
-
const [content, setContent] =
|
|
2154
|
-
const editorRef =
|
|
2155
|
-
const textareaRef =
|
|
2156
|
-
|
|
2544
|
+
const [currentMode, setCurrentMode] = React9.useState(mode);
|
|
2545
|
+
const [content, setContent] = React9.useState(value);
|
|
2546
|
+
const editorRef = React9.useRef(null);
|
|
2547
|
+
const textareaRef = React9.useRef(null);
|
|
2548
|
+
React9.useEffect(() => {
|
|
2157
2549
|
setContent(value);
|
|
2158
2550
|
if (currentMode === "wysiwyg" && editorRef.current) {
|
|
2159
2551
|
editorRef.current.innerHTML = value;
|
|
@@ -2241,7 +2633,7 @@ function RichTextEditor({
|
|
|
2241
2633
|
}
|
|
2242
2634
|
}
|
|
2243
2635
|
};
|
|
2244
|
-
const hasValue =
|
|
2636
|
+
const hasValue = React9.useMemo(() => {
|
|
2245
2637
|
if (!content) return false;
|
|
2246
2638
|
const stripped = content.replace(/<[^>]+>/g, "").trim();
|
|
2247
2639
|
return stripped.length > 0;
|
|
@@ -2258,10 +2650,10 @@ function RichTextEditor({
|
|
|
2258
2650
|
maxHeight,
|
|
2259
2651
|
overflowY: maxHeight ? "auto" : void 0
|
|
2260
2652
|
};
|
|
2261
|
-
return /* @__PURE__ */
|
|
2653
|
+
return /* @__PURE__ */ React9.createElement("div", { className: combinedClassName }, /* @__PURE__ */ React9.createElement("input", { type: "hidden", name, value: content }), showToolbar && /* @__PURE__ */ React9.createElement("div", { className: "flex items-center justify-between p-2 border-b border-border bg-muted/50" }, /* @__PURE__ */ React9.createElement("div", { className: "flex items-center gap-1" }, toolbarButtons.map((buttonName) => {
|
|
2262
2654
|
const button = toolbarConfig[buttonName];
|
|
2263
2655
|
if (!button) return null;
|
|
2264
|
-
return /* @__PURE__ */
|
|
2656
|
+
return /* @__PURE__ */ React9.createElement(
|
|
2265
2657
|
"button",
|
|
2266
2658
|
{
|
|
2267
2659
|
key: buttonName,
|
|
@@ -2274,7 +2666,7 @@ function RichTextEditor({
|
|
|
2274
2666
|
},
|
|
2275
2667
|
button.icon
|
|
2276
2668
|
);
|
|
2277
|
-
})), allowModeSwitch && /* @__PURE__ */
|
|
2669
|
+
})), allowModeSwitch && /* @__PURE__ */ React9.createElement(
|
|
2278
2670
|
"button",
|
|
2279
2671
|
{
|
|
2280
2672
|
type: "button",
|
|
@@ -2285,7 +2677,7 @@ function RichTextEditor({
|
|
|
2285
2677
|
"aria-label": `Switch to ${currentMode === "wysiwyg" ? "Markdown" : "WYSIWYG"}`
|
|
2286
2678
|
},
|
|
2287
2679
|
currentMode === "wysiwyg" ? "MD" : "WYSIWYG"
|
|
2288
|
-
)), /* @__PURE__ */
|
|
2680
|
+
)), /* @__PURE__ */ React9.createElement("div", { style: editorStyle }, currentMode === "wysiwyg" ? /* @__PURE__ */ React9.createElement(
|
|
2289
2681
|
"div",
|
|
2290
2682
|
{
|
|
2291
2683
|
ref: editorRef,
|
|
@@ -2300,7 +2692,7 @@ function RichTextEditor({
|
|
|
2300
2692
|
"aria-required": required || props["aria-required"],
|
|
2301
2693
|
suppressContentEditableWarning: true
|
|
2302
2694
|
}
|
|
2303
|
-
) : /* @__PURE__ */
|
|
2695
|
+
) : /* @__PURE__ */ React9.createElement(
|
|
2304
2696
|
"textarea",
|
|
2305
2697
|
{
|
|
2306
2698
|
ref: textareaRef,
|
|
@@ -2323,6 +2715,6 @@ function RichTextEditor({
|
|
|
2323
2715
|
}
|
|
2324
2716
|
RichTextEditor.displayName = "RichTextEditor";
|
|
2325
2717
|
|
|
2326
|
-
export { Checkbox, CheckboxGroup, DatePicker, DateRangePicker, FileInput, Radio, RichTextEditor, Select, TextArea, TextInput, TimePicker };
|
|
2718
|
+
export { Checkbox, CheckboxGroup, DatePicker, DateRangePicker, FileInput, MultiSelect, Radio, RichTextEditor, Select, TextArea, TextInput, TimePicker };
|
|
2327
2719
|
//# sourceMappingURL=inputs.js.map
|
|
2328
2720
|
//# sourceMappingURL=inputs.js.map
|