@robr0/design-system 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/README.md +6 -4
  2. package/components/Breadcrumb/Breadcrumb.css +9 -1
  3. package/components/Button/Button.d.ts +32 -16
  4. package/components/Button/Button.js +66 -58
  5. package/components/Card/Card.d.ts +17 -5
  6. package/components/Card/Card.js +101 -80
  7. package/components/Checkbox/Checkbox.d.ts +24 -12
  8. package/components/Checkbox/Checkbox.js +99 -85
  9. package/components/Combobox/Combobox.d.ts +19 -7
  10. package/components/Combobox/Combobox.js +18 -9
  11. package/components/DateInput/DateInput.d.ts +18 -21
  12. package/components/DateInput/DateInput.js +71 -63
  13. package/components/DatePicker/DatePicker.d.ts +9 -2
  14. package/components/DatePicker/DatePicker.js +127 -129
  15. package/components/Dialog/Dialog.d.ts +15 -4
  16. package/components/Dialog/Dialog.js +133 -116
  17. package/components/Drawer/Drawer.d.ts +15 -4
  18. package/components/Drawer/Drawer.js +133 -119
  19. package/components/Dropdown/Dropdown.d.ts +24 -8
  20. package/components/Dropdown/Dropdown.js +226 -186
  21. package/components/FileInput/FileInput.d.ts +13 -17
  22. package/components/FileInput/FileInput.js +177 -158
  23. package/components/Input/Input.d.ts +23 -22
  24. package/components/Input/Input.js +87 -65
  25. package/components/RadioButton/RadioButton.d.ts +26 -13
  26. package/components/RadioButton/RadioButton.js +95 -70
  27. package/components/SelectionCard/SelectionCard.d.ts +10 -4
  28. package/components/SelectionCard/SelectionCard.js +72 -56
  29. package/components/Slider/Slider.d.ts +19 -10
  30. package/components/Slider/Slider.js +50 -40
  31. package/components/Table/Table.d.ts +10 -2
  32. package/components/Table/Table.js +58 -58
  33. package/components/Textarea/Textarea.d.ts +21 -22
  34. package/components/Textarea/Textarea.js +77 -68
  35. package/components/ToggleGroup/ToggleGroup.d.ts +18 -8
  36. package/components/ToggleGroup/ToggleGroup.js +61 -44
  37. package/components/ToggleSwitch/ToggleSwitch.d.ts +17 -9
  38. package/components/ToggleSwitch/ToggleSwitch.js +57 -44
  39. package/package.json +1 -1
@@ -1,5 +1,5 @@
1
1
  import { jsxs, jsx } from "react/jsx-runtime";
2
- import { useState, useRef, useId } from "react";
2
+ import React, { useState, useRef, useId } from "react";
3
3
  import "./FileInput.css";
4
4
  import "../../fonts/material-symbols.css";
