@edux-design/forms 0.0.3 → 0.0.4
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/index.d.mts +187 -0
- package/dist/index.d.ts +187 -0
- package/dist/index.js +211 -68
- package/dist/index.mjs +208 -67
- package/package.json +7 -4
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
|
|
3
|
+
declare function Label({ children, hint, description, ...props }: {
|
|
4
|
+
children: React.ReactNode;
|
|
5
|
+
hint?: "required" | "optional" | undefined;
|
|
6
|
+
description?: string;
|
|
7
|
+
hidden?: boolean;
|
|
8
|
+
}): React.ReactElement;
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Props for the Input component.
|
|
12
|
+
*
|
|
13
|
+
* Extends all native HTML `<input>` attributes, while adding
|
|
14
|
+
* custom props for variants, icons, and clearable control.
|
|
15
|
+
*
|
|
16
|
+
* @typedef {React.InputHTMLAttributes<HTMLInputElement> & {
|
|
17
|
+
* children?: React.ReactNode,
|
|
18
|
+
* autocomplete?: string,
|
|
19
|
+
* variant?: "primary"|"error"|"corrective"|"success"|"inactive",
|
|
20
|
+
* clearable?: boolean,
|
|
21
|
+
* startIcon?: React.ReactNode,
|
|
22
|
+
* endIcon?: React.ReactNode|string,
|
|
23
|
+
* value?: any,
|
|
24
|
+
* onChange?: (e: React.ChangeEvent<HTMLInputElement> | { target: { value: string } }) => void,
|
|
25
|
+
* }} InputProps
|
|
26
|
+
*/
|
|
27
|
+
/**
|
|
28
|
+
* Input component for form fields.
|
|
29
|
+
*
|
|
30
|
+
* Provides a styled text input that integrates with `useFieldContext` for
|
|
31
|
+
* accessible label association. Supports variants, start/end icons, and
|
|
32
|
+
* an optional clearable control.
|
|
33
|
+
*
|
|
34
|
+
* @component
|
|
35
|
+
* @type {React.ForwardRefExoticComponent<InputProps & React.RefAttributes<HTMLInputElement>>}
|
|
36
|
+
*/
|
|
37
|
+
declare const Input: React.ForwardRefExoticComponent<InputProps & React.RefAttributes<HTMLInputElement>>;
|
|
38
|
+
/**
|
|
39
|
+
* Props for the Input component.
|
|
40
|
+
*
|
|
41
|
+
* Extends all native HTML `<input>` attributes, while adding
|
|
42
|
+
* custom props for variants, icons, and clearable control.
|
|
43
|
+
*/
|
|
44
|
+
type InputProps = React.InputHTMLAttributes<HTMLInputElement> & {
|
|
45
|
+
children?: React.ReactNode;
|
|
46
|
+
autocomplete?: string;
|
|
47
|
+
variant?: "primary" | "error" | "corrective" | "success" | "inactive";
|
|
48
|
+
clearable?: boolean;
|
|
49
|
+
startIcon?: React.ReactNode;
|
|
50
|
+
endIcon?: React.ReactNode | string;
|
|
51
|
+
value?: any;
|
|
52
|
+
onChange?: (e: React.ChangeEvent<HTMLInputElement> | {
|
|
53
|
+
target: {
|
|
54
|
+
value: string;
|
|
55
|
+
};
|
|
56
|
+
}) => void;
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
declare function Radio(): react_jsx_runtime.JSX.Element;
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Props for the Textarea component.
|
|
63
|
+
*
|
|
64
|
+
* Extends all native HTML `<textarea>` attributes, while adding
|
|
65
|
+
* custom props for variants, icons, and clearable control.
|
|
66
|
+
*
|
|
67
|
+
* @typedef {React.TextareaHTMLAttributes<HTMLTextAreaElement> & {
|
|
68
|
+
* children?: React.ReactNode,
|
|
69
|
+
* variant?: "primary"|"error"|"corrective"|"success"|"inactive",
|
|
70
|
+
* clearable?: boolean,
|
|
71
|
+
* startIcon?: React.ReactNode,
|
|
72
|
+
* endIcon?: React.ReactNode|string,
|
|
73
|
+
* value?: any,
|
|
74
|
+
* onChange?: (e: React.ChangeEvent<HTMLTextAreaElement> | { target: { value: string } }) => void,
|
|
75
|
+
* }} TextareaProps
|
|
76
|
+
*/
|
|
77
|
+
/**
|
|
78
|
+
* Textarea component for form fields.
|
|
79
|
+
*
|
|
80
|
+
* Provides a styled multi-line text area that integrates with `useFieldContext`
|
|
81
|
+
* for accessible label association. Supports variants, start/end icons, and
|
|
82
|
+
* an optional clearable control.
|
|
83
|
+
*
|
|
84
|
+
* @component
|
|
85
|
+
* @type {React.ForwardRefExoticComponent<TextareaProps & React.RefAttributes<HTMLTextAreaElement>>}
|
|
86
|
+
*/
|
|
87
|
+
declare const Textarea: React.ForwardRefExoticComponent<TextareaProps & React.RefAttributes<HTMLTextAreaElement>>;
|
|
88
|
+
/**
|
|
89
|
+
* Props for the Textarea component.
|
|
90
|
+
*
|
|
91
|
+
* Extends all native HTML `<textarea>` attributes, while adding
|
|
92
|
+
* custom props for variants, icons, and clearable control.
|
|
93
|
+
*/
|
|
94
|
+
type TextareaProps = React.TextareaHTMLAttributes<HTMLTextAreaElement> & {
|
|
95
|
+
children?: React.ReactNode;
|
|
96
|
+
variant?: "primary" | "error" | "corrective" | "success" | "inactive";
|
|
97
|
+
clearable?: boolean;
|
|
98
|
+
startIcon?: React.ReactNode;
|
|
99
|
+
endIcon?: React.ReactNode | string;
|
|
100
|
+
value?: any;
|
|
101
|
+
onChange?: (e: React.ChangeEvent<HTMLTextAreaElement> | {
|
|
102
|
+
target: {
|
|
103
|
+
value: string;
|
|
104
|
+
};
|
|
105
|
+
}) => void;
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Feedback tone values.
|
|
110
|
+
* @typedef {"info"|"success"|"warning"|"error" | "corrective" | undefined} FeedbackTone
|
|
111
|
+
*/
|
|
112
|
+
/**
|
|
113
|
+
* Props for the Feedback component.
|
|
114
|
+
*
|
|
115
|
+
* @typedef {Object} FeedbackProps
|
|
116
|
+
* @property {string} [id] - Optional ID; falls back to auto-generated based on parent Field.
|
|
117
|
+
* @property {FeedbackTone} [tone] - Visual + semantic feedback tone.
|
|
118
|
+
* @property {React.ReactNode} [children] - Content of the feedback message.
|
|
119
|
+
* @property {string} [className] - Additional CSS classes.
|
|
120
|
+
* @property {any} [rest] - Extra props passed to the container `<div>`.
|
|
121
|
+
*/
|
|
122
|
+
/**
|
|
123
|
+
* Context-aware field feedback (help, error, success, etc.)
|
|
124
|
+
* Registers its id with the parent Field so Input can set `aria-describedby`.
|
|
125
|
+
*
|
|
126
|
+
* Can be used as:
|
|
127
|
+
* ```jsx
|
|
128
|
+
* <Field.Feedback tone="help">Helpful hint</Field.Feedback>
|
|
129
|
+
* ```
|
|
130
|
+
* or imported directly:
|
|
131
|
+
* ```jsx
|
|
132
|
+
* import { Feedback } from "./Field";
|
|
133
|
+
* ```
|
|
134
|
+
*
|
|
135
|
+
* Accessibility:
|
|
136
|
+
* - `"error"` tone sets `role="alert"` and `aria-live="assertive"`.
|
|
137
|
+
* - All other tones use `aria-live="polite"`.
|
|
138
|
+
*
|
|
139
|
+
* @component
|
|
140
|
+
* @param {FeedbackProps} props
|
|
141
|
+
* @returns {React.ReactElement}
|
|
142
|
+
*/
|
|
143
|
+
declare function Feedback({ id, tone, children, className, ...rest }: FeedbackProps): React.ReactElement;
|
|
144
|
+
declare function Field({ children }: FieldProps): React.ReactElement;
|
|
145
|
+
declare namespace Field {
|
|
146
|
+
export { Feedback };
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Feedback tone values.
|
|
150
|
+
*/
|
|
151
|
+
type FeedbackTone = "info" | "success" | "warning" | "error" | "corrective" | undefined;
|
|
152
|
+
/**
|
|
153
|
+
* Props for the Feedback component.
|
|
154
|
+
*/
|
|
155
|
+
type FeedbackProps = {
|
|
156
|
+
/**
|
|
157
|
+
* - Optional ID; falls back to auto-generated based on parent Field.
|
|
158
|
+
*/
|
|
159
|
+
id?: string;
|
|
160
|
+
/**
|
|
161
|
+
* - Visual + semantic feedback tone.
|
|
162
|
+
*/
|
|
163
|
+
tone?: FeedbackTone;
|
|
164
|
+
/**
|
|
165
|
+
* - Content of the feedback message.
|
|
166
|
+
*/
|
|
167
|
+
children?: React.ReactNode;
|
|
168
|
+
/**
|
|
169
|
+
* - Additional CSS classes.
|
|
170
|
+
*/
|
|
171
|
+
className?: string;
|
|
172
|
+
/**
|
|
173
|
+
* - Extra props passed to the container `<div>`.
|
|
174
|
+
*/
|
|
175
|
+
rest?: any;
|
|
176
|
+
};
|
|
177
|
+
/**
|
|
178
|
+
* Props for the Field component.
|
|
179
|
+
*/
|
|
180
|
+
type FieldProps = {
|
|
181
|
+
/**
|
|
182
|
+
* - Elements to render inside the field wrapper.
|
|
183
|
+
*/
|
|
184
|
+
children: React.ReactNode;
|
|
185
|
+
};
|
|
186
|
+
|
|
187
|
+
export { Feedback, Field, Input, Label, Radio, Textarea };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
|
|
3
|
+
declare function Label({ children, hint, description, ...props }: {
|
|
4
|
+
children: React.ReactNode;
|
|
5
|
+
hint?: "required" | "optional" | undefined;
|
|
6
|
+
description?: string;
|
|
7
|
+
hidden?: boolean;
|
|
8
|
+
}): React.ReactElement;
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Props for the Input component.
|
|
12
|
+
*
|
|
13
|
+
* Extends all native HTML `<input>` attributes, while adding
|
|
14
|
+
* custom props for variants, icons, and clearable control.
|
|
15
|
+
*
|
|
16
|
+
* @typedef {React.InputHTMLAttributes<HTMLInputElement> & {
|
|
17
|
+
* children?: React.ReactNode,
|
|
18
|
+
* autocomplete?: string,
|
|
19
|
+
* variant?: "primary"|"error"|"corrective"|"success"|"inactive",
|
|
20
|
+
* clearable?: boolean,
|
|
21
|
+
* startIcon?: React.ReactNode,
|
|
22
|
+
* endIcon?: React.ReactNode|string,
|
|
23
|
+
* value?: any,
|
|
24
|
+
* onChange?: (e: React.ChangeEvent<HTMLInputElement> | { target: { value: string } }) => void,
|
|
25
|
+
* }} InputProps
|
|
26
|
+
*/
|
|
27
|
+
/**
|
|
28
|
+
* Input component for form fields.
|
|
29
|
+
*
|
|
30
|
+
* Provides a styled text input that integrates with `useFieldContext` for
|
|
31
|
+
* accessible label association. Supports variants, start/end icons, and
|
|
32
|
+
* an optional clearable control.
|
|
33
|
+
*
|
|
34
|
+
* @component
|
|
35
|
+
* @type {React.ForwardRefExoticComponent<InputProps & React.RefAttributes<HTMLInputElement>>}
|
|
36
|
+
*/
|
|
37
|
+
declare const Input: React.ForwardRefExoticComponent<InputProps & React.RefAttributes<HTMLInputElement>>;
|
|
38
|
+
/**
|
|
39
|
+
* Props for the Input component.
|
|
40
|
+
*
|
|
41
|
+
* Extends all native HTML `<input>` attributes, while adding
|
|
42
|
+
* custom props for variants, icons, and clearable control.
|
|
43
|
+
*/
|
|
44
|
+
type InputProps = React.InputHTMLAttributes<HTMLInputElement> & {
|
|
45
|
+
children?: React.ReactNode;
|
|
46
|
+
autocomplete?: string;
|
|
47
|
+
variant?: "primary" | "error" | "corrective" | "success" | "inactive";
|
|
48
|
+
clearable?: boolean;
|
|
49
|
+
startIcon?: React.ReactNode;
|
|
50
|
+
endIcon?: React.ReactNode | string;
|
|
51
|
+
value?: any;
|
|
52
|
+
onChange?: (e: React.ChangeEvent<HTMLInputElement> | {
|
|
53
|
+
target: {
|
|
54
|
+
value: string;
|
|
55
|
+
};
|
|
56
|
+
}) => void;
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
declare function Radio(): react_jsx_runtime.JSX.Element;
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Props for the Textarea component.
|
|
63
|
+
*
|
|
64
|
+
* Extends all native HTML `<textarea>` attributes, while adding
|
|
65
|
+
* custom props for variants, icons, and clearable control.
|
|
66
|
+
*
|
|
67
|
+
* @typedef {React.TextareaHTMLAttributes<HTMLTextAreaElement> & {
|
|
68
|
+
* children?: React.ReactNode,
|
|
69
|
+
* variant?: "primary"|"error"|"corrective"|"success"|"inactive",
|
|
70
|
+
* clearable?: boolean,
|
|
71
|
+
* startIcon?: React.ReactNode,
|
|
72
|
+
* endIcon?: React.ReactNode|string,
|
|
73
|
+
* value?: any,
|
|
74
|
+
* onChange?: (e: React.ChangeEvent<HTMLTextAreaElement> | { target: { value: string } }) => void,
|
|
75
|
+
* }} TextareaProps
|
|
76
|
+
*/
|
|
77
|
+
/**
|
|
78
|
+
* Textarea component for form fields.
|
|
79
|
+
*
|
|
80
|
+
* Provides a styled multi-line text area that integrates with `useFieldContext`
|
|
81
|
+
* for accessible label association. Supports variants, start/end icons, and
|
|
82
|
+
* an optional clearable control.
|
|
83
|
+
*
|
|
84
|
+
* @component
|
|
85
|
+
* @type {React.ForwardRefExoticComponent<TextareaProps & React.RefAttributes<HTMLTextAreaElement>>}
|
|
86
|
+
*/
|
|
87
|
+
declare const Textarea: React.ForwardRefExoticComponent<TextareaProps & React.RefAttributes<HTMLTextAreaElement>>;
|
|
88
|
+
/**
|
|
89
|
+
* Props for the Textarea component.
|
|
90
|
+
*
|
|
91
|
+
* Extends all native HTML `<textarea>` attributes, while adding
|
|
92
|
+
* custom props for variants, icons, and clearable control.
|
|
93
|
+
*/
|
|
94
|
+
type TextareaProps = React.TextareaHTMLAttributes<HTMLTextAreaElement> & {
|
|
95
|
+
children?: React.ReactNode;
|
|
96
|
+
variant?: "primary" | "error" | "corrective" | "success" | "inactive";
|
|
97
|
+
clearable?: boolean;
|
|
98
|
+
startIcon?: React.ReactNode;
|
|
99
|
+
endIcon?: React.ReactNode | string;
|
|
100
|
+
value?: any;
|
|
101
|
+
onChange?: (e: React.ChangeEvent<HTMLTextAreaElement> | {
|
|
102
|
+
target: {
|
|
103
|
+
value: string;
|
|
104
|
+
};
|
|
105
|
+
}) => void;
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Feedback tone values.
|
|
110
|
+
* @typedef {"info"|"success"|"warning"|"error" | "corrective" | undefined} FeedbackTone
|
|
111
|
+
*/
|
|
112
|
+
/**
|
|
113
|
+
* Props for the Feedback component.
|
|
114
|
+
*
|
|
115
|
+
* @typedef {Object} FeedbackProps
|
|
116
|
+
* @property {string} [id] - Optional ID; falls back to auto-generated based on parent Field.
|
|
117
|
+
* @property {FeedbackTone} [tone] - Visual + semantic feedback tone.
|
|
118
|
+
* @property {React.ReactNode} [children] - Content of the feedback message.
|
|
119
|
+
* @property {string} [className] - Additional CSS classes.
|
|
120
|
+
* @property {any} [rest] - Extra props passed to the container `<div>`.
|
|
121
|
+
*/
|
|
122
|
+
/**
|
|
123
|
+
* Context-aware field feedback (help, error, success, etc.)
|
|
124
|
+
* Registers its id with the parent Field so Input can set `aria-describedby`.
|
|
125
|
+
*
|
|
126
|
+
* Can be used as:
|
|
127
|
+
* ```jsx
|
|
128
|
+
* <Field.Feedback tone="help">Helpful hint</Field.Feedback>
|
|
129
|
+
* ```
|
|
130
|
+
* or imported directly:
|
|
131
|
+
* ```jsx
|
|
132
|
+
* import { Feedback } from "./Field";
|
|
133
|
+
* ```
|
|
134
|
+
*
|
|
135
|
+
* Accessibility:
|
|
136
|
+
* - `"error"` tone sets `role="alert"` and `aria-live="assertive"`.
|
|
137
|
+
* - All other tones use `aria-live="polite"`.
|
|
138
|
+
*
|
|
139
|
+
* @component
|
|
140
|
+
* @param {FeedbackProps} props
|
|
141
|
+
* @returns {React.ReactElement}
|
|
142
|
+
*/
|
|
143
|
+
declare function Feedback({ id, tone, children, className, ...rest }: FeedbackProps): React.ReactElement;
|
|
144
|
+
declare function Field({ children }: FieldProps): React.ReactElement;
|
|
145
|
+
declare namespace Field {
|
|
146
|
+
export { Feedback };
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Feedback tone values.
|
|
150
|
+
*/
|
|
151
|
+
type FeedbackTone = "info" | "success" | "warning" | "error" | "corrective" | undefined;
|
|
152
|
+
/**
|
|
153
|
+
* Props for the Feedback component.
|
|
154
|
+
*/
|
|
155
|
+
type FeedbackProps = {
|
|
156
|
+
/**
|
|
157
|
+
* - Optional ID; falls back to auto-generated based on parent Field.
|
|
158
|
+
*/
|
|
159
|
+
id?: string;
|
|
160
|
+
/**
|
|
161
|
+
* - Visual + semantic feedback tone.
|
|
162
|
+
*/
|
|
163
|
+
tone?: FeedbackTone;
|
|
164
|
+
/**
|
|
165
|
+
* - Content of the feedback message.
|
|
166
|
+
*/
|
|
167
|
+
children?: React.ReactNode;
|
|
168
|
+
/**
|
|
169
|
+
* - Additional CSS classes.
|
|
170
|
+
*/
|
|
171
|
+
className?: string;
|
|
172
|
+
/**
|
|
173
|
+
* - Extra props passed to the container `<div>`.
|
|
174
|
+
*/
|
|
175
|
+
rest?: any;
|
|
176
|
+
};
|
|
177
|
+
/**
|
|
178
|
+
* Props for the Field component.
|
|
179
|
+
*/
|
|
180
|
+
type FieldProps = {
|
|
181
|
+
/**
|
|
182
|
+
* - Elements to render inside the field wrapper.
|
|
183
|
+
*/
|
|
184
|
+
children: React.ReactNode;
|
|
185
|
+
};
|
|
186
|
+
|
|
187
|
+
export { Feedback, Field, Input, Label, Radio, Textarea };
|
package/dist/index.js
CHANGED
|
@@ -32,7 +32,9 @@ __export(index_exports, {
|
|
|
32
32
|
Feedback: () => Feedback,
|
|
33
33
|
Field: () => Field,
|
|
34
34
|
Input: () => Input,
|
|
35
|
-
Label: () => Label
|
|
35
|
+
Label: () => Label,
|
|
36
|
+
Radio: () => Radio,
|
|
37
|
+
Textarea: () => Textarea
|
|
36
38
|
});
|
|
37
39
|
module.exports = __toCommonJS(index_exports);
|
|
38
40
|
|
|
@@ -42,6 +44,7 @@ var import_react3 = require("react");
|
|
|
42
44
|
|
|
43
45
|
// src/utils/useFieldContext.jsx
|
|
44
46
|
var import_react = __toESM(require("react"));
|
|
47
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
45
48
|
var FieldContext = (0, import_react.createContext)(null);
|
|
46
49
|
var FieldProvider = ({ children }) => {
|
|
47
50
|
const baseId = (0, import_react.useId)();
|
|
@@ -66,7 +69,7 @@ var FieldProvider = ({ children }) => {
|
|
|
66
69
|
}),
|
|
67
70
|
[baseId, type, describedByIds, registerDescription, unregisterDescription]
|
|
68
71
|
);
|
|
69
|
-
return /* @__PURE__ */
|
|
72
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(FieldContext.Provider, { value, children });
|
|
70
73
|
};
|
|
71
74
|
var useFieldContext = () => {
|
|
72
75
|
const context = (0, import_react.useContext)(FieldContext);
|
|
@@ -77,6 +80,7 @@ var useFieldContext = () => {
|
|
|
77
80
|
};
|
|
78
81
|
|
|
79
82
|
// src/elements/Label.jsx
|
|
83
|
+
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
80
84
|
var Label = ({ children, hint, description, ...props }) => {
|
|
81
85
|
const { labelHTMLForId } = useFieldContext();
|
|
82
86
|
const returnHintType = (0, import_react3.useCallback)((hint2) => {
|
|
@@ -84,9 +88,9 @@ var Label = ({ children, hint, description, ...props }) => {
|
|
|
84
88
|
case void 0:
|
|
85
89
|
return;
|
|
86
90
|
case "required":
|
|
87
|
-
return /* @__PURE__ */
|
|
91
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "ml-2 text-fg-danger-base", children: "[required]" });
|
|
88
92
|
case "optional":
|
|
89
|
-
return /* @__PURE__ */
|
|
93
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "ml-2", children: "[optional]" });
|
|
90
94
|
default:
|
|
91
95
|
console.warn(
|
|
92
96
|
"[Invalid prop arg] - The <Label> component only accepts 'Required' || 'Optional'. Nothing has been returned."
|
|
@@ -94,15 +98,20 @@ var Label = ({ children, hint, description, ...props }) => {
|
|
|
94
98
|
}
|
|
95
99
|
}, []);
|
|
96
100
|
const hintEl = returnHintType(hint);
|
|
97
|
-
return /* @__PURE__ */
|
|
101
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
98
102
|
"label",
|
|
99
103
|
{
|
|
100
104
|
hidden: props.hidden,
|
|
101
105
|
className: "tracking-normal leading-none flex flex-col gap-4",
|
|
102
|
-
htmlFor: labelHTMLForId
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
+
htmlFor: labelHTMLForId,
|
|
107
|
+
children: [
|
|
108
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "h-[21px]", children: [
|
|
109
|
+
children,
|
|
110
|
+
hintEl
|
|
111
|
+
] }),
|
|
112
|
+
description && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "h-[21px] text-sm font-light text-fg-base", children: description })
|
|
113
|
+
]
|
|
114
|
+
}
|
|
106
115
|
);
|
|
107
116
|
};
|
|
108
117
|
|
|
@@ -110,6 +119,7 @@ var Label = ({ children, hint, description, ...props }) => {
|
|
|
110
119
|
var import_react4 = __toESM(require("react"));
|
|
111
120
|
var import_utils = require("@edux-design/utils");
|
|
112
121
|
var import_icons = require("@edux-design/icons");
|
|
122
|
+
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
113
123
|
var Input = (0, import_react4.forwardRef)(
|
|
114
124
|
({
|
|
115
125
|
children,
|
|
@@ -140,51 +150,56 @@ var Input = (0, import_react4.forwardRef)(
|
|
|
140
150
|
clearable && endIcon && "pr-10",
|
|
141
151
|
clearable && !endIcon && "pr-5"
|
|
142
152
|
);
|
|
143
|
-
return /* @__PURE__ */
|
|
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
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
153
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "w-full relative flex items-center", children: [
|
|
154
|
+
startIcon && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
155
|
+
"span",
|
|
156
|
+
{
|
|
157
|
+
className: "absolute left-3 flex items-center pointer-events-none text-fg-subtle",
|
|
158
|
+
"aria-hidden": "true",
|
|
159
|
+
children: startIcon
|
|
160
|
+
}
|
|
161
|
+
),
|
|
162
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
163
|
+
"input",
|
|
164
|
+
{
|
|
165
|
+
id: labelHTMLForId,
|
|
166
|
+
ref,
|
|
167
|
+
className: INPUT_STYLES,
|
|
168
|
+
autoComplete: autocomplete || "",
|
|
169
|
+
"aria-disabled": props.disabled || variant === "inactive",
|
|
170
|
+
"aria-invalid": variant === "error" ? "true" : void 0,
|
|
171
|
+
disabled: props.disabled || variant === "inactive",
|
|
172
|
+
...props
|
|
173
|
+
}
|
|
174
|
+
),
|
|
175
|
+
clearable && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
176
|
+
"button",
|
|
177
|
+
{
|
|
178
|
+
type: "button",
|
|
179
|
+
"aria-label": "Clear input",
|
|
180
|
+
onClick: () => {
|
|
181
|
+
var _a;
|
|
182
|
+
return (_a = props.onChange) == null ? void 0 : _a.call(props, { target: { value: "" } });
|
|
183
|
+
},
|
|
184
|
+
className: (0, import_utils.cx)(
|
|
185
|
+
clearable && hasValue && endIcon ? "right-9" : "right-3",
|
|
186
|
+
"absolute flex items-center p-1 rounded-full outline-none",
|
|
187
|
+
"transition-all duration-300 ease-in-out",
|
|
188
|
+
hasValue ? "opacity-100 scale-100" : "opacity-0 scale-90 pointer-events-none",
|
|
189
|
+
"focus:shadow-focus"
|
|
190
|
+
),
|
|
191
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_icons.Close, { "aria-hidden": "true", className: "text-fg-subtle" })
|
|
192
|
+
}
|
|
193
|
+
),
|
|
194
|
+
endIcon && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
195
|
+
"span",
|
|
196
|
+
{
|
|
197
|
+
className: (0, import_utils.cx)("absolute flex items-center right-3 text-fg-subtle"),
|
|
198
|
+
"aria-hidden": typeof endIcon === "string" ? void 0 : "true",
|
|
199
|
+
children: endIcon
|
|
200
|
+
}
|
|
201
|
+
)
|
|
202
|
+
] });
|
|
188
203
|
}
|
|
189
204
|
);
|
|
190
205
|
|
|
@@ -192,13 +207,14 @@ var Input = (0, import_react4.forwardRef)(
|
|
|
192
207
|
var import_react5 = __toESM(require("react"));
|
|
193
208
|
var import_utils2 = require("@edux-design/utils");
|
|
194
209
|
var import_icons2 = require("@edux-design/icons");
|
|
210
|
+
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
195
211
|
var Field = ({ children }) => {
|
|
196
212
|
const FIELD_GROUP_WRAPPER_STYLES = (0, import_utils2.cx)(
|
|
197
213
|
"flex flex-col items-start relative gap-8"
|
|
198
214
|
);
|
|
199
|
-
return /* @__PURE__ */
|
|
215
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(FieldProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: FIELD_GROUP_WRAPPER_STYLES, children }) });
|
|
200
216
|
};
|
|
201
|
-
function Feedback({ id, tone
|
|
217
|
+
function Feedback({ id, tone, children, className, ...rest }) {
|
|
202
218
|
const { labelHTMLForId, registerDescription, unregisterDescription } = useFieldContext();
|
|
203
219
|
const autoId = (0, import_react5.useId)();
|
|
204
220
|
const feedbackId = id ?? `${labelHTMLForId}-fb-${autoId}`;
|
|
@@ -214,29 +230,156 @@ function Feedback({ id, tone = "help", children, className, ...rest }) {
|
|
|
214
230
|
error: "bg-fg-danger-base"
|
|
215
231
|
}[tone];
|
|
216
232
|
const liveProps = tone === "error" ? { role: "alert", "aria-live": "assertive" } : { "aria-live": "polite" };
|
|
217
|
-
return /* @__PURE__ */
|
|
233
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
218
234
|
"div",
|
|
219
235
|
{
|
|
220
236
|
id: feedbackId,
|
|
221
237
|
className: (0, import_utils2.cx)("text-sm mt-1 flex gap-6", className),
|
|
222
238
|
...liveProps,
|
|
223
|
-
...rest
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
239
|
+
...rest,
|
|
240
|
+
children: [
|
|
241
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
242
|
+
"div",
|
|
243
|
+
{
|
|
244
|
+
className: `h-[20px] w-[20px] ${colorByTone} rounded-full flex flex-col justify-center items-center`,
|
|
245
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_icons2.Close, { className: "text-white" })
|
|
246
|
+
}
|
|
247
|
+
),
|
|
248
|
+
children
|
|
249
|
+
]
|
|
250
|
+
}
|
|
233
251
|
);
|
|
234
252
|
}
|
|
235
253
|
Field.Feedback = Feedback;
|
|
254
|
+
|
|
255
|
+
// src/elements/Radio.jsx
|
|
256
|
+
var import_react6 = __toESM(require("react"));
|
|
257
|
+
var import_utils3 = require("@edux-design/utils");
|
|
258
|
+
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
259
|
+
function Radio() {
|
|
260
|
+
const { labelHTMLForId } = useFieldContext();
|
|
261
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "relative inline-flex items-center justify-center", children: [
|
|
262
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
263
|
+
"input",
|
|
264
|
+
{
|
|
265
|
+
id: labelHTMLForId,
|
|
266
|
+
type: "radio",
|
|
267
|
+
className: (0, import_utils3.cx)(
|
|
268
|
+
"peer absolute inset-0 z-10 cursor-pointer appearance-none rounded-full",
|
|
269
|
+
"focus:shadow-focus focus-visible:shadow-focus focus:outline-none focus-visible:outline-none"
|
|
270
|
+
)
|
|
271
|
+
}
|
|
272
|
+
),
|
|
273
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
274
|
+
"span",
|
|
275
|
+
{
|
|
276
|
+
className: (0, import_utils3.cx)(
|
|
277
|
+
"block rounded-full border-1 border-border-base",
|
|
278
|
+
"h-[28px] w-[28px]",
|
|
279
|
+
"peer-checked:border-border-primary-base peer-checked:border-8",
|
|
280
|
+
"transition-colors",
|
|
281
|
+
"peer-hover:border-2 peer-hover:border-border-primary-base peer-checked:peer-hover:border-8 peer-checked:peer-hover:border-border-primary-base"
|
|
282
|
+
)
|
|
283
|
+
}
|
|
284
|
+
)
|
|
285
|
+
] });
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
// src/elements/Textarea.jsx
|
|
289
|
+
var import_react7 = __toESM(require("react"));
|
|
290
|
+
var import_utils4 = require("@edux-design/utils");
|
|
291
|
+
var import_icons3 = require("@edux-design/icons");
|
|
292
|
+
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
293
|
+
var Textarea = (0, import_react7.forwardRef)(
|
|
294
|
+
({
|
|
295
|
+
children,
|
|
296
|
+
validation,
|
|
297
|
+
variant = "primary",
|
|
298
|
+
clearable = false,
|
|
299
|
+
startIcon,
|
|
300
|
+
endIcon,
|
|
301
|
+
rows = 4,
|
|
302
|
+
...props
|
|
303
|
+
}, ref) => {
|
|
304
|
+
const { labelHTMLForId } = useFieldContext();
|
|
305
|
+
const hasValue = Boolean(props.value);
|
|
306
|
+
const defaults = "w-full border-2 rounded-md border-border-base focus:shadow-focus focus-visible:shadow-focus outline-none transition-all duration-300 ease-in-out pl-5 py-3 resize-y";
|
|
307
|
+
const fonts = "font-normal text-base leading-relaxed";
|
|
308
|
+
const variants = {
|
|
309
|
+
primary: "hover:border-2 hover:border-border-primary-base focus:border-2 focus:border-border-primary-base focus-within:border-2 focus-within:border-border-primary-base",
|
|
310
|
+
error: "border-border-danger-base bg-bg-danger-subtle",
|
|
311
|
+
corrective: "border-border-corrective-base",
|
|
312
|
+
success: "border-border-success-base",
|
|
313
|
+
inactive: "border-border-subtle bg-bg-subtle"
|
|
314
|
+
};
|
|
315
|
+
const TEXTAREA_STYLES = (0, import_utils4.cx)(
|
|
316
|
+
defaults,
|
|
317
|
+
fonts,
|
|
318
|
+
variants[variant],
|
|
319
|
+
startIcon && "pl-10",
|
|
320
|
+
clearable && endIcon && "pr-10",
|
|
321
|
+
clearable && !endIcon && "pr-5"
|
|
322
|
+
);
|
|
323
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "w-full relative flex items-start", children: [
|
|
324
|
+
startIcon && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
325
|
+
"span",
|
|
326
|
+
{
|
|
327
|
+
className: "absolute left-3 top-3 flex items-center pointer-events-none text-fg-subtle",
|
|
328
|
+
"aria-hidden": "true",
|
|
329
|
+
children: startIcon
|
|
330
|
+
}
|
|
331
|
+
),
|
|
332
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
333
|
+
"textarea",
|
|
334
|
+
{
|
|
335
|
+
id: labelHTMLForId,
|
|
336
|
+
ref,
|
|
337
|
+
className: TEXTAREA_STYLES,
|
|
338
|
+
"aria-disabled": props.disabled || variant === "inactive",
|
|
339
|
+
"aria-invalid": variant === "error" ? "true" : void 0,
|
|
340
|
+
disabled: props.disabled || variant === "inactive",
|
|
341
|
+
rows,
|
|
342
|
+
...props
|
|
343
|
+
}
|
|
344
|
+
),
|
|
345
|
+
clearable && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
346
|
+
"button",
|
|
347
|
+
{
|
|
348
|
+
type: "button",
|
|
349
|
+
"aria-label": "Clear text area",
|
|
350
|
+
onClick: () => {
|
|
351
|
+
var _a;
|
|
352
|
+
return (_a = props.onChange) == null ? void 0 : _a.call(props, { target: { value: "" } });
|
|
353
|
+
},
|
|
354
|
+
className: (0, import_utils4.cx)(
|
|
355
|
+
clearable && hasValue && endIcon ? "right-9" : "right-3",
|
|
356
|
+
"absolute top-3 flex items-center p-1 rounded-full outline-none",
|
|
357
|
+
"transition-all duration-300 ease-in-out",
|
|
358
|
+
hasValue ? "opacity-100 scale-100" : "opacity-0 scale-90 pointer-events-none",
|
|
359
|
+
"focus:shadow-focus"
|
|
360
|
+
),
|
|
361
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_icons3.Close, { "aria-hidden": "true", className: "text-fg-subtle" })
|
|
362
|
+
}
|
|
363
|
+
),
|
|
364
|
+
endIcon && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
365
|
+
"span",
|
|
366
|
+
{
|
|
367
|
+
className: (0, import_utils4.cx)(
|
|
368
|
+
"absolute flex items-center right-3 top-3 text-fg-subtle"
|
|
369
|
+
),
|
|
370
|
+
"aria-hidden": typeof endIcon === "string" ? void 0 : "true",
|
|
371
|
+
children: endIcon
|
|
372
|
+
}
|
|
373
|
+
)
|
|
374
|
+
] });
|
|
375
|
+
}
|
|
376
|
+
);
|
|
236
377
|
// Annotate the CommonJS export names for ESM import in node:
|
|
237
378
|
0 && (module.exports = {
|
|
238
379
|
Feedback,
|
|
239
380
|
Field,
|
|
240
381
|
Input,
|
|
241
|
-
Label
|
|
382
|
+
Label,
|
|
383
|
+
Radio,
|
|
384
|
+
Textarea
|
|
242
385
|
});
|
package/dist/index.mjs
CHANGED
|
@@ -11,6 +11,7 @@ import React, {
|
|
|
11
11
|
useState,
|
|
12
12
|
useCallback
|
|
13
13
|
} from "react";
|
|
14
|
+
import { jsx } from "react/jsx-runtime";
|
|
14
15
|
var FieldContext = createContext(null);
|
|
15
16
|
var FieldProvider = ({ children }) => {
|
|
16
17
|
const baseId = useId();
|
|
@@ -35,7 +36,7 @@ var FieldProvider = ({ children }) => {
|
|
|
35
36
|
}),
|
|
36
37
|
[baseId, type, describedByIds, registerDescription, unregisterDescription]
|
|
37
38
|
);
|
|
38
|
-
return /* @__PURE__ */
|
|
39
|
+
return /* @__PURE__ */ jsx(FieldContext.Provider, { value, children });
|
|
39
40
|
};
|
|
40
41
|
var useFieldContext = () => {
|
|
41
42
|
const context = useContext(FieldContext);
|
|
@@ -46,6 +47,7 @@ var useFieldContext = () => {
|
|
|
46
47
|
};
|
|
47
48
|
|
|
48
49
|
// src/elements/Label.jsx
|
|
50
|
+
import { jsx as jsx2, jsxs } from "react/jsx-runtime";
|
|
49
51
|
var Label = ({ children, hint, description, ...props }) => {
|
|
50
52
|
const { labelHTMLForId } = useFieldContext();
|
|
51
53
|
const returnHintType = useCallback2((hint2) => {
|
|
@@ -53,9 +55,9 @@ var Label = ({ children, hint, description, ...props }) => {
|
|
|
53
55
|
case void 0:
|
|
54
56
|
return;
|
|
55
57
|
case "required":
|
|
56
|
-
return /* @__PURE__ */
|
|
58
|
+
return /* @__PURE__ */ jsx2("span", { className: "ml-2 text-fg-danger-base", children: "[required]" });
|
|
57
59
|
case "optional":
|
|
58
|
-
return /* @__PURE__ */
|
|
60
|
+
return /* @__PURE__ */ jsx2("span", { className: "ml-2", children: "[optional]" });
|
|
59
61
|
default:
|
|
60
62
|
console.warn(
|
|
61
63
|
"[Invalid prop arg] - The <Label> component only accepts 'Required' || 'Optional'. Nothing has been returned."
|
|
@@ -63,15 +65,20 @@ var Label = ({ children, hint, description, ...props }) => {
|
|
|
63
65
|
}
|
|
64
66
|
}, []);
|
|
65
67
|
const hintEl = returnHintType(hint);
|
|
66
|
-
return /* @__PURE__ */
|
|
68
|
+
return /* @__PURE__ */ jsxs(
|
|
67
69
|
"label",
|
|
68
70
|
{
|
|
69
71
|
hidden: props.hidden,
|
|
70
72
|
className: "tracking-normal leading-none flex flex-col gap-4",
|
|
71
|
-
htmlFor: labelHTMLForId
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
73
|
+
htmlFor: labelHTMLForId,
|
|
74
|
+
children: [
|
|
75
|
+
/* @__PURE__ */ jsxs("div", { className: "h-[21px]", children: [
|
|
76
|
+
children,
|
|
77
|
+
hintEl
|
|
78
|
+
] }),
|
|
79
|
+
description && /* @__PURE__ */ jsx2("div", { className: "h-[21px] text-sm font-light text-fg-base", children: description })
|
|
80
|
+
]
|
|
81
|
+
}
|
|
75
82
|
);
|
|
76
83
|
};
|
|
77
84
|
|
|
@@ -79,6 +86,7 @@ var Label = ({ children, hint, description, ...props }) => {
|
|
|
79
86
|
import React3, { forwardRef } from "react";
|
|
80
87
|
import { cx } from "@edux-design/utils";
|
|
81
88
|
import { Close } from "@edux-design/icons";
|
|
89
|
+
import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
82
90
|
var Input = forwardRef(
|
|
83
91
|
({
|
|
84
92
|
children,
|
|
@@ -109,51 +117,56 @@ var Input = forwardRef(
|
|
|
109
117
|
clearable && endIcon && "pr-10",
|
|
110
118
|
clearable && !endIcon && "pr-5"
|
|
111
119
|
);
|
|
112
|
-
return /* @__PURE__ */
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
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
|
-
|
|
120
|
+
return /* @__PURE__ */ jsxs2("div", { className: "w-full relative flex items-center", children: [
|
|
121
|
+
startIcon && /* @__PURE__ */ jsx3(
|
|
122
|
+
"span",
|
|
123
|
+
{
|
|
124
|
+
className: "absolute left-3 flex items-center pointer-events-none text-fg-subtle",
|
|
125
|
+
"aria-hidden": "true",
|
|
126
|
+
children: startIcon
|
|
127
|
+
}
|
|
128
|
+
),
|
|
129
|
+
/* @__PURE__ */ jsx3(
|
|
130
|
+
"input",
|
|
131
|
+
{
|
|
132
|
+
id: labelHTMLForId,
|
|
133
|
+
ref,
|
|
134
|
+
className: INPUT_STYLES,
|
|
135
|
+
autoComplete: autocomplete || "",
|
|
136
|
+
"aria-disabled": props.disabled || variant === "inactive",
|
|
137
|
+
"aria-invalid": variant === "error" ? "true" : void 0,
|
|
138
|
+
disabled: props.disabled || variant === "inactive",
|
|
139
|
+
...props
|
|
140
|
+
}
|
|
141
|
+
),
|
|
142
|
+
clearable && /* @__PURE__ */ jsx3(
|
|
143
|
+
"button",
|
|
144
|
+
{
|
|
145
|
+
type: "button",
|
|
146
|
+
"aria-label": "Clear input",
|
|
147
|
+
onClick: () => {
|
|
148
|
+
var _a;
|
|
149
|
+
return (_a = props.onChange) == null ? void 0 : _a.call(props, { target: { value: "" } });
|
|
150
|
+
},
|
|
151
|
+
className: cx(
|
|
152
|
+
clearable && hasValue && endIcon ? "right-9" : "right-3",
|
|
153
|
+
"absolute flex items-center p-1 rounded-full outline-none",
|
|
154
|
+
"transition-all duration-300 ease-in-out",
|
|
155
|
+
hasValue ? "opacity-100 scale-100" : "opacity-0 scale-90 pointer-events-none",
|
|
156
|
+
"focus:shadow-focus"
|
|
157
|
+
),
|
|
158
|
+
children: /* @__PURE__ */ jsx3(Close, { "aria-hidden": "true", className: "text-fg-subtle" })
|
|
159
|
+
}
|
|
160
|
+
),
|
|
161
|
+
endIcon && /* @__PURE__ */ jsx3(
|
|
162
|
+
"span",
|
|
163
|
+
{
|
|
164
|
+
className: cx("absolute flex items-center right-3 text-fg-subtle"),
|
|
165
|
+
"aria-hidden": typeof endIcon === "string" ? void 0 : "true",
|
|
166
|
+
children: endIcon
|
|
167
|
+
}
|
|
168
|
+
)
|
|
169
|
+
] });
|
|
157
170
|
}
|
|
158
171
|
);
|
|
159
172
|
|
|
@@ -161,13 +174,14 @@ var Input = forwardRef(
|
|
|
161
174
|
import React4, { useEffect, useId as useId2 } from "react";
|
|
162
175
|
import { cx as cx2 } from "@edux-design/utils";
|
|
163
176
|
import { Close as Close2 } from "@edux-design/icons";
|
|
177
|
+
import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
164
178
|
var Field = ({ children }) => {
|
|
165
179
|
const FIELD_GROUP_WRAPPER_STYLES = cx2(
|
|
166
180
|
"flex flex-col items-start relative gap-8"
|
|
167
181
|
);
|
|
168
|
-
return /* @__PURE__ */
|
|
182
|
+
return /* @__PURE__ */ jsx4(FieldProvider, { children: /* @__PURE__ */ jsx4("div", { className: FIELD_GROUP_WRAPPER_STYLES, children }) });
|
|
169
183
|
};
|
|
170
|
-
function Feedback({ id, tone
|
|
184
|
+
function Feedback({ id, tone, children, className, ...rest }) {
|
|
171
185
|
const { labelHTMLForId, registerDescription, unregisterDescription } = useFieldContext();
|
|
172
186
|
const autoId = useId2();
|
|
173
187
|
const feedbackId = id ?? `${labelHTMLForId}-fb-${autoId}`;
|
|
@@ -183,28 +197,155 @@ function Feedback({ id, tone = "help", children, className, ...rest }) {
|
|
|
183
197
|
error: "bg-fg-danger-base"
|
|
184
198
|
}[tone];
|
|
185
199
|
const liveProps = tone === "error" ? { role: "alert", "aria-live": "assertive" } : { "aria-live": "polite" };
|
|
186
|
-
return /* @__PURE__ */
|
|
200
|
+
return /* @__PURE__ */ jsxs3(
|
|
187
201
|
"div",
|
|
188
202
|
{
|
|
189
203
|
id: feedbackId,
|
|
190
204
|
className: cx2("text-sm mt-1 flex gap-6", className),
|
|
191
205
|
...liveProps,
|
|
192
|
-
...rest
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
206
|
+
...rest,
|
|
207
|
+
children: [
|
|
208
|
+
/* @__PURE__ */ jsx4(
|
|
209
|
+
"div",
|
|
210
|
+
{
|
|
211
|
+
className: `h-[20px] w-[20px] ${colorByTone} rounded-full flex flex-col justify-center items-center`,
|
|
212
|
+
children: /* @__PURE__ */ jsx4(Close2, { className: "text-white" })
|
|
213
|
+
}
|
|
214
|
+
),
|
|
215
|
+
children
|
|
216
|
+
]
|
|
217
|
+
}
|
|
202
218
|
);
|
|
203
219
|
}
|
|
204
220
|
Field.Feedback = Feedback;
|
|
221
|
+
|
|
222
|
+
// src/elements/Radio.jsx
|
|
223
|
+
import React5 from "react";
|
|
224
|
+
import { cx as cx3 } from "@edux-design/utils";
|
|
225
|
+
import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
226
|
+
function Radio() {
|
|
227
|
+
const { labelHTMLForId } = useFieldContext();
|
|
228
|
+
return /* @__PURE__ */ jsxs4("div", { className: "relative inline-flex items-center justify-center", children: [
|
|
229
|
+
/* @__PURE__ */ jsx5(
|
|
230
|
+
"input",
|
|
231
|
+
{
|
|
232
|
+
id: labelHTMLForId,
|
|
233
|
+
type: "radio",
|
|
234
|
+
className: cx3(
|
|
235
|
+
"peer absolute inset-0 z-10 cursor-pointer appearance-none rounded-full",
|
|
236
|
+
"focus:shadow-focus focus-visible:shadow-focus focus:outline-none focus-visible:outline-none"
|
|
237
|
+
)
|
|
238
|
+
}
|
|
239
|
+
),
|
|
240
|
+
/* @__PURE__ */ jsx5(
|
|
241
|
+
"span",
|
|
242
|
+
{
|
|
243
|
+
className: cx3(
|
|
244
|
+
"block rounded-full border-1 border-border-base",
|
|
245
|
+
"h-[28px] w-[28px]",
|
|
246
|
+
"peer-checked:border-border-primary-base peer-checked:border-8",
|
|
247
|
+
"transition-colors",
|
|
248
|
+
"peer-hover:border-2 peer-hover:border-border-primary-base peer-checked:peer-hover:border-8 peer-checked:peer-hover:border-border-primary-base"
|
|
249
|
+
)
|
|
250
|
+
}
|
|
251
|
+
)
|
|
252
|
+
] });
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
// src/elements/Textarea.jsx
|
|
256
|
+
import React6, { forwardRef as forwardRef2 } from "react";
|
|
257
|
+
import { cx as cx4 } from "@edux-design/utils";
|
|
258
|
+
import { Close as Close3 } from "@edux-design/icons";
|
|
259
|
+
import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
260
|
+
var Textarea = forwardRef2(
|
|
261
|
+
({
|
|
262
|
+
children,
|
|
263
|
+
validation,
|
|
264
|
+
variant = "primary",
|
|
265
|
+
clearable = false,
|
|
266
|
+
startIcon,
|
|
267
|
+
endIcon,
|
|
268
|
+
rows = 4,
|
|
269
|
+
...props
|
|
270
|
+
}, ref) => {
|
|
271
|
+
const { labelHTMLForId } = useFieldContext();
|
|
272
|
+
const hasValue = Boolean(props.value);
|
|
273
|
+
const defaults = "w-full border-2 rounded-md border-border-base focus:shadow-focus focus-visible:shadow-focus outline-none transition-all duration-300 ease-in-out pl-5 py-3 resize-y";
|
|
274
|
+
const fonts = "font-normal text-base leading-relaxed";
|
|
275
|
+
const variants = {
|
|
276
|
+
primary: "hover:border-2 hover:border-border-primary-base focus:border-2 focus:border-border-primary-base focus-within:border-2 focus-within:border-border-primary-base",
|
|
277
|
+
error: "border-border-danger-base bg-bg-danger-subtle",
|
|
278
|
+
corrective: "border-border-corrective-base",
|
|
279
|
+
success: "border-border-success-base",
|
|
280
|
+
inactive: "border-border-subtle bg-bg-subtle"
|
|
281
|
+
};
|
|
282
|
+
const TEXTAREA_STYLES = cx4(
|
|
283
|
+
defaults,
|
|
284
|
+
fonts,
|
|
285
|
+
variants[variant],
|
|
286
|
+
startIcon && "pl-10",
|
|
287
|
+
clearable && endIcon && "pr-10",
|
|
288
|
+
clearable && !endIcon && "pr-5"
|
|
289
|
+
);
|
|
290
|
+
return /* @__PURE__ */ jsxs5("div", { className: "w-full relative flex items-start", children: [
|
|
291
|
+
startIcon && /* @__PURE__ */ jsx6(
|
|
292
|
+
"span",
|
|
293
|
+
{
|
|
294
|
+
className: "absolute left-3 top-3 flex items-center pointer-events-none text-fg-subtle",
|
|
295
|
+
"aria-hidden": "true",
|
|
296
|
+
children: startIcon
|
|
297
|
+
}
|
|
298
|
+
),
|
|
299
|
+
/* @__PURE__ */ jsx6(
|
|
300
|
+
"textarea",
|
|
301
|
+
{
|
|
302
|
+
id: labelHTMLForId,
|
|
303
|
+
ref,
|
|
304
|
+
className: TEXTAREA_STYLES,
|
|
305
|
+
"aria-disabled": props.disabled || variant === "inactive",
|
|
306
|
+
"aria-invalid": variant === "error" ? "true" : void 0,
|
|
307
|
+
disabled: props.disabled || variant === "inactive",
|
|
308
|
+
rows,
|
|
309
|
+
...props
|
|
310
|
+
}
|
|
311
|
+
),
|
|
312
|
+
clearable && /* @__PURE__ */ jsx6(
|
|
313
|
+
"button",
|
|
314
|
+
{
|
|
315
|
+
type: "button",
|
|
316
|
+
"aria-label": "Clear text area",
|
|
317
|
+
onClick: () => {
|
|
318
|
+
var _a;
|
|
319
|
+
return (_a = props.onChange) == null ? void 0 : _a.call(props, { target: { value: "" } });
|
|
320
|
+
},
|
|
321
|
+
className: cx4(
|
|
322
|
+
clearable && hasValue && endIcon ? "right-9" : "right-3",
|
|
323
|
+
"absolute top-3 flex items-center p-1 rounded-full outline-none",
|
|
324
|
+
"transition-all duration-300 ease-in-out",
|
|
325
|
+
hasValue ? "opacity-100 scale-100" : "opacity-0 scale-90 pointer-events-none",
|
|
326
|
+
"focus:shadow-focus"
|
|
327
|
+
),
|
|
328
|
+
children: /* @__PURE__ */ jsx6(Close3, { "aria-hidden": "true", className: "text-fg-subtle" })
|
|
329
|
+
}
|
|
330
|
+
),
|
|
331
|
+
endIcon && /* @__PURE__ */ jsx6(
|
|
332
|
+
"span",
|
|
333
|
+
{
|
|
334
|
+
className: cx4(
|
|
335
|
+
"absolute flex items-center right-3 top-3 text-fg-subtle"
|
|
336
|
+
),
|
|
337
|
+
"aria-hidden": typeof endIcon === "string" ? void 0 : "true",
|
|
338
|
+
children: endIcon
|
|
339
|
+
}
|
|
340
|
+
)
|
|
341
|
+
] });
|
|
342
|
+
}
|
|
343
|
+
);
|
|
205
344
|
export {
|
|
206
345
|
Feedback,
|
|
207
346
|
Field,
|
|
208
347
|
Input,
|
|
209
|
-
Label
|
|
348
|
+
Label,
|
|
349
|
+
Radio,
|
|
350
|
+
Textarea
|
|
210
351
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@edux-design/forms",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.4",
|
|
4
4
|
"sideEffects": [
|
|
5
5
|
"**/*.css"
|
|
6
6
|
],
|
|
@@ -8,20 +8,23 @@
|
|
|
8
8
|
"files": [
|
|
9
9
|
"dist"
|
|
10
10
|
],
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
11
12
|
"exports": {
|
|
12
13
|
".": {
|
|
13
14
|
"import": "./dist/index.mjs",
|
|
14
|
-
"require": "./dist/index.js"
|
|
15
|
+
"require": "./dist/index.js",
|
|
16
|
+
"types": "./dist/index.d.ts"
|
|
15
17
|
}
|
|
16
18
|
},
|
|
17
19
|
"scripts": {
|
|
18
20
|
"lint": "eslint . --max-warnings 0",
|
|
19
|
-
"build": "tsup src/index.js --format esm,cjs",
|
|
20
|
-
"dev": "tsup src/index.js --watch --format esm,cjs",
|
|
21
|
+
"build": "tsup src/index.js --format esm,cjs --dts",
|
|
22
|
+
"dev": "tsup src/index.js --watch --format esm,cjs --dts",
|
|
21
23
|
"generate:component": "turbo gen react-component",
|
|
22
24
|
"check-types": "tsc --noEmit"
|
|
23
25
|
},
|
|
24
26
|
"devDependencies": {
|
|
27
|
+
"@repo/typescript-config": "*",
|
|
25
28
|
"typescript": "^5.9.2",
|
|
26
29
|
"tailwindcss": "^4.1.12",
|
|
27
30
|
"postcss": "^8.5.6",
|