@page-speed/forms 0.4.1 → 0.4.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/core.cjs +1 -1
- package/dist/core.cjs.map +1 -1
- package/dist/core.js +1 -1
- package/dist/core.js.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/inputs.cjs +551 -330
- package/dist/inputs.cjs.map +1 -1
- package/dist/inputs.d.cts +5 -1
- package/dist/inputs.d.ts +5 -1
- package/dist/inputs.js +551 -330
- package/dist/inputs.js.map +1 -1
- package/package.json +4 -2
package/dist/inputs.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import * as React7 from 'react';
|
|
2
|
+
import { clsx } from 'clsx';
|
|
3
|
+
import { twMerge } from 'tailwind-merge';
|
|
2
4
|
|
|
3
5
|
// src/inputs/TextInput.tsx
|
|
4
6
|
function TextInput({
|
|
@@ -21,7 +23,7 @@ function TextInput({
|
|
|
21
23
|
const handleBlur = () => {
|
|
22
24
|
onBlur?.();
|
|
23
25
|
};
|
|
24
|
-
const baseClassName = "flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-base shadow-sm transition-colors
|
|
26
|
+
const baseClassName = "flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-base shadow-sm transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 md:text-sm";
|
|
25
27
|
const errorClassName = error ? "border-red-500 ring-1 ring-red-500" : "";
|
|
26
28
|
const combinedClassName = `${baseClassName} ${errorClassName} ${className}`.trim();
|
|
27
29
|
return /* @__PURE__ */ React7.createElement(
|
|
@@ -68,7 +70,7 @@ function TextArea({
|
|
|
68
70
|
const handleBlur = () => {
|
|
69
71
|
onBlur?.();
|
|
70
72
|
};
|
|
71
|
-
const baseClassName = "flex min-h-20 w-full rounded-md border border-input bg-transparent px-3 py-2 text-base shadow-sm transition-colors
|
|
73
|
+
const baseClassName = "flex min-h-20 w-full rounded-md border border-input bg-transparent px-3 py-2 text-base shadow-sm transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 md:text-sm";
|
|
72
74
|
const errorClassName = error ? "border-red-500 ring-1 ring-red-500" : "";
|
|
73
75
|
const combinedClassName = `${baseClassName} ${errorClassName} ${className}`.trim();
|
|
74
76
|
return /* @__PURE__ */ React7.createElement(
|
|
@@ -95,6 +97,11 @@ function TextArea({
|
|
|
95
97
|
);
|
|
96
98
|
}
|
|
97
99
|
TextArea.displayName = "TextArea";
|
|
100
|
+
function cn(...inputs) {
|
|
101
|
+
return twMerge(clsx(inputs));
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// src/inputs/Checkbox.tsx
|
|
98
105
|
function Checkbox({
|
|
99
106
|
name,
|
|
100
107
|
value,
|
|
@@ -107,6 +114,7 @@ function Checkbox({
|
|
|
107
114
|
indeterminate = false,
|
|
108
115
|
label,
|
|
109
116
|
description,
|
|
117
|
+
checkboxVariant = "boxed",
|
|
110
118
|
...props
|
|
111
119
|
}) {
|
|
112
120
|
const inputRef = React7.useRef(null);
|
|
@@ -122,36 +130,92 @@ function Checkbox({
|
|
|
122
130
|
const handleBlur = () => {
|
|
123
131
|
onBlur?.();
|
|
124
132
|
};
|
|
125
|
-
const
|
|
126
|
-
|
|
133
|
+
const isActive = value || indeterminate && !value;
|
|
134
|
+
const checkbox = /* @__PURE__ */ React7.createElement(
|
|
135
|
+
"div",
|
|
127
136
|
{
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
137
|
+
className: cn(
|
|
138
|
+
"relative inline-flex items-center justify-center",
|
|
139
|
+
!label && className
|
|
140
|
+
)
|
|
141
|
+
},
|
|
142
|
+
/* @__PURE__ */ React7.createElement(
|
|
143
|
+
"input",
|
|
144
|
+
{
|
|
145
|
+
ref: inputRef,
|
|
146
|
+
type: "checkbox",
|
|
147
|
+
id: checkboxId,
|
|
148
|
+
name,
|
|
149
|
+
checked: value,
|
|
150
|
+
onChange: handleChange,
|
|
151
|
+
onBlur: handleBlur,
|
|
152
|
+
disabled,
|
|
153
|
+
required,
|
|
154
|
+
className: "peer sr-only",
|
|
155
|
+
"aria-invalid": error || props["aria-invalid"],
|
|
156
|
+
"aria-describedby": description ? `${checkboxId}-description` : props["aria-describedby"],
|
|
157
|
+
"aria-required": required || props["aria-required"],
|
|
158
|
+
...props
|
|
159
|
+
}
|
|
160
|
+
),
|
|
161
|
+
/* @__PURE__ */ React7.createElement(
|
|
162
|
+
"div",
|
|
163
|
+
{
|
|
164
|
+
className: cn(
|
|
165
|
+
"flex shrink-0 items-center justify-center rounded-full border-2 transition-colors size-6",
|
|
166
|
+
!error && isActive && "border-primary bg-primary text-primary-foreground",
|
|
167
|
+
!error && !isActive && "border-input bg-transparent",
|
|
168
|
+
error && isActive && "border-destructive bg-destructive text-destructive-foreground",
|
|
169
|
+
error && !isActive && "border-destructive bg-transparent",
|
|
170
|
+
disabled && "opacity-50",
|
|
171
|
+
"peer-focus-visible:ring-2 peer-focus-visible:ring-ring/50 peer-focus-visible:ring-offset-1"
|
|
172
|
+
)
|
|
173
|
+
},
|
|
174
|
+
value && /* @__PURE__ */ React7.createElement(
|
|
175
|
+
"svg",
|
|
176
|
+
{
|
|
177
|
+
className: "size-3.5",
|
|
178
|
+
viewBox: "0 0 24 24",
|
|
179
|
+
fill: "none",
|
|
180
|
+
stroke: "currentColor",
|
|
181
|
+
strokeWidth: "3",
|
|
182
|
+
strokeLinecap: "round",
|
|
183
|
+
strokeLinejoin: "round"
|
|
184
|
+
},
|
|
185
|
+
/* @__PURE__ */ React7.createElement("polyline", { points: "20 6 9 17 4 12" })
|
|
186
|
+
),
|
|
187
|
+
indeterminate && !value && /* @__PURE__ */ React7.createElement(
|
|
188
|
+
"svg",
|
|
189
|
+
{
|
|
190
|
+
className: "size-3.5",
|
|
191
|
+
viewBox: "0 0 24 24",
|
|
192
|
+
fill: "none",
|
|
193
|
+
stroke: "currentColor",
|
|
194
|
+
strokeWidth: "3",
|
|
195
|
+
strokeLinecap: "round",
|
|
196
|
+
strokeLinejoin: "round"
|
|
197
|
+
},
|
|
198
|
+
/* @__PURE__ */ React7.createElement("line", { x1: "5", y1: "12", x2: "19", y2: "12" })
|
|
199
|
+
)
|
|
200
|
+
)
|
|
201
|
+
);
|
|
144
202
|
if (label) {
|
|
145
203
|
return /* @__PURE__ */ React7.createElement(
|
|
146
204
|
"label",
|
|
147
205
|
{
|
|
148
|
-
className:
|
|
206
|
+
className: cn(
|
|
207
|
+
"w-full h-full flex gap-3 p-3 duration-200",
|
|
208
|
+
checkboxVariant === "boxed" && "border rounded-lg hover:ring-2",
|
|
209
|
+
checkboxVariant === "boxed" && value && "ring-2",
|
|
210
|
+
disabled ? "opacity-50 cursor-not-allowed hover:ring-0" : "cursor-pointer",
|
|
211
|
+
className
|
|
212
|
+
),
|
|
149
213
|
htmlFor: checkboxId
|
|
150
214
|
},
|
|
151
|
-
/* @__PURE__ */ React7.createElement("div", { className: "flex w-full flex-row
|
|
215
|
+
/* @__PURE__ */ React7.createElement("div", { className: "flex w-full flex-row gap-2" }, checkbox, /* @__PURE__ */ React7.createElement("div", { className: "flex flex-col gap-0.5" }, /* @__PURE__ */ React7.createElement("div", { className: "text-sm font-medium" }, label), description && /* @__PURE__ */ React7.createElement(
|
|
152
216
|
"p",
|
|
153
217
|
{
|
|
154
|
-
className: "text-
|
|
218
|
+
className: "text-xs opacity-75",
|
|
155
219
|
id: `${checkboxId}-description`
|
|
156
220
|
},
|
|
157
221
|
description
|
|
@@ -189,6 +253,18 @@ function CheckboxGroup({
|
|
|
189
253
|
).length;
|
|
190
254
|
const allSelected = selectedEnabledCount === enabledOptions.length;
|
|
191
255
|
const someSelected = selectedEnabledCount > 0 && !allSelected;
|
|
256
|
+
const checkboxVariant = React7.useMemo(() => {
|
|
257
|
+
if (options.some((opt) => opt.description)) {
|
|
258
|
+
return "boxed";
|
|
259
|
+
}
|
|
260
|
+
return "inline";
|
|
261
|
+
}, [options]);
|
|
262
|
+
const countableValue = React7.useMemo(() => {
|
|
263
|
+
if (value?.length > 0) {
|
|
264
|
+
return value.length;
|
|
265
|
+
}
|
|
266
|
+
return 0;
|
|
267
|
+
}, [value]);
|
|
192
268
|
const handleChange = (optionValue, checked) => {
|
|
193
269
|
const newValues = checked ? [...value, optionValue] : value.filter((v) => v !== optionValue);
|
|
194
270
|
if (maxSelections && checked && newValues.length > maxSelections) {
|
|
@@ -207,9 +283,14 @@ function CheckboxGroup({
|
|
|
207
283
|
const handleBlur = () => {
|
|
208
284
|
onBlur?.();
|
|
209
285
|
};
|
|
210
|
-
const
|
|
211
|
-
const containerClass =
|
|
212
|
-
|
|
286
|
+
const maxReached = Boolean(maxSelections && countableValue >= maxSelections);
|
|
287
|
+
const containerClass = cn(
|
|
288
|
+
"w-full gap-3",
|
|
289
|
+
layout === "stacked" && "flex flex-col",
|
|
290
|
+
layout === "inline" && "flex flex-row flex-wrap",
|
|
291
|
+
layout === "grid" && "grid",
|
|
292
|
+
className
|
|
293
|
+
);
|
|
213
294
|
return /* @__PURE__ */ React7.createElement(
|
|
214
295
|
"div",
|
|
215
296
|
{
|
|
@@ -223,68 +304,56 @@ function CheckboxGroup({
|
|
|
223
304
|
gridTemplateColumns: `repeat(${gridColumns}, 1fr)`
|
|
224
305
|
} : void 0
|
|
225
306
|
},
|
|
226
|
-
label
|
|
227
|
-
description
|
|
307
|
+
label ? /* @__PURE__ */ React7.createElement("div", { className: "text-sm font-medium" }, label) : null,
|
|
308
|
+
description ? /* @__PURE__ */ React7.createElement("div", { className: "text-xs opacity-70" }, description) : null,
|
|
228
309
|
showSelectAll && enabledOptions.length > 0 && /* @__PURE__ */ React7.createElement(
|
|
229
|
-
|
|
310
|
+
Checkbox,
|
|
230
311
|
{
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
},
|
|
243
|
-
onChange: (e) => handleSelectAll(e.target.checked),
|
|
244
|
-
onBlur: handleBlur,
|
|
245
|
-
disabled,
|
|
246
|
-
className: "peer relative flex size-4 shrink-0 appearance-none items-center justify-center rounded-lg border border-input bg-transparent outline-none transition-colors focus-visible:ring-3 focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50",
|
|
247
|
-
"aria-label": selectAllLabel
|
|
248
|
-
}
|
|
249
|
-
), allSelected && /* @__PURE__ */ React7.createElement("span", { className: "pointer-events-none absolute top-1/2 left-1/2 flex -translate-x-1/2 -translate-y-1/2 items-center justify-center text-primary-foreground" }, /* @__PURE__ */ React7.createElement("svg", { className: "size-3", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "3" }, /* @__PURE__ */ React7.createElement("polyline", { points: "20 6 9 17 4 12" }))), someSelected && !allSelected && /* @__PURE__ */ React7.createElement("span", { className: "pointer-events-none absolute top-1/2 left-1/2 flex -translate-x-1/2 -translate-y-1/2 items-center justify-center text-primary" }, /* @__PURE__ */ React7.createElement("svg", { className: "size-3", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "3" }, /* @__PURE__ */ React7.createElement("line", { x1: "5", y1: "12", x2: "19", y2: "12" })))), /* @__PURE__ */ React7.createElement("span", { className: "text-sm font-medium" }, selectAllLabel))
|
|
312
|
+
name: `${name}-select-all`,
|
|
313
|
+
id: `${name}-select-all`,
|
|
314
|
+
value: allSelected,
|
|
315
|
+
onChange: handleSelectAll,
|
|
316
|
+
onBlur: handleBlur,
|
|
317
|
+
indeterminate: someSelected,
|
|
318
|
+
label: selectAllLabel,
|
|
319
|
+
checkboxVariant: "inline",
|
|
320
|
+
disabled,
|
|
321
|
+
"aria-label": selectAllLabel
|
|
322
|
+
}
|
|
250
323
|
),
|
|
251
324
|
options.map((option) => {
|
|
252
325
|
const isChecked = value.includes(option.value);
|
|
253
326
|
const isDisabled = disabled || option.disabled || maxReached && !isChecked;
|
|
254
|
-
const checkboxId = `${name}-${option.value}`;
|
|
255
327
|
return /* @__PURE__ */ React7.createElement(
|
|
256
|
-
|
|
328
|
+
Checkbox,
|
|
257
329
|
{
|
|
258
330
|
key: option.value,
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
onBlur: handleBlur,
|
|
272
|
-
disabled: isDisabled,
|
|
273
|
-
required: required && minSelections ? value.length < minSelections : false,
|
|
274
|
-
className: `peer relative flex size-4 shrink-0 appearance-none items-center justify-center rounded-lg border border-input bg-transparent outline-none transition-colors focus-visible:ring-3 focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 ${error ? "border-destructive ring-3 ring-destructive/20" : ""} ${isChecked ? "bg-primary border-primary" : ""}`,
|
|
275
|
-
"aria-describedby": option.description ? `${checkboxId}-description` : props["aria-describedby"]
|
|
276
|
-
}
|
|
277
|
-
), isChecked && /* @__PURE__ */ React7.createElement("span", { className: "pointer-events-none absolute top-1/2 left-1/2 flex -translate-x-1/2 -translate-y-1/2 items-center justify-center text-primary-foreground" }, /* @__PURE__ */ React7.createElement("svg", { className: "size-3", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "3" }, /* @__PURE__ */ React7.createElement("polyline", { points: "20 6 9 17 4 12" })))), /* @__PURE__ */ React7.createElement("div", { className: "flex flex-1 flex-col gap-0.5" }, renderOption ? renderOption(option) : /* @__PURE__ */ React7.createElement(React7.Fragment, null, /* @__PURE__ */ React7.createElement("div", { className: "flex items-center gap-2 text-sm font-medium" }, option.label), option.description && /* @__PURE__ */ React7.createElement(
|
|
278
|
-
"p",
|
|
279
|
-
{
|
|
280
|
-
className: "text-muted-foreground text-sm",
|
|
281
|
-
id: `${checkboxId}-description`
|
|
282
|
-
},
|
|
283
|
-
option.description
|
|
284
|
-
))))
|
|
331
|
+
name,
|
|
332
|
+
id: `${name}-${option.value}`,
|
|
333
|
+
value: isChecked,
|
|
334
|
+
onChange: (checked) => handleChange(option.value, checked),
|
|
335
|
+
onBlur: handleBlur,
|
|
336
|
+
disabled: isDisabled,
|
|
337
|
+
required: required && minSelections ? value.length < minSelections : false,
|
|
338
|
+
error,
|
|
339
|
+
label: renderOption ? renderOption(option) : option.label,
|
|
340
|
+
description: renderOption ? void 0 : option.description,
|
|
341
|
+
checkboxVariant
|
|
342
|
+
}
|
|
285
343
|
);
|
|
286
344
|
}),
|
|
287
|
-
(minSelections || maxSelections) && /* @__PURE__ */ React7.createElement(
|
|
345
|
+
(minSelections || maxSelections) && /* @__PURE__ */ React7.createElement(
|
|
346
|
+
"div",
|
|
347
|
+
{
|
|
348
|
+
className: cn(
|
|
349
|
+
"text-sm p-2 rounded-lg border font-semibold mt-2",
|
|
350
|
+
minSelections && countableValue < minSelections ? "border-destructive bg-destructive/80 text-destructive-foreground" : "border-border bg-card text-card-foreground"
|
|
351
|
+
),
|
|
352
|
+
"aria-live": "polite"
|
|
353
|
+
},
|
|
354
|
+
minSelections && countableValue < minSelections && /* @__PURE__ */ React7.createElement("span", null, "Select at least ", minSelections, " option", minSelections !== 1 ? "s" : ""),
|
|
355
|
+
maxSelections && /* @__PURE__ */ React7.createElement("span", null, countableValue, "/", maxSelections, " selected")
|
|
356
|
+
)
|
|
288
357
|
);
|
|
289
358
|
}
|
|
290
359
|
CheckboxGroup.displayName = "CheckboxGroup";
|
|
@@ -333,8 +402,16 @@ function Radio({
|
|
|
333
402
|
const handleBlur = () => {
|
|
334
403
|
onBlur?.();
|
|
335
404
|
};
|
|
336
|
-
const
|
|
337
|
-
|
|
405
|
+
const useChoiceCard = React7.useMemo(() => {
|
|
406
|
+
return options.some((option) => option.description);
|
|
407
|
+
}, [options]);
|
|
408
|
+
const containerClass = React7.useMemo(() => {
|
|
409
|
+
return cn(
|
|
410
|
+
"w-full gap-3 grid grid-cols-1",
|
|
411
|
+
layout === "inline" && "md:grid-cols-2",
|
|
412
|
+
className
|
|
413
|
+
);
|
|
414
|
+
}, [layout, className]);
|
|
338
415
|
return /* @__PURE__ */ React7.createElement(
|
|
339
416
|
"div",
|
|
340
417
|
{
|
|
@@ -350,38 +427,53 @@ function Radio({
|
|
|
350
427
|
const isChecked = value === option.value;
|
|
351
428
|
const isDisabled = disabled || option.disabled;
|
|
352
429
|
const radioId = `${name}-${option.value}`;
|
|
430
|
+
const hasDescription = option.description != null && option.description !== "";
|
|
431
|
+
const radioIndicator = /* @__PURE__ */ React7.createElement("div", { className: "relative inline-flex items-center justify-center" }, /* @__PURE__ */ React7.createElement(
|
|
432
|
+
"input",
|
|
433
|
+
{
|
|
434
|
+
type: "radio",
|
|
435
|
+
id: radioId,
|
|
436
|
+
name,
|
|
437
|
+
value: option.value,
|
|
438
|
+
checked: isChecked,
|
|
439
|
+
onChange: (e) => handleChange(e.target.value),
|
|
440
|
+
onBlur: handleBlur,
|
|
441
|
+
disabled: isDisabled,
|
|
442
|
+
required,
|
|
443
|
+
className: "peer sr-only",
|
|
444
|
+
"aria-describedby": hasDescription ? `${radioId}-description` : props["aria-describedby"]
|
|
445
|
+
}
|
|
446
|
+
), /* @__PURE__ */ React7.createElement(
|
|
447
|
+
"div",
|
|
448
|
+
{
|
|
449
|
+
className: cn(
|
|
450
|
+
"flex shrink-0 items-center justify-center rounded-full border-2 transition-colors size-6",
|
|
451
|
+
!error && isChecked && "border-primary bg-transparent",
|
|
452
|
+
!error && !isChecked && "border-input bg-transparent",
|
|
453
|
+
error && isChecked && "border-destructive bg-transparent",
|
|
454
|
+
error && !isChecked && "border-destructive bg-transparent",
|
|
455
|
+
isDisabled && "opacity-50",
|
|
456
|
+
"peer-focus-visible:ring-2 peer-focus-visible:ring-ring/50 peer-focus-visible:ring-offset-1"
|
|
457
|
+
)
|
|
458
|
+
},
|
|
459
|
+
isChecked && /* @__PURE__ */ React7.createElement("div", { className: "size-3 rounded-full bg-primary" })
|
|
460
|
+
));
|
|
461
|
+
const labelContent = /* @__PURE__ */ React7.createElement("div", { className: "flex flex-col gap-0.5" }, /* @__PURE__ */ React7.createElement("div", { className: "text-sm font-medium" }, option.label), hasDescription && /* @__PURE__ */ React7.createElement("p", { className: "text-xs opacity-75", id: `${radioId}-description` }, option.description));
|
|
353
462
|
return /* @__PURE__ */ React7.createElement(
|
|
354
463
|
"label",
|
|
355
464
|
{
|
|
356
465
|
key: option.value,
|
|
357
|
-
className:
|
|
466
|
+
className: cn(
|
|
467
|
+
"w-full h-full flex gap-3 p-3 duration-200",
|
|
468
|
+
useChoiceCard && "border rounded-lg hover:ring-2",
|
|
469
|
+
useChoiceCard && isChecked && "ring-2",
|
|
470
|
+
isDisabled ? "opacity-50 cursor-not-allowed hover:ring-0" : "cursor-pointer"
|
|
471
|
+
),
|
|
358
472
|
htmlFor: radioId,
|
|
359
473
|
onKeyDown: (e) => handleKeyDown(e, index),
|
|
360
474
|
tabIndex: isDisabled ? -1 : 0
|
|
361
475
|
},
|
|
362
|
-
/* @__PURE__ */ React7.createElement("div", { className: "flex w-full flex-row items-center gap-2" }, /* @__PURE__ */ React7.createElement("div", { className: "flex flex-1 flex-col gap-0.5" },
|
|
363
|
-
"p",
|
|
364
|
-
{
|
|
365
|
-
className: "text-muted-foreground text-sm",
|
|
366
|
-
id: `${radioId}-description`
|
|
367
|
-
},
|
|
368
|
-
option.description
|
|
369
|
-
)) : /* @__PURE__ */ React7.createElement("span", { className: "text-sm font-medium" }, option.label)), /* @__PURE__ */ React7.createElement("div", { className: "relative" }, /* @__PURE__ */ React7.createElement(
|
|
370
|
-
"input",
|
|
371
|
-
{
|
|
372
|
-
type: "radio",
|
|
373
|
-
id: radioId,
|
|
374
|
-
name,
|
|
375
|
-
value: option.value,
|
|
376
|
-
checked: isChecked,
|
|
377
|
-
onChange: (e) => handleChange(e.target.value),
|
|
378
|
-
onBlur: handleBlur,
|
|
379
|
-
disabled: isDisabled,
|
|
380
|
-
required,
|
|
381
|
-
className: `peer relative flex aspect-square size-4 shrink-0 appearance-none rounded-full border border-input outline-none transition-colors focus-visible:ring-3 focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 ${error ? "border-destructive" : ""} ${isChecked ? "border-primary bg-primary" : "bg-transparent"}`,
|
|
382
|
-
"aria-describedby": option.description ? `${radioId}-description` : props["aria-describedby"]
|
|
383
|
-
}
|
|
384
|
-
), isChecked && /* @__PURE__ */ React7.createElement("span", { className: "pointer-events-none absolute top-1/2 left-1/2 flex size-4 -translate-x-1/2 -translate-y-1/2 items-center justify-center text-primary-foreground" }, /* @__PURE__ */ React7.createElement("svg", { className: "size-2 fill-current", viewBox: "0 0 24 24" }, /* @__PURE__ */ React7.createElement("circle", { cx: "12", cy: "12", r: "10" })))))
|
|
476
|
+
/* @__PURE__ */ React7.createElement("div", { className: "flex w-full flex-row items-center gap-2" }, !useChoiceCard && radioIndicator, /* @__PURE__ */ React7.createElement("div", { className: "flex flex-1 flex-col gap-0.5" }, labelContent), useChoiceCard && radioIndicator)
|
|
385
477
|
);
|
|
386
478
|
})
|
|
387
479
|
);
|
|
@@ -471,9 +563,7 @@ function Select({
|
|
|
471
563
|
if (enabledOptions.length > 0) {
|
|
472
564
|
const currentIndexInFiltered = focusedIndex;
|
|
473
565
|
const nextIndex = (currentIndexInFiltered + 1) % enabledOptions.length;
|
|
474
|
-
setFocusedIndex(
|
|
475
|
-
filteredOptions.indexOf(enabledOptions[nextIndex])
|
|
476
|
-
);
|
|
566
|
+
setFocusedIndex(filteredOptions.indexOf(enabledOptions[nextIndex]));
|
|
477
567
|
}
|
|
478
568
|
}
|
|
479
569
|
break;
|
|
@@ -484,9 +574,7 @@ function Select({
|
|
|
484
574
|
if (enabledOptions.length > 0) {
|
|
485
575
|
const currentIndexInFiltered = focusedIndex;
|
|
486
576
|
const prevIndex = (currentIndexInFiltered - 1 + enabledOptions.length) % enabledOptions.length;
|
|
487
|
-
setFocusedIndex(
|
|
488
|
-
filteredOptions.indexOf(enabledOptions[prevIndex])
|
|
489
|
-
);
|
|
577
|
+
setFocusedIndex(filteredOptions.indexOf(enabledOptions[prevIndex]));
|
|
490
578
|
}
|
|
491
579
|
}
|
|
492
580
|
break;
|
|
@@ -576,7 +664,7 @@ function Select({
|
|
|
576
664
|
/* @__PURE__ */ React7.createElement(
|
|
577
665
|
"div",
|
|
578
666
|
{
|
|
579
|
-
className: `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 cursor-pointer transition-colors hover:bg-
|
|
667
|
+
className: `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 cursor-pointer transition-colors hover:bg-muted focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring ${disabled ? "cursor-not-allowed opacity-50 pointer-events-none" : ""} ${error ? "border-red-500 ring-1 ring-red-500" : ""}`,
|
|
580
668
|
onClick: handleToggle,
|
|
581
669
|
role: "combobox",
|
|
582
670
|
"aria-expanded": isOpen,
|
|
@@ -587,48 +675,76 @@ function Select({
|
|
|
587
675
|
"aria-disabled": disabled,
|
|
588
676
|
tabIndex: disabled ? -1 : 0
|
|
589
677
|
},
|
|
590
|
-
/* @__PURE__ */ React7.createElement("span", { className: "flex items-center flex-1 overflow-hidden text-ellipsis" }, selectedOption ? renderOption ? renderOption(selectedOption) : selectedOption.label : /* @__PURE__ */ React7.createElement("span", { className: "
|
|
678
|
+
/* @__PURE__ */ React7.createElement("span", { className: "flex items-center flex-1 overflow-hidden text-ellipsis" }, selectedOption ? renderOption ? renderOption(selectedOption) : selectedOption.label : /* @__PURE__ */ React7.createElement("span", { className: "relative" }, placeholder)),
|
|
591
679
|
/* @__PURE__ */ React7.createElement("div", { className: "flex items-center gap-1 ml-2" }, loading && /* @__PURE__ */ React7.createElement("span", { className: "text-xs" }, "\u23F3"), clearable && value && !disabled && !loading && /* @__PURE__ */ React7.createElement(
|
|
592
680
|
"button",
|
|
593
681
|
{
|
|
594
682
|
type: "button",
|
|
595
|
-
className: "flex items-center justify-center h-4 w-4 rounded-sm border-none bg-transparent
|
|
683
|
+
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",
|
|
596
684
|
onClick: handleClear,
|
|
597
685
|
"aria-label": "Clear selection",
|
|
598
686
|
tabIndex: -1
|
|
599
687
|
},
|
|
600
688
|
"\u2715"
|
|
601
|
-
), /* @__PURE__ */ React7.createElement("span", { className: "text-
|
|
689
|
+
), /* @__PURE__ */ React7.createElement("span", { className: "text-xs leading-none", "aria-hidden": "true" }, isOpen ? "\u25B2" : "\u25BC"))
|
|
602
690
|
),
|
|
603
|
-
isOpen && /* @__PURE__ */ React7.createElement(
|
|
604
|
-
"
|
|
691
|
+
isOpen && /* @__PURE__ */ React7.createElement(
|
|
692
|
+
"div",
|
|
605
693
|
{
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
(
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
694
|
+
id: dropdownId,
|
|
695
|
+
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",
|
|
696
|
+
role: "listbox"
|
|
697
|
+
},
|
|
698
|
+
searchable && /* @__PURE__ */ React7.createElement("div", { className: "p-2 border-b border-border" }, /* @__PURE__ */ React7.createElement(
|
|
699
|
+
"input",
|
|
700
|
+
{
|
|
701
|
+
ref: searchInputRef,
|
|
702
|
+
type: "text",
|
|
703
|
+
className: "w-full border border-input rounded px-2 py-1 text-sm bg-transparent outline-none focus:ring-1 focus:ring-ring",
|
|
704
|
+
placeholder: "Search...",
|
|
705
|
+
value: searchQuery,
|
|
706
|
+
onChange: handleSearchChange,
|
|
707
|
+
onClick: (e) => e.stopPropagation(),
|
|
708
|
+
"aria-label": "Search options"
|
|
709
|
+
}
|
|
710
|
+
)),
|
|
711
|
+
/* @__PURE__ */ React7.createElement("div", { className: "max-h-64 overflow-y-auto p-1" }, filteredOptions.length === 0 ? /* @__PURE__ */ React7.createElement("div", { className: "py-2 px-3 text-center text-sm " }, "No options found") : optionGroups.length > 0 ? (
|
|
712
|
+
// Render grouped options
|
|
713
|
+
optionGroups.map((group, groupIndex) => {
|
|
714
|
+
const groupOptions = group.options.filter(
|
|
715
|
+
(opt) => filteredOptions.includes(opt)
|
|
716
|
+
);
|
|
717
|
+
if (groupOptions.length === 0) return null;
|
|
718
|
+
return /* @__PURE__ */ React7.createElement("div", { key: groupIndex, className: "py-1" }, /* @__PURE__ */ React7.createElement("div", { className: "py-1.5 px-2 text-xs font-semibold " }, group.label), groupOptions.map((option) => {
|
|
719
|
+
const globalIndex = filteredOptions.indexOf(option);
|
|
720
|
+
const isSelected = value === option.value;
|
|
721
|
+
const isFocused = globalIndex === focusedIndex;
|
|
722
|
+
const isDisabled = option.disabled;
|
|
723
|
+
return /* @__PURE__ */ React7.createElement(
|
|
724
|
+
"div",
|
|
725
|
+
{
|
|
726
|
+
key: option.value,
|
|
727
|
+
className: `relative flex w-full cursor-pointer items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors hover:bg-muted ${isFocused ? "bg-muted" : ""} ${isSelected ? "font-medium bg-muted" : ""} ${isDisabled ? "pointer-events-none opacity-50" : ""}`,
|
|
728
|
+
onClick: () => !isDisabled && handleSelect(option.value),
|
|
729
|
+
role: "option",
|
|
730
|
+
"aria-selected": isSelected,
|
|
731
|
+
"aria-disabled": isDisabled
|
|
732
|
+
},
|
|
733
|
+
renderOption ? renderOption(option) : option.label
|
|
734
|
+
);
|
|
735
|
+
}));
|
|
736
|
+
})
|
|
737
|
+
) : (
|
|
738
|
+
// Render flat options
|
|
739
|
+
filteredOptions.map((option, index) => {
|
|
624
740
|
const isSelected = value === option.value;
|
|
625
|
-
const isFocused =
|
|
741
|
+
const isFocused = index === focusedIndex;
|
|
626
742
|
const isDisabled = option.disabled;
|
|
627
743
|
return /* @__PURE__ */ React7.createElement(
|
|
628
744
|
"div",
|
|
629
745
|
{
|
|
630
746
|
key: option.value,
|
|
631
|
-
className: `relative flex w-full cursor-pointer items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors hover:bg-
|
|
747
|
+
className: `relative flex w-full cursor-pointer items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors hover:bg-muted ${isFocused ? "bg-muted" : ""} ${isSelected ? "font-medium bg-muted" : ""} ${isDisabled ? "pointer-events-none opacity-50" : ""}`,
|
|
632
748
|
onClick: () => !isDisabled && handleSelect(option.value),
|
|
633
749
|
role: "option",
|
|
634
750
|
"aria-selected": isSelected,
|
|
@@ -636,28 +752,9 @@ function Select({
|
|
|
636
752
|
},
|
|
637
753
|
renderOption ? renderOption(option) : option.label
|
|
638
754
|
);
|
|
639
|
-
})
|
|
640
|
-
|
|
641
|
-
)
|
|
642
|
-
// Render flat options
|
|
643
|
-
filteredOptions.map((option, index) => {
|
|
644
|
-
const isSelected = value === option.value;
|
|
645
|
-
const isFocused = index === focusedIndex;
|
|
646
|
-
const isDisabled = option.disabled;
|
|
647
|
-
return /* @__PURE__ */ React7.createElement(
|
|
648
|
-
"div",
|
|
649
|
-
{
|
|
650
|
-
key: option.value,
|
|
651
|
-
className: `relative flex w-full cursor-pointer items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors hover:bg-accent hover:text-accent-foreground ${isFocused ? "bg-accent text-accent-foreground" : ""} ${isSelected ? "font-medium bg-accent" : ""} ${isDisabled ? "pointer-events-none opacity-50" : ""}`,
|
|
652
|
-
onClick: () => !isDisabled && handleSelect(option.value),
|
|
653
|
-
role: "option",
|
|
654
|
-
"aria-selected": isSelected,
|
|
655
|
-
"aria-disabled": isDisabled
|
|
656
|
-
},
|
|
657
|
-
renderOption ? renderOption(option) : option.label
|
|
658
|
-
);
|
|
659
|
-
})
|
|
660
|
-
)))
|
|
755
|
+
})
|
|
756
|
+
))
|
|
757
|
+
)
|
|
661
758
|
);
|
|
662
759
|
}
|
|
663
760
|
Select.displayName = "Select";
|
|
@@ -666,7 +763,7 @@ function FileInput({
|
|
|
666
763
|
value = [],
|
|
667
764
|
onChange,
|
|
668
765
|
onBlur,
|
|
669
|
-
placeholder = "Choose file
|
|
766
|
+
placeholder = "Choose file...",
|
|
670
767
|
disabled = false,
|
|
671
768
|
required = false,
|
|
672
769
|
error = false,
|
|
@@ -769,7 +866,15 @@ function FileInput({
|
|
|
769
866
|
inputRef.current.value = "";
|
|
770
867
|
}
|
|
771
868
|
},
|
|
772
|
-
[
|
|
869
|
+
[
|
|
870
|
+
value,
|
|
871
|
+
onChange,
|
|
872
|
+
validateFile,
|
|
873
|
+
maxFiles,
|
|
874
|
+
multiple,
|
|
875
|
+
enableCropping,
|
|
876
|
+
onValidationError
|
|
877
|
+
]
|
|
773
878
|
);
|
|
774
879
|
const createCroppedImage = React7.useCallback(
|
|
775
880
|
async (imageUrl, cropArea) => {
|
|
@@ -795,13 +900,17 @@ function FileInput({
|
|
|
795
900
|
cropArea.width,
|
|
796
901
|
cropArea.height
|
|
797
902
|
);
|
|
798
|
-
canvas.toBlob(
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
903
|
+
canvas.toBlob(
|
|
904
|
+
(blob) => {
|
|
905
|
+
if (blob) {
|
|
906
|
+
resolve(blob);
|
|
907
|
+
} else {
|
|
908
|
+
reject(new Error("Failed to create blob from canvas"));
|
|
909
|
+
}
|
|
910
|
+
},
|
|
911
|
+
"image/jpeg",
|
|
912
|
+
0.95
|
|
913
|
+
);
|
|
805
914
|
};
|
|
806
915
|
image.onerror = () => {
|
|
807
916
|
reject(new Error("Failed to load image"));
|
|
@@ -821,11 +930,9 @@ function FileInput({
|
|
|
821
930
|
if (onCropComplete) {
|
|
822
931
|
onCropComplete(croppedBlob, imageToCrop.file);
|
|
823
932
|
}
|
|
824
|
-
const croppedFile = new File(
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
{ type: "image/jpeg" }
|
|
828
|
-
);
|
|
933
|
+
const croppedFile = new File([croppedBlob], imageToCrop.file.name, {
|
|
934
|
+
type: "image/jpeg"
|
|
935
|
+
});
|
|
829
936
|
const updatedFiles = multiple ? [...value, croppedFile] : [croppedFile];
|
|
830
937
|
onChange(updatedFiles);
|
|
831
938
|
setCropperOpen(false);
|
|
@@ -837,7 +944,15 @@ function FileInput({
|
|
|
837
944
|
} catch (error2) {
|
|
838
945
|
console.error("Failed to crop image:", error2);
|
|
839
946
|
}
|
|
840
|
-
}, [
|
|
947
|
+
}, [
|
|
948
|
+
imageToCrop,
|
|
949
|
+
croppedAreaPixels,
|
|
950
|
+
createCroppedImage,
|
|
951
|
+
onCropComplete,
|
|
952
|
+
value,
|
|
953
|
+
onChange,
|
|
954
|
+
multiple
|
|
955
|
+
]);
|
|
841
956
|
const handleCropCancel = React7.useCallback(() => {
|
|
842
957
|
if (imageToCrop) {
|
|
843
958
|
URL.revokeObjectURL(imageToCrop.url);
|
|
@@ -949,7 +1064,7 @@ function FileInput({
|
|
|
949
1064
|
), /* @__PURE__ */ React7.createElement(
|
|
950
1065
|
"div",
|
|
951
1066
|
{
|
|
952
|
-
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-
|
|
1067
|
+
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-red-500" : ""}`,
|
|
953
1068
|
onDragEnter: handleDrag,
|
|
954
1069
|
onDragLeave: handleDrag,
|
|
955
1070
|
onDragOver: handleDrag,
|
|
@@ -964,7 +1079,6 @@ function FileInput({
|
|
|
964
1079
|
/* @__PURE__ */ React7.createElement("div", { className: "flex flex-col items-center gap-2 text-center" }, /* @__PURE__ */ React7.createElement(
|
|
965
1080
|
"svg",
|
|
966
1081
|
{
|
|
967
|
-
className: "text-muted-foreground",
|
|
968
1082
|
width: "48",
|
|
969
1083
|
height: "48",
|
|
970
1084
|
viewBox: "0 0 24 24",
|
|
@@ -978,92 +1092,102 @@ function FileInput({
|
|
|
978
1092
|
/* @__PURE__ */ React7.createElement("path", { d: "M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" }),
|
|
979
1093
|
/* @__PURE__ */ React7.createElement("polyline", { points: "17 8 12 3 7 8" }),
|
|
980
1094
|
/* @__PURE__ */ React7.createElement("line", { x1: "12", y1: "3", x2: "12", y2: "15" })
|
|
981
|
-
), /* @__PURE__ */ React7.createElement("p", { className: "text-sm font-medium" }, value.length > 0 ? `${value.length} file(s) selected` : placeholder), accept && /* @__PURE__ */ React7.createElement("p", { className: "text-xs
|
|
1095
|
+
), /* @__PURE__ */ React7.createElement("p", { className: "text-sm font-medium" }, value.length > 0 ? `${value.length} file(s) selected` : placeholder), accept && /* @__PURE__ */ React7.createElement("p", { className: "text-xs" }, "Accepted: ", accept), maxSize && /* @__PURE__ */ React7.createElement("p", { className: "text-xs " }, "Max size: ", formatFileSize(maxSize)))
|
|
982
1096
|
), value.length > 0 && /* @__PURE__ */ React7.createElement("ul", { className: "flex flex-col gap-2 mt-4", role: "list" }, value.map((file, index) => {
|
|
983
1097
|
const previewUrl = showPreview ? getPreviewUrl(file) : null;
|
|
984
|
-
return /* @__PURE__ */ React7.createElement(
|
|
985
|
-
"
|
|
986
|
-
{
|
|
987
|
-
src: previewUrl,
|
|
988
|
-
alt: file.name,
|
|
989
|
-
className: "w-12 h-12 rounded object-cover",
|
|
990
|
-
width: "48",
|
|
991
|
-
height: "48"
|
|
992
|
-
}
|
|
993
|
-
), /* @__PURE__ */ React7.createElement("div", { className: "flex flex-col flex-1 min-w-0" }, /* @__PURE__ */ React7.createElement("span", { className: "text-sm font-medium truncate" }, file.name), /* @__PURE__ */ React7.createElement("span", { className: "text-xs text-muted-foreground" }, formatFileSize(file.size)), showProgress && uploadProgress[file.name] !== void 0 && /* @__PURE__ */ React7.createElement("div", { className: "flex items-center gap-2 mt-1" }, /* @__PURE__ */ React7.createElement(
|
|
994
|
-
"div",
|
|
1098
|
+
return /* @__PURE__ */ React7.createElement(
|
|
1099
|
+
"li",
|
|
995
1100
|
{
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
"aria-valuenow": uploadProgress[file.name],
|
|
999
|
-
"aria-valuemin": 0,
|
|
1000
|
-
"aria-valuemax": 100,
|
|
1001
|
-
"aria-label": `Upload progress: ${uploadProgress[file.name]}%`
|
|
1101
|
+
key: `${file.name}-${index}`,
|
|
1102
|
+
className: "flex items-center gap-3 p-3 rounded-md border border-border bg-card text-card-foreground hover:bg-primary/50 transition-colors"
|
|
1002
1103
|
},
|
|
1003
|
-
/* @__PURE__ */ React7.createElement(
|
|
1004
|
-
"
|
|
1104
|
+
previewUrl && /* @__PURE__ */ React7.createElement(
|
|
1105
|
+
"img",
|
|
1005
1106
|
{
|
|
1006
|
-
|
|
1007
|
-
|
|
1107
|
+
src: previewUrl,
|
|
1108
|
+
alt: file.name,
|
|
1109
|
+
className: "w-12 h-12 rounded object-cover",
|
|
1110
|
+
width: "48",
|
|
1111
|
+
height: "48"
|
|
1008
1112
|
}
|
|
1009
|
-
)
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
{
|
|
1013
|
-
type: "button",
|
|
1014
|
-
onClick: (e) => {
|
|
1015
|
-
e.stopPropagation();
|
|
1016
|
-
handleCrop(file);
|
|
1017
|
-
},
|
|
1018
|
-
disabled,
|
|
1019
|
-
className: "flex items-center justify-center h-8 w-8 rounded border-none bg-transparent hover:bg-accent text-muted-foreground hover:text-foreground transition-colors",
|
|
1020
|
-
"aria-label": `Crop ${file.name}`
|
|
1021
|
-
},
|
|
1022
|
-
/* @__PURE__ */ React7.createElement(
|
|
1023
|
-
"svg",
|
|
1113
|
+
),
|
|
1114
|
+
/* @__PURE__ */ React7.createElement("div", { className: "flex flex-col flex-1 min-w-0" }, /* @__PURE__ */ React7.createElement("span", { className: "text-sm font-medium truncate" }, file.name), /* @__PURE__ */ React7.createElement("span", { className: "text-xs" }, formatFileSize(file.size)), showProgress && uploadProgress[file.name] !== void 0 && /* @__PURE__ */ React7.createElement("div", { className: "flex items-center gap-2 mt-1" }, /* @__PURE__ */ React7.createElement(
|
|
1115
|
+
"div",
|
|
1024
1116
|
{
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
strokeLinecap: "round",
|
|
1032
|
-
strokeLinejoin: "round",
|
|
1033
|
-
"aria-hidden": "true"
|
|
1117
|
+
className: "h-1.5 bg-muted rounded-full overflow-hidden flex-1",
|
|
1118
|
+
role: "progressbar",
|
|
1119
|
+
"aria-valuenow": uploadProgress[file.name],
|
|
1120
|
+
"aria-valuemin": 0,
|
|
1121
|
+
"aria-valuemax": 100,
|
|
1122
|
+
"aria-label": `Upload progress: ${uploadProgress[file.name]}%`
|
|
1034
1123
|
},
|
|
1035
|
-
/* @__PURE__ */ React7.createElement(
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1124
|
+
/* @__PURE__ */ React7.createElement(
|
|
1125
|
+
"div",
|
|
1126
|
+
{
|
|
1127
|
+
className: "h-full bg-primary transition-all",
|
|
1128
|
+
style: { width: `${uploadProgress[file.name]}%` }
|
|
1129
|
+
}
|
|
1130
|
+
)
|
|
1131
|
+
), /* @__PURE__ */ React7.createElement("span", { className: "text-xs " }, uploadProgress[file.name], "%"))),
|
|
1132
|
+
enableCropping && file.type.startsWith("image/") && /* @__PURE__ */ React7.createElement(
|
|
1133
|
+
"button",
|
|
1134
|
+
{
|
|
1135
|
+
type: "button",
|
|
1136
|
+
onClick: (e) => {
|
|
1137
|
+
e.stopPropagation();
|
|
1138
|
+
handleCrop(file);
|
|
1139
|
+
},
|
|
1140
|
+
disabled,
|
|
1141
|
+
className: "flex items-center justify-center h-8 w-8 rounded border-none bg-transparent hover:bg-primary hover:text-primary-foreground transition-colors",
|
|
1142
|
+
"aria-label": `Crop ${file.name}`
|
|
1045
1143
|
},
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1144
|
+
/* @__PURE__ */ React7.createElement(
|
|
1145
|
+
"svg",
|
|
1146
|
+
{
|
|
1147
|
+
width: "20",
|
|
1148
|
+
height: "20",
|
|
1149
|
+
viewBox: "0 0 24 24",
|
|
1150
|
+
fill: "none",
|
|
1151
|
+
stroke: "currentColor",
|
|
1152
|
+
strokeWidth: "2",
|
|
1153
|
+
strokeLinecap: "round",
|
|
1154
|
+
strokeLinejoin: "round",
|
|
1155
|
+
"aria-hidden": "true"
|
|
1156
|
+
},
|
|
1157
|
+
/* @__PURE__ */ React7.createElement("path", { d: "M6.13 1L6 16a2 2 0 0 0 2 2h15" }),
|
|
1158
|
+
/* @__PURE__ */ React7.createElement("path", { d: "M1 6.13L16 6a2 2 0 0 1 2 2v15" })
|
|
1159
|
+
)
|
|
1160
|
+
),
|
|
1050
1161
|
/* @__PURE__ */ React7.createElement(
|
|
1051
|
-
"
|
|
1162
|
+
"button",
|
|
1052
1163
|
{
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
"aria-hidden": "true"
|
|
1164
|
+
type: "button",
|
|
1165
|
+
onClick: (e) => {
|
|
1166
|
+
e.stopPropagation();
|
|
1167
|
+
handleRemove(index);
|
|
1168
|
+
},
|
|
1169
|
+
disabled,
|
|
1170
|
+
className: "flex items-center justify-center h-8 w-8 rounded border-none bg-transparent hover:bg-primary hover:text-primary-foreground transition-colors",
|
|
1171
|
+
"aria-label": `Remove ${file.name}`
|
|
1062
1172
|
},
|
|
1063
|
-
/* @__PURE__ */ React7.createElement(
|
|
1064
|
-
|
|
1173
|
+
/* @__PURE__ */ React7.createElement(
|
|
1174
|
+
"svg",
|
|
1175
|
+
{
|
|
1176
|
+
width: "20",
|
|
1177
|
+
height: "20",
|
|
1178
|
+
viewBox: "0 0 24 24",
|
|
1179
|
+
fill: "none",
|
|
1180
|
+
stroke: "currentColor",
|
|
1181
|
+
strokeWidth: "2",
|
|
1182
|
+
strokeLinecap: "round",
|
|
1183
|
+
strokeLinejoin: "round",
|
|
1184
|
+
"aria-hidden": "true"
|
|
1185
|
+
},
|
|
1186
|
+
/* @__PURE__ */ React7.createElement("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
|
|
1187
|
+
/* @__PURE__ */ React7.createElement("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
|
|
1188
|
+
)
|
|
1065
1189
|
)
|
|
1066
|
-
)
|
|
1190
|
+
);
|
|
1067
1191
|
})), cropperOpen && imageToCrop && /* @__PURE__ */ React7.createElement("div", { className: "fixed inset-0 z-50 flex items-center justify-center" }, /* @__PURE__ */ React7.createElement(
|
|
1068
1192
|
"div",
|
|
1069
1193
|
{
|
|
@@ -1075,7 +1199,7 @@ function FileInput({
|
|
|
1075
1199
|
"button",
|
|
1076
1200
|
{
|
|
1077
1201
|
type: "button",
|
|
1078
|
-
className: "flex items-center justify-center h-8 w-8 rounded hover:bg-
|
|
1202
|
+
className: "flex items-center justify-center h-8 w-8 rounded hover:bg-primary hover:text-primary-foreground transition-colors",
|
|
1079
1203
|
onClick: handleCropCancel,
|
|
1080
1204
|
"aria-label": "Close"
|
|
1081
1205
|
},
|
|
@@ -1116,7 +1240,10 @@ function FileInput({
|
|
|
1116
1240
|
const img = e.currentTarget;
|
|
1117
1241
|
const containerWidth = 600;
|
|
1118
1242
|
const containerHeight = 400;
|
|
1119
|
-
const cropWidth = cropAspectRatio ? Math.min(
|
|
1243
|
+
const cropWidth = cropAspectRatio ? Math.min(
|
|
1244
|
+
containerWidth * 0.8,
|
|
1245
|
+
containerHeight * 0.8 * cropAspectRatio
|
|
1246
|
+
) : containerWidth * 0.8;
|
|
1120
1247
|
const cropHeight = cropAspectRatio ? cropWidth / cropAspectRatio : containerHeight * 0.8;
|
|
1121
1248
|
const scale = zoom;
|
|
1122
1249
|
const imgWidth = img.naturalWidth;
|
|
@@ -1145,7 +1272,16 @@ function FileInput({
|
|
|
1145
1272
|
},
|
|
1146
1273
|
/* @__PURE__ */ React7.createElement("div", { className: "absolute inset-0 grid grid-cols-3 grid-rows-3" }, /* @__PURE__ */ React7.createElement("div", { className: "border-r border-b border-primary/30" }), /* @__PURE__ */ React7.createElement("div", { className: "border-r border-b border-primary/30" }), /* @__PURE__ */ React7.createElement("div", { className: "border-b border-primary/30" }), /* @__PURE__ */ React7.createElement("div", { className: "border-r border-b border-primary/30" }), /* @__PURE__ */ React7.createElement("div", { className: "border-r border-b border-primary/30" }), /* @__PURE__ */ React7.createElement("div", { className: "border-b border-primary/30" }), /* @__PURE__ */ React7.createElement("div", { className: "border-r border-primary/30" }), /* @__PURE__ */ React7.createElement("div", { className: "border-r border-primary/30" }), /* @__PURE__ */ React7.createElement("div", null))
|
|
1147
1274
|
)
|
|
1148
|
-
), /* @__PURE__ */ React7.createElement("div", { className: "flex items-center gap-3 mt-4" }, /* @__PURE__ */ React7.createElement(
|
|
1275
|
+
), /* @__PURE__ */ React7.createElement("div", { className: "flex items-center gap-3 mt-4" }, /* @__PURE__ */ React7.createElement(
|
|
1276
|
+
"label",
|
|
1277
|
+
{
|
|
1278
|
+
htmlFor: "zoom-slider",
|
|
1279
|
+
className: "text-sm font-medium whitespace-nowrap"
|
|
1280
|
+
},
|
|
1281
|
+
"Zoom: ",
|
|
1282
|
+
zoom.toFixed(1),
|
|
1283
|
+
"x"
|
|
1284
|
+
), /* @__PURE__ */ React7.createElement(
|
|
1149
1285
|
"input",
|
|
1150
1286
|
{
|
|
1151
1287
|
id: "zoom-slider",
|
|
@@ -1162,7 +1298,7 @@ function FileInput({
|
|
|
1162
1298
|
"button",
|
|
1163
1299
|
{
|
|
1164
1300
|
type: "button",
|
|
1165
|
-
className: "inline-flex items-center justify-center h-9 rounded-md px-4 text-sm font-medium border border-input bg-transparent hover:bg-
|
|
1301
|
+
className: "inline-flex items-center justify-center h-9 rounded-md px-4 text-sm font-medium border border-input bg-transparent hover:bg-primary hover:text-primary-foreground transition-colors",
|
|
1166
1302
|
onClick: handleCropCancel
|
|
1167
1303
|
},
|
|
1168
1304
|
"Cancel"
|
|
@@ -1231,7 +1367,9 @@ function DatePicker({
|
|
|
1231
1367
|
}) {
|
|
1232
1368
|
const [isOpen, setIsOpen] = React7.useState(false);
|
|
1233
1369
|
const [inputValue, setInputValue] = React7.useState("");
|
|
1234
|
-
const [selectedMonth, setSelectedMonth] = React7.useState(
|
|
1370
|
+
const [selectedMonth, setSelectedMonth] = React7.useState(
|
|
1371
|
+
value || /* @__PURE__ */ new Date()
|
|
1372
|
+
);
|
|
1235
1373
|
const containerRef = React7.useRef(null);
|
|
1236
1374
|
const inputRef = React7.useRef(null);
|
|
1237
1375
|
React7.useEffect(() => {
|
|
@@ -1322,7 +1460,7 @@ function DatePicker({
|
|
|
1322
1460
|
"button",
|
|
1323
1461
|
{
|
|
1324
1462
|
type: "button",
|
|
1325
|
-
className: "flex items-center justify-center h-8 w-8 rounded border-none bg-transparent hover:bg-
|
|
1463
|
+
className: "flex items-center justify-center h-8 w-8 rounded border-none bg-transparent hover:bg-primary hover:text-primary-foreground cursor-pointer",
|
|
1326
1464
|
onClick: handlePrevMonth,
|
|
1327
1465
|
"aria-label": "Previous month"
|
|
1328
1466
|
},
|
|
@@ -1331,12 +1469,19 @@ function DatePicker({
|
|
|
1331
1469
|
"button",
|
|
1332
1470
|
{
|
|
1333
1471
|
type: "button",
|
|
1334
|
-
className: "flex items-center justify-center h-8 w-8 rounded border-none bg-transparent hover:bg-
|
|
1472
|
+
className: "flex items-center justify-center h-8 w-8 rounded border-none bg-transparent hover:bg-primary hover:text-primary-foreground cursor-pointer",
|
|
1335
1473
|
onClick: handleNextMonth,
|
|
1336
1474
|
"aria-label": "Next month"
|
|
1337
1475
|
},
|
|
1338
1476
|
"\u2192"
|
|
1339
|
-
)), /* @__PURE__ */ React7.createElement("div", { className: "grid grid-cols-7 gap-1 mt-2" }, ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"].map((day) => /* @__PURE__ */ React7.createElement(
|
|
1477
|
+
)), /* @__PURE__ */ React7.createElement("div", { className: "grid grid-cols-7 gap-1 mt-2" }, ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"].map((day) => /* @__PURE__ */ React7.createElement(
|
|
1478
|
+
"div",
|
|
1479
|
+
{
|
|
1480
|
+
key: day,
|
|
1481
|
+
className: "flex items-center justify-center h-8 w-full text-xs font-medium"
|
|
1482
|
+
},
|
|
1483
|
+
day
|
|
1484
|
+
))), /* @__PURE__ */ React7.createElement("div", { className: "grid grid-cols-7 gap-1" }, days.map((date, index) => {
|
|
1340
1485
|
if (!date) {
|
|
1341
1486
|
return /* @__PURE__ */ React7.createElement("div", { key: `empty-${index}` });
|
|
1342
1487
|
}
|
|
@@ -1348,7 +1493,7 @@ function DatePicker({
|
|
|
1348
1493
|
{
|
|
1349
1494
|
key: date.toISOString(),
|
|
1350
1495
|
type: "button",
|
|
1351
|
-
className: `flex items-center justify-center h-8 w-full rounded border-none bg-transparent cursor-pointer text-sm transition-colors hover:bg-
|
|
1496
|
+
className: `flex items-center justify-center h-8 w-full rounded border-none bg-transparent cursor-pointer text-sm transition-colors hover:bg-primary hover:text-primary-foreground ${isSelected ? "bg-primary text-primary-foreground font-semibold" : ""} ${isToday ? "border border-primary" : ""} ${disabled2 ? "cursor-not-allowed opacity-50 pointer-events-none" : ""}`,
|
|
1352
1497
|
onClick: () => !disabled2 && handleDateSelect(date),
|
|
1353
1498
|
disabled: disabled2,
|
|
1354
1499
|
"aria-label": formatDate(date, format)
|
|
@@ -1365,26 +1510,33 @@ function DatePicker({
|
|
|
1365
1510
|
name,
|
|
1366
1511
|
value: value ? value.toISOString() : ""
|
|
1367
1512
|
}
|
|
1368
|
-
), /* @__PURE__ */ React7.createElement("div", { className: "relative" }, showIcon && /* @__PURE__ */ React7.createElement(
|
|
1369
|
-
"
|
|
1513
|
+
), /* @__PURE__ */ React7.createElement("div", { className: "relative" }, showIcon && /* @__PURE__ */ React7.createElement(
|
|
1514
|
+
"span",
|
|
1370
1515
|
{
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
height: "18",
|
|
1374
|
-
viewBox: "0 0 24 24",
|
|
1375
|
-
fill: "none",
|
|
1376
|
-
stroke: "currentColor",
|
|
1377
|
-
strokeLinecap: "round",
|
|
1378
|
-
strokeLinejoin: "round",
|
|
1379
|
-
strokeWidth: "2"
|
|
1516
|
+
className: "absolute left-3 top-1/2 -translate-y-1/2 pointer-events-none",
|
|
1517
|
+
"aria-hidden": "true"
|
|
1380
1518
|
},
|
|
1381
|
-
/* @__PURE__ */ React7.createElement(
|
|
1382
|
-
|
|
1519
|
+
/* @__PURE__ */ React7.createElement(
|
|
1520
|
+
"svg",
|
|
1521
|
+
{
|
|
1522
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
1523
|
+
width: "18",
|
|
1524
|
+
height: "18",
|
|
1525
|
+
viewBox: "0 0 24 24",
|
|
1526
|
+
fill: "none",
|
|
1527
|
+
stroke: "currentColor",
|
|
1528
|
+
strokeLinecap: "round",
|
|
1529
|
+
strokeLinejoin: "round",
|
|
1530
|
+
strokeWidth: "2"
|
|
1531
|
+
},
|
|
1532
|
+
/* @__PURE__ */ React7.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" })
|
|
1533
|
+
)
|
|
1534
|
+
), /* @__PURE__ */ React7.createElement(
|
|
1383
1535
|
"input",
|
|
1384
1536
|
{
|
|
1385
1537
|
ref: inputRef,
|
|
1386
1538
|
type: "text",
|
|
1387
|
-
className: `flex h-9 w-full rounded-md border border-input bg-transparent ${showIcon ? "pl-10" : "pl-3"} ${clearable && value ? "pr-10" : "pr-3"} py-1 text-base shadow-sm transition-colors
|
|
1539
|
+
className: `flex h-9 w-full rounded-md border border-input bg-transparent ${showIcon ? "pl-10" : "pl-3"} ${clearable && value ? "pr-10" : "pr-3"} py-1 text-base shadow-sm transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 md:text-sm ${error ? "border-red-500 ring-1 ring-red-500" : ""}`,
|
|
1388
1540
|
value: inputValue,
|
|
1389
1541
|
onChange: handleInputChange,
|
|
1390
1542
|
onClick: handleToggle,
|
|
@@ -1401,7 +1553,7 @@ function DatePicker({
|
|
|
1401
1553
|
"button",
|
|
1402
1554
|
{
|
|
1403
1555
|
type: "button",
|
|
1404
|
-
className: "absolute right-3 top-1/2 -translate-y-1/2
|
|
1556
|
+
className: "absolute right-3 top-1/2 -translate-y-1/2 transition-colors",
|
|
1405
1557
|
onClick: handleClear,
|
|
1406
1558
|
"aria-label": "Clear date",
|
|
1407
1559
|
tabIndex: -1
|
|
@@ -1540,36 +1692,43 @@ function TimePicker({
|
|
|
1540
1692
|
}
|
|
1541
1693
|
return mins;
|
|
1542
1694
|
}, [minuteStep]);
|
|
1543
|
-
const combinedClassName =
|
|
1695
|
+
const combinedClassName = cn("relative", className);
|
|
1544
1696
|
const displayValue = formatTimeValue(timeValue, use24Hour);
|
|
1545
|
-
return /* @__PURE__ */ React7.createElement("div", { ref: containerRef, className: combinedClassName }, /* @__PURE__ */ React7.createElement(
|
|
1546
|
-
"
|
|
1697
|
+
return /* @__PURE__ */ React7.createElement("div", { ref: containerRef, className: combinedClassName }, /* @__PURE__ */ React7.createElement("input", { type: "hidden", name, value }), /* @__PURE__ */ React7.createElement("div", { className: "relative" }, showIcon && /* @__PURE__ */ React7.createElement(
|
|
1698
|
+
"span",
|
|
1547
1699
|
{
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
value
|
|
1551
|
-
}
|
|
1552
|
-
), /* @__PURE__ */ React7.createElement("div", { className: "relative" }, showIcon && /* @__PURE__ */ React7.createElement("span", { className: "absolute left-3 top-1/2 -translate-y-1/2 text-muted-foreground pointer-events-none", "aria-hidden": "true" }, /* @__PURE__ */ React7.createElement(
|
|
1553
|
-
"svg",
|
|
1554
|
-
{
|
|
1555
|
-
xmlns: "http://www.w3.org/2000/svg",
|
|
1556
|
-
width: "18",
|
|
1557
|
-
height: "18",
|
|
1558
|
-
viewBox: "0 0 24 24",
|
|
1559
|
-
fill: "none",
|
|
1560
|
-
stroke: "currentColor",
|
|
1561
|
-
strokeLinecap: "round",
|
|
1562
|
-
strokeLinejoin: "round",
|
|
1563
|
-
strokeWidth: "2"
|
|
1700
|
+
className: "absolute left-3 top-1/2 -translate-y-1/2 pointer-events-none",
|
|
1701
|
+
"aria-hidden": "true"
|
|
1564
1702
|
},
|
|
1565
|
-
/* @__PURE__ */ React7.createElement(
|
|
1566
|
-
|
|
1567
|
-
|
|
1703
|
+
/* @__PURE__ */ React7.createElement(
|
|
1704
|
+
"svg",
|
|
1705
|
+
{
|
|
1706
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
1707
|
+
width: "18",
|
|
1708
|
+
height: "18",
|
|
1709
|
+
viewBox: "0 0 24 24",
|
|
1710
|
+
fill: "none",
|
|
1711
|
+
stroke: "currentColor",
|
|
1712
|
+
strokeLinecap: "round",
|
|
1713
|
+
strokeLinejoin: "round",
|
|
1714
|
+
strokeWidth: "2"
|
|
1715
|
+
},
|
|
1716
|
+
/* @__PURE__ */ React7.createElement("circle", { cx: "12", cy: "12", r: "10" }),
|
|
1717
|
+
/* @__PURE__ */ React7.createElement("path", { d: "M12 6v6l4 2" })
|
|
1718
|
+
)
|
|
1719
|
+
), /* @__PURE__ */ React7.createElement(
|
|
1568
1720
|
"input",
|
|
1569
1721
|
{
|
|
1570
1722
|
ref: inputRef,
|
|
1571
1723
|
type: "text",
|
|
1572
|
-
className:
|
|
1724
|
+
className: cn(
|
|
1725
|
+
"flex h-9 w-full rounded-md border border-input bg-transparent py-1 text-base shadow-sm transition-colors",
|
|
1726
|
+
"focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring",
|
|
1727
|
+
"disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
|
|
1728
|
+
showIcon ? "pl-10" : "pl-3",
|
|
1729
|
+
clearable && value ? "pr-10" : "pr-3",
|
|
1730
|
+
error && "border-red-500 ring-1 ring-red-500"
|
|
1731
|
+
),
|
|
1573
1732
|
value: displayValue,
|
|
1574
1733
|
onClick: handleToggle,
|
|
1575
1734
|
onBlur,
|
|
@@ -1585,13 +1744,13 @@ function TimePicker({
|
|
|
1585
1744
|
"button",
|
|
1586
1745
|
{
|
|
1587
1746
|
type: "button",
|
|
1588
|
-
className: "absolute right-3 top-1/2 -translate-y-1/2
|
|
1747
|
+
className: "absolute right-3 top-1/2 -translate-y-1/2 transition-colors",
|
|
1589
1748
|
onClick: handleClear,
|
|
1590
1749
|
"aria-label": "Clear time",
|
|
1591
1750
|
tabIndex: -1
|
|
1592
1751
|
},
|
|
1593
1752
|
"\u2715"
|
|
1594
|
-
)), isOpen && !disabled && /* @__PURE__ */ React7.createElement("div", { className: "absolute z-50 top-full mt-1 min-w-full rounded-md border border-border bg-popover text-popover-foreground shadow-md p-3" }, /* @__PURE__ */ React7.createElement("div", { className: "flex gap-2" }, /* @__PURE__ */ React7.createElement("div", { className: "flex flex-col flex-1" }, /* @__PURE__ */ React7.createElement("div", { className: "text-xs font-medium
|
|
1753
|
+
)), isOpen && !disabled && /* @__PURE__ */ React7.createElement("div", { className: "absolute z-50 top-full mt-1 min-w-full rounded-md border border-border bg-popover text-popover-foreground shadow-md p-3" }, /* @__PURE__ */ React7.createElement("div", { className: "flex gap-2" }, /* @__PURE__ */ React7.createElement("div", { className: "flex flex-col flex-1" }, /* @__PURE__ */ React7.createElement("div", { className: "text-xs font-medium mb-2 text-center" }, use24Hour ? "Hour" : "Hour"), /* @__PURE__ */ React7.createElement("div", { className: "flex flex-col gap-1 max-h-48 overflow-y-auto" }, hours.map((hour) => {
|
|
1595
1754
|
const displayHour = use24Hour ? hour : hour;
|
|
1596
1755
|
const isSelected = use24Hour ? timeValue?.hour === (hour === 0 ? 12 : hour > 12 ? hour - 12 : hour) && timeValue?.period === (hour >= 12 ? "PM" : "AM") : timeValue?.hour === hour;
|
|
1597
1756
|
return /* @__PURE__ */ React7.createElement(
|
|
@@ -1599,7 +1758,12 @@ function TimePicker({
|
|
|
1599
1758
|
{
|
|
1600
1759
|
key: hour,
|
|
1601
1760
|
type: "button",
|
|
1602
|
-
className:
|
|
1761
|
+
className: cn(
|
|
1762
|
+
"flex items-center justify-center h-8 w-full rounded",
|
|
1763
|
+
"border-none bg-transparent cursor-pointer text-sm transition-colors",
|
|
1764
|
+
"hover:bg-primary hover:text-primary-foreground",
|
|
1765
|
+
isSelected ? "bg-primary text-primary-foreground font-semibold" : ""
|
|
1766
|
+
),
|
|
1603
1767
|
onClick: () => {
|
|
1604
1768
|
if (use24Hour) {
|
|
1605
1769
|
const hour12 = hour === 0 ? 12 : hour > 12 ? hour - 12 : hour;
|
|
@@ -1619,24 +1783,34 @@ function TimePicker({
|
|
|
1619
1783
|
},
|
|
1620
1784
|
String(displayHour).padStart(2, "0")
|
|
1621
1785
|
);
|
|
1622
|
-
}))), /* @__PURE__ */ React7.createElement("div", { className: "flex flex-col flex-1" }, /* @__PURE__ */ React7.createElement("div", { className: "text-xs font-medium
|
|
1786
|
+
}))), /* @__PURE__ */ React7.createElement("div", { className: "flex flex-col flex-1" }, /* @__PURE__ */ React7.createElement("div", { className: "text-xs font-medium mb-2 text-center" }, "Minute"), /* @__PURE__ */ React7.createElement("div", { className: "flex flex-col gap-1 max-h-48 overflow-y-auto" }, minutes.map((minute) => {
|
|
1623
1787
|
const isSelected = timeValue?.minute === minute;
|
|
1624
1788
|
return /* @__PURE__ */ React7.createElement(
|
|
1625
1789
|
"button",
|
|
1626
1790
|
{
|
|
1627
1791
|
key: minute,
|
|
1628
1792
|
type: "button",
|
|
1629
|
-
className:
|
|
1793
|
+
className: cn(
|
|
1794
|
+
"flex items-center justify-center h-8 w-full",
|
|
1795
|
+
"rounded border-none bg-transparent cursor-pointer text-sm transition-colors",
|
|
1796
|
+
"hover:bg-primary hover:text-primary-foreground",
|
|
1797
|
+
isSelected ? "bg-primary text-primary-foreground font-semibold" : ""
|
|
1798
|
+
),
|
|
1630
1799
|
onClick: () => handleMinuteChange(minute),
|
|
1631
1800
|
"aria-label": `${String(minute).padStart(2, "0")} minutes`
|
|
1632
1801
|
},
|
|
1633
1802
|
String(minute).padStart(2, "0")
|
|
1634
1803
|
);
|
|
1635
|
-
}))), !use24Hour && /* @__PURE__ */ React7.createElement("div", { className: "flex flex-col w-20" }, /* @__PURE__ */ React7.createElement("div", { className: "text-xs font-medium
|
|
1804
|
+
}))), !use24Hour && /* @__PURE__ */ React7.createElement("div", { className: "flex flex-col w-20" }, /* @__PURE__ */ React7.createElement("div", { className: "text-xs font-medium mb-2 text-center" }, "Period"), /* @__PURE__ */ React7.createElement("div", { className: "flex flex-col gap-1" }, /* @__PURE__ */ React7.createElement(
|
|
1636
1805
|
"button",
|
|
1637
1806
|
{
|
|
1638
1807
|
type: "button",
|
|
1639
|
-
className:
|
|
1808
|
+
className: cn(
|
|
1809
|
+
"flex items-center justify-center h-8 w-full",
|
|
1810
|
+
"rounded border-none bg-transparent cursor-pointer text-sm",
|
|
1811
|
+
"transition-colors hover:bg-primary hover:text-primary-foreground",
|
|
1812
|
+
timeValue?.period === "AM" ? "bg-muted font-semibold" : ""
|
|
1813
|
+
),
|
|
1640
1814
|
onClick: () => handlePeriodChange("AM")
|
|
1641
1815
|
},
|
|
1642
1816
|
"AM"
|
|
@@ -1644,7 +1818,12 @@ function TimePicker({
|
|
|
1644
1818
|
"button",
|
|
1645
1819
|
{
|
|
1646
1820
|
type: "button",
|
|
1647
|
-
className:
|
|
1821
|
+
className: cn(
|
|
1822
|
+
"flex items-center justify-center h-8 w-full",
|
|
1823
|
+
"rounded border-none bg-transparent cursor-pointer text-sm",
|
|
1824
|
+
"transition-colors hover:bg-primary hover:text-primary-foreground",
|
|
1825
|
+
timeValue?.period === "PM" ? "bg-muted font-semibold" : ""
|
|
1826
|
+
),
|
|
1648
1827
|
onClick: () => handlePeriodChange("PM")
|
|
1649
1828
|
},
|
|
1650
1829
|
"PM"
|
|
@@ -1689,7 +1868,9 @@ function DateRangePicker({
|
|
|
1689
1868
|
...props
|
|
1690
1869
|
}) {
|
|
1691
1870
|
const [isOpen, setIsOpen] = React7.useState(false);
|
|
1692
|
-
const [selectedMonth, setSelectedMonth] = React7.useState(
|
|
1871
|
+
const [selectedMonth, setSelectedMonth] = React7.useState(
|
|
1872
|
+
value.start || /* @__PURE__ */ new Date()
|
|
1873
|
+
);
|
|
1693
1874
|
const [rangeStart, setRangeStart] = React7.useState(value.start);
|
|
1694
1875
|
const [rangeEnd, setRangeEnd] = React7.useState(value.end);
|
|
1695
1876
|
const [hoverDate, setHoverDate] = React7.useState(null);
|
|
@@ -1787,7 +1968,7 @@ function DateRangePicker({
|
|
|
1787
1968
|
"button",
|
|
1788
1969
|
{
|
|
1789
1970
|
type: "button",
|
|
1790
|
-
className: "flex items-center justify-center h-8 w-8 rounded border-none bg-transparent hover:bg-
|
|
1971
|
+
className: "flex items-center justify-center h-8 w-8 rounded border-none bg-transparent hover:bg-primary hover:text-primary-foreground cursor-pointer",
|
|
1791
1972
|
onClick: handlePrevMonth,
|
|
1792
1973
|
"aria-label": "Previous month"
|
|
1793
1974
|
},
|
|
@@ -1796,19 +1977,30 @@ function DateRangePicker({
|
|
|
1796
1977
|
"button",
|
|
1797
1978
|
{
|
|
1798
1979
|
type: "button",
|
|
1799
|
-
className: "flex items-center justify-center h-8 w-8 rounded border-none bg-transparent hover:bg-
|
|
1980
|
+
className: "flex items-center justify-center h-8 w-8 rounded border-none bg-transparent hover:bg-primary hover:text-primary-foreground cursor-pointer",
|
|
1800
1981
|
onClick: handleNextMonth,
|
|
1801
1982
|
"aria-label": "Next month"
|
|
1802
1983
|
},
|
|
1803
1984
|
"\u2192"
|
|
1804
|
-
)), /* @__PURE__ */ React7.createElement("div", { className: "grid grid-cols-7 gap-1 mt-2" }, ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"].map((day) => /* @__PURE__ */ React7.createElement(
|
|
1985
|
+
)), /* @__PURE__ */ React7.createElement("div", { className: "grid grid-cols-7 gap-1 mt-2" }, ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"].map((day) => /* @__PURE__ */ React7.createElement(
|
|
1986
|
+
"div",
|
|
1987
|
+
{
|
|
1988
|
+
key: day,
|
|
1989
|
+
className: "flex items-center justify-center h-8 w-full text-xs font-medium"
|
|
1990
|
+
},
|
|
1991
|
+
day
|
|
1992
|
+
))), /* @__PURE__ */ React7.createElement("div", { className: "grid grid-cols-7 gap-1" }, days.map((date, index) => {
|
|
1805
1993
|
if (!date) {
|
|
1806
1994
|
return /* @__PURE__ */ React7.createElement("div", { key: `empty-${index}` });
|
|
1807
1995
|
}
|
|
1808
1996
|
const isStart = rangeStart && date.toDateString() === rangeStart.toDateString();
|
|
1809
1997
|
const isEnd = rangeEnd && date.toDateString() === rangeEnd.toDateString();
|
|
1998
|
+
const isRangeEndpoint = Boolean(isStart || isEnd);
|
|
1810
1999
|
const isInRange = rangeStart && rangeEnd && isDateInRange(date, rangeStart, rangeEnd);
|
|
1811
2000
|
const isInHoverRange = rangeStart && !rangeEnd && hoverDate && (date >= rangeStart && date <= hoverDate || date <= rangeStart && date >= hoverDate);
|
|
2001
|
+
const isRangeHighlight = Boolean(
|
|
2002
|
+
(isInRange || isInHoverRange) && !isRangeEndpoint
|
|
2003
|
+
);
|
|
1812
2004
|
const isToday = date.toDateString() === (/* @__PURE__ */ new Date()).toDateString();
|
|
1813
2005
|
const disabled2 = isDisabled(date);
|
|
1814
2006
|
return /* @__PURE__ */ React7.createElement(
|
|
@@ -1816,7 +2008,14 @@ function DateRangePicker({
|
|
|
1816
2008
|
{
|
|
1817
2009
|
key: date.toISOString(),
|
|
1818
2010
|
type: "button",
|
|
1819
|
-
className:
|
|
2011
|
+
className: cn(
|
|
2012
|
+
"flex items-center justify-center h-8 w-full rounded border-none bg-transparent",
|
|
2013
|
+
"cursor-pointer text-sm transition-colors hover:bg-muted",
|
|
2014
|
+
isRangeEndpoint && "bg-muted font-semibold",
|
|
2015
|
+
isRangeHighlight && "bg-muted/70",
|
|
2016
|
+
isToday && "border border-primary",
|
|
2017
|
+
disabled2 && "cursor-not-allowed opacity-50 pointer-events-none"
|
|
2018
|
+
),
|
|
1820
2019
|
onClick: () => !disabled2 && handleDateSelect(date),
|
|
1821
2020
|
onMouseEnter: () => setHoverDate(date),
|
|
1822
2021
|
onMouseLeave: () => setHoverDate(null),
|
|
@@ -1827,7 +2026,7 @@ function DateRangePicker({
|
|
|
1827
2026
|
);
|
|
1828
2027
|
})));
|
|
1829
2028
|
};
|
|
1830
|
-
const combinedClassName =
|
|
2029
|
+
const combinedClassName = cn("relative", className);
|
|
1831
2030
|
const displayValue = rangeStart && rangeEnd ? `${formatDate2(rangeStart, format)}${separator}${formatDate2(rangeEnd, format)}` : rangeStart ? formatDate2(rangeStart, format) : "";
|
|
1832
2031
|
return /* @__PURE__ */ React7.createElement("div", { ref: containerRef, className: combinedClassName }, /* @__PURE__ */ React7.createElement(
|
|
1833
2032
|
"input",
|
|
@@ -1843,25 +2042,39 @@ function DateRangePicker({
|
|
|
1843
2042
|
name: `${name}[end]`,
|
|
1844
2043
|
value: rangeEnd ? rangeEnd.toISOString() : ""
|
|
1845
2044
|
}
|
|
1846
|
-
), /* @__PURE__ */ React7.createElement("div", { className: "relative" }, showIcon && /* @__PURE__ */ React7.createElement(
|
|
1847
|
-
"
|
|
2045
|
+
), /* @__PURE__ */ React7.createElement("div", { className: "relative" }, showIcon && /* @__PURE__ */ React7.createElement(
|
|
2046
|
+
"span",
|
|
1848
2047
|
{
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
height: "18",
|
|
1852
|
-
viewBox: "0 0 24 24",
|
|
1853
|
-
fill: "none",
|
|
1854
|
-
stroke: "currentColor",
|
|
1855
|
-
strokeLinecap: "round",
|
|
1856
|
-
strokeLinejoin: "round",
|
|
1857
|
-
strokeWidth: "2"
|
|
2048
|
+
className: "absolute left-3 top-1/2 -translate-y-1/2 pointer-events-none",
|
|
2049
|
+
"aria-hidden": "true"
|
|
1858
2050
|
},
|
|
1859
|
-
/* @__PURE__ */ React7.createElement(
|
|
1860
|
-
|
|
2051
|
+
/* @__PURE__ */ React7.createElement(
|
|
2052
|
+
"svg",
|
|
2053
|
+
{
|
|
2054
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
2055
|
+
width: "18",
|
|
2056
|
+
height: "18",
|
|
2057
|
+
viewBox: "0 0 24 24",
|
|
2058
|
+
fill: "none",
|
|
2059
|
+
stroke: "currentColor",
|
|
2060
|
+
strokeLinecap: "round",
|
|
2061
|
+
strokeLinejoin: "round",
|
|
2062
|
+
strokeWidth: "2"
|
|
2063
|
+
},
|
|
2064
|
+
/* @__PURE__ */ React7.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" })
|
|
2065
|
+
)
|
|
2066
|
+
), /* @__PURE__ */ React7.createElement(
|
|
1861
2067
|
"input",
|
|
1862
2068
|
{
|
|
1863
2069
|
type: "text",
|
|
1864
|
-
className:
|
|
2070
|
+
className: cn(
|
|
2071
|
+
"flex h-9 w-full rounded-md border border-input bg-transparent py-1 text-base shadow-sm transition-colors",
|
|
2072
|
+
"focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring",
|
|
2073
|
+
"disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
|
|
2074
|
+
showIcon ? "pl-10" : "pl-3",
|
|
2075
|
+
clearable && (rangeStart || rangeEnd) ? "pr-10" : "pr-3",
|
|
2076
|
+
error && "border-red-500 ring-1 ring-red-500"
|
|
2077
|
+
),
|
|
1865
2078
|
value: displayValue,
|
|
1866
2079
|
onClick: handleToggle,
|
|
1867
2080
|
onBlur,
|
|
@@ -1877,13 +2090,13 @@ function DateRangePicker({
|
|
|
1877
2090
|
"button",
|
|
1878
2091
|
{
|
|
1879
2092
|
type: "button",
|
|
1880
|
-
className: "absolute right-3 top-1/2 -translate-y-1/2
|
|
2093
|
+
className: "absolute right-3 top-1/2 -translate-y-1/2 transition-colors",
|
|
1881
2094
|
onClick: handleClear,
|
|
1882
2095
|
"aria-label": "Clear date range",
|
|
1883
2096
|
tabIndex: -1
|
|
1884
2097
|
},
|
|
1885
2098
|
"\u2715"
|
|
1886
|
-
)), isOpen && !disabled && /* @__PURE__ */ React7.createElement("div", { className: "absolute z-50 top-full mt-1 min-w-full rounded-md border border-border bg-popover text-popover-foreground shadow-md p-3" }, renderCalendar(), rangeStart && !rangeEnd && /* @__PURE__ */ React7.createElement("div", { className: "text-xs text-
|
|
2099
|
+
)), isOpen && !disabled && /* @__PURE__ */ React7.createElement("div", { className: "absolute z-50 top-full mt-1 min-w-full rounded-md border border-border bg-popover text-popover-foreground shadow-md p-3" }, renderCalendar(), rangeStart && !rangeEnd && /* @__PURE__ */ React7.createElement("div", { className: "text-xs text-center pt-2 border-t border-border mt-2" }, "Select end date")));
|
|
1887
2100
|
}
|
|
1888
2101
|
DateRangePicker.displayName = "DateRangePicker";
|
|
1889
2102
|
function htmlToMarkdown(html) {
|
|
@@ -1939,11 +2152,19 @@ function RichTextEditor({
|
|
|
1939
2152
|
className = "",
|
|
1940
2153
|
mode = "wysiwyg",
|
|
1941
2154
|
allowModeSwitch = false,
|
|
1942
|
-
placeholder = "
|
|
2155
|
+
placeholder = "Your message...",
|
|
1943
2156
|
minHeight = "200px",
|
|
1944
2157
|
maxHeight,
|
|
1945
2158
|
showToolbar = true,
|
|
1946
|
-
toolbarButtons = [
|
|
2159
|
+
toolbarButtons = [
|
|
2160
|
+
"bold",
|
|
2161
|
+
"italic",
|
|
2162
|
+
"underline",
|
|
2163
|
+
"heading",
|
|
2164
|
+
"bulletList",
|
|
2165
|
+
"orderedList",
|
|
2166
|
+
"link"
|
|
2167
|
+
],
|
|
1947
2168
|
...props
|
|
1948
2169
|
}) {
|
|
1949
2170
|
const [currentMode, setCurrentMode] = React7.useState(mode);
|
|
@@ -2052,7 +2273,7 @@ function RichTextEditor({
|
|
|
2052
2273
|
{
|
|
2053
2274
|
key: buttonName,
|
|
2054
2275
|
type: "button",
|
|
2055
|
-
className: "flex items-center justify-center h-8 w-8 rounded border-none bg-transparent hover:bg-
|
|
2276
|
+
className: "flex items-center justify-center h-8 w-8 rounded border-none bg-transparent hover:bg-muted cursor-pointer transition-colors disabled:cursor-not-allowed disabled:opacity-50",
|
|
2056
2277
|
onClick: () => editorRef.current && button.action(editorRef.current),
|
|
2057
2278
|
title: button.title,
|
|
2058
2279
|
disabled: disabled || currentMode === "markdown",
|
|
@@ -2064,7 +2285,7 @@ function RichTextEditor({
|
|
|
2064
2285
|
"button",
|
|
2065
2286
|
{
|
|
2066
2287
|
type: "button",
|
|
2067
|
-
className: "flex items-center justify-center h-8 px-3 rounded border-none bg-transparent hover:bg-
|
|
2288
|
+
className: "flex items-center justify-center h-8 px-3 rounded border-none bg-transparent hover:bg-muted text-xs font-medium cursor-pointer transition-colors disabled:cursor-not-allowed disabled:opacity-50",
|
|
2068
2289
|
onClick: handleModeToggle,
|
|
2069
2290
|
disabled,
|
|
2070
2291
|
title: `Switch to ${currentMode === "wysiwyg" ? "Markdown" : "WYSIWYG"}`,
|
|
@@ -2075,7 +2296,7 @@ function RichTextEditor({
|
|
|
2075
2296
|
"div",
|
|
2076
2297
|
{
|
|
2077
2298
|
ref: editorRef,
|
|
2078
|
-
className: "w-full p-3 text-base md:text-sm outline-none bg-transparent focus-visible:outline-none [&:empty:before]:content-[attr(data-placeholder)]
|
|
2299
|
+
className: "w-full p-3 text-base md:text-sm outline-none bg-transparent focus-visible:outline-none [&:empty:before]:content-[attr(data-placeholder)]",
|
|
2079
2300
|
role: "textbox",
|
|
2080
2301
|
contentEditable: !disabled,
|
|
2081
2302
|
onInput: handleWysiwygChange,
|
|
@@ -2090,7 +2311,7 @@ function RichTextEditor({
|
|
|
2090
2311
|
"textarea",
|
|
2091
2312
|
{
|
|
2092
2313
|
ref: textareaRef,
|
|
2093
|
-
className: "w-full p-3 text-base md:text-sm outline-none bg-transparent resize-none focus-visible:outline-none
|
|
2314
|
+
className: "w-full p-3 text-base md:text-sm outline-none bg-transparent resize-none focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50",
|
|
2094
2315
|
value: content,
|
|
2095
2316
|
onChange: handleMarkdownChange,
|
|
2096
2317
|
onBlur,
|