@flikk/ui 1.0.0-beta.23 → 1.0.0-beta.24
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/components/charts/AreaChart/AreaChart.types.d.ts +2 -2
- package/dist/components/charts/BarChart/BarChart.types.d.ts +2 -2
- package/dist/components/charts/ComboChart/ComboChart.types.d.ts +2 -2
- package/dist/components/charts/LineChart/LineChart.types.d.ts +2 -2
- package/dist/components/charts/ScatterPlot/ScatterPlot.types.d.ts +2 -2
- package/dist/components/charts/StackedBarChart/StackedBarChart.types.d.ts +2 -2
- package/dist/components/core/Accordion/AccordionTrigger.js +28 -1
- package/dist/components/core/Alert/Alert.js +2 -1
- package/dist/components/core/AlertDialog/AlertDialog.js +1 -1
- package/dist/components/core/Badge/Badge.js +6 -17
- package/dist/components/core/Breadcrumbs/Breadcrumbs.js +17 -28
- package/dist/components/core/Calendar/Calendar.js +1 -1
- package/dist/components/core/Carousel/CarouselBody.js +6 -1
- package/dist/components/core/ContextMenu/ContextMenuBody.js +6 -3
- package/dist/components/core/ContextMenu/ContextMenuSubBody.js +6 -3
- package/dist/components/core/DragDrop/DragDrop.js +170 -17
- package/dist/components/core/DragDrop/DragDrop.types.d.ts +6 -0
- package/dist/components/core/Drawer/Drawer.d.ts +1 -1
- package/dist/components/core/Drawer/Drawer.js +2 -0
- package/dist/components/core/Drawer/Drawer.types.d.ts +2 -0
- package/dist/components/core/Drawer/DrawerTitle.d.ts +1 -1
- package/dist/components/core/Drawer/DrawerTitle.js +2 -2
- package/dist/components/core/Dropdown/DropdownMenu.js +2 -30
- package/dist/components/core/Masonry/Masonry.js +7 -2
- package/dist/components/core/Modal/Modal.d.ts +1 -1
- package/dist/components/core/Modal/Modal.js +3 -3
- package/dist/components/core/Modal/Modal.types.d.ts +2 -0
- package/dist/components/core/Modal/ModalTitle.d.ts +1 -1
- package/dist/components/core/Modal/ModalTitle.js +2 -2
- package/dist/components/core/NavItem/NavItem.js +13 -8
- package/dist/components/core/Pagination/Pagination.js +1 -1
- package/dist/components/core/Popover/PopoverBody.js +3 -27
- package/dist/components/core/Popover/PopoverTrigger.js +1 -1
- package/dist/components/core/Progress/Progress.js +4 -4
- package/dist/components/core/Rating/Rating.js +1 -1
- package/dist/components/core/ScrollArea/ScrollArea.js +3 -2
- package/dist/components/core/Segmented/Segmented.js +6 -6
- package/dist/components/core/Segmented/SegmentedItem.js +28 -2
- package/dist/components/core/Skeleton/Skeleton.js +2 -2
- package/dist/components/core/Sortable/Sortable.d.ts +1 -1
- package/dist/components/core/Sortable/Sortable.js +20 -4
- package/dist/components/core/Sortable/Sortable.types.d.ts +2 -0
- package/dist/components/core/Tabs/Tabs.js +6 -4
- package/dist/components/core/Tabs/Tabs.types.d.ts +2 -0
- package/dist/components/core/Tabs/TabsBody.js +3 -3
- package/dist/components/core/Tabs/TabsList.js +19 -21
- package/dist/components/core/Tabs/TabsTrigger.js +47 -28
- package/dist/components/core/Toast/Toast.js +1 -1
- package/dist/components/core/Toast/ToastProvider.js +3 -2
- package/dist/components/core/Tooltip/Tooltip.js +25 -34
- package/dist/components/core/Tree/Tree.js +178 -8
- package/dist/components/data-display/GanttChart/GanttSplitter.js +15 -1
- package/dist/components/data-display/Table/Table.js +2 -2
- package/dist/components/data-display/Table/Table.types.d.ts +2 -0
- package/dist/components/data-display/Table/TableFilter.js +21 -18
- package/dist/components/effects/CustomCursor/CustomCursor.js +3 -7
- package/dist/components/effects/Overlay/Overlay.js +4 -9
- package/dist/components/effects/PageTransition/PageTransition.js +17 -6
- package/dist/components/effects/SpotlightBorder/SpotlightBorder.js +3 -4
- package/dist/components/forms/Checkbox/Checkbox.js +11 -1
- package/dist/components/forms/Checkbox/Checkbox.theme.js +4 -1
- package/dist/components/forms/Checkbox/Checkbox.types.d.ts +7 -5
- package/dist/components/forms/Checkbox/CheckboxGroup.js +9 -4
- package/dist/components/forms/ColorPicker/ColorPicker.js +7 -4
- package/dist/components/forms/ColorPicker/ColorPicker.types.d.ts +2 -2
- package/dist/components/forms/ColorPicker/ColorPickerBody.js +5 -3
- package/dist/components/forms/ColorPicker/ColorPickerEyeDropper.js +3 -3
- package/dist/components/forms/ColorPicker/ColorPickerGradient.js +8 -8
- package/dist/components/forms/ColorPicker/ColorPickerInput.js +1 -1
- package/dist/components/forms/ColorPicker/index.d.ts +1 -1
- package/dist/components/forms/Combobox/Combobox.js +20 -45
- package/dist/components/forms/Combobox/Combobox.types.d.ts +4 -2
- package/dist/components/forms/CronInput/CronInput.js +10 -4
- package/dist/components/forms/CronInput/CronInput.types.d.ts +12 -1
- package/dist/components/forms/DatePicker/DatePicker.js +2 -2
- package/dist/components/forms/DatePicker/DatePicker.types.d.ts +4 -2
- package/dist/components/forms/DatePicker/DatePickerBody.js +1 -29
- package/dist/components/forms/DatePicker/DatePickerTrigger.js +2 -2
- package/dist/components/forms/DateRangePicker/DateRangePicker.js +3 -3
- package/dist/components/forms/DateRangePicker/DateRangePicker.types.d.ts +4 -2
- package/dist/components/forms/DateRangePicker/DateRangePickerBody.js +1 -28
- package/dist/components/forms/DateRangePicker/DateRangePickerTrigger.js +2 -2
- package/dist/components/forms/FileUpload/FileUpload.js +14 -10
- package/dist/components/forms/FileUpload/FileUpload.types.d.ts +15 -0
- package/dist/components/forms/FormLabel/FormLabel.js +2 -2
- package/dist/components/forms/Input/Input.js +5 -3
- package/dist/components/forms/Input/Input.types.d.ts +2 -0
- package/dist/components/forms/InputAddress/InputAddress.d.ts +1 -1
- package/dist/components/forms/InputAddress/InputAddress.js +8 -9
- package/dist/components/forms/InputCounter/InputCounter.js +25 -18
- package/dist/components/forms/InputCounter/InputCounter.types.d.ts +8 -1
- package/dist/components/forms/InputCreditCard/InputCreditCard.d.ts +1 -1
- package/dist/components/forms/InputCreditCard/InputCreditCard.js +27 -9
- package/dist/components/forms/InputCreditCard/InputCreditCard.types.d.ts +5 -0
- package/dist/components/forms/InputOTP/InputOTP.js +26 -17
- package/dist/components/forms/InputOTP/InputOTP.types.d.ts +21 -4
- package/dist/components/forms/InputTag/InputTag.js +12 -39
- package/dist/components/forms/InputTag/InputTag.types.d.ts +2 -2
- package/dist/components/forms/Mention/Mention.js +13 -6
- package/dist/components/forms/Mention/Mention.types.d.ts +9 -0
- package/dist/components/forms/Radio/Radio.js +12 -2
- package/dist/components/forms/Radio/Radio.theme.js +5 -1
- package/dist/components/forms/Radio/Radio.types.d.ts +7 -5
- package/dist/components/forms/Radio/RadioGroup.js +8 -3
- package/dist/components/forms/RichTextEditor/RichTextEditor.js +21 -21
- package/dist/components/forms/RichTextEditor/RichTextEditor.types.d.ts +2 -2
- package/dist/components/forms/Select/Select.d.ts +2 -0
- package/dist/components/forms/Select/Select.js +26 -56
- package/dist/components/forms/Select/Select.types.d.ts +14 -0
- package/dist/components/forms/Signature/Signature.js +1 -1
- package/dist/components/forms/Signature/Signature.types.d.ts +3 -3
- package/dist/components/forms/Slider/Slider.js +18 -4
- package/dist/components/forms/Slider/Slider.types.d.ts +2 -2
- package/dist/components/forms/Switch/Switch.js +12 -19
- package/dist/components/forms/Switch/Switch.theme.js +12 -2
- package/dist/components/forms/Switch/Switch.types.d.ts +20 -2
- package/dist/components/forms/Textarea/Textarea.js +8 -3
- package/dist/components/forms/Textarea/Textarea.types.d.ts +2 -0
- package/dist/components/forms/TimePicker/TimePicker.js +1 -1
- package/dist/components/forms/TimePicker/TimePicker.types.d.ts +6 -2
- package/dist/components/forms/TimePicker/TimePickerContent.js +2 -29
- package/dist/components/forms/TimePicker/TimePickerTrigger.js +2 -2
- package/dist/components/forms/index.js +1 -1
- package/dist/components/layout/index.js +4 -0
- package/dist/hooks/index.d.ts +1 -0
- package/dist/hooks/useClickOutside.d.ts +10 -4
- package/dist/hooks/useClickOutside.js +44 -24
- package/dist/hooks/useDarkMode.d.ts +1 -0
- package/dist/hooks/useDarkMode.js +42 -0
- package/dist/hooks/useFormStateMachine.d.ts +1 -1
- package/dist/hooks/useNetworkStatus.js +1 -1
- package/dist/hooks/useOverlay.js +4 -0
- package/dist/hooks/useScaleBackground.js +5 -2
- package/dist/hooks/useSelectPortal.js +14 -5
- package/dist/index.d.ts +0 -2
- package/dist/index.js +1 -57
- package/dist/shadcn-compat.css +80 -0
- package/dist/styles.css +1 -1
- package/dist/utils/stateMachine.d.ts +4 -4
- package/package.json +11 -10
- package/tailwind.preset.cjs +32 -3
- /package/{src/theme-plugin.css → dist/theme.css} +0 -0
|
@@ -21,11 +21,16 @@ import { inputOTPTheme } from './InputOTP.theme.js';
|
|
|
21
21
|
* />
|
|
22
22
|
* ```
|
|
23
23
|
*/
|
|
24
|
-
const InputOTP = React__default.forwardRef(({ length = 6, value
|
|
24
|
+
const InputOTP = React__default.forwardRef(({ length = 6, value, defaultValue, onChange, onComplete, state = 'default', disabled = false, label, helperText, error, autoFocus = true, className, id: idProp, ...props }, ref) => {
|
|
25
25
|
const inputRefs = useRef([]);
|
|
26
26
|
const theme = inputOTPTheme;
|
|
27
|
-
|
|
28
|
-
const
|
|
27
|
+
const generatedId = React__default.useId();
|
|
28
|
+
const helperTextId = `${idProp !== null && idProp !== void 0 ? idProp : generatedId}-helper`;
|
|
29
|
+
// Derive unified state flags for backward compat
|
|
30
|
+
const isDisabled = state === 'disabled' || disabled;
|
|
31
|
+
const isInvalid = state === 'invalid' || !!error;
|
|
32
|
+
// Internal state for uncontrolled usage — seeded with defaultValue
|
|
33
|
+
const [internalValue, setInternalValue] = useState(defaultValue !== null && defaultValue !== void 0 ? defaultValue : '');
|
|
29
34
|
// Use controlled value if provided, otherwise use internal state
|
|
30
35
|
const currentValue = value !== undefined ? value : internalValue;
|
|
31
36
|
const setValue = onChange || setInternalValue;
|
|
@@ -33,14 +38,14 @@ const InputOTP = React__default.forwardRef(({ length = 6, value = '', onChange,
|
|
|
33
38
|
const valueArray = currentValue.padEnd(length, '').split('').slice(0, length);
|
|
34
39
|
// Auto-focus first input on mount
|
|
35
40
|
useEffect(() => {
|
|
36
|
-
if (autoFocus && inputRefs.current[0] && !
|
|
41
|
+
if (autoFocus && inputRefs.current[0] && !isDisabled) {
|
|
37
42
|
inputRefs.current[0].focus();
|
|
38
43
|
}
|
|
39
|
-
}, [autoFocus,
|
|
44
|
+
}, [autoFocus, isDisabled]);
|
|
40
45
|
// Handle input change
|
|
41
46
|
const handleChange = useCallback((index, newValue) => {
|
|
42
47
|
var _a;
|
|
43
|
-
if (
|
|
48
|
+
if (isDisabled)
|
|
44
49
|
return;
|
|
45
50
|
// Only allow single character (take last character if multiple)
|
|
46
51
|
const char = newValue.slice(-1);
|
|
@@ -58,11 +63,11 @@ const InputOTP = React__default.forwardRef(({ length = 6, value = '', onChange,
|
|
|
58
63
|
if (newValueString.length === length) {
|
|
59
64
|
onComplete === null || onComplete === void 0 ? void 0 : onComplete(newValueString);
|
|
60
65
|
}
|
|
61
|
-
}, [
|
|
66
|
+
}, [isDisabled, valueArray, length, setValue, onComplete]);
|
|
62
67
|
// Handle key down for navigation and deletion
|
|
63
68
|
const handleKeyDown = useCallback((index, event) => {
|
|
64
69
|
var _a, _b, _c, _d, _e;
|
|
65
|
-
if (
|
|
70
|
+
if (isDisabled)
|
|
66
71
|
return;
|
|
67
72
|
switch (event.key) {
|
|
68
73
|
case 'Backspace':
|
|
@@ -99,11 +104,11 @@ const InputOTP = React__default.forwardRef(({ length = 6, value = '', onChange,
|
|
|
99
104
|
(_e = inputRefs.current[length - 1]) === null || _e === void 0 ? void 0 : _e.focus();
|
|
100
105
|
break;
|
|
101
106
|
}
|
|
102
|
-
}, [
|
|
107
|
+
}, [isDisabled, valueArray, length, handleChange]);
|
|
103
108
|
// Handle paste
|
|
104
109
|
const handlePaste = useCallback((event) => {
|
|
105
110
|
var _a;
|
|
106
|
-
if (
|
|
111
|
+
if (isDisabled)
|
|
107
112
|
return;
|
|
108
113
|
event.preventDefault();
|
|
109
114
|
const pastedData = event.clipboardData.getData('text').slice(0, length);
|
|
@@ -117,7 +122,7 @@ const InputOTP = React__default.forwardRef(({ length = 6, value = '', onChange,
|
|
|
117
122
|
onComplete === null || onComplete === void 0 ? void 0 : onComplete(pastedData);
|
|
118
123
|
}
|
|
119
124
|
}
|
|
120
|
-
}, [
|
|
125
|
+
}, [isDisabled, length, setValue, onComplete]);
|
|
121
126
|
// Handle focus and blur (simplified since we removed focus state)
|
|
122
127
|
const handleFocus = useCallback((index) => {
|
|
123
128
|
// Focus logic can be added here if needed
|
|
@@ -126,11 +131,15 @@ const InputOTP = React__default.forwardRef(({ length = 6, value = '', onChange,
|
|
|
126
131
|
// Blur logic can be added here if needed
|
|
127
132
|
}, []);
|
|
128
133
|
// State class for CSS selectors (matches Input component pattern)
|
|
129
|
-
const stateClass =
|
|
134
|
+
const stateClass = isInvalid
|
|
130
135
|
? "state-invalid"
|
|
131
|
-
:
|
|
136
|
+
: isDisabled
|
|
132
137
|
? "state-disabled"
|
|
133
138
|
: "state-default";
|
|
139
|
+
// Resolved label state for FormLabel
|
|
140
|
+
const labelState = isInvalid ? 'invalid' : isDisabled ? 'disabled' : 'default';
|
|
141
|
+
// Resolved helper text to display — prefer helperText, fall back to error
|
|
142
|
+
const displayedHelperText = helperText !== null && helperText !== void 0 ? helperText : error;
|
|
134
143
|
// Build classes with shadcn pattern - user className has highest priority
|
|
135
144
|
const wrapperClasses = cn(theme.wrapperStyle, stateClass, className);
|
|
136
145
|
const containerClasses = cn(theme.containerStyle);
|
|
@@ -155,20 +164,20 @@ const InputOTP = React__default.forwardRef(({ length = 6, value = '', onChange,
|
|
|
155
164
|
});
|
|
156
165
|
}
|
|
157
166
|
};
|
|
158
|
-
return (jsxs("div", { ref: ref, className: wrapperClasses, ...props, children: [label && (jsx(FormLabel, { htmlFor:
|
|
167
|
+
return (jsxs("div", { ref: ref, className: wrapperClasses, ...props, children: [label && (typeof label === 'string' ? (jsx(FormLabel, { htmlFor: "otp-input-0", state: labelState, children: label })) : (label)), jsx("div", { className: containerClasses, children: length === 6 ? (
|
|
159
168
|
// For 6-digit OTP, create two groups of 3
|
|
160
169
|
jsxs(Fragment, { children: [jsx("div", { className: "flex", children: Array.from({ length: 3 }, (_, i) => (jsx(Input, { ref: (el) => {
|
|
161
170
|
inputRefs.current[i] = el;
|
|
162
|
-
}, id: `otp-input-${i}`, type: "text", value: valueArray[i] || '', onChange: (e) => handleChange(i, e.target.value), onKeyDown: (e) => handleKeyDown(i, e), onFocus: () => handleFocus(i), onBlur: handleBlur, onPaste: i === 0 ? handlePaste : undefined, disabled: disabled, maxLength: 1, className: theme.inputStyle, inputGroupClassName: getInputClasses(i), wrapperClassName: "space-y-0 w-auto" }, i))) }), jsx("span", { className: theme.separatorStyle, children: "\u2014" }), jsx("div", { className: "flex", children: Array.from({ length: 3 }, (_, i) => {
|
|
171
|
+
}, id: `otp-input-${i}`, type: "text", value: valueArray[i] || '', onChange: (e) => handleChange(i, e.target.value), onKeyDown: (e) => handleKeyDown(i, e), onFocus: () => handleFocus(i), onBlur: handleBlur, onPaste: i === 0 ? handlePaste : undefined, disabled: isDisabled, state: isInvalid ? 'invalid' : isDisabled ? 'disabled' : 'default', "aria-describedby": displayedHelperText ? helperTextId : undefined, maxLength: 1, className: theme.inputStyle, inputGroupClassName: getInputClasses(i), wrapperClassName: "space-y-0 w-auto" }, i))) }), jsx("span", { className: theme.separatorStyle, children: "\u2014" }), jsx("div", { className: "flex", children: Array.from({ length: 3 }, (_, i) => {
|
|
163
172
|
const index = i + 3;
|
|
164
173
|
return (jsx(Input, { ref: (el) => {
|
|
165
174
|
inputRefs.current[index] = el;
|
|
166
|
-
}, id: `otp-input-${index}`, type: "text", value: valueArray[index] || '', onChange: (e) => handleChange(index, e.target.value), onKeyDown: (e) => handleKeyDown(index, e), onFocus: () => handleFocus(index), onBlur: handleBlur, disabled: disabled, maxLength: 1, className: theme.inputStyle, inputGroupClassName: getInputClasses(index), wrapperClassName: "space-y-0 w-auto" }, index));
|
|
175
|
+
}, id: `otp-input-${index}`, type: "text", value: valueArray[index] || '', onChange: (e) => handleChange(index, e.target.value), onKeyDown: (e) => handleKeyDown(index, e), onFocus: () => handleFocus(index), onBlur: handleBlur, disabled: isDisabled, state: isInvalid ? 'invalid' : isDisabled ? 'disabled' : 'default', "aria-describedby": displayedHelperText ? helperTextId : undefined, maxLength: 1, className: theme.inputStyle, inputGroupClassName: getInputClasses(index), wrapperClassName: "space-y-0 w-auto" }, index));
|
|
167
176
|
}) })] })) : (
|
|
168
177
|
// For other lengths, create one group
|
|
169
178
|
jsx("div", { className: "flex", children: Array.from({ length }, (_, index) => (jsx(Input, { ref: (el) => {
|
|
170
179
|
inputRefs.current[index] = el;
|
|
171
|
-
}, id: `otp-input-${index}`, type: "text", value: valueArray[index] || '', onChange: (e) => handleChange(index, e.target.value), onKeyDown: (e) => handleKeyDown(index, e), onFocus: () => handleFocus(index), onBlur: handleBlur, onPaste: index === 0 ? handlePaste : undefined, disabled: disabled, maxLength: 1, className: theme.inputStyle, inputGroupClassName: getInputClasses(index), wrapperClassName: "space-y-0 w-auto" }, index))) })) }),
|
|
180
|
+
}, id: `otp-input-${index}`, type: "text", value: valueArray[index] || '', onChange: (e) => handleChange(index, e.target.value), onKeyDown: (e) => handleKeyDown(index, e), onFocus: () => handleFocus(index), onBlur: handleBlur, onPaste: index === 0 ? handlePaste : undefined, disabled: isDisabled, state: isInvalid ? 'invalid' : isDisabled ? 'disabled' : 'default', "aria-describedby": displayedHelperText ? helperTextId : undefined, maxLength: 1, className: theme.inputStyle, inputGroupClassName: getInputClasses(index), wrapperClassName: "space-y-0 w-auto" }, index))) })) }), displayedHelperText && (jsx("div", { id: helperTextId, className: cn(theme.helperText), children: displayedHelperText }))] }));
|
|
172
181
|
});
|
|
173
182
|
InputOTP.displayName = 'InputOTP';
|
|
174
183
|
|
|
@@ -1,13 +1,21 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* State variants for the InputOTP component
|
|
3
|
+
*/
|
|
4
|
+
export type InputOTPState = 'default' | 'disabled' | 'invalid';
|
|
5
|
+
export interface InputOTPProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'onChange' | 'defaultValue'> {
|
|
2
6
|
/**
|
|
3
7
|
* Number of OTP input fields
|
|
4
8
|
* @default 6
|
|
5
9
|
*/
|
|
6
10
|
length?: number;
|
|
7
11
|
/**
|
|
8
|
-
* Current OTP value
|
|
12
|
+
* Current OTP value (controlled)
|
|
9
13
|
*/
|
|
10
14
|
value?: string;
|
|
15
|
+
/**
|
|
16
|
+
* Default OTP value (uncontrolled)
|
|
17
|
+
*/
|
|
18
|
+
defaultValue?: string;
|
|
11
19
|
/**
|
|
12
20
|
* Callback when OTP value changes
|
|
13
21
|
*/
|
|
@@ -16,21 +24,30 @@ export interface InputOTPProps extends Omit<React.HTMLAttributes<HTMLDivElement>
|
|
|
16
24
|
* Callback when OTP is complete (all fields filled)
|
|
17
25
|
*/
|
|
18
26
|
onComplete?: (value: string) => void;
|
|
27
|
+
/**
|
|
28
|
+
* Visual and functional state of the OTP input group.
|
|
29
|
+
* Use 'disabled' instead of the deprecated `disabled` boolean prop.
|
|
30
|
+
* Use 'invalid' instead of the deprecated `error` string prop.
|
|
31
|
+
* @default 'default'
|
|
32
|
+
*/
|
|
33
|
+
state?: InputOTPState;
|
|
19
34
|
/**
|
|
20
35
|
* Whether the input is disabled
|
|
36
|
+
* @deprecated Use `state='disabled'` instead.
|
|
21
37
|
* @default false
|
|
22
38
|
*/
|
|
23
39
|
disabled?: boolean;
|
|
24
40
|
/**
|
|
25
41
|
* Label for the OTP input group
|
|
26
42
|
*/
|
|
27
|
-
label?:
|
|
43
|
+
label?: React.ReactNode;
|
|
28
44
|
/**
|
|
29
45
|
* Helper text below the inputs
|
|
30
46
|
*/
|
|
31
|
-
helperText?:
|
|
47
|
+
helperText?: React.ReactNode;
|
|
32
48
|
/**
|
|
33
49
|
* Error message
|
|
50
|
+
* @deprecated Use `state='invalid'` with `helperText` instead.
|
|
34
51
|
*/
|
|
35
52
|
error?: string;
|
|
36
53
|
/**
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
1
|
+
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
2
2
|
import React__default, { useMemo, useState, useRef, useEffect, useCallback } from 'react';
|
|
3
3
|
import { AnimatePresence, motion } from 'motion/react';
|
|
4
4
|
import { createPortal } from 'react-dom';
|
|
@@ -11,35 +11,8 @@ import { inputTagTheme } from './InputTag.theme.js';
|
|
|
11
11
|
import { useSelectPortal } from '../../../hooks/useSelectPortal.js';
|
|
12
12
|
import { createDropdownAnimations } from '../Select/Select.animations.js';
|
|
13
13
|
import { useIsClient } from '../../../hooks/useIsClient.js';
|
|
14
|
+
import { useDarkMode } from '../../../hooks/useDarkMode.js';
|
|
14
15
|
|
|
15
|
-
/**
|
|
16
|
-
* Hook to detect dark mode state from document
|
|
17
|
-
*/
|
|
18
|
-
const useDarkMode = () => {
|
|
19
|
-
const [isDark, setIsDark] = useState(false);
|
|
20
|
-
useEffect(() => {
|
|
21
|
-
if (typeof document === "undefined")
|
|
22
|
-
return;
|
|
23
|
-
const checkDarkMode = () => {
|
|
24
|
-
const hasDarkClass = document.documentElement.classList.contains("dark") ||
|
|
25
|
-
document.body.classList.contains("dark") ||
|
|
26
|
-
document.querySelector(".dark") !== null;
|
|
27
|
-
setIsDark(hasDarkClass);
|
|
28
|
-
};
|
|
29
|
-
checkDarkMode();
|
|
30
|
-
const observer = new MutationObserver(checkDarkMode);
|
|
31
|
-
observer.observe(document.documentElement, {
|
|
32
|
-
attributes: true,
|
|
33
|
-
attributeFilter: ["class"],
|
|
34
|
-
});
|
|
35
|
-
observer.observe(document.body, {
|
|
36
|
-
attributes: true,
|
|
37
|
-
attributeFilter: ["class"],
|
|
38
|
-
});
|
|
39
|
-
return () => observer.disconnect();
|
|
40
|
-
}, []);
|
|
41
|
-
return isDark;
|
|
42
|
-
};
|
|
43
16
|
/**
|
|
44
17
|
* Default filter function for suggestions
|
|
45
18
|
*/
|
|
@@ -97,16 +70,16 @@ const InputTagOptions = ({ isOpen, onClose, triggerRef, filteredOptions, selecte
|
|
|
97
70
|
width: `${position.width}px`,
|
|
98
71
|
}
|
|
99
72
|
: {}),
|
|
100
|
-
}, tabIndex: -1, variants: animations, initial: "initial", animate: "visible", exit: "exit", children: filteredOptions.length === 0 ? (jsx("div", { className: theme.emptyMessageStyle, children: emptyMessage })) : (filteredOptions.map((option, index) => {
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
73
|
+
}, tabIndex: -1, variants: animations, initial: "initial", animate: "visible", exit: "exit", children: filteredOptions.length === 0 ? (jsx("div", { className: theme.emptyMessageStyle, children: emptyMessage })) : (jsxs(Fragment, { children: [(filteredOptions.length > 100 ? filteredOptions.slice(0, 100) : filteredOptions).map((option, index) => {
|
|
74
|
+
const isSelected = selectedTags.includes(option.value);
|
|
75
|
+
const isHighlighted = index === highlightedIndex;
|
|
76
|
+
const isCreateOption = option.id === "__create__";
|
|
77
|
+
return (jsx("div", { role: "option", "aria-selected": isSelected, "aria-disabled": option.disabled, "data-option-index": index, className: cn(theme.optionStyle, isHighlighted && theme.highlightedOptionStyle, option.disabled && theme.disabledOptionStyle, isCreateOption && theme.createOptionStyle), onMouseEnter: () => !option.disabled && setHighlightedIndex(index), onClick: () => {
|
|
78
|
+
if (!option.disabled) {
|
|
79
|
+
onSelectOption(option, isCreateOption);
|
|
80
|
+
}
|
|
81
|
+
}, children: isCreateOption ? (jsxs("span", { className: "flex items-center gap-1", children: [jsx(PlusIcon, { className: "size-4 shrink-0", strokeWidth: 2 }), jsx("span", { className: "block truncate", children: option.label })] })) : (jsxs("span", { className: "flex items-center justify-between gap-2", children: [jsx("span", { className: "block truncate", children: option.label }), showSelectedIndicator && isSelected && (jsx(CheckIcon, { className: "size-4 shrink-0 text-[var(--color-primary)]", strokeWidth: 2 }))] })) }, option.id));
|
|
82
|
+
}), filteredOptions.length > 100 && (jsxs("div", { className: "px-3 py-2 text-xs text-[var(--color-text-muted)] text-center border-t border-[var(--color-border)]", children: ["Showing 100 of ", filteredOptions.length, " results \u2014 refine your search"] }))] })) })) }));
|
|
110
83
|
if (portal && isClient) {
|
|
111
84
|
return createPortal(jsx("div", { className: isDarkMode ? "dark" : undefined, children: optionsContent }), document.body);
|
|
112
85
|
}
|
|
@@ -33,9 +33,9 @@ export interface InputTagProps extends Omit<React.HTMLAttributes<HTMLDivElement>
|
|
|
33
33
|
/** The state of the input */
|
|
34
34
|
state?: InputTagState;
|
|
35
35
|
/** Label for the input */
|
|
36
|
-
label?:
|
|
36
|
+
label?: React.ReactNode;
|
|
37
37
|
/** Helper text displayed below the tags */
|
|
38
|
-
helperText?:
|
|
38
|
+
helperText?: React.ReactNode;
|
|
39
39
|
/** Placeholder text for the input */
|
|
40
40
|
placeholder?: string;
|
|
41
41
|
/** Whether the input is disabled */
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
2
|
-
import React__default, { useMemo, useState, useRef, useEffect, useCallback, useLayoutEffect } from 'react';
|
|
2
|
+
import React__default, { useMemo, useId, useState, useRef, useEffect, useCallback, useLayoutEffect } from 'react';
|
|
3
3
|
import { createPortal } from 'react-dom';
|
|
4
4
|
import { AnimatePresence, motion } from 'motion/react';
|
|
5
5
|
import { mentionTheme } from './Mention.theme.js';
|
|
6
6
|
import { cn } from '../../../utils/cn.js';
|
|
7
7
|
import { Avatar } from '../../core/Avatar/Avatar.js';
|
|
8
8
|
import { Tag } from '../../core/Tag/Tag.js';
|
|
9
|
+
import { FormLabel } from '../FormLabel/FormLabel.js';
|
|
9
10
|
import { useIsClient } from '../../../hooks/useIsClient.js';
|
|
10
11
|
import { normalizeSegments, setCaretAtOffset, getPlainTextOffset, parseDOMToSegments, serializeSegments, serializeSegmentsMasked, insertMentionIntoSegments, MENTION_ATTR } from './Mention.utils.js';
|
|
11
12
|
|
|
@@ -73,8 +74,11 @@ const dropdownVariants = {
|
|
|
73
74
|
// ---------------------------------------------------------------------------
|
|
74
75
|
// Mention component
|
|
75
76
|
// ---------------------------------------------------------------------------
|
|
76
|
-
const Mention = React__default.forwardRef(({ triggers: triggersProp, suggestions: suggestionsProp, onSearch: onSearchProp, value: controlledValue, defaultValue = "", onChange, onMentionSelect, onMentionsChange, placeholder, size = "md", maxSuggestions = 8, className, wrapperClassName, dropdownClassName, theme: themeOverrides, disabled = false, renderSuggestion, emptyMessage = "No results found", loading = false, mentionTagSize = "sm", mentionTagClassName, rows = 3, ...props }, ref) => {
|
|
77
|
+
const Mention = React__default.forwardRef(({ triggers: triggersProp, suggestions: suggestionsProp, onSearch: onSearchProp, value: controlledValue, defaultValue = "", onChange, onMentionSelect, onMentionsChange, placeholder, size = "md", maxSuggestions = 8, className, wrapperClassName, dropdownClassName, theme: themeOverrides, state = "default", disabled = false, helperText, required, label, renderSuggestion, emptyMessage = "No results found", loading = false, mentionTagSize = "sm", mentionTagClassName, rows = 3, ...props }, ref) => {
|
|
77
78
|
const theme = useMemo(() => ({ ...mentionTheme, ...(themeOverrides || {}) }), [themeOverrides]);
|
|
79
|
+
const generatedId = useId();
|
|
80
|
+
const isDisabled = state === "disabled" || disabled;
|
|
81
|
+
const isInvalid = state === "invalid";
|
|
78
82
|
const triggers = useMemo(() => {
|
|
79
83
|
if (triggersProp && triggersProp.length > 0)
|
|
80
84
|
return triggersProp;
|
|
@@ -150,7 +154,7 @@ const Mention = React__default.forwardRef(({ triggers: triggersProp, suggestions
|
|
|
150
154
|
if (!activeMention || !(activeTriggerConfig === null || activeTriggerConfig === void 0 ? void 0 : activeTriggerConfig.onSearch))
|
|
151
155
|
return;
|
|
152
156
|
activeTriggerConfig.onSearch(activeMention.query);
|
|
153
|
-
}, [activeMention === null || activeMention === void 0 ? void 0 : activeMention.query, activeMention === null || activeMention === void 0 ? void 0 : activeMention.trigger]);
|
|
157
|
+
}, [activeMention === null || activeMention === void 0 ? void 0 : activeMention.query, activeMention === null || activeMention === void 0 ? void 0 : activeMention.trigger, activeTriggerConfig]);
|
|
154
158
|
// Reset highlighted index when suggestions change
|
|
155
159
|
useEffect(() => {
|
|
156
160
|
setHighlightedIndex(filteredSuggestions.length > 0 ? 0 : -1);
|
|
@@ -596,11 +600,14 @@ const Mention = React__default.forwardRef(({ triggers: triggersProp, suggestions
|
|
|
596
600
|
// -----------------------------------------------------------------------
|
|
597
601
|
// Render
|
|
598
602
|
// -----------------------------------------------------------------------
|
|
599
|
-
|
|
600
|
-
|
|
603
|
+
const helperId = `${generatedId}-helper`;
|
|
604
|
+
return (jsxs("div", { className: cn(theme.wrapperStyle, wrapperClassName), children: [label && (jsx(FormLabel, { htmlFor: generatedId, state: isDisabled ? "disabled" : isInvalid ? "invalid" : "default", required: required, className: "mb-1.5", children: label })), jsx("div", { ref: wrapperRef, className: cn(theme.inputGroupStyle, isFocused && theme.inputGroupFocusStyle, isInvalid && "border-[var(--color-danger)] ring-1 ring-[var(--color-danger)]"), children: jsx("div", { ref: setEditableRef, id: generatedId, contentEditable: !isDisabled, suppressContentEditableWarning: true, onInput: handleInput, onKeyDown: handleKeyDown, onClick: handleClick, onFocus: handleFocus, onBlur: handleBlur, onPaste: handlePaste, onSelect: handleSelect, onCompositionStart: handleCompositionStart, onCompositionEnd: handleCompositionEnd, role: "textbox", "aria-multiline": "true", "aria-autocomplete": "list", "aria-expanded": isDropdownOpen, "aria-haspopup": "listbox", "aria-placeholder": placeholder, "aria-required": required || undefined, "data-placeholder": placeholder, "aria-disabled": isDisabled || undefined, "aria-invalid": isInvalid || undefined, "aria-describedby": helperText ? helperId : undefined, className: cn(theme.editableStyle, theme.sizes[size], isContentEmpty &&
|
|
605
|
+
"before:content-[attr(data-placeholder)] before:text-[var(--color-text-placeholder)] before:pointer-events-none before:absolute dark:before:text-[var(--color-neutral-500)]", isDisabled && "cursor-not-allowed opacity-60", className), style: {
|
|
601
606
|
minHeight: rows ? `${rows * 1.5}em` : undefined,
|
|
602
607
|
position: "relative",
|
|
603
|
-
}, ...props, children: renderedSegments }) }),
|
|
608
|
+
}, ...props, children: renderedSegments }) }), helperText && (jsx("div", { id: helperId, className: cn("text-sm mt-1", isInvalid
|
|
609
|
+
? "text-[var(--color-danger)]"
|
|
610
|
+
: "text-[var(--color-text-muted)]"), children: helperText })), isClient && createPortal(dropdownContent, document.body)] }));
|
|
604
611
|
});
|
|
605
612
|
Mention.displayName = "Mention";
|
|
606
613
|
|
|
@@ -100,6 +100,7 @@ export interface MentionTheme {
|
|
|
100
100
|
* Partial theme overrides for the Mention component.
|
|
101
101
|
*/
|
|
102
102
|
export type MentionThemeOverrides = Partial<MentionTheme>;
|
|
103
|
+
export type MentionState = "default" | "disabled" | "invalid";
|
|
103
104
|
/**
|
|
104
105
|
* Props for the Mention component.
|
|
105
106
|
*/
|
|
@@ -134,8 +135,14 @@ export interface MentionProps extends Omit<React.HTMLAttributes<HTMLDivElement>,
|
|
|
134
135
|
dropdownClassName?: string;
|
|
135
136
|
/** Theme overrides */
|
|
136
137
|
theme?: MentionThemeOverrides;
|
|
138
|
+
/** Validation/interaction state */
|
|
139
|
+
state?: MentionState;
|
|
137
140
|
/** Whether the mention input is disabled */
|
|
138
141
|
disabled?: boolean;
|
|
142
|
+
/** Helper text rendered below the mention input */
|
|
143
|
+
helperText?: React.ReactNode;
|
|
144
|
+
/** Whether the field is required */
|
|
145
|
+
required?: boolean;
|
|
139
146
|
/** Custom renderer for suggestion items */
|
|
140
147
|
renderSuggestion?: (suggestion: MentionSuggestion, isHighlighted: boolean, trigger: string) => React.ReactNode;
|
|
141
148
|
/** Message shown when no suggestions match */
|
|
@@ -148,4 +155,6 @@ export interface MentionProps extends Omit<React.HTMLAttributes<HTMLDivElement>,
|
|
|
148
155
|
mentionTagClassName?: string;
|
|
149
156
|
/** Number of visible text rows (controls min-height) */
|
|
150
157
|
rows?: number;
|
|
158
|
+
/** Label rendered above the mention input */
|
|
159
|
+
label?: string;
|
|
151
160
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
2
|
-
import React__default, { useId, useState } from 'react';
|
|
2
|
+
import React__default, { useId, useState, useEffect } from 'react';
|
|
3
3
|
import { useReducedMotion, motion } from 'motion/react';
|
|
4
4
|
import { radioTheme } from './Radio.theme.js';
|
|
5
5
|
import { formLabelTheme } from '../FormLabel/FormLabel.theme.js';
|
|
@@ -22,6 +22,7 @@ const RadioComponent = React__default.forwardRef(({ id: idProp, name: nameProp,
|
|
|
22
22
|
const size = (_c = groupContext === null || groupContext === void 0 ? void 0 : groupContext.size) !== null && _c !== void 0 ? _c : sizeProp;
|
|
23
23
|
const state = stateProp === "disabled" ? "disabled" : ((_d = groupContext === null || groupContext === void 0 ? void 0 : groupContext.state) !== null && _d !== void 0 ? _d : stateProp);
|
|
24
24
|
const isDisabled = state === "disabled";
|
|
25
|
+
const isInvalid = state === "invalid";
|
|
25
26
|
// Determine checked state
|
|
26
27
|
const isInGroup = groupContext !== undefined;
|
|
27
28
|
const checked = isInGroup ? groupContext.value === value : checkedProp;
|
|
@@ -43,7 +44,16 @@ const RadioComponent = React__default.forwardRef(({ id: idProp, name: nameProp,
|
|
|
43
44
|
const inputProps = isControlled
|
|
44
45
|
? { checked }
|
|
45
46
|
: { defaultChecked };
|
|
46
|
-
|
|
47
|
+
// Dev-only warning when no accessible name is provided
|
|
48
|
+
useEffect(() => {
|
|
49
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
50
|
+
if (!label && !restProps['aria-label'] && !restProps['aria-labelledby']) {
|
|
51
|
+
console.warn('[Radio]: No accessible name provided. Add a `label` prop, `aria-label`, or `aria-labelledby`.');
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
55
|
+
}, []);
|
|
56
|
+
return (jsxs("div", { className: cn(radioTheme.baseStyle, className), ...restProps, children: [jsxs("div", { className: cn(radioTheme.inputContainerStyle, radioTheme.sizes[size]), children: [jsx("input", { ref: ref, type: "radio", id: id, name: name, value: value, ...inputProps, onChange: handleChange, disabled: isDisabled, "aria-describedby": description ? `${id}-description` : undefined, "aria-invalid": isInvalid || undefined, "data-state": isDisabled ? "disabled" : isInvalid ? "invalid" : "default", className: cn("peer", radioTheme.inputStyle, radioTheme.sizes[size]) }), jsx(motion.div, { className: cn(radioTheme.dotStyle, radioTheme.dotSizes[size], isDisabled && "saturate-0 opacity-80"), initial: false, animate: isChecked ? "checked" : "unchecked", variants: shouldReduceMotion ? reducedMotionDotVariants : radioDotVariants })] }), (label || description) && (jsxs("label", { htmlFor: id, className: cn("cursor-pointer", isDisabled && "cursor-not-allowed"), children: [label && (typeof label === 'string' ? (jsx("span", { className: cn(formLabelTheme.baseStyle, formLabelTheme.stateStyles[state], "mb-0"), children: label })) : label), description && (typeof description === 'string' ? (jsx("div", { id: `${id}-description`, className: radioTheme.descriptionStyle, children: description })) : description)] }))] }));
|
|
47
57
|
});
|
|
48
58
|
RadioComponent.displayName = "Radio";
|
|
49
59
|
const Radio = Object.assign(RadioComponent, { Group: RadioGroup });
|
|
@@ -23,16 +23,20 @@ const radioTheme = {
|
|
|
23
23
|
"data-[state=disabled]:border-[var(--color-border)] data-[state=disabled]:bg-[var(--color-background-disabled)] data-[state=disabled]:cursor-not-allowed " +
|
|
24
24
|
// Disabled state - dark
|
|
25
25
|
"dark:disabled:bg-[var(--color-neutral-700)] dark:disabled:border-[var(--color-neutral-600)] " +
|
|
26
|
-
"dark:data-[state=disabled]:bg-[var(--color-neutral-700)] dark:data-[state=disabled]:border-[var(--color-neutral-600)]"
|
|
26
|
+
"dark:data-[state=disabled]:bg-[var(--color-neutral-700)] dark:data-[state=disabled]:border-[var(--color-neutral-600)] " +
|
|
27
|
+
// Invalid state
|
|
28
|
+
"data-[state=invalid]:border-[var(--color-danger)] data-[state=invalid]:focus-visible:outline-[var(--color-danger)]",
|
|
27
29
|
dotStyle: "absolute top-1/2 left-1/2 pointer-events-none rounded-full bg-[var(--color-primary)]",
|
|
28
30
|
dotSizes: {
|
|
29
31
|
sm: "size-2.5 mt-0.25",
|
|
30
32
|
md: "size-3",
|
|
33
|
+
lg: "size-3.5",
|
|
31
34
|
},
|
|
32
35
|
descriptionStyle: "text-sm text-[var(--color-text-secondary)]/80 mt-0",
|
|
33
36
|
sizes: {
|
|
34
37
|
sm: "size-5 mt-0.5",
|
|
35
38
|
md: "size-6",
|
|
39
|
+
lg: "size-7",
|
|
36
40
|
},
|
|
37
41
|
// Group styles
|
|
38
42
|
groupStyle: "flex flex-col gap-1.5",
|
|
@@ -2,11 +2,11 @@ import React from 'react';
|
|
|
2
2
|
/**
|
|
3
3
|
* State variants for the radio component
|
|
4
4
|
*/
|
|
5
|
-
export type RadioState = 'default' | 'disabled';
|
|
5
|
+
export type RadioState = 'default' | 'disabled' | 'invalid';
|
|
6
6
|
/**
|
|
7
7
|
* Size variants for the radio component
|
|
8
8
|
*/
|
|
9
|
-
export type RadioSize = 'sm' | 'md';
|
|
9
|
+
export type RadioSize = 'sm' | 'md' | 'lg';
|
|
10
10
|
/**
|
|
11
11
|
* Orientation for Radio.Group layout
|
|
12
12
|
*/
|
|
@@ -14,11 +14,9 @@ export type RadioGroupOrientation = 'vertical' | 'horizontal';
|
|
|
14
14
|
/**
|
|
15
15
|
* Radio component props
|
|
16
16
|
*/
|
|
17
|
-
export interface RadioProps extends Omit<React.
|
|
17
|
+
export interface RadioProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'onChange' | 'size'> {
|
|
18
18
|
id?: string;
|
|
19
|
-
name?: string;
|
|
20
19
|
value: string | number;
|
|
21
|
-
checked?: boolean;
|
|
22
20
|
onChange?: (checked: boolean, value: string | number) => void;
|
|
23
21
|
label?: React.ReactNode;
|
|
24
22
|
description?: React.ReactNode;
|
|
@@ -39,7 +37,11 @@ export interface RadioGroupProps extends Omit<React.HTMLAttributes<HTMLFieldSetE
|
|
|
39
37
|
orientation?: RadioGroupOrientation;
|
|
40
38
|
label?: React.ReactNode;
|
|
41
39
|
description?: React.ReactNode;
|
|
40
|
+
/**
|
|
41
|
+
* @deprecated Use `state='invalid'` with `errorMessage` instead.
|
|
42
|
+
*/
|
|
42
43
|
error?: React.ReactNode;
|
|
44
|
+
errorMessage?: React.ReactNode;
|
|
43
45
|
required?: boolean;
|
|
44
46
|
className?: string;
|
|
45
47
|
}
|
|
@@ -5,7 +5,12 @@ import { radioTheme } from './Radio.theme.js';
|
|
|
5
5
|
import { formLabelTheme } from '../FormLabel/FormLabel.theme.js';
|
|
6
6
|
import { RadioGroupContext } from './RadioContext.js';
|
|
7
7
|
|
|
8
|
-
const RadioGroup = React__default.forwardRef(({ value: controlledValue, defaultValue, onChange, name, size = "md", state = "default", orientation = "vertical", label, description, error, required, className, children, ...props }, ref) => {
|
|
8
|
+
const RadioGroup = React__default.forwardRef(({ value: controlledValue, defaultValue, onChange, name, size = "md", state: stateProp = "default", orientation = "vertical", label, description, error, errorMessage, required, className, children, ...props }, ref) => {
|
|
9
|
+
// Prefer errorMessage; fall back to deprecated error prop
|
|
10
|
+
const resolvedError = errorMessage !== null && errorMessage !== void 0 ? errorMessage : error;
|
|
11
|
+
// If error (deprecated) is provided and state not explicitly set to something else,
|
|
12
|
+
// implicitly treat the group as invalid
|
|
13
|
+
const state = resolvedError && stateProp === "default" ? "invalid" : stateProp;
|
|
9
14
|
const autoId = useId();
|
|
10
15
|
const groupName = name !== null && name !== void 0 ? name : `radio-group-${autoId}`;
|
|
11
16
|
const labelId = `${autoId}-label`;
|
|
@@ -28,8 +33,8 @@ const RadioGroup = React__default.forwardRef(({ value: controlledValue, defaultV
|
|
|
28
33
|
size,
|
|
29
34
|
state,
|
|
30
35
|
}), [groupName, currentValue, size, state]);
|
|
31
|
-
const labelState =
|
|
32
|
-
return (jsx(RadioGroupContext.Provider, { value: contextValue, children: jsxs("fieldset", { ref: ref, role: "radiogroup", "aria-labelledby": label ? labelId : undefined, "aria-describedby": description ? descriptionId : undefined, "aria-required": required || undefined, "aria-invalid":
|
|
36
|
+
const labelState = state === "invalid" ? "invalid" : state === "disabled" ? "disabled" : "default";
|
|
37
|
+
return (jsx(RadioGroupContext.Provider, { value: contextValue, children: jsxs("fieldset", { ref: ref, role: "radiogroup", "aria-labelledby": label ? labelId : undefined, "aria-describedby": description ? descriptionId : undefined, "aria-required": required || undefined, "aria-invalid": resolvedError ? true : undefined, "aria-errormessage": resolvedError ? errorId : undefined, className: cn("border-0 p-0 m-0", radioTheme.groupStyle, className), ...props, children: [label && (typeof label === 'string' ? (jsxs("legend", { id: labelId, className: cn(formLabelTheme.baseStyle, formLabelTheme.stateStyles[labelState]), children: [label, required && (jsx("span", { className: formLabelTheme.requiredIndicatorStyle, children: "*" }))] })) : label), description && (typeof description === 'string' ? (jsx("p", { id: descriptionId, className: radioTheme.groupDescriptionStyle, children: description })) : description), jsx("div", { className: cn(radioTheme.groupItemsStyle, orientation === "horizontal" && radioTheme.groupHorizontalStyle), children: children }), resolvedError && (typeof resolvedError === 'string' ? (jsx("p", { id: errorId, role: "alert", className: radioTheme.groupErrorStyle, children: resolvedError })) : resolvedError)] }) }));
|
|
33
38
|
});
|
|
34
39
|
RadioGroup.displayName = "Radio.Group";
|
|
35
40
|
|