5
5
  const formatBytes = (bytes) => {
@@ -9,169 +9,188 @@ const formatBytes = (bytes) => {
9
9
  const value = bytes / Math.pow(1024, exponent);
10
10
  return `${exponent === 0 ? value : value.toFixed(1)} ${units[exponent]}`;
11
11
  };
12
- const FileInput = ({
13
- label,
14
- placeholder = "Drag and drop, or click to browse",
15
- accept,
16
- multiple = false,
17
- files = [],
18
- size = "default",
19
- disabled = false,
20
- required = false,
21
- error = false,
22
- helperText,
23
- onFilesSelected,
24
- onFileRemove,
25
- className = "",
26
- ariaLabel,
27
- name,
28
- id
29
- }) => {
30
- const [isDragging, setIsDragging] = useState(false);
31
- const inputRef = useRef(null);
32
- const generatedId = useId();
33
- const inputId = id || name || generatedId;
34
- const baseClass = "ds-file-input";
35
- const emitFiles = (fileList) => {
36
- if (!fileList || fileList.length === 0) return;
37
- onFilesSelected?.(Array.from(fileList));
38
- };
39
- const handleChange = (e) => {
40
- emitFiles(e.target.files);
41
- e.target.value = "";
42
- };
43
- const handleDrop = (e) => {
44
- e.preventDefault();
45
- setIsDragging(false);
46
- if (disabled) return;
47
- emitFiles(e.dataTransfer.files);
48
- };
49
- const handleDragOver = (e) => {
50
- e.preventDefault();
51
- if (!disabled) setIsDragging(true);
52
- };
53
- const handleDragLeave = (e) => {
54
- if (e.currentTarget.contains(e.relatedTarget)) return;
55
- setIsDragging(false);
56
- };
57
- const openPicker = () => {
58
- if (!disabled) inputRef.current?.click();
59
- };
60
- const handleKeyDown = (e) => {
61
- if (e.key === "Enter" || e.key === " ") {
12
+ const FileInput = React.forwardRef(
13
+ ({
14
+ label,
15
+ placeholder = "Drag and drop, or click to browse",
16
+ accept,
17
+ multiple = false,
18
+ files = [],
19
+ size = "default",
20
+ disabled = false,
21
+ required = false,
22
+ error = false,
23
+ helperText,
24
+ onFilesSelected,
25
+ onFileRemove,
26
+ onChange,
27
+ className = "",
28
+ ariaLabel,
29
+ name,
30
+ id,
31
+ ...rest
32
+ }, ref) => {
33
+ const [isDragging, setIsDragging] = useState(false);
34
+ const inputRef = useRef(null);
35
+ const generatedId = useId();
36
+ const inputId = id || name || generatedId;
37
+ const baseClass = "ds-file-input";
38
+ const setInputRef = (node) => {
39
+ inputRef.current = node;
40
+ if (typeof ref === "function") ref(node);
41
+ else if (ref) ref.current = node;
42
+ };
43
+ const emitFiles = (fileList) => {
44
+ if (!fileList || fileList.length === 0) return;
45
+ onFilesSelected?.(Array.from(fileList));
46
+ };
47
+ const handleChange = (e) => {
48
+ onChange?.(e);
49
+ emitFiles(e.target.files);
50
+ e.target.value = "";
51
+ };
52
+ const handleDrop = (e) => {
62
53
  e.preventDefault();
63
- openPicker();
64
- }
65
- };
66
- const classes = [
67
- baseClass,
68
- size === "compact" ? `${baseClass}--compact` : "",
69
- error ? `${baseClass}--error` : "",
70
- disabled ? `${baseClass}--disabled` : "",
71
- isDragging ? `${baseClass}--dragging` : "",
72
- className
73
- ].filter(Boolean).join(" ");
74
- return /* @__PURE__ */ jsxs("div", { className: classes, children: [
75
- label && /* @__PURE__ */ jsxs("label", { className: `${baseClass}__label`, htmlFor: inputId, children: [
76
- label,
77
- required && /* @__PURE__ */ jsxs("span", { className: `${baseClass}__required`, "aria-hidden": "true", children: [
78
- " ",
79
- "*"
80
- ] })
81
- ] }),
82
- /* @__PURE__ */ jsxs(
83
- "div",
84
- {
85
- className: `${baseClass}__dropzone`,
86
- role: "button",
87
- tabIndex: disabled ? -1 : 0,
88
- "aria-label": ariaLabel || placeholder,
89
- "aria-describedby": helperText ? `${inputId}-helper` : void 0,
90
- "aria-disabled": disabled || void 0,
91
- onClick: openPicker,
92
- onKeyDown: handleKeyDown,
93
- onDrop: handleDrop,
94
- onDragOver: handleDragOver,
95
- onDragLeave: handleDragLeave,
96
- children: [
97
- /* @__PURE__ */ jsx("span", { className: `${baseClass}__dropzone-icon material-symbols-rounded`, "aria-hidden": "true", children: "upload_file" }),
98
- /* @__PURE__ */ jsx("span", { className: `${baseClass}__dropzone-text`, children: placeholder }),
99
- accept && /* @__PURE__ */ jsxs("span", { className: `${baseClass}__dropzone-hint`, children: [
100
- "Accepts ",
101
- accept
102
- ] }),
103
- /* @__PURE__ */ jsx(
104
- "input",
105
- {
106
- ref: inputRef,
107
- id: inputId,
108
- name,
109
- type: "file",
110
- className: `${baseClass}__native`,
111
- accept,
112
- multiple,
113
- disabled,
114
- required,
115
- tabIndex: -1,
116
- onChange: handleChange
117
- }
118
- )
119
- ]
54
+ setIsDragging(false);
55
+ if (disabled) return;
56
+ emitFiles(e.dataTransfer.files);
57
+ };
58
+ const handleDragOver = (e) => {
59
+ e.preventDefault();
60
+ if (!disabled) setIsDragging(true);
61
+ };
62
+ const handleDragLeave = (e) => {
63
+ if (e.currentTarget.contains(e.relatedTarget)) return;
64
+ setIsDragging(false);
65
+ };
66
+ const openPicker = () => {
67
+ if (!disabled) inputRef.current?.click();
68
+ };
69
+ const handleKeyDown = (e) => {
70
+ if (e.key === "Enter" || e.key === " ") {
71
+ e.preventDefault();
72
+ openPicker();
120
73
  }
121
- ),
122
- files.length > 0 && /* @__PURE__ */ jsx("ul", { className: `${baseClass}__list`, children: files.map((file) => /* @__PURE__ */ jsxs(
123
- "li",
124
- {
125
- className: [`${baseClass}__file`, file.error ? `${baseClass}__file--error` : ""].filter(Boolean).join(" "),
126
- children: [
127
- /* @__PURE__ */ jsx(
128
- "span",
129
- {
130
- className: `${baseClass}__file-icon material-symbols-rounded`,
131
- "aria-hidden": "true",
132
- children: file.error ? "error" : "description"
133
- }
134
- ),
135
- /* @__PURE__ */ jsxs("span", { className: `${baseClass}__file-details`, children: [
136
- /* @__PURE__ */ jsx("span", { className: `${baseClass}__file-name`, children: file.name }),
137
- file.error ? /* @__PURE__ */ jsx("span", { className: `${baseClass}__file-error`, children: file.error }) : file.size !== void 0 && /* @__PURE__ */ jsx("span", { className: `${baseClass}__file-size`, children: formatBytes(file.size) }),
138
- file.error === void 0 && file.progress !== void 0 && /* @__PURE__ */ jsx(
74
+ };
75
+ const classes = [
76
+ baseClass,
77
+ size === "compact" ? `${baseClass}--compact` : "",
78
+ error ? `${baseClass}--error` : "",
79
+ disabled ? `${baseClass}--disabled` : "",
80
+ isDragging ? `${baseClass}--dragging` : "",
81
+ className
82
+ ].filter(Boolean).join(" ");
83
+ return /* @__PURE__ */ jsxs("div", { className: classes, children: [
84
+ label && /* @__PURE__ */ jsxs("label", { className: `${baseClass}__label`, htmlFor: inputId, children: [
85
+ label,
86
+ required && /* @__PURE__ */ jsxs("span", { className: `${baseClass}__required`, "aria-hidden": "true", children: [
87
+ " ",
88
+ "*"
89
+ ] })
90
+ ] }),
91
+ /* @__PURE__ */ jsxs(
92
+ "div",
93
+ {
94
+ className: `${baseClass}__dropzone`,
95
+ role: "button",
96
+ tabIndex: disabled ? -1 : 0,
97
+ "aria-label": ariaLabel || rest["aria-label"] || placeholder,
98
+ "aria-describedby": helperText ? `${inputId}-helper` : void 0,
99
+ "aria-disabled": disabled || void 0,
100
+ onClick: openPicker,
101
+ onKeyDown: handleKeyDown,
102
+ onDrop: handleDrop,
103
+ onDragOver: handleDragOver,
104
+ onDragLeave: handleDragLeave,
105
+ children: [
106
+ /* @__PURE__ */ jsx(
139
107
  "span",
140
108
  {
141
- className: `${baseClass}__progress`,
142
- role: "progressbar",
143
- "aria-valuenow": file.progress,
144
- "aria-valuemin": 0,
145
- "aria-valuemax": 100,
146
- "aria-label": `Uploading ${file.name}`,
147
- children: /* @__PURE__ */ jsx(
148
- "span",
149
- {
150
- className: `${baseClass}__progress-fill`,
151
- style: { width: `${Math.min(100, Math.max(0, file.progress))}%` }
152
- }
153
- )
109
+ className: `${baseClass}__dropzone-icon material-symbols-rounded`,
110
+ "aria-hidden": "true",
111
+ children: "upload_file"
112
+ }
113
+ ),
114
+ /* @__PURE__ */ jsx("span", { className: `${baseClass}__dropzone-text`, children: placeholder }),
115
+ accept && /* @__PURE__ */ jsxs("span", { className: `${baseClass}__dropzone-hint`, children: [
116
+ "Accepts ",
117
+ accept
118
+ ] }),
119
+ /* @__PURE__ */ jsx(
120
+ "input",
121
+ {
122
+ ...rest,
123
+ ref: setInputRef,
124
+ id: inputId,
125
+ name,
126
+ type: "file",
127
+ className: `${baseClass}__native`,
128
+ accept,
129
+ multiple,
130
+ disabled,
131
+ required,
132
+ tabIndex: -1,
133
+ onChange: handleChange
154
134
  }
155
135
  )
156
- ] }),
157
- onFileRemove && /* @__PURE__ */ jsx(
158
- "button",
159
- {
160
- type: "button",
161
- className: `${baseClass}__file-remove`,
162
- onClick: () => onFileRemove(file.id),
163
- disabled,
164
- "aria-label": `Remove ${file.name}`,
165
- children: /* @__PURE__ */ jsx("span", { className: "material-symbols-rounded", "aria-hidden": "true", children: "close" })
166
- }
167
- )
168
- ]
169
- },
170
- file.id
171
- )) }),
172
- helperText && /* @__PURE__ */ jsx("p", { className: `${baseClass}__helper`, id: `${inputId}-helper`, children: helperText })
173
- ] });
174
- };
136
+ ]
137
+ }
138
+ ),
139
+ files.length > 0 && /* @__PURE__ */ jsx("ul", { className: `${baseClass}__list`, children: files.map((file) => /* @__PURE__ */ jsxs(
140
+ "li",
141
+ {
142
+ className: [`${baseClass}__file`, file.error ? `${baseClass}__file--error` : ""].filter(Boolean).join(" "),
143
+ children: [
144
+ /* @__PURE__ */ jsx(
145
+ "span",
146
+ {
147
+ className: `${baseClass}__file-icon material-symbols-rounded`,
148
+ "aria-hidden": "true",
149
+ children: file.error ? "error" : "description"
150
+ }
151
+ ),
152
+ /* @__PURE__ */ jsxs("span", { className: `${baseClass}__file-details`, children: [
153
+ /* @__PURE__ */ jsx("span", { className: `${baseClass}__file-name`, children: file.name }),
154
+ file.error ? /* @__PURE__ */ jsx("span", { className: `${baseClass}__file-error`, children: file.error }) : file.size !== void 0 && /* @__PURE__ */ jsx("span", { className: `${baseClass}__file-size`, children: formatBytes(file.size) }),
155
+ file.error === void 0 && file.progress !== void 0 && /* @__PURE__ */ jsx(
156
+ "span",
157
+ {
158
+ className: `${baseClass}__progress`,
159
+ role: "progressbar",
160
+ "aria-valuenow": file.progress,
161
+ "aria-valuemin": 0,
162
+ "aria-valuemax": 100,
163
+ "aria-label": `Uploading ${file.name}`,
164
+ children: /* @__PURE__ */ jsx(
165
+ "span",
166
+ {
167
+ className: `${baseClass}__progress-fill`,
168
+ style: { width: `${Math.min(100, Math.max(0, file.progress))}%` }
169
+ }
170
+ )
171
+ }
172
+ )
173
+ ] }),
174
+ onFileRemove && /* @__PURE__ */ jsx(
175
+ "button",
176
+ {
177
+ type: "button",
178
+ className: `${baseClass}__file-remove`,
179
+ onClick: () => onFileRemove(file.id),
180
+ disabled,
181
+ "aria-label": `Remove ${file.name}`,
182
+ children: /* @__PURE__ */ jsx("span", { className: "material-symbols-rounded", "aria-hidden": "true", children: "close" })
183
+ }
184
+ )
185
+ ]
186
+ },
187
+ file.id
188
+ )) }),
189
+ helperText && /* @__PURE__ */ jsx("p", { className: `${baseClass}__helper`, id: `${inputId}-helper`, children: helperText })
190
+ ] });
191
+ }
192
+ );
193
+ FileInput.displayName = "FileInput";
175
194
  export {
176
195
  FileInput
177
196
  };
@@ -1,19 +1,14 @@
1
1
  import { default as React } from 'react';
2
- export interface InputProps {
2
+ /** Props owned by Input itself — everything else falls through to the <input>. */
3
+ type InputOwnProps = {
3
4
  /** Input label text */
4
5
  label?: string;
5
- /** Placeholder text */
6
- placeholder?: string;
7
6
  /** Current value */
8
7
  value?: string;
9
- /** Input type */
8
+ /** Input type — curated subset; use a dedicated component for checkbox/radio/file */
10
9
  type?: 'text' | 'email' | 'password' | 'number' | 'search' | 'tel' | 'url';
11
- /** Component size */
10
+ /** Component size (not the native character-width `size` attribute) */
12
11
  size?: 'default' | 'compact';
13
- /** Whether the input is disabled */
14
- disabled?: boolean;
15
- /** Whether the input is required */
16
- required?: boolean;
17
12
  /** Error state — shows error styling and message */
18
13
  error?: boolean;
19
14
  /** Helper or error message displayed below the input */
@@ -22,19 +17,25 @@ export interface InputProps {
22
17
  iconLeft?: string;
23
18
  /** Material Symbol icon name on the right */
24
19
  iconRight?: string;
25
- /** Callback when value changes */
26
- onChange?: (value: string) => void;
27
- /** Callback on focus */
28
- onFocus?: () => void;
29
- /** Callback on blur */
30
- onBlur?: () => void;
31
- /** Additional CSS classes */
20
+ /**
21
+ * Convenience callback receiving the value directly.
22
+ * Fires alongside `onChange`, which keeps the standard React event signature
23
+ * so form libraries (react-hook-form, Formik, TanStack Form) work unmodified.
24
+ */
25
+ onValueChange?: (value: string) => void;
26
+ /** Additional CSS classes — applied to the wrapper, not the <input> */
32
27
  className?: string;
33
- /** Accessible name override */
28
+ /** @deprecated Pass the native `aria-label` attribute instead. */
34
29
  ariaLabel?: string;
35
- /** HTML name attribute */
36
- name?: string;
37
- /** HTML id attribute */
38
- id?: string;
30
+ };
31
+ export interface InputProps extends InputOwnProps, Omit<React.ComponentPropsWithoutRef<'input'>, keyof InputOwnProps> {
39
32
  }
40
- export declare const Input: ({ label, placeholder, value, type, size, disabled, required, error, helperText, iconLeft, iconRight, onChange, onFocus, onBlur, className, ariaLabel, name, id, }: InputProps) => React.JSX.Element;
33
+ /**
34
+ * Text input with optional label, helper text, icons and error state.
35
+ *
36
+ * Forwards a ref to the underlying `<input>` and spreads unrecognised props onto
37
+ * it, so `autoComplete`, `maxLength`, `inputMode`, `data-*` and form-library
38
+ * registration all work.
39
+ */
40
+ export declare const Input: React.ForwardRefExoticComponent<InputProps & React.RefAttributes<HTMLInputElement>>;
41
+ export {};
@@ -1,71 +1,93 @@
1
1
  import { jsxs, jsx } from "react/jsx-runtime";
2
- import "react";
2
+ import React from "react";
3
3
  import "./Input.css";
4
4
  import "../../fonts/material-symbols.css";
5
- const Input = ({
6
- label,
7
- placeholder = "",
8
- value,
9
- type = "text",
10
- size = "default",
11
- disabled = false,
12
- required = false,
13
- error = false,
14
- helperText,
15
- iconLeft,
16
- iconRight,
17
- onChange,
18
- onFocus,
19
- onBlur,
20
- className = "",
21
- ariaLabel,
22
- name,
23
- id
24
- }) => {
25
- const baseClass = "ds-input";
26
- const sizeClass = size === "compact" ? `${baseClass}--compact` : "";
27
- const errorClass = error ? `${baseClass}--error` : "";
28
- const disabledClass = disabled ? `${baseClass}--disabled` : "";
29
- const hasLeftIcon = iconLeft ? `${baseClass}--has-icon-left` : "";
30
- const hasRightIcon = iconRight ? `${baseClass}--has-icon-right` : "";
31
- const classes = [baseClass, sizeClass, errorClass, disabledClass, hasLeftIcon, hasRightIcon, className].filter(Boolean).join(" ");
32
- const handleChange = (e) => {
33
- if (onChange) {
34
- onChange(e.target.value);
35
- }
36
- };
37
- const inputId = id || name || label?.toLowerCase().replace(/\s+/g, "-");
38
- return /* @__PURE__ */ jsxs("div", { className: classes, children: [
39
- label && /* @__PURE__ */ jsxs("label", { className: `${baseClass}__label`, htmlFor: inputId, children: [
40
- label,
41
- required && /* @__PURE__ */ jsx("span", { className: `${baseClass}__required`, "aria-hidden": "true", children: " *" })
42
- ] }),
43
- /* @__PURE__ */ jsxs("div", { className: `${baseClass}__field-wrapper`, children: [
44
- iconLeft && /* @__PURE__ */ jsx("span", { className: `${baseClass}__icon ${baseClass}__icon--left material-symbols-rounded`, "aria-hidden": "true", children: iconLeft }),
45
- /* @__PURE__ */ jsx(
46
- "input",
47
- {
48
- className: `${baseClass}__field`,
49
- type,
50
- id: inputId,
51
- name,
52
- value,
53
- placeholder,
54
- disabled,
55
- required,
56
- "aria-label": ariaLabel || label,
57
- "aria-invalid": error,
58
- "aria-describedby": helperText ? `${inputId}-helper` : void 0,
59
- onChange: handleChange,
60
- onFocus,
61
- onBlur
62
- }
63
- ),
64
- iconRight && /* @__PURE__ */ jsx("span", { className: `${baseClass}__icon ${baseClass}__icon--right material-symbols-rounded`, "aria-hidden": "true", children: iconRight })
65
- ] }),
66
- helperText && /* @__PURE__ */ jsx("p", { className: `${baseClass}__helper`, id: `${inputId}-helper`, children: helperText })
67
- ] });
68
- };
5
+ const Input = React.forwardRef(
6
+ ({
7
+ label,
8
+ placeholder = "",
9
+ value,
10
+ type = "text",
11
+ size = "default",
12
+ disabled = false,
13
+ required = false,
14
+ error = false,
15
+ helperText,
16
+ iconLeft,
17
+ iconRight,
18
+ onChange,
19
+ onValueChange,
20
+ className = "",
21
+ ariaLabel,
22
+ name,
23
+ id,
24
+ ...rest
25
+ }, ref) => {
26
+ const baseClass = "ds-input";
27
+ const classes = [
28
+ baseClass,
29
+ size === "compact" ? `${baseClass}--compact` : "",
30
+ error ? `${baseClass}--error` : "",
31
+ disabled ? `${baseClass}--disabled` : "",
32
+ iconLeft ? `${baseClass}--has-icon-left` : "",
33
+ iconRight ? `${baseClass}--has-icon-right` : "",
34
+ className
35
+ ].filter(Boolean).join(" ");
36
+ const handleChange = (e) => {
37
+ onChange?.(e);
38
+ onValueChange?.(e.target.value);
39
+ };
40
+ const inputId = id || name || label?.toLowerCase().replace(/\s+/g, "-");
41
+ return /* @__PURE__ */ jsxs("div", { className: classes, children: [
42
+ label && /* @__PURE__ */ jsxs("label", { className: `${baseClass}__label`, htmlFor: inputId, children: [
43
+ label,
44
+ required && /* @__PURE__ */ jsxs("span", { className: `${baseClass}__required`, "aria-hidden": "true", children: [
45
+ " ",
46
+ "*"
47
+ ] })
48
+ ] }),
49
+ /* @__PURE__ */ jsxs("div", { className: `${baseClass}__field-wrapper`, children: [
50
+ iconLeft && /* @__PURE__ */ jsx(
51
+ "span",
52
+ {
53
+ className: `${baseClass}__icon ${baseClass}__icon--left material-symbols-rounded`,
54
+ "aria-hidden": "true",
55
+ children: iconLeft
56
+ }
57
+ ),
58
+ /* @__PURE__ */ jsx(
59
+ "input",
60
+ {
61
+ ...rest,
62
+ ref,
63
+ className: `${baseClass}__field`,
64
+ type,
65
+ id: inputId,
66
+ name,
67
+ value,
68
+ placeholder,
69
+ disabled,
70
+ required,
71
+ "aria-label": ariaLabel || rest["aria-label"] || label,
72
+ "aria-invalid": error,
73
+ "aria-describedby": helperText ? `${inputId}-helper` : rest["aria-describedby"],
74
+ onChange: handleChange
75
+ }
76
+ ),
77
+ iconRight && /* @__PURE__ */ jsx(
78
+ "span",
79
+ {
80
+ className: `${baseClass}__icon ${baseClass}__icon--right material-symbols-rounded`,
81
+ "aria-hidden": "true",
82
+ children: iconRight
83
+ }
84
+ )
85
+ ] }),
86
+ helperText && /* @__PURE__ */ jsx("p", { className: `${baseClass}__helper`, id: `${inputId}-helper`, children: helperText })
87
+ ] });
88
+ }
89
+ );
90
+ Input.displayName = "Input";
69
91
  export {
70
92
  Input
71
93
  };
@@ -1,26 +1,34 @@
1
1
  import { default as React } from 'react';
2
- export interface RadioButtonProps {
2
+ /** Props owned by RadioButton itself — everything else falls through to the wrapper. */
3
+ type RadioButtonOwnProps = {
3
4
  /** Label text */
4
5
  label?: string;
5
6
  /** Whether this radio is selected */
6
7
  checked?: boolean;
7
8
  /** Whether the radio is disabled */
8
9
  disabled?: boolean;
9
- /** Radio group name — groups radios together */
10
- name?: string;
11
10
  /** Value for this radio option */
12
11
  value?: string;
13
- /** Callback when selected */
14
- onChange?: (value: string) => void;
12
+ /** Called with this radio's value when selected */
13
+ onValueChange?: (value: string) => void;
15
14
  /** Additional CSS classes */
16
15
  className?: string;
17
- /** Accessible label override */
16
+ /** @deprecated Use `onValueChange` instead. */
17
+ onChange?: (value: string) => void;
18
+ /** @deprecated Pass the native `aria-label` attribute instead. */
18
19
  ariaLabel?: string;
19
- /** HTML id attribute */
20
- id?: string;
20
+ /**
21
+ * @deprecated No-op. This component renders a `<div role="radio">`, not a
22
+ * native `<input type="radio">`, so it does not group by name or participate
23
+ * in native form submission — `RadioGroup` handles grouping in React state.
24
+ * Declared only so the attribute is not forwarded to an element that rejects it.
25
+ */
26
+ name?: string;
27
+ };
28
+ export interface RadioButtonProps extends RadioButtonOwnProps, Omit<React.ComponentPropsWithoutRef<'div'>, keyof RadioButtonOwnProps> {
21
29
  }
22
- export declare const RadioButton: ({ label, checked, disabled, value, onChange, className, ariaLabel, }: RadioButtonProps) => React.JSX.Element;
23
- export interface RadioGroupProps {
30
+ export declare const RadioButton: React.ForwardRefExoticComponent<RadioButtonProps & React.RefAttributes<HTMLDivElement>>;
31
+ type RadioGroupOwnProps = {
24
32
  /** Group label */
25
33
  label?: string;
26
34
  /** Currently selected value */
@@ -35,9 +43,14 @@ export interface RadioGroupProps {
35
43
  }[];
36
44
  /** Layout direction */
37
45
  direction?: 'vertical' | 'horizontal';
38
- /** Callback when selection changes */
39
- onChange?: (value: string) => void;
46
+ /** Called with the newly selected value */
47
+ onValueChange?: (value: string) => void;
40
48
  /** Additional CSS classes */
41
49
  className?: string;
50
+ /** @deprecated Use `onValueChange` instead. */
51
+ onChange?: (value: string) => void;
52
+ };
53
+ export interface RadioGroupProps extends RadioGroupOwnProps, Omit<React.ComponentPropsWithoutRef<'div'>, keyof RadioGroupOwnProps> {
42
54
  }
43
- export declare const RadioGroup: ({ label, value, name, options, direction, onChange, className, }: RadioGroupProps) => React.JSX.Element;
55
+ export declare const RadioGroup: React.ForwardRefExoticComponent<RadioGroupProps & React.RefAttributes<HTMLDivElement>>;
56
+ export {};