@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,5 +1,5 @@
|
|
|
1
1
|
import { jsxs, jsx } from "react/jsx-runtime";
|
|
2
|
-
import "react";
|
|
2
|
+
import React from "react";
|
|
3
3
|
import "./Checkbox.css";
|
|
4
4
|
const CheckIcon = () => /* @__PURE__ */ jsx(
|
|
5
5
|
"svg",
|
|
@@ -31,94 +31,108 @@ const MinusIcon = () => /* @__PURE__ */ jsx(
|
|
|
31
31
|
viewBox: "0 0 14 14",
|
|
32
32
|
fill: "none",
|
|
33
33
|
"aria-hidden": "true",
|
|
34
|
-
children: /* @__PURE__ */ jsx(
|
|
35
|
-
|
|
34
|
+
children: /* @__PURE__ */ jsx("path", { d: "M2 7H12", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" })
|
|
35
|
+
}
|
|
36
|
+
);
|
|
37
|
+
const Checkbox = React.forwardRef(
|
|
38
|
+
({
|
|
39
|
+
label,
|
|
40
|
+
checked = false,
|
|
41
|
+
indeterminate = false,
|
|
42
|
+
disabled = false,
|
|
43
|
+
size = "default",
|
|
44
|
+
onCheckedChange,
|
|
45
|
+
onChange,
|
|
46
|
+
className = "",
|
|
47
|
+
ariaLabel,
|
|
48
|
+
name: _name,
|
|
49
|
+
onClick,
|
|
50
|
+
onKeyDown,
|
|
51
|
+
...rest
|
|
52
|
+
}, ref) => {
|
|
53
|
+
const baseClass = "ds-checkbox";
|
|
54
|
+
const classes = [
|
|
55
|
+
baseClass,
|
|
56
|
+
size === "compact" ? `${baseClass}--compact` : "",
|
|
57
|
+
checked ? `${baseClass}--checked` : "",
|
|
58
|
+
indeterminate && !checked ? `${baseClass}--indeterminate` : "",
|
|
59
|
+
disabled ? `${baseClass}--disabled` : "",
|
|
60
|
+
className
|
|
61
|
+
].filter(Boolean).join(" ");
|
|
62
|
+
const toggle = () => {
|
|
63
|
+
if (disabled) return;
|
|
64
|
+
onCheckedChange?.(!checked);
|
|
65
|
+
onChange?.(!checked);
|
|
66
|
+
};
|
|
67
|
+
const handleClick = (e) => {
|
|
68
|
+
onClick?.(e);
|
|
69
|
+
toggle();
|
|
70
|
+
};
|
|
71
|
+
const handleKeyDown = (e) => {
|
|
72
|
+
onKeyDown?.(e);
|
|
73
|
+
if (e.key === " " || e.key === "Enter") {
|
|
74
|
+
e.preventDefault();
|
|
75
|
+
toggle();
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
return /* @__PURE__ */ jsxs(
|
|
79
|
+
"div",
|
|
36
80
|
{
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
81
|
+
...rest,
|
|
82
|
+
ref,
|
|
83
|
+
className: classes,
|
|
84
|
+
onClick: handleClick,
|
|
85
|
+
onKeyDown: handleKeyDown,
|
|
86
|
+
role: "checkbox",
|
|
87
|
+
"aria-checked": indeterminate && !checked ? "mixed" : checked,
|
|
88
|
+
"aria-disabled": disabled,
|
|
89
|
+
"aria-label": ariaLabel || rest["aria-label"] || label,
|
|
90
|
+
tabIndex: disabled ? -1 : 0,
|
|
91
|
+
children: [
|
|
92
|
+
/* @__PURE__ */ jsx("div", { className: `${baseClass}__box`, children: indeterminate && !checked ? /* @__PURE__ */ jsx(MinusIcon, {}) : /* @__PURE__ */ jsx(CheckIcon, {}) }),
|
|
93
|
+
label && /* @__PURE__ */ jsx("span", { className: `${baseClass}__label`, children: label })
|
|
94
|
+
]
|
|
41
95
|
}
|
|
42
|
-
)
|
|
96
|
+
);
|
|
43
97
|
}
|
|
44
98
|
);
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
const
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
{
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
size = "default",
|
|
83
|
-
onChange,
|
|
84
|
-
className = "",
|
|
85
|
-
ariaLabel
|
|
86
|
-
}) => {
|
|
87
|
-
const baseClass = "ds-checkbox";
|
|
88
|
-
const checkedClass = checked ? `${baseClass}--checked` : "";
|
|
89
|
-
const indeterminateClass = indeterminate && !checked ? `${baseClass}--indeterminate` : "";
|
|
90
|
-
const disabledClass = disabled ? `${baseClass}--disabled` : "";
|
|
91
|
-
const sizeClass = size === "compact" ? `${baseClass}--compact` : "";
|
|
92
|
-
const classes = [baseClass, sizeClass, checkedClass, indeterminateClass, disabledClass, className].filter(Boolean).join(" ");
|
|
93
|
-
const handleClick = () => {
|
|
94
|
-
if (!disabled && onChange) {
|
|
95
|
-
onChange(!checked);
|
|
96
|
-
}
|
|
97
|
-
};
|
|
98
|
-
const handleKeyDown = (e) => {
|
|
99
|
-
if (e.key === " " || e.key === "Enter") {
|
|
100
|
-
e.preventDefault();
|
|
101
|
-
handleClick();
|
|
102
|
-
}
|
|
103
|
-
};
|
|
104
|
-
return /* @__PURE__ */ jsxs(
|
|
105
|
-
"div",
|
|
106
|
-
{
|
|
107
|
-
className: classes,
|
|
108
|
-
onClick: handleClick,
|
|
109
|
-
onKeyDown: handleKeyDown,
|
|
110
|
-
role: "checkbox",
|
|
111
|
-
"aria-checked": indeterminate && !checked ? "mixed" : checked,
|
|
112
|
-
"aria-disabled": disabled,
|
|
113
|
-
"aria-label": ariaLabel || label,
|
|
114
|
-
tabIndex: disabled ? -1 : 0,
|
|
115
|
-
children: [
|
|
116
|
-
/* @__PURE__ */ jsx("div", { className: `${baseClass}__box`, children: indeterminate && !checked ? /* @__PURE__ */ jsx(MinusIcon, {}) : /* @__PURE__ */ jsx(CheckIcon, {}) }),
|
|
117
|
-
label && /* @__PURE__ */ jsx("span", { className: `${baseClass}__label`, children: label })
|
|
118
|
-
]
|
|
119
|
-
}
|
|
120
|
-
);
|
|
121
|
-
};
|
|
99
|
+
Checkbox.displayName = "Checkbox";
|
|
100
|
+
const CheckboxGroup = React.forwardRef(
|
|
101
|
+
({
|
|
102
|
+
label,
|
|
103
|
+
items,
|
|
104
|
+
values = [],
|
|
105
|
+
direction = "vertical",
|
|
106
|
+
size = "default",
|
|
107
|
+
onValuesChange,
|
|
108
|
+
onChange,
|
|
109
|
+
className = "",
|
|
110
|
+
...rest
|
|
111
|
+
}, ref) => {
|
|
112
|
+
const baseClass = "ds-checkbox-group";
|
|
113
|
+
const classes = [baseClass, `${baseClass}--${direction}`, className].filter(Boolean).join(" ");
|
|
114
|
+
const handleToggle = (itemValue) => {
|
|
115
|
+
const next = values.includes(itemValue) ? values.filter((v) => v !== itemValue) : [...values, itemValue];
|
|
116
|
+
onValuesChange?.(next);
|
|
117
|
+
onChange?.(next);
|
|
118
|
+
};
|
|
119
|
+
return /* @__PURE__ */ jsxs("div", { ...rest, ref, className: classes, role: "group", "aria-label": label, children: [
|
|
120
|
+
label && /* @__PURE__ */ jsx("span", { className: `${baseClass}__label`, children: label }),
|
|
121
|
+
/* @__PURE__ */ jsx("div", { className: `${baseClass}__items`, children: items.map((item) => /* @__PURE__ */ jsx(
|
|
122
|
+
Checkbox,
|
|
123
|
+
{
|
|
124
|
+
label: item.label,
|
|
125
|
+
checked: values.includes(item.value),
|
|
126
|
+
disabled: item.disabled,
|
|
127
|
+
size,
|
|
128
|
+
onCheckedChange: () => handleToggle(item.value)
|
|
129
|
+
},
|
|
130
|
+
item.value
|
|
131
|
+
)) })
|
|
132
|
+
] });
|
|
133
|
+
}
|
|
134
|
+
);
|
|
135
|
+
CheckboxGroup.displayName = "CheckboxGroup";
|
|
122
136
|
export {
|
|
123
137
|
Checkbox,
|
|
124
138
|
CheckboxGroup
|
|
@@ -15,7 +15,8 @@ export interface ComboboxOptionGroup {
|
|
|
15
15
|
/** Options within the group */
|
|
16
16
|
options: ComboboxOption[];
|
|
17
17
|
}
|
|
18
|
-
|
|
18
|
+
/** Props owned by Combobox itself — everything else falls through to the wrapper. */
|
|
19
|
+
type ComboboxOwnProps = {
|
|
19
20
|
/** Combobox label text */
|
|
20
21
|
label?: string;
|
|
21
22
|
/** Placeholder shown in the text field when nothing is selected */
|
|
@@ -51,23 +52,34 @@ export interface ComboboxProps {
|
|
|
51
52
|
* Called with the new selection — a `string` in single mode,
|
|
52
53
|
* `string[]` when `multiple` is set.
|
|
53
54
|
*/
|
|
54
|
-
|
|
55
|
+
onValueChange?: (value: string | string[]) => void;
|
|
55
56
|
/** Called as the user types, for async/server-side filtering */
|
|
56
57
|
onSearchChange?: (query: string) => void;
|
|
57
58
|
/** Skip built-in filtering — use when options are filtered upstream */
|
|
58
59
|
manualFiltering?: boolean;
|
|
59
60
|
/** Additional CSS classes */
|
|
60
61
|
className?: string;
|
|
61
|
-
/**
|
|
62
|
+
/** @deprecated Use `onValueChange` instead. */
|
|
63
|
+
onChange?: (value: string | string[]) => void;
|
|
64
|
+
/** @deprecated Pass the native `aria-label` attribute instead. */
|
|
62
65
|
ariaLabel?: string;
|
|
63
|
-
/**
|
|
66
|
+
/**
|
|
67
|
+
* Used only as a fallback for deriving the element id (`id || name || generated`).
|
|
68
|
+
*
|
|
69
|
+
* Note: Combobox renders a `<div>` wrapper around a text input, not a native
|
|
70
|
+
* `<select>`, so `name` does **not** make the selection participate in native
|
|
71
|
+
* form submission.
|
|
72
|
+
*/
|
|
64
73
|
name?: string;
|
|
65
|
-
|
|
66
|
-
|
|
74
|
+
};
|
|
75
|
+
export interface ComboboxProps extends ComboboxOwnProps, Omit<React.ComponentPropsWithoutRef<'div'>, keyof ComboboxOwnProps> {
|
|
67
76
|
}
|
|
68
77
|
/**
|
|
69
78
|
* Combobox component — a text field combined with a filterable listbox.
|
|
70
79
|
* Unlike Dropdown (a static select), it narrows options as the user types
|
|
71
80
|
* and supports multi-select chips and async option loading.
|
|
81
|
+
*
|
|
82
|
+
* Forwards a ref to the wrapping element and spreads unrecognised props onto it.
|
|
72
83
|
*/
|
|
73
|
-
export declare const Combobox:
|
|
84
|
+
export declare const Combobox: React.ForwardRefExoticComponent<ComboboxProps & React.RefAttributes<HTMLDivElement>>;
|
|
85
|
+
export {};
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { jsxs, jsx } from "react/jsx-runtime";
|
|
2
|
-
import { useState, useRef, useId, useMemo, useCallback, useEffect } from "react";
|
|
2
|
+
import React, { useState, useRef, useId, useMemo, useCallback, useEffect } from "react";
|
|
3
3
|
import "./Combobox.css";
|
|
4
4
|
import "../../fonts/material-symbols.css";
|
|
5
|
-
const Combobox = ({
|
|
5
|
+
const Combobox = React.forwardRef(({
|
|
6
6
|
label,
|
|
7
7
|
placeholder = "Search…",
|
|
8
8
|
value,
|
|
@@ -17,14 +17,16 @@ const Combobox = ({
|
|
|
17
17
|
loading = false,
|
|
18
18
|
emptyMessage = "No results found",
|
|
19
19
|
clearable = false,
|
|
20
|
+
onValueChange,
|
|
20
21
|
onChange,
|
|
21
22
|
onSearchChange,
|
|
22
23
|
manualFiltering = false,
|
|
23
24
|
className = "",
|
|
24
25
|
ariaLabel,
|
|
25
26
|
name,
|
|
26
|
-
id
|
|
27
|
-
|
|
27
|
+
id,
|
|
28
|
+
...rest
|
|
29
|
+
}, ref) => {
|
|
28
30
|
const [isOpen, setIsOpen] = useState(false);
|
|
29
31
|
const [query, setQuery] = useState("");
|
|
30
32
|
const [focusedIndex, setFocusedIndex] = useState(-1);
|
|
@@ -32,6 +34,11 @@ const Combobox = ({
|
|
|
32
34
|
const inputRef = useRef(null);
|
|
33
35
|
const listRef = useRef(null);
|
|
34
36
|
const generatedId = useId();
|
|
37
|
+
const setRootRef = (node) => {
|
|
38
|
+
rootRef.current = node;
|
|
39
|
+
if (typeof ref === "function") ref(node);
|
|
40
|
+
else if (ref) ref.current = node;
|
|
41
|
+
};
|
|
35
42
|
const baseClass = "ds-combobox";
|
|
36
43
|
const isGrouped = Boolean(groups && groups.length > 0);
|
|
37
44
|
const inputId = id || name || generatedId;
|
|
@@ -75,8 +82,9 @@ const Combobox = ({
|
|
|
75
82
|
setQuery("");
|
|
76
83
|
};
|
|
77
84
|
const emitChange = (next) => {
|
|
78
|
-
|
|
79
|
-
|
|
85
|
+
const payload = multiple ? next : next[0] ?? "";
|
|
86
|
+
onValueChange?.(payload);
|
|
87
|
+
onChange?.(payload);
|
|
80
88
|
};
|
|
81
89
|
const handleSelect = (option) => {
|
|
82
90
|
if (option.disabled) return;
|
|
@@ -215,7 +223,7 @@ const Combobox = ({
|
|
|
215
223
|
);
|
|
216
224
|
};
|
|
217
225
|
const hasSelection = selectedValues.length > 0;
|
|
218
|
-
return /* @__PURE__ */ jsxs("div", { className: classes, ref:
|
|
226
|
+
return /* @__PURE__ */ jsxs("div", { ...rest, className: classes, ref: setRootRef, children: [
|
|
219
227
|
label && /* @__PURE__ */ jsxs("label", { className: `${baseClass}__label`, htmlFor: inputId, children: [
|
|
220
228
|
label,
|
|
221
229
|
required && /* @__PURE__ */ jsxs("span", { className: `${baseClass}__required`, "aria-hidden": "true", children: [
|
|
@@ -257,7 +265,7 @@ const Combobox = ({
|
|
|
257
265
|
"aria-controls": listboxId,
|
|
258
266
|
"aria-autocomplete": "list",
|
|
259
267
|
"aria-activedescendant": activeOptionId,
|
|
260
|
-
"aria-label": ariaLabel || (!label ? placeholder : void 0),
|
|
268
|
+
"aria-label": ariaLabel || rest["aria-label"] || (!label ? placeholder : void 0),
|
|
261
269
|
"aria-describedby": helperText ? `${inputId}-helper` : void 0,
|
|
262
270
|
"aria-invalid": error || void 0,
|
|
263
271
|
"aria-required": required || void 0,
|
|
@@ -306,7 +314,8 @@ const Combobox = ({
|
|
|
306
314
|
] }),
|
|
307
315
|
helperText && /* @__PURE__ */ jsx("p", { className: `${baseClass}__helper`, id: `${inputId}-helper`, children: helperText })
|
|
308
316
|
] });
|
|
309
|
-
};
|
|
317
|
+
});
|
|
318
|
+
Combobox.displayName = "Combobox";
|
|
310
319
|
export {
|
|
311
320
|
Combobox
|
|
312
321
|
};
|
|
@@ -1,17 +1,12 @@
|
|
|
1
1
|
import { default as React } from 'react';
|
|
2
|
-
|
|
2
|
+
/** Props owned by DateInput itself — everything else falls through to the <input>. */
|
|
3
|
+
type DateInputOwnProps = {
|
|
3
4
|
/** Input label text */
|
|
4
5
|
label?: string;
|
|
5
6
|
/** Current value (YYYY-MM-DD format) */
|
|
6
7
|
value?: string;
|
|
7
|
-
/**
|
|
8
|
-
placeholder?: string;
|
|
9
|
-
/** Component size */
|
|
8
|
+
/** Component size (not the native character-width `size` attribute) */
|
|
10
9
|
size?: 'default' | 'compact';
|
|
11
|
-
/** Whether the input is disabled */
|
|
12
|
-
disabled?: boolean;
|
|
13
|
-
/** Whether the input is required */
|
|
14
|
-
required?: boolean;
|
|
15
10
|
/** Error state */
|
|
16
11
|
error?: boolean;
|
|
17
12
|
/** Helper or error message */
|
|
@@ -20,24 +15,26 @@ export interface DateInputProps {
|
|
|
20
15
|
min?: string;
|
|
21
16
|
/** Maximum selectable date (YYYY-MM-DD) */
|
|
22
17
|
max?: string;
|
|
23
|
-
/**
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
/** Additional CSS classes */
|
|
18
|
+
/**
|
|
19
|
+
* Convenience callback receiving the value directly.
|
|
20
|
+
* Fires alongside `onChange`, which keeps the standard React event signature
|
|
21
|
+
* so form libraries work unmodified.
|
|
22
|
+
*/
|
|
23
|
+
onValueChange?: (value: string) => void;
|
|
24
|
+
/** Additional CSS classes — applied to the wrapper, not the <input> */
|
|
30
25
|
className?: string;
|
|
31
|
-
/**
|
|
26
|
+
/** @deprecated Pass the native `aria-label` attribute instead. */
|
|
32
27
|
ariaLabel?: string;
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
/** HTML id attribute */
|
|
36
|
-
id?: string;
|
|
28
|
+
};
|
|
29
|
+
export interface DateInputProps extends DateInputOwnProps, Omit<React.ComponentPropsWithoutRef<'input'>, keyof DateInputOwnProps | 'type'> {
|
|
37
30
|
}
|
|
38
31
|
/**
|
|
39
32
|
* Date input component with native date picker.
|
|
40
33
|
* Uses the browser's built-in date input with custom styling,
|
|
41
34
|
* calendar icon, label, and validation states.
|
|
35
|
+
*
|
|
36
|
+
* Forwards a ref to the underlying `<input type="date">` and spreads
|
|
37
|
+
* unrecognised props onto it.
|
|
42
38
|
*/
|
|
43
|
-
export declare const DateInput:
|
|
39
|
+
export declare const DateInput: React.ForwardRefExoticComponent<DateInputProps & React.RefAttributes<HTMLInputElement>>;
|
|
40
|
+
export {};
|
|
@@ -1,69 +1,77 @@
|
|
|
1
1
|
import { jsxs, jsx } from "react/jsx-runtime";
|
|
2
|
-
import "react";
|
|
2
|
+
import React from "react";
|
|
3
3
|
import "./DateInput.css";
|
|
4
4
|
import "../../fonts/material-symbols.css";
|
|
5
|
-
const DateInput = (
|
|
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
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
5
|
+
const DateInput = React.forwardRef(
|
|
6
|
+
({
|
|
7
|
+
label,
|
|
8
|
+
value,
|
|
9
|
+
placeholder,
|
|
10
|
+
size = "default",
|
|
11
|
+
disabled = false,
|
|
12
|
+
required = false,
|
|
13
|
+
error = false,
|
|
14
|
+
helperText,
|
|
15
|
+
min,
|
|
16
|
+
max,
|
|
17
|
+
onChange,
|
|
18
|
+
onValueChange,
|
|
19
|
+
className = "",
|
|
20
|
+
ariaLabel,
|
|
21
|
+
name,
|
|
22
|
+
id,
|
|
23
|
+
...rest
|
|
24
|
+
}, ref) => {
|
|
25
|
+
const baseClass = "ds-date-input";
|
|
26
|
+
const classes = [
|
|
27
|
+
baseClass,
|
|
28
|
+
`${baseClass}--${size}`,
|
|
29
|
+
error ? `${baseClass}--error` : "",
|
|
30
|
+
disabled ? `${baseClass}--disabled` : "",
|
|
31
|
+
className
|
|
32
|
+
].filter(Boolean).join(" ");
|
|
33
|
+
const handleChange = (e) => {
|
|
34
|
+
onChange?.(e);
|
|
35
|
+
onValueChange?.(e.target.value);
|
|
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__ */ jsxs("span", { className: `${baseClass}__required`, "aria-hidden": "true", children: [
|
|
42
|
+
" ",
|
|
43
|
+
"*"
|
|
44
|
+
] })
|
|
45
|
+
] }),
|
|
46
|
+
/* @__PURE__ */ jsxs("div", { className: `${baseClass}__field-wrapper`, children: [
|
|
47
|
+
/* @__PURE__ */ jsx("span", { className: `${baseClass}__icon material-symbols-rounded`, "aria-hidden": "true", children: "calendar_today" }),
|
|
48
|
+
/* @__PURE__ */ jsx(
|
|
49
|
+
"input",
|
|
50
|
+
{
|
|
51
|
+
...rest,
|
|
52
|
+
ref,
|
|
53
|
+
className: `${baseClass}__field`,
|
|
54
|
+
type: "date",
|
|
55
|
+
id: inputId,
|
|
56
|
+
name,
|
|
57
|
+
value,
|
|
58
|
+
placeholder,
|
|
59
|
+
disabled,
|
|
60
|
+
required,
|
|
61
|
+
min,
|
|
62
|
+
max,
|
|
63
|
+
"aria-label": ariaLabel || rest["aria-label"] || label,
|
|
64
|
+
"aria-invalid": error,
|
|
65
|
+
"aria-describedby": helperText ? `${inputId}-helper` : rest["aria-describedby"],
|
|
66
|
+
onChange: handleChange
|
|
67
|
+
}
|
|
68
|
+
)
|
|
69
|
+
] }),
|
|
70
|
+
helperText && /* @__PURE__ */ jsx("p", { className: `${baseClass}__helper`, id: `${inputId}-helper`, children: helperText })
|
|
71
|
+
] });
|
|
72
|
+
}
|
|
73
|
+
);
|
|
74
|
+
DateInput.displayName = "DateInput";
|
|
67
75
|
export {
|
|
68
76
|
DateInput
|
|
69
77
|
};
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
import { default as React } from 'react';
|
|
2
|
+
/** Props owned by DatePicker itself — everything else falls through to the wrapper. */
|
|
3
|
+
type DatePickerOwnProps = {
|
|
2
4
|
/** Currently selected date (YYYY-MM-DD) */
|
|
3
5
|
value?: string;
|
|
4
6
|
/** Component size */
|
|
@@ -13,10 +15,15 @@ export interface DatePickerProps {
|
|
|
13
15
|
onDateSelect?: (date: string) => void;
|
|
14
16
|
/** Additional CSS classes */
|
|
15
17
|
className?: string;
|
|
18
|
+
};
|
|
19
|
+
export interface DatePickerProps extends DatePickerOwnProps, Omit<React.ComponentPropsWithoutRef<'div'>, keyof DatePickerOwnProps> {
|
|
16
20
|
}
|
|
17
21
|
/**
|
|
18
22
|
* Inline date picker calendar component.
|
|
19
23
|
* Displays a full month grid with navigation,
|
|
20
24
|
* day headers, and selectable date cells.
|
|
25
|
+
*
|
|
26
|
+
* Forwards a ref to the wrapping element and spreads unrecognised props onto it.
|
|
21
27
|
*/
|
|
22
|
-
export declare const DatePicker:
|
|
28
|
+
export declare const DatePicker: React.ForwardRefExoticComponent<DatePickerProps & React.RefAttributes<HTMLDivElement>>;
|
|
29
|
+
export {};
|