@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.
- package/README.md +6 -4
- package/components/Breadcrumb/Breadcrumb.css +9 -1
- package/components/Button/Button.d.ts +32 -16
- package/components/Button/Button.js +66 -58
- package/components/Card/Card.d.ts +17 -5
- package/components/Card/Card.js +101 -80
- package/components/Checkbox/Checkbox.d.ts +24 -12
- package/components/Checkbox/Checkbox.js +99 -85
- package/components/Combobox/Combobox.d.ts +19 -7
- package/components/Combobox/Combobox.js +18 -9
- package/components/DateInput/DateInput.d.ts +18 -21
- package/components/DateInput/DateInput.js +71 -63
- package/components/DatePicker/DatePicker.d.ts +9 -2
- package/components/DatePicker/DatePicker.js +127 -129
- package/components/Dialog/Dialog.d.ts +15 -4
- package/components/Dialog/Dialog.js +133 -116
- package/components/Drawer/Drawer.d.ts +15 -4
- package/components/Drawer/Drawer.js +133 -119
- package/components/Dropdown/Dropdown.d.ts +24 -8
- package/components/Dropdown/Dropdown.js +226 -186
- package/components/FileInput/FileInput.d.ts +13 -17
- package/components/FileInput/FileInput.js +177 -158
- package/components/Input/Input.d.ts +23 -22
- package/components/Input/Input.js +87 -65
- package/components/RadioButton/RadioButton.d.ts +26 -13
- package/components/RadioButton/RadioButton.js +95 -70
- package/components/SelectionCard/SelectionCard.d.ts +10 -4
- package/components/SelectionCard/SelectionCard.js +72 -56
- package/components/Slider/Slider.d.ts +19 -10
- package/components/Slider/Slider.js +50 -40
- package/components/Table/Table.d.ts +10 -2
- package/components/Table/Table.js +58 -58
- package/components/Textarea/Textarea.d.ts +21 -22
- package/components/Textarea/Textarea.js +77 -68
- package/components/ToggleGroup/ToggleGroup.d.ts +18 -8
- package/components/ToggleGroup/ToggleGroup.js +61 -44
- package/components/ToggleSwitch/ToggleSwitch.d.ts +17 -9
- package/components/ToggleSwitch/ToggleSwitch.js +57 -44
- package/package.json +1 -1
|
@@ -1,196 +1,236 @@
|
|
|
1
1
|
import { jsxs, jsx } from "react/jsx-runtime";
|
|
2
|
-
import { useState, useRef, useCallback, useEffect } from "react";
|
|
2
|
+
import React, { useState, useRef, useCallback, useEffect } from "react";
|
|
3
3
|
import "./Dropdown.css";
|
|
4
4
|
import "../../fonts/material-symbols.css";
|
|
5
|
-
const Dropdown = (
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
5
|
+
const Dropdown = React.forwardRef(
|
|
6
|
+
({
|
|
7
|
+
label,
|
|
8
|
+
placeholder = "Select an option",
|
|
9
|
+
value,
|
|
10
|
+
options,
|
|
11
|
+
groups,
|
|
12
|
+
size = "default",
|
|
13
|
+
disabled = false,
|
|
14
|
+
required = false,
|
|
15
|
+
error = false,
|
|
16
|
+
helperText,
|
|
17
|
+
onValueChange,
|
|
18
|
+
onChange,
|
|
19
|
+
className = "",
|
|
20
|
+
ariaLabel,
|
|
21
|
+
name,
|
|
22
|
+
id,
|
|
23
|
+
...rest
|
|
24
|
+
}, ref) => {
|
|
25
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
26
|
+
const [focusedIndex, setFocusedIndex] = useState(-1);
|
|
27
|
+
const dropdownRef = useRef(null);
|
|
28
|
+
const listRef = useRef(null);
|
|
29
|
+
const setRootRef = (node) => {
|
|
30
|
+
dropdownRef.current = node;
|
|
31
|
+
if (typeof ref === "function") ref(node);
|
|
32
|
+
else if (ref) ref.current = node;
|
|
33
|
+
};
|
|
34
|
+
const baseClass = "ds-dropdown";
|
|
35
|
+
const isGrouped = groups && groups.length > 0;
|
|
36
|
+
const classes = [
|
|
37
|
+
baseClass,
|
|
38
|
+
size === "compact" ? `${baseClass}--compact` : "",
|
|
39
|
+
isOpen ? `${baseClass}--open` : "",
|
|
40
|
+
error ? `${baseClass}--error` : "",
|
|
41
|
+
disabled ? `${baseClass}--disabled` : "",
|
|
42
|
+
className
|
|
43
|
+
].filter(Boolean).join(" ");
|
|
44
|
+
const flatOptions = isGrouped ? groups.flatMap((g) => g.options) : options;
|
|
45
|
+
const selectedOption = flatOptions.find((opt) => opt.value === value);
|
|
46
|
+
const inputId = id || name || label?.toLowerCase().replace(/\s+/g, "-");
|
|
47
|
+
const handleToggle = () => {
|
|
48
|
+
if (!disabled) {
|
|
49
|
+
setIsOpen((prev) => !prev);
|
|
50
|
+
setFocusedIndex(-1);
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
const handleSelect = (optionValue) => {
|
|
54
|
+
onValueChange?.(optionValue);
|
|
55
|
+
onChange?.(optionValue);
|
|
50
56
|
setIsOpen(false);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
document.addEventListener("mousedown", handleClickOutside);
|
|
55
|
-
return () => document.removeEventListener("mousedown", handleClickOutside);
|
|
56
|
-
}, [handleClickOutside]);
|
|
57
|
-
const handleKeyDown = (e) => {
|
|
58
|
-
if (disabled) return;
|
|
59
|
-
switch (e.key) {
|
|
60
|
-
case "Enter":
|
|
61
|
-
case " ":
|
|
62
|
-
e.preventDefault();
|
|
63
|
-
if (isOpen && focusedIndex >= 0 && !flatOptions[focusedIndex]?.disabled) {
|
|
64
|
-
handleSelect(flatOptions[focusedIndex].value);
|
|
65
|
-
} else {
|
|
66
|
-
setIsOpen((prev) => !prev);
|
|
67
|
-
}
|
|
68
|
-
break;
|
|
69
|
-
case "ArrowDown":
|
|
70
|
-
e.preventDefault();
|
|
71
|
-
if (!isOpen) {
|
|
72
|
-
setIsOpen(true);
|
|
73
|
-
} else {
|
|
74
|
-
setFocusedIndex((prev) => {
|
|
75
|
-
let next = prev + 1;
|
|
76
|
-
while (next < flatOptions.length && flatOptions[next].disabled) next++;
|
|
77
|
-
return next < flatOptions.length ? next : prev;
|
|
78
|
-
});
|
|
79
|
-
}
|
|
80
|
-
break;
|
|
81
|
-
case "ArrowUp":
|
|
82
|
-
e.preventDefault();
|
|
83
|
-
if (isOpen) {
|
|
84
|
-
setFocusedIndex((prev) => {
|
|
85
|
-
let next = prev - 1;
|
|
86
|
-
while (next >= 0 && flatOptions[next].disabled) next--;
|
|
87
|
-
return next >= 0 ? next : prev;
|
|
88
|
-
});
|
|
89
|
-
}
|
|
90
|
-
break;
|
|
91
|
-
case "Escape":
|
|
92
|
-
setIsOpen(false);
|
|
93
|
-
break;
|
|
94
|
-
case "Tab":
|
|
57
|
+
};
|
|
58
|
+
const handleClickOutside = useCallback((e) => {
|
|
59
|
+
if (dropdownRef.current && !dropdownRef.current.contains(e.target)) {
|
|
95
60
|
setIsOpen(false);
|
|
96
|
-
break;
|
|
97
|
-
}
|
|
98
|
-
};
|
|
99
|
-
useEffect(() => {
|
|
100
|
-
if (isOpen && focusedIndex >= 0 && listRef.current) {
|
|
101
|
-
const focusedEl = listRef.current.children[focusedIndex];
|
|
102
|
-
focusedEl?.scrollIntoView({ block: "nearest" });
|
|
103
|
-
}
|
|
104
|
-
}, [focusedIndex, isOpen]);
|
|
105
|
-
return /* @__PURE__ */ jsxs("div", { className: classes, ref: dropdownRef, children: [
|
|
106
|
-
label && /* @__PURE__ */ jsxs("label", { className: `${baseClass}__label`, id: `${inputId}-label`, children: [
|
|
107
|
-
label,
|
|
108
|
-
required && /* @__PURE__ */ jsx("span", { className: `${baseClass}__required`, "aria-hidden": "true", children: " *" })
|
|
109
|
-
] }),
|
|
110
|
-
/* @__PURE__ */ jsxs(
|
|
111
|
-
"div",
|
|
112
|
-
{
|
|
113
|
-
className: `${baseClass}__trigger`,
|
|
114
|
-
role: "combobox",
|
|
115
|
-
"aria-expanded": isOpen,
|
|
116
|
-
"aria-haspopup": "listbox",
|
|
117
|
-
"aria-labelledby": label ? `${inputId}-label` : void 0,
|
|
118
|
-
"aria-label": ariaLabel || (!label ? placeholder : void 0),
|
|
119
|
-
"aria-controls": `${inputId}-listbox`,
|
|
120
|
-
tabIndex: disabled ? -1 : 0,
|
|
121
|
-
onClick: handleToggle,
|
|
122
|
-
onKeyDown: handleKeyDown,
|
|
123
|
-
children: [
|
|
124
|
-
/* @__PURE__ */ jsx("span", { className: `${baseClass}__value ${!selectedOption ? `${baseClass}__value--placeholder` : ""}`, children: selectedOption ? selectedOption.label : placeholder }),
|
|
125
|
-
/* @__PURE__ */ jsx("span", { className: `${baseClass}__chevron material-symbols-rounded`, "aria-hidden": "true", children: "expand_more" })
|
|
126
|
-
]
|
|
127
61
|
}
|
|
128
|
-
)
|
|
129
|
-
|
|
130
|
-
"
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
`${baseClass}__option`,
|
|
174
|
-
option.value === value ? `${baseClass}__option--selected` : "",
|
|
175
|
-
option.disabled ? `${baseClass}__option--disabled` : "",
|
|
176
|
-
index === focusedIndex ? `${baseClass}__option--focused` : ""
|
|
177
|
-
].filter(Boolean).join(" "),
|
|
178
|
-
role: "option",
|
|
179
|
-
"aria-selected": option.value === value,
|
|
180
|
-
"aria-disabled": option.disabled,
|
|
181
|
-
onClick: () => !option.disabled && handleSelect(option.value),
|
|
182
|
-
children: [
|
|
183
|
-
option.label,
|
|
184
|
-
option.value === value && /* @__PURE__ */ jsx("span", { className: `${baseClass}__check material-symbols-rounded`, "aria-hidden": "true", children: "check" })
|
|
185
|
-
]
|
|
186
|
-
},
|
|
187
|
-
option.value
|
|
188
|
-
))
|
|
62
|
+
}, []);
|
|
63
|
+
useEffect(() => {
|
|
64
|
+
document.addEventListener("mousedown", handleClickOutside);
|
|
65
|
+
return () => document.removeEventListener("mousedown", handleClickOutside);
|
|
66
|
+
}, [handleClickOutside]);
|
|
67
|
+
const handleKeyDown = (e) => {
|
|
68
|
+
if (disabled) return;
|
|
69
|
+
switch (e.key) {
|
|
70
|
+
case "Enter":
|
|
71
|
+
case " ":
|
|
72
|
+
e.preventDefault();
|
|
73
|
+
if (isOpen && focusedIndex >= 0 && !flatOptions[focusedIndex]?.disabled) {
|
|
74
|
+
handleSelect(flatOptions[focusedIndex].value);
|
|
75
|
+
} else {
|
|
76
|
+
setIsOpen((prev) => !prev);
|
|
77
|
+
}
|
|
78
|
+
break;
|
|
79
|
+
case "ArrowDown":
|
|
80
|
+
e.preventDefault();
|
|
81
|
+
if (!isOpen) {
|
|
82
|
+
setIsOpen(true);
|
|
83
|
+
} else {
|
|
84
|
+
setFocusedIndex((prev) => {
|
|
85
|
+
let next = prev + 1;
|
|
86
|
+
while (next < flatOptions.length && flatOptions[next].disabled) next++;
|
|
87
|
+
return next < flatOptions.length ? next : prev;
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
break;
|
|
91
|
+
case "ArrowUp":
|
|
92
|
+
e.preventDefault();
|
|
93
|
+
if (isOpen) {
|
|
94
|
+
setFocusedIndex((prev) => {
|
|
95
|
+
let next = prev - 1;
|
|
96
|
+
while (next >= 0 && flatOptions[next].disabled) next--;
|
|
97
|
+
return next >= 0 ? next : prev;
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
break;
|
|
101
|
+
case "Escape":
|
|
102
|
+
setIsOpen(false);
|
|
103
|
+
break;
|
|
104
|
+
case "Tab":
|
|
105
|
+
setIsOpen(false);
|
|
106
|
+
break;
|
|
189
107
|
}
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
108
|
+
};
|
|
109
|
+
useEffect(() => {
|
|
110
|
+
if (isOpen && focusedIndex >= 0 && listRef.current) {
|
|
111
|
+
const focusedEl = listRef.current.children[focusedIndex];
|
|
112
|
+
focusedEl?.scrollIntoView({ block: "nearest" });
|
|
113
|
+
}
|
|
114
|
+
}, [focusedIndex, isOpen]);
|
|
115
|
+
return /* @__PURE__ */ jsxs("div", { ...rest, className: classes, ref: setRootRef, children: [
|
|
116
|
+
label && /* @__PURE__ */ jsxs("label", { className: `${baseClass}__label`, id: `${inputId}-label`, children: [
|
|
117
|
+
label,
|
|
118
|
+
required && /* @__PURE__ */ jsxs("span", { className: `${baseClass}__required`, "aria-hidden": "true", children: [
|
|
119
|
+
" ",
|
|
120
|
+
"*"
|
|
121
|
+
] })
|
|
122
|
+
] }),
|
|
123
|
+
/* @__PURE__ */ jsxs(
|
|
124
|
+
"div",
|
|
125
|
+
{
|
|
126
|
+
className: `${baseClass}__trigger`,
|
|
127
|
+
role: "combobox",
|
|
128
|
+
"aria-expanded": isOpen,
|
|
129
|
+
"aria-haspopup": "listbox",
|
|
130
|
+
"aria-labelledby": label ? `${inputId}-label` : void 0,
|
|
131
|
+
"aria-label": ariaLabel || rest["aria-label"] || (!label ? placeholder : void 0),
|
|
132
|
+
"aria-controls": `${inputId}-listbox`,
|
|
133
|
+
tabIndex: disabled ? -1 : 0,
|
|
134
|
+
onClick: handleToggle,
|
|
135
|
+
onKeyDown: handleKeyDown,
|
|
136
|
+
children: [
|
|
137
|
+
/* @__PURE__ */ jsx(
|
|
138
|
+
"span",
|
|
139
|
+
{
|
|
140
|
+
className: `${baseClass}__value ${!selectedOption ? `${baseClass}__value--placeholder` : ""}`,
|
|
141
|
+
children: selectedOption ? selectedOption.label : placeholder
|
|
142
|
+
}
|
|
143
|
+
),
|
|
144
|
+
/* @__PURE__ */ jsx("span", { className: `${baseClass}__chevron material-symbols-rounded`, "aria-hidden": "true", children: "expand_more" })
|
|
145
|
+
]
|
|
146
|
+
}
|
|
147
|
+
),
|
|
148
|
+
isOpen && /* @__PURE__ */ jsx(
|
|
149
|
+
"ul",
|
|
150
|
+
{
|
|
151
|
+
className: [`${baseClass}__menu`, isGrouped ? `${baseClass}__menu--grouped` : ""].filter(Boolean).join(" "),
|
|
152
|
+
role: "listbox",
|
|
153
|
+
id: `${inputId}-listbox`,
|
|
154
|
+
ref: listRef,
|
|
155
|
+
"aria-labelledby": label ? `${inputId}-label` : void 0,
|
|
156
|
+
children: isGrouped ? (() => {
|
|
157
|
+
let flatIndex = 0;
|
|
158
|
+
return groups.map((group, groupIdx) => /* @__PURE__ */ jsxs("li", { className: `${baseClass}__group`, role: "none", children: [
|
|
159
|
+
/* @__PURE__ */ jsx("span", { className: `${baseClass}__group-label`, role: "presentation", children: group.label }),
|
|
160
|
+
/* @__PURE__ */ jsx(
|
|
161
|
+
"ul",
|
|
162
|
+
{
|
|
163
|
+
className: `${baseClass}__group-list`,
|
|
164
|
+
role: "group",
|
|
165
|
+
"aria-label": group.label,
|
|
166
|
+
children: group.options.map((option) => {
|
|
167
|
+
const myIndex = flatIndex++;
|
|
168
|
+
return /* @__PURE__ */ jsxs(
|
|
169
|
+
"li",
|
|
170
|
+
{
|
|
171
|
+
className: [
|
|
172
|
+
`${baseClass}__option`,
|
|
173
|
+
option.value === value ? `${baseClass}__option--selected` : "",
|
|
174
|
+
option.disabled ? `${baseClass}__option--disabled` : "",
|
|
175
|
+
myIndex === focusedIndex ? `${baseClass}__option--focused` : ""
|
|
176
|
+
].filter(Boolean).join(" "),
|
|
177
|
+
role: "option",
|
|
178
|
+
"aria-selected": option.value === value,
|
|
179
|
+
"aria-disabled": option.disabled,
|
|
180
|
+
onClick: () => !option.disabled && handleSelect(option.value),
|
|
181
|
+
children: [
|
|
182
|
+
option.label,
|
|
183
|
+
option.value === value && /* @__PURE__ */ jsx(
|
|
184
|
+
"span",
|
|
185
|
+
{
|
|
186
|
+
className: `${baseClass}__check material-symbols-rounded`,
|
|
187
|
+
"aria-hidden": "true",
|
|
188
|
+
children: "check"
|
|
189
|
+
}
|
|
190
|
+
)
|
|
191
|
+
]
|
|
192
|
+
},
|
|
193
|
+
option.value
|
|
194
|
+
);
|
|
195
|
+
})
|
|
196
|
+
}
|
|
197
|
+
),
|
|
198
|
+
groupIdx < groups.length - 1 && /* @__PURE__ */ jsx("li", { className: `${baseClass}__separator`, role: "separator" })
|
|
199
|
+
] }, `group-${groupIdx}`));
|
|
200
|
+
})() : options.map((option, index) => /* @__PURE__ */ jsxs(
|
|
201
|
+
"li",
|
|
202
|
+
{
|
|
203
|
+
className: [
|
|
204
|
+
`${baseClass}__option`,
|
|
205
|
+
option.value === value ? `${baseClass}__option--selected` : "",
|
|
206
|
+
option.disabled ? `${baseClass}__option--disabled` : "",
|
|
207
|
+
index === focusedIndex ? `${baseClass}__option--focused` : ""
|
|
208
|
+
].filter(Boolean).join(" "),
|
|
209
|
+
role: "option",
|
|
210
|
+
"aria-selected": option.value === value,
|
|
211
|
+
"aria-disabled": option.disabled,
|
|
212
|
+
onClick: () => !option.disabled && handleSelect(option.value),
|
|
213
|
+
children: [
|
|
214
|
+
option.label,
|
|
215
|
+
option.value === value && /* @__PURE__ */ jsx(
|
|
216
|
+
"span",
|
|
217
|
+
{
|
|
218
|
+
className: `${baseClass}__check material-symbols-rounded`,
|
|
219
|
+
"aria-hidden": "true",
|
|
220
|
+
children: "check"
|
|
221
|
+
}
|
|
222
|
+
)
|
|
223
|
+
]
|
|
224
|
+
},
|
|
225
|
+
option.value
|
|
226
|
+
))
|
|
227
|
+
}
|
|
228
|
+
),
|
|
229
|
+
helperText && /* @__PURE__ */ jsx("p", { className: `${baseClass}__helper`, id: `${inputId}-helper`, children: helperText })
|
|
230
|
+
] });
|
|
231
|
+
}
|
|
232
|
+
);
|
|
233
|
+
Dropdown.displayName = "Dropdown";
|
|
194
234
|
export {
|
|
195
235
|
Dropdown
|
|
196
236
|
};
|
|
@@ -11,23 +11,16 @@ export interface FileInputFile {
|
|
|
11
11
|
/** Per-file error message — replaces the size line */
|
|
12
12
|
error?: string;
|
|
13
13
|
}
|
|
14
|
-
|
|
14
|
+
/** Props owned by FileInput itself — everything else falls through to the native <input type="file">. */
|
|
15
|
+
type FileInputOwnProps = {
|
|
15
16
|
/** Field label above the dropzone */
|
|
16
17
|
label?: string;
|
|
17
18
|
/** Instructional copy inside the dropzone */
|
|
18
19
|
placeholder?: string;
|
|
19
|
-
/** Comma-separated accept list, e.g. 'image/*,.pdf' */
|
|
20
|
-
accept?: string;
|
|
21
|
-
/** Allow selecting more than one file */
|
|
22
|
-
multiple?: boolean;
|
|
23
20
|
/** Files to list under the dropzone */
|
|
24
21
|
files?: FileInputFile[];
|
|
25
|
-
/** Component size */
|
|
22
|
+
/** Component size (not the native character-width `size` attribute) */
|
|
26
23
|
size?: 'default' | 'compact';
|
|
27
|
-
/** Whether the input is disabled */
|
|
28
|
-
disabled?: boolean;
|
|
29
|
-
/** Whether the input is required */
|
|
30
|
-
required?: boolean;
|
|
31
24
|
/** Error state — shows error styling and message */
|
|
32
25
|
error?: boolean;
|
|
33
26
|
/** Helper or error message displayed below the field */
|
|
@@ -36,19 +29,22 @@ export interface FileInputProps {
|
|
|
36
29
|
onFilesSelected?: (files: File[]) => void;
|
|
37
30
|
/** Called with the id of a file whose remove button was pressed */
|
|
38
31
|
onFileRemove?: (id: string) => void;
|
|
39
|
-
/** Additional CSS classes */
|
|
32
|
+
/** Additional CSS classes — applied to the wrapper, not the <input> */
|
|
40
33
|
className?: string;
|
|
41
|
-
/**
|
|
34
|
+
/** @deprecated Pass the native `aria-label` attribute instead. */
|
|
42
35
|
ariaLabel?: string;
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
/** HTML id attribute */
|
|
46
|
-
id?: string;
|
|
36
|
+
};
|
|
37
|
+
export interface FileInputProps extends FileInputOwnProps, Omit<React.ComponentPropsWithoutRef<'input'>, keyof FileInputOwnProps | 'type'> {
|
|
47
38
|
}
|
|
48
39
|
/**
|
|
49
40
|
* FileInput component — a click-or-drop zone paired with a list of the
|
|
50
41
|
* chosen files. The list is fully controlled: pass `files` and handle
|
|
51
42
|
* `onFilesSelected` / `onFileRemove` so upload progress and per-file
|
|
52
43
|
* errors stay owned by the host app.
|
|
44
|
+
*
|
|
45
|
+
* Forwards a ref to the underlying `<input type="file">` — useful for
|
|
46
|
+
* programmatically opening the picker or clearing the selection — and spreads
|
|
47
|
+
* unrecognised props onto it.
|
|
53
48
|
*/
|
|
54
|
-
export declare const FileInput:
|
|
49
|
+
export declare const FileInput: React.ForwardRefExoticComponent<FileInputProps & React.RefAttributes<HTMLInputElement>>;
|
|
50
|
+
export {};
|