@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.
@@ -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 };
@@ -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__ */ import_react.default.createElement(FieldContext.Provider, { value }, children);
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__ */ import_react2.default.createElement("span", { className: "ml-2 text-fg-danger-base" }, "[required]");
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__ */ import_react2.default.createElement("span", { className: "ml-2" }, "[optional]");
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__ */ import_react2.default.createElement(
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
- /* @__PURE__ */ import_react2.default.createElement("div", { className: "h-[21px]" }, children, hintEl),
105
- description && /* @__PURE__ */ import_react2.default.createElement("div", { className: "h-[21px] text-sm font-light text-fg-base" }, description)
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
- (clearable || endIcon) && "pr-10"
150
+ clearable && endIcon && "pr-10",
151
+ clearable && !endIcon && "pr-5"
141
152
  );
142
- return /* @__PURE__ */ import_react4.default.createElement("div", { className: "w-full relative flex items-center" }, startIcon && /* @__PURE__ */ import_react4.default.createElement(
143
- "span",
144
- {
145
- className: "absolute left-3 flex items-center pointer-events-none text-fg-subtle",
146
- "aria-hidden": "true"
147
- },
148
- startIcon
149
- ), /* @__PURE__ */ import_react4.default.createElement(
150
- "input",
151
- {
152
- id: labelHTMLForId,
153
- ref,
154
- className: INPUT_STYLES,
155
- autoComplete: autocomplete || "",
156
- "aria-disabled": props.disabled || variant === "inactive",
157
- "aria-invalid": variant === "error" ? "true" : void 0,
158
- disabled: props.disabled || variant === "inactive",
159
- ...props
160
- }
161
- ), clearable && /* @__PURE__ */ import_react4.default.createElement(
162
- "button",
163
- {
164
- type: "button",
165
- "aria-label": "Clear input",
166
- onClick: () => {
167
- var _a;
168
- return (_a = props.onChange) == null ? void 0 : _a.call(props, { target: { value: "" } });
169
- },
170
- className: (0, import_utils.cx)(
171
- clearable && hasValue ? "right-9" : "right-3",
172
- "absolute flex items-center p-1 rounded-full outline-none",
173
- "transition-all duration-300 ease-in-out",
174
- hasValue ? "opacity-100 scale-100" : "opacity-0 scale-90 pointer-events-none",
175
- "focus:shadow-focus"
176
- )
177
- },
178
- /* @__PURE__ */ import_react4.default.createElement(import_icons.Close, { "aria-hidden": "true", className: "text-fg-subtle" })
179
- ), endIcon && /* @__PURE__ */ import_react4.default.createElement(
180
- "span",
181
- {
182
- className: (0, import_utils.cx)("absolute flex items-center right-3 text-fg-subtle"),
183
- "aria-hidden": typeof endIcon === "string" ? void 0 : "true"
184
- },
185
- endIcon
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__ */ import_react5.default.createElement(FieldProvider, null, /* @__PURE__ */ import_react5.default.createElement("div", { className: FIELD_GROUP_WRAPPER_STYLES }, children));
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 = "help", children, className, ...rest }) {
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__ */ import_react5.default.createElement(
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
- /* @__PURE__ */ import_react5.default.createElement(
225
- "div",
226
- {
227
- className: `h-[20px] w-[20px] ${colorByTone} rounded-full flex flex-col justify-center items-center`
228
- },
229
- /* @__PURE__ */ import_react5.default.createElement(import_icons2.Close, { className: "text-white" })
230
- ),
231
- children
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__ */ React.createElement(FieldContext.Provider, { value }, children);
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__ */ React2.createElement("span", { className: "ml-2 text-fg-danger-base" }, "[required]");
58
+ return /* @__PURE__ */ jsx2("span", { className: "ml-2 text-fg-danger-base", children: "[required]" });
57
59
  case "optional":
58
- return /* @__PURE__ */ React2.createElement("span", { className: "ml-2" }, "[optional]");
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__ */ React2.createElement(
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
- /* @__PURE__ */ React2.createElement("div", { className: "h-[21px]" }, children, hintEl),
74
- description && /* @__PURE__ */ React2.createElement("div", { className: "h-[21px] text-sm font-light text-fg-base" }, description)
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
- (clearable || endIcon) && "pr-10"
117
+ clearable && endIcon && "pr-10",
118
+ clearable && !endIcon && "pr-5"
110
119
  );
111
- return /* @__PURE__ */ React3.createElement("div", { className: "w-full relative flex items-center" }, startIcon && /* @__PURE__ */ React3.createElement(
112
- "span",
113
- {
114
- className: "absolute left-3 flex items-center pointer-events-none text-fg-subtle",
115
- "aria-hidden": "true"
116
- },
117
- startIcon
118
- ), /* @__PURE__ */ React3.createElement(
119
- "input",
120
- {
121
- id: labelHTMLForId,
122
- ref,
123
- className: INPUT_STYLES,
124
- autoComplete: autocomplete || "",
125
- "aria-disabled": props.disabled || variant === "inactive",
126
- "aria-invalid": variant === "error" ? "true" : void 0,
127
- disabled: props.disabled || variant === "inactive",
128
- ...props
129
- }
130
- ), clearable && /* @__PURE__ */ React3.createElement(
131
- "button",
132
- {
133
- type: "button",
134
- "aria-label": "Clear input",
135
- onClick: () => {
136
- var _a;
137
- return (_a = props.onChange) == null ? void 0 : _a.call(props, { target: { value: "" } });
138
- },
139
- className: cx(
140
- clearable && hasValue ? "right-9" : "right-3",
141
- "absolute flex items-center p-1 rounded-full outline-none",
142
- "transition-all duration-300 ease-in-out",
143
- hasValue ? "opacity-100 scale-100" : "opacity-0 scale-90 pointer-events-none",
144
- "focus:shadow-focus"
145
- )
146
- },
147
- /* @__PURE__ */ React3.createElement(Close, { "aria-hidden": "true", className: "text-fg-subtle" })
148
- ), endIcon && /* @__PURE__ */ React3.createElement(
149
- "span",
150
- {
151
- className: cx("absolute flex items-center right-3 text-fg-subtle"),
152
- "aria-hidden": typeof endIcon === "string" ? void 0 : "true"
153
- },
154
- endIcon
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__ */ React4.createElement(FieldProvider, null, /* @__PURE__ */ React4.createElement("div", { className: FIELD_GROUP_WRAPPER_STYLES }, children));
182
+ return /* @__PURE__ */ jsx4(FieldProvider, { children: /* @__PURE__ */ jsx4("div", { className: FIELD_GROUP_WRAPPER_STYLES, children }) });
168
183
  };
169
- function Feedback({ id, tone = "help", children, className, ...rest }) {
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__ */ React4.createElement(
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
- /* @__PURE__ */ React4.createElement(
194
- "div",
195
- {
196
- className: `h-[20px] w-[20px] ${colorByTone} rounded-full flex flex-col justify-center items-center`
197
- },
198
- /* @__PURE__ */ React4.createElement(Close2, { className: "text-white" })
199
- ),
200
- children
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.2",
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",