@edux-design/forms 0.0.2 → 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 +214 -70
- package/dist/index.mjs +211 -69
- 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,
|
|
@@ -123,7 +133,7 @@ var Input = (0, import_react4.forwardRef)(
|
|
|
123
133
|
}, ref) => {
|
|
124
134
|
const { labelHTMLForId } = useFieldContext();
|
|
125
135
|
const hasValue = Boolean(props.value);
|
|
126
|
-
const defaults = "h-[44px] 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";
|
|
136
|
+
const defaults = "h-[44px] 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";
|
|
127
137
|
const fonts = "font-normal text-base";
|
|
128
138
|
const variants = {
|
|
129
139
|
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",
|
|
@@ -137,53 +147,59 @@ var Input = (0, import_react4.forwardRef)(
|
|
|
137
147
|
fonts,
|
|
138
148
|
variants[variant],
|
|
139
149
|
startIcon && "pl-10",
|
|
140
|
-
|
|
150
|
+
clearable && endIcon && "pr-10",
|
|
151
|
+
clearable && !endIcon && "pr-5"
|
|
141
152
|
);
|
|
142
|
-
return /* @__PURE__ */
|
|
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
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
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
|
+
] });
|
|
187
203
|
}
|
|
188
204
|
);
|
|
189
205
|
|
|
@@ -191,13 +207,14 @@ var Input = (0, import_react4.forwardRef)(
|
|
|
191
207
|
var import_react5 = __toESM(require("react"));
|
|
192
208
|
var import_utils2 = require("@edux-design/utils");
|
|
193
209
|
var import_icons2 = require("@edux-design/icons");
|
|
210
|
+
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
194
211
|
var Field = ({ children }) => {
|
|
195
212
|
const FIELD_GROUP_WRAPPER_STYLES = (0, import_utils2.cx)(
|
|
196
213
|
"flex flex-col items-start relative gap-8"
|
|
197
214
|
);
|
|
198
|
-
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 }) });
|
|
199
216
|
};
|
|
200
|
-
function Feedback({ id, tone
|
|
217
|
+
function Feedback({ id, tone, children, className, ...rest }) {
|
|
201
218
|
const { labelHTMLForId, registerDescription, unregisterDescription } = useFieldContext();
|
|
202
219
|
const autoId = (0, import_react5.useId)();
|
|
203
220
|
const feedbackId = id ?? `${labelHTMLForId}-fb-${autoId}`;
|
|
@@ -213,29 +230,156 @@ function Feedback({ id, tone = "help", children, className, ...rest }) {
|
|
|
213
230
|
error: "bg-fg-danger-base"
|
|
214
231
|
}[tone];
|
|
215
232
|
const liveProps = tone === "error" ? { role: "alert", "aria-live": "assertive" } : { "aria-live": "polite" };
|
|
216
|
-
return /* @__PURE__ */
|
|
233
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
217
234
|
"div",
|
|
218
235
|
{
|
|
219
236
|
id: feedbackId,
|
|
220
237
|
className: (0, import_utils2.cx)("text-sm mt-1 flex gap-6", className),
|
|
221
238
|
...liveProps,
|
|
222
|
-
...rest
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
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
|
+
}
|
|
232
251
|
);
|
|
233
252
|
}
|
|
234
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
|
+
);
|
|
235
377
|
// Annotate the CommonJS export names for ESM import in node:
|
|
236
378
|
0 && (module.exports = {
|
|
237
379
|
Feedback,
|
|
238
380
|
Field,
|
|
239
381
|
Input,
|
|
240
|
-
Label
|
|
382
|
+
Label,
|
|
383
|
+
Radio,
|
|
384
|
+
Textarea
|
|
241
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,
|
|
@@ -92,7 +100,7 @@ var Input = forwardRef(
|
|
|
92
100
|
}, ref) => {
|
|
93
101
|
const { labelHTMLForId } = useFieldContext();
|
|
94
102
|
const hasValue = Boolean(props.value);
|
|
95
|
-
const defaults = "h-[44px] 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";
|
|
103
|
+
const defaults = "h-[44px] 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";
|
|
96
104
|
const fonts = "font-normal text-base";
|
|
97
105
|
const variants = {
|
|
98
106
|
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",
|
|
@@ -106,53 +114,59 @@ var Input = forwardRef(
|
|
|
106
114
|
fonts,
|
|
107
115
|
variants[variant],
|
|
108
116
|
startIcon && "pl-10",
|
|
109
|
-
|
|
117
|
+
clearable && endIcon && "pr-10",
|
|
118
|
+
clearable && !endIcon && "pr-5"
|
|
110
119
|
);
|
|
111
|
-
return /* @__PURE__ */
|
|
112
|
-
|
|
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
|
-
|
|
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
|
+
] });
|
|
156
170
|
}
|
|
157
171
|
);
|
|
158
172
|
|
|
@@ -160,13 +174,14 @@ var Input = forwardRef(
|
|
|
160
174
|
import React4, { useEffect, useId as useId2 } from "react";
|
|
161
175
|
import { cx as cx2 } from "@edux-design/utils";
|
|
162
176
|
import { Close as Close2 } from "@edux-design/icons";
|
|
177
|
+
import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
163
178
|
var Field = ({ children }) => {
|
|
164
179
|
const FIELD_GROUP_WRAPPER_STYLES = cx2(
|
|
165
180
|
"flex flex-col items-start relative gap-8"
|
|
166
181
|
);
|
|
167
|
-
return /* @__PURE__ */
|
|
182
|
+
return /* @__PURE__ */ jsx4(FieldProvider, { children: /* @__PURE__ */ jsx4("div", { className: FIELD_GROUP_WRAPPER_STYLES, children }) });
|
|
168
183
|
};
|
|
169
|
-
function Feedback({ id, tone
|
|
184
|
+
function Feedback({ id, tone, children, className, ...rest }) {
|
|
170
185
|
const { labelHTMLForId, registerDescription, unregisterDescription } = useFieldContext();
|
|
171
186
|
const autoId = useId2();
|
|
172
187
|
const feedbackId = id ?? `${labelHTMLForId}-fb-${autoId}`;
|
|
@@ -182,28 +197,155 @@ function Feedback({ id, tone = "help", children, className, ...rest }) {
|
|
|
182
197
|
error: "bg-fg-danger-base"
|
|
183
198
|
}[tone];
|
|
184
199
|
const liveProps = tone === "error" ? { role: "alert", "aria-live": "assertive" } : { "aria-live": "polite" };
|
|
185
|
-
return /* @__PURE__ */
|
|
200
|
+
return /* @__PURE__ */ jsxs3(
|
|
186
201
|
"div",
|
|
187
202
|
{
|
|
188
203
|
id: feedbackId,
|
|
189
204
|
className: cx2("text-sm mt-1 flex gap-6", className),
|
|
190
205
|
...liveProps,
|
|
191
|
-
...rest
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
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
|
+
}
|
|
201
218
|
);
|
|
202
219
|
}
|
|
203
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
|
+
);
|
|
204
344
|
export {
|
|
205
345
|
Feedback,
|
|
206
346
|
Field,
|
|
207
347
|
Input,
|
|
208
|
-
Label
|
|
348
|
+
Label,
|
|
349
|
+
Radio,
|
|
350
|
+
Textarea
|
|
209
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",
|