@page-speed/forms 0.4.1 → 0.4.2
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/inputs.cjs +231 -119
- package/dist/inputs.cjs.map +1 -1
- package/dist/inputs.d.cts +13 -2
- package/dist/inputs.d.ts +13 -2
- package/dist/inputs.js +231 -119
- package/dist/inputs.js.map +1 -1
- package/package.json +4 -2
package/dist/inputs.d.cts
CHANGED
|
@@ -131,6 +131,10 @@ interface CheckboxProps extends Omit<InputProps<boolean>, "onChange" | "placehol
|
|
|
131
131
|
* Optional description text below the label (secondary text)
|
|
132
132
|
*/
|
|
133
133
|
description?: React.ReactNode;
|
|
134
|
+
/**
|
|
135
|
+
* Layout variant
|
|
136
|
+
*/
|
|
137
|
+
checkboxVariant?: "boxed" | "inline";
|
|
134
138
|
/**
|
|
135
139
|
* Additional native input attributes
|
|
136
140
|
*/
|
|
@@ -178,7 +182,7 @@ interface CheckboxProps extends Omit<InputProps<boolean>, "onChange" | "placehol
|
|
|
178
182
|
*
|
|
179
183
|
* @see https://opensite.ai/developers/page-speed/forms/checkbox
|
|
180
184
|
*/
|
|
181
|
-
declare function Checkbox({ name, value, onChange, onBlur, disabled, required, error, className, indeterminate, label, description, ...props }: CheckboxProps): React.JSX.Element;
|
|
185
|
+
declare function Checkbox({ name, value, onChange, onBlur, disabled, required, error, className, indeterminate, label, description, checkboxVariant, ...props }: CheckboxProps): React.JSX.Element;
|
|
182
186
|
declare namespace Checkbox {
|
|
183
187
|
var displayName: string;
|
|
184
188
|
}
|
|
@@ -363,6 +367,13 @@ interface RadioProps extends Omit<InputProps<string>, "onChange" | "placeholder"
|
|
|
363
367
|
* @default "stacked"
|
|
364
368
|
*/
|
|
365
369
|
layout?: "inline" | "stacked";
|
|
370
|
+
/**
|
|
371
|
+
* Visual variant for radio options
|
|
372
|
+
* - "boxed": bordered card with ring on hover/selected, radio circle on right
|
|
373
|
+
* - "inline": minimal style, radio circle on left
|
|
374
|
+
* @default "inline"
|
|
375
|
+
*/
|
|
376
|
+
radioVariant?: "boxed" | "inline";
|
|
366
377
|
/**
|
|
367
378
|
* Group-level label
|
|
368
379
|
*/
|
|
@@ -424,7 +435,7 @@ interface RadioProps extends Omit<InputProps<string>, "onChange" | "placeholder"
|
|
|
424
435
|
*
|
|
425
436
|
* @see https://opensite.ai/developers/page-speed/forms/radio
|
|
426
437
|
*/
|
|
427
|
-
declare function Radio({ name, value, onChange, onBlur, disabled, required, error, className, layout, label, options, ...props }: RadioProps): React.JSX.Element;
|
|
438
|
+
declare function Radio({ name, value, onChange, onBlur, disabled, required, error, className, layout, radioVariant, label, options, ...props }: RadioProps): React.JSX.Element;
|
|
428
439
|
declare namespace Radio {
|
|
429
440
|
var displayName: string;
|
|
430
441
|
}
|
package/dist/inputs.d.ts
CHANGED
|
@@ -131,6 +131,10 @@ interface CheckboxProps extends Omit<InputProps<boolean>, "onChange" | "placehol
|
|
|
131
131
|
* Optional description text below the label (secondary text)
|
|
132
132
|
*/
|
|
133
133
|
description?: React.ReactNode;
|
|
134
|
+
/**
|
|
135
|
+
* Layout variant
|
|
136
|
+
*/
|
|
137
|
+
checkboxVariant?: "boxed" | "inline";
|
|
134
138
|
/**
|
|
135
139
|
* Additional native input attributes
|
|
136
140
|
*/
|
|
@@ -178,7 +182,7 @@ interface CheckboxProps extends Omit<InputProps<boolean>, "onChange" | "placehol
|
|
|
178
182
|
*
|
|
179
183
|
* @see https://opensite.ai/developers/page-speed/forms/checkbox
|
|
180
184
|
*/
|
|
181
|
-
declare function Checkbox({ name, value, onChange, onBlur, disabled, required, error, className, indeterminate, label, description, ...props }: CheckboxProps): React.JSX.Element;
|
|
185
|
+
declare function Checkbox({ name, value, onChange, onBlur, disabled, required, error, className, indeterminate, label, description, checkboxVariant, ...props }: CheckboxProps): React.JSX.Element;
|
|
182
186
|
declare namespace Checkbox {
|
|
183
187
|
var displayName: string;
|
|
184
188
|
}
|
|
@@ -363,6 +367,13 @@ interface RadioProps extends Omit<InputProps<string>, "onChange" | "placeholder"
|
|
|
363
367
|
* @default "stacked"
|
|
364
368
|
*/
|
|
365
369
|
layout?: "inline" | "stacked";
|
|
370
|
+
/**
|
|
371
|
+
* Visual variant for radio options
|
|
372
|
+
* - "boxed": bordered card with ring on hover/selected, radio circle on right
|
|
373
|
+
* - "inline": minimal style, radio circle on left
|
|
374
|
+
* @default "inline"
|
|
375
|
+
*/
|
|
376
|
+
radioVariant?: "boxed" | "inline";
|
|
366
377
|
/**
|
|
367
378
|
* Group-level label
|
|
368
379
|
*/
|
|
@@ -424,7 +435,7 @@ interface RadioProps extends Omit<InputProps<string>, "onChange" | "placeholder"
|
|
|
424
435
|
*
|
|
425
436
|
* @see https://opensite.ai/developers/page-speed/forms/radio
|
|
426
437
|
*/
|
|
427
|
-
declare function Radio({ name, value, onChange, onBlur, disabled, required, error, className, layout, label, options, ...props }: RadioProps): React.JSX.Element;
|
|
438
|
+
declare function Radio({ name, value, onChange, onBlur, disabled, required, error, className, layout, radioVariant, label, options, ...props }: RadioProps): React.JSX.Element;
|
|
428
439
|
declare namespace Radio {
|
|
429
440
|
var displayName: string;
|
|
430
441
|
}
|
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({
|
|
@@ -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
|
{
|
|
@@ -226,65 +307,53 @@ function CheckboxGroup({
|
|
|
226
307
|
label && /* @__PURE__ */ React7.createElement("div", { className: "text-sm font-medium" }, label),
|
|
227
308
|
description && /* @__PURE__ */ React7.createElement("div", { className: "text-muted-foreground text-sm" }, description),
|
|
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";
|
|
@@ -298,6 +367,7 @@ function Radio({
|
|
|
298
367
|
error = false,
|
|
299
368
|
className = "",
|
|
300
369
|
layout = "stacked",
|
|
370
|
+
radioVariant = "inline",
|
|
301
371
|
label,
|
|
302
372
|
options,
|
|
303
373
|
...props
|
|
@@ -333,8 +403,12 @@ function Radio({
|
|
|
333
403
|
const handleBlur = () => {
|
|
334
404
|
onBlur?.();
|
|
335
405
|
};
|
|
336
|
-
const
|
|
337
|
-
|
|
406
|
+
const containerClass = cn(
|
|
407
|
+
"w-full gap-3",
|
|
408
|
+
layout === "stacked" && "flex flex-col",
|
|
409
|
+
layout === "inline" && "flex flex-row flex-wrap",
|
|
410
|
+
className
|
|
411
|
+
);
|
|
338
412
|
return /* @__PURE__ */ React7.createElement(
|
|
339
413
|
"div",
|
|
340
414
|
{
|
|
@@ -350,38 +424,60 @@ function Radio({
|
|
|
350
424
|
const isChecked = value === option.value;
|
|
351
425
|
const isDisabled = disabled || option.disabled;
|
|
352
426
|
const radioId = `${name}-${option.value}`;
|
|
427
|
+
const hasDescription = option.description != null && option.description !== "";
|
|
428
|
+
const radioIndicator = /* @__PURE__ */ React7.createElement("div", { className: "relative inline-flex items-center justify-center" }, /* @__PURE__ */ React7.createElement(
|
|
429
|
+
"input",
|
|
430
|
+
{
|
|
431
|
+
type: "radio",
|
|
432
|
+
id: radioId,
|
|
433
|
+
name,
|
|
434
|
+
value: option.value,
|
|
435
|
+
checked: isChecked,
|
|
436
|
+
onChange: (e) => handleChange(e.target.value),
|
|
437
|
+
onBlur: handleBlur,
|
|
438
|
+
disabled: isDisabled,
|
|
439
|
+
required,
|
|
440
|
+
className: "peer sr-only",
|
|
441
|
+
"aria-describedby": hasDescription ? `${radioId}-description` : props["aria-describedby"]
|
|
442
|
+
}
|
|
443
|
+
), /* @__PURE__ */ React7.createElement(
|
|
444
|
+
"div",
|
|
445
|
+
{
|
|
446
|
+
className: cn(
|
|
447
|
+
"flex shrink-0 items-center justify-center rounded-full border-2 transition-colors size-6",
|
|
448
|
+
!error && isChecked && "border-primary bg-transparent",
|
|
449
|
+
!error && !isChecked && "border-input bg-transparent",
|
|
450
|
+
error && isChecked && "border-destructive bg-transparent",
|
|
451
|
+
error && !isChecked && "border-destructive bg-transparent",
|
|
452
|
+
isDisabled && "opacity-50",
|
|
453
|
+
"peer-focus-visible:ring-2 peer-focus-visible:ring-ring/50 peer-focus-visible:ring-offset-1"
|
|
454
|
+
)
|
|
455
|
+
},
|
|
456
|
+
isChecked && /* @__PURE__ */ React7.createElement("div", { className: "size-3 rounded-full bg-primary" })
|
|
457
|
+
));
|
|
458
|
+
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(
|
|
459
|
+
"p",
|
|
460
|
+
{
|
|
461
|
+
className: "text-xs opacity-75",
|
|
462
|
+
id: `${radioId}-description`
|
|
463
|
+
},
|
|
464
|
+
option.description
|
|
465
|
+
));
|
|
353
466
|
return /* @__PURE__ */ React7.createElement(
|
|
354
467
|
"label",
|
|
355
468
|
{
|
|
356
469
|
key: option.value,
|
|
357
|
-
className:
|
|
470
|
+
className: cn(
|
|
471
|
+
"w-full h-full flex gap-3 p-3 duration-200",
|
|
472
|
+
radioVariant === "boxed" && "border rounded-lg hover:ring-2",
|
|
473
|
+
radioVariant === "boxed" && isChecked && "ring-2",
|
|
474
|
+
isDisabled ? "opacity-50 cursor-not-allowed hover:ring-0" : "cursor-pointer"
|
|
475
|
+
),
|
|
358
476
|
htmlFor: radioId,
|
|
359
477
|
onKeyDown: (e) => handleKeyDown(e, index),
|
|
360
478
|
tabIndex: isDisabled ? -1 : 0
|
|
361
479
|
},
|
|
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" })))))
|
|
480
|
+
/* @__PURE__ */ React7.createElement("div", { className: "flex w-full flex-row items-center gap-2" }, radioVariant === "inline" && radioIndicator, /* @__PURE__ */ React7.createElement("div", { className: "flex flex-1 flex-col gap-0.5" }, labelContent), radioVariant === "boxed" && radioIndicator)
|
|
385
481
|
);
|
|
386
482
|
})
|
|
387
483
|
);
|
|
@@ -1231,7 +1327,9 @@ function DatePicker({
|
|
|
1231
1327
|
}) {
|
|
1232
1328
|
const [isOpen, setIsOpen] = React7.useState(false);
|
|
1233
1329
|
const [inputValue, setInputValue] = React7.useState("");
|
|
1234
|
-
const [selectedMonth, setSelectedMonth] = React7.useState(
|
|
1330
|
+
const [selectedMonth, setSelectedMonth] = React7.useState(
|
|
1331
|
+
value || /* @__PURE__ */ new Date()
|
|
1332
|
+
);
|
|
1235
1333
|
const containerRef = React7.useRef(null);
|
|
1236
1334
|
const inputRef = React7.useRef(null);
|
|
1237
1335
|
React7.useEffect(() => {
|
|
@@ -1322,7 +1420,7 @@ function DatePicker({
|
|
|
1322
1420
|
"button",
|
|
1323
1421
|
{
|
|
1324
1422
|
type: "button",
|
|
1325
|
-
className: "flex items-center justify-center h-8 w-8 rounded border-none bg-transparent hover:bg-
|
|
1423
|
+
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
1424
|
onClick: handlePrevMonth,
|
|
1327
1425
|
"aria-label": "Previous month"
|
|
1328
1426
|
},
|
|
@@ -1331,12 +1429,19 @@ function DatePicker({
|
|
|
1331
1429
|
"button",
|
|
1332
1430
|
{
|
|
1333
1431
|
type: "button",
|
|
1334
|
-
className: "flex items-center justify-center h-8 w-8 rounded border-none bg-transparent hover:bg-
|
|
1432
|
+
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
1433
|
onClick: handleNextMonth,
|
|
1336
1434
|
"aria-label": "Next month"
|
|
1337
1435
|
},
|
|
1338
1436
|
"\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(
|
|
1437
|
+
)), /* @__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(
|
|
1438
|
+
"div",
|
|
1439
|
+
{
|
|
1440
|
+
key: day,
|
|
1441
|
+
className: "flex items-center justify-center h-8 w-full text-xs font-medium"
|
|
1442
|
+
},
|
|
1443
|
+
day
|
|
1444
|
+
))), /* @__PURE__ */ React7.createElement("div", { className: "grid grid-cols-7 gap-1" }, days.map((date, index) => {
|
|
1340
1445
|
if (!date) {
|
|
1341
1446
|
return /* @__PURE__ */ React7.createElement("div", { key: `empty-${index}` });
|
|
1342
1447
|
}
|
|
@@ -1348,7 +1453,7 @@ function DatePicker({
|
|
|
1348
1453
|
{
|
|
1349
1454
|
key: date.toISOString(),
|
|
1350
1455
|
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-
|
|
1456
|
+
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
1457
|
onClick: () => !disabled2 && handleDateSelect(date),
|
|
1353
1458
|
disabled: disabled2,
|
|
1354
1459
|
"aria-label": formatDate(date, format)
|
|
@@ -1365,26 +1470,33 @@ function DatePicker({
|
|
|
1365
1470
|
name,
|
|
1366
1471
|
value: value ? value.toISOString() : ""
|
|
1367
1472
|
}
|
|
1368
|
-
), /* @__PURE__ */ React7.createElement("div", { className: "relative" }, showIcon && /* @__PURE__ */ React7.createElement(
|
|
1369
|
-
"
|
|
1473
|
+
), /* @__PURE__ */ React7.createElement("div", { className: "relative" }, showIcon && /* @__PURE__ */ React7.createElement(
|
|
1474
|
+
"span",
|
|
1370
1475
|
{
|
|
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"
|
|
1476
|
+
className: "absolute left-3 top-1/2 -translate-y-1/2 pointer-events-none",
|
|
1477
|
+
"aria-hidden": "true"
|
|
1380
1478
|
},
|
|
1381
|
-
/* @__PURE__ */ React7.createElement(
|
|
1382
|
-
|
|
1479
|
+
/* @__PURE__ */ React7.createElement(
|
|
1480
|
+
"svg",
|
|
1481
|
+
{
|
|
1482
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
1483
|
+
width: "18",
|
|
1484
|
+
height: "18",
|
|
1485
|
+
viewBox: "0 0 24 24",
|
|
1486
|
+
fill: "none",
|
|
1487
|
+
stroke: "currentColor",
|
|
1488
|
+
strokeLinecap: "round",
|
|
1489
|
+
strokeLinejoin: "round",
|
|
1490
|
+
strokeWidth: "2"
|
|
1491
|
+
},
|
|
1492
|
+
/* @__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" })
|
|
1493
|
+
)
|
|
1494
|
+
), /* @__PURE__ */ React7.createElement(
|
|
1383
1495
|
"input",
|
|
1384
1496
|
{
|
|
1385
1497
|
ref: inputRef,
|
|
1386
1498
|
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
|
|
1499
|
+
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
1500
|
value: inputValue,
|
|
1389
1501
|
onChange: handleInputChange,
|
|
1390
1502
|
onClick: handleToggle,
|
|
@@ -1401,7 +1513,7 @@ function DatePicker({
|
|
|
1401
1513
|
"button",
|
|
1402
1514
|
{
|
|
1403
1515
|
type: "button",
|
|
1404
|
-
className: "absolute right-3 top-1/2 -translate-y-1/2
|
|
1516
|
+
className: "absolute right-3 top-1/2 -translate-y-1/2 transition-colors",
|
|
1405
1517
|
onClick: handleClear,
|
|
1406
1518
|
"aria-label": "Clear date",
|
|
1407
1519
|
tabIndex: -1
|