react-smart-fields 2.1.0 → 2.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -28,6 +28,9 @@ yarn add react-smart-fields
28
28
  ## Quick Start
29
29
 
30
30
  ```tsx
31
+ // 1. Import the default styles once (e.g. in your root layout or App.tsx)
32
+ import 'react-smart-fields/styles.css';
33
+
31
34
  import { DynamicFields, FieldConfig } from "react-smart-fields";
32
35
 
33
36
  const fields: FieldConfig[] = [
package/dist/index.cjs CHANGED
@@ -113,88 +113,88 @@ var buildInitialValues = (fields, defaultValues, controlledValues) => {
113
113
  };
114
114
  var baseTheme = {
115
115
  default: {
116
- wrapper: "w-full max-w-2xl mx-auto p-6 bg-white dark:bg-gray-900 text-gray-800 dark:text-gray-200 rounded-xl border border-gray-200 dark:border-gray-700 shadow-sm dark:shadow-2xl",
117
- title: "text-2xl font-semibold tracking-tight text-gray-900 dark:text-gray-100",
118
- description: "text-sm text-gray-500 dark:text-gray-400",
119
- fieldsContainer: "space-y-3",
120
- field: "w-full",
121
- label: "flex text-sm font-medium text-gray-800 dark:text-gray-200 mb-1.5",
122
- help: "text-xs text-gray-500 dark:text-gray-400",
123
- control: "w-full rounded-lg border border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-800 text-gray-800 dark:text-gray-200 focus:outline-none focus:ring-2 focus:ring-blue-500 dark:focus:ring-blue-400 focus:border-blue-500 dark:focus:border-blue-400 transition-colors",
124
- textarea: "w-full rounded-lg border border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-800 text-gray-800 dark:text-gray-200 focus:outline-none focus:ring-2 focus:ring-blue-500 dark:focus:ring-blue-400 focus:border-blue-500 dark:focus:border-blue-400 transition-colors min-h-24",
125
- select: "w-full rounded-lg border border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-800 text-gray-800 dark:text-gray-200 focus:outline-none focus:ring-2 focus:ring-blue-500 dark:focus:ring-blue-400 focus:border-blue-500 dark:focus:border-blue-400 transition-colors",
126
- option: "text-gray-800 dark:text-gray-200",
127
- checkbox: "h-4 w-4 rounded border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700 focus:outline-none",
128
- radio: "h-4 w-4 rounded-full border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700 focus:outline-none",
129
- error: "text-sm font-medium text-red-500 dark:text-red-400"
116
+ wrapper: "rsf-wrapper",
117
+ title: "rsf-title",
118
+ description: "rsf-description",
119
+ fieldsContainer: "rsf-fields-container",
120
+ field: "rsf-field",
121
+ label: "rsf-label",
122
+ help: "rsf-help",
123
+ control: "rsf-input",
124
+ textarea: "rsf-textarea",
125
+ select: "rsf-select",
126
+ option: "",
127
+ checkbox: "rsf-checkbox",
128
+ radio: "rsf-radio",
129
+ error: "rsf-error"
130
130
  },
131
131
  minimal: {
132
- wrapper: "w-full max-w-2xl mx-auto",
133
- title: "text-xl font-semibold text-gray-900 dark:text-gray-100",
134
- description: "text-sm text-gray-500 dark:text-gray-400",
135
- fieldsContainer: "space-y-3",
136
- field: "w-full",
137
- label: "text-sm font-medium text-gray-700 dark:text-gray-300 mb-1",
138
- help: "text-xs text-gray-500 dark:text-gray-400",
139
- control: "w-full rounded-md border border-gray-300 dark:border-gray-600 bg-transparent text-gray-900 dark:text-gray-100 focus:outline-none focus:ring-2 focus:ring-blue-500",
140
- textarea: "w-full rounded-md border border-gray-300 dark:border-gray-600 bg-transparent text-gray-900 dark:text-gray-100 focus:outline-none focus:ring-2 focus:ring-blue-500 min-h-24",
141
- select: "w-full rounded-md border border-gray-300 dark:border-gray-600 bg-transparent text-gray-900 dark:text-gray-100 focus:outline-none focus:ring-2 focus:ring-blue-500",
142
- option: "text-gray-900 dark:text-gray-100",
143
- checkbox: "h-4 w-4 rounded border border-gray-300 dark:border-gray-600 bg-transparent focus:outline-none",
144
- radio: "h-4 w-4 rounded-full border border-gray-300 dark:border-gray-600 bg-transparent focus:outline-none",
145
- error: "text-sm text-red-500"
132
+ wrapper: "rsf-wrapper rsf-wrapper--minimal",
133
+ title: "rsf-title",
134
+ description: "rsf-description",
135
+ fieldsContainer: "rsf-fields-container",
136
+ field: "rsf-field",
137
+ label: "rsf-label",
138
+ help: "rsf-help",
139
+ control: "rsf-input",
140
+ textarea: "rsf-textarea",
141
+ select: "rsf-select",
142
+ option: "",
143
+ checkbox: "rsf-checkbox",
144
+ radio: "rsf-radio",
145
+ error: "rsf-error"
146
146
  },
147
147
  filled: {
148
- wrapper: "w-full max-w-2xl mx-auto p-6 bg-gray-50 dark:bg-gray-900/50 text-gray-800 dark:text-gray-200 rounded-xl border border-gray-100 dark:border-gray-800",
149
- title: "text-2xl font-semibold text-gray-900 dark:text-gray-100",
150
- description: "text-sm text-gray-500 dark:text-gray-400",
151
- fieldsContainer: "space-y-3",
152
- field: "w-full",
153
- label: "text-sm font-medium text-gray-700 dark:text-gray-300 mb-1.5",
154
- help: "text-xs text-gray-500 dark:text-gray-400",
155
- control: "w-full rounded-lg border border-transparent bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 focus:outline-none focus:ring-2 focus:ring-blue-500",
156
- textarea: "w-full rounded-lg border border-transparent bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 focus:outline-none focus:ring-2 focus:ring-blue-500 min-h-24",
157
- select: "w-full rounded-lg border border-transparent bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 focus:outline-none focus:ring-2 focus:ring-blue-500",
158
- option: "text-gray-900 dark:text-gray-100",
159
- checkbox: "h-4 w-4 rounded border border-transparent bg-white dark:bg-gray-800 focus:outline-none",
160
- radio: "h-4 w-4 rounded-full border border-transparent bg-white dark:bg-gray-800 focus:outline-none",
161
- error: "text-sm text-red-500"
148
+ wrapper: "rsf-wrapper rsf-wrapper--filled",
149
+ title: "rsf-title",
150
+ description: "rsf-description",
151
+ fieldsContainer: "rsf-fields-container",
152
+ field: "rsf-field",
153
+ label: "rsf-label",
154
+ help: "rsf-help",
155
+ control: "rsf-input",
156
+ textarea: "rsf-textarea",
157
+ select: "rsf-select",
158
+ option: "",
159
+ checkbox: "rsf-checkbox",
160
+ radio: "rsf-radio",
161
+ error: "rsf-error"
162
162
  },
163
163
  underline: {
164
- wrapper: "w-full max-w-2xl mx-auto p-4",
165
- title: "text-xl font-semibold text-gray-900 dark:text-gray-100",
166
- description: "text-sm text-gray-500 dark:text-gray-400",
167
- fieldsContainer: "space-y-4",
168
- field: "w-full",
169
- label: "text-sm font-medium text-gray-700 dark:text-gray-300 mb-1",
170
- help: "text-xs text-gray-500 dark:text-gray-400",
171
- control: "w-full border-0 border-b border-gray-300 dark:border-gray-600 bg-transparent text-gray-900 dark:text-gray-100 rounded-none focus:outline-none focus:ring-0 focus:border-blue-500",
172
- textarea: "w-full border-0 border-b border-gray-300 dark:border-gray-600 bg-transparent text-gray-900 dark:text-gray-100 rounded-none focus:outline-none focus:ring-0 focus:border-blue-500 min-h-24",
173
- select: "w-full border-0 border-b border-gray-300 dark:border-gray-600 bg-transparent text-gray-900 dark:text-gray-100 rounded-none focus:outline-none focus:ring-0 focus:border-blue-500",
174
- option: "text-gray-900 dark:text-gray-100",
175
- checkbox: "h-4 w-4 rounded border border-gray-300 dark:border-gray-600",
176
- radio: "h-4 w-4 rounded-full border border-gray-300 dark:border-gray-600",
177
- error: "text-sm text-red-500"
164
+ wrapper: "rsf-wrapper rsf-wrapper--underline",
165
+ title: "rsf-title",
166
+ description: "rsf-description",
167
+ fieldsContainer: "rsf-fields-container",
168
+ field: "rsf-field",
169
+ label: "rsf-label",
170
+ help: "rsf-help",
171
+ control: "rsf-input",
172
+ textarea: "rsf-textarea",
173
+ select: "rsf-select",
174
+ option: "",
175
+ checkbox: "rsf-checkbox",
176
+ radio: "rsf-radio",
177
+ error: "rsf-error"
178
178
  }
179
179
  };
180
180
  var sizeMap = {
181
181
  sm: {
182
- control: "px-3 py-1.5 text-xs",
183
- label: "text-xs",
184
- help: "text-[11px]",
185
- error: "text-xs"
182
+ control: "rsf-input--sm",
183
+ label: "",
184
+ help: "",
185
+ error: ""
186
186
  },
187
187
  md: {
188
- control: "px-3.5 py-2 text-sm",
189
- label: "text-sm",
190
- help: "text-xs",
191
- error: "text-sm"
188
+ control: "",
189
+ label: "",
190
+ help: "",
191
+ error: ""
192
192
  },
193
193
  lg: {
194
- control: "px-4 py-2.5 text-base",
195
- label: "text-base",
196
- help: "text-sm",
197
- error: "text-sm"
194
+ control: "rsf-input--lg",
195
+ label: "",
196
+ help: "",
197
+ error: ""
198
198
  }
199
199
  };
200
200
  var DynamicFields = ({
@@ -417,7 +417,7 @@ var DynamicFields = ({
417
417
  error: cn(defaultUi.error, sizeClasses.error, errorClassName, field?.errorClassName, ui?.error, field?.ui?.error)
418
418
  });
419
419
  const buildStateClassName = (field, hasError, disabled, readOnly) => cn(
420
- hasError && stateClassNames?.invalid,
420
+ hasError && (stateClassNames?.invalid ?? "rsf-input--invalid"),
421
421
  disabled && stateClassNames?.disabled,
422
422
  readOnly && stateClassNames?.readonly,
423
423
  dirtyMap[field.name] && stateClassNames?.dirty,
@@ -434,7 +434,8 @@ var DynamicFields = ({
434
434
  };
435
435
  const renderDefaultControl = (context) => {
436
436
  const { field, value: value2, options, isLoadingOptions, classes, handleChange, handleBlur, disabled, readOnly, error } = context;
437
- const controlStateClass = buildStateClassName(field, Boolean(error), disabled, readOnly);
437
+ const showsError = Boolean(error) && shouldShowError(field.name);
438
+ const controlStateClass = buildStateClassName(field, showsError, disabled, readOnly);
438
439
  if (field.type === "textarea") {
439
440
  return /* @__PURE__ */ import_react.default.createElement(
440
441
  "textarea",
@@ -477,12 +478,12 @@ var DynamicFields = ({
477
478
  );
478
479
  }
479
480
  if (field.type === "radio") {
480
- return /* @__PURE__ */ import_react.default.createElement("div", { className: "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-3" }, options.map((option) => /* @__PURE__ */ import_react.default.createElement(
481
+ return /* @__PURE__ */ import_react.default.createElement("div", { className: "rsf-radio-group" }, options.map((option) => /* @__PURE__ */ import_react.default.createElement(
481
482
  "label",
482
483
  {
483
484
  key: `${field.name}-${String(option.value)}`,
484
485
  htmlFor: `${field.name}-${String(option.value)}`,
485
- className: "flex items-center gap-2 cursor-pointer"
486
+ className: "rsf-radio-item"
486
487
  },
487
488
  /* @__PURE__ */ import_react.default.createElement(
488
489
  "input",
@@ -499,7 +500,7 @@ var DynamicFields = ({
499
500
  className: cn(classes.radio, controlStateClass)
500
501
  }
501
502
  ),
502
- /* @__PURE__ */ import_react.default.createElement("span", { className: "text-sm text-gray-800 dark:text-gray-200" }, option.label)
503
+ /* @__PURE__ */ import_react.default.createElement("span", { className: "rsf-radio-label" }, option.label)
503
504
  )));
504
505
  }
505
506
  if (field.type === "checkbox") {
@@ -541,7 +542,7 @@ var DynamicFields = ({
541
542
  }
542
543
  );
543
544
  };
544
- return /* @__PURE__ */ import_react.default.createElement("div", { className: resolveUi().wrapper }, title && /* @__PURE__ */ import_react.default.createElement("div", { className: "mb-4" }, /* @__PURE__ */ import_react.default.createElement("h2", { className: resolveUi().title }, title), description && /* @__PURE__ */ import_react.default.createElement("p", { className: resolveUi().description }, description)), /* @__PURE__ */ import_react.default.createElement("div", { className: resolveUi().fieldsContainer }, visibleFields.map((field) => {
545
+ return /* @__PURE__ */ import_react.default.createElement("div", { className: resolveUi().wrapper }, title && /* @__PURE__ */ import_react.default.createElement("div", { className: "rsf-header" }, /* @__PURE__ */ import_react.default.createElement("h2", { className: resolveUi().title }, title), description && /* @__PURE__ */ import_react.default.createElement("p", { className: resolveUi().description }, description)), /* @__PURE__ */ import_react.default.createElement("div", { className: resolveUi().fieldsContainer }, visibleFields.map((field) => {
545
546
  const classes = resolveUi(field);
546
547
  const storedValue = getIn(values, field.name);
547
548
  const renderedValue = field.transformIn ? field.transformIn(storedValue, values) : storedValue;
@@ -569,7 +570,7 @@ var DynamicFields = ({
569
570
  handleBlur: () => handleFieldBlur(field)
570
571
  };
571
572
  const requiredMark = field.required || field.requiredWhen?.(values);
572
- const labelNode = field.type === "checkbox" ? null : renderLabel ? renderLabel(context) : field.label ? /* @__PURE__ */ import_react.default.createElement("label", { htmlFor: field.name, className: classes.label }, field.label, requiredMark && /* @__PURE__ */ import_react.default.createElement("span", { className: "text-red-500 dark:text-red-400 ml-1" }, "*")) : null;
573
+ const labelNode = field.type === "checkbox" ? null : renderLabel ? renderLabel(context) : field.label ? /* @__PURE__ */ import_react.default.createElement("label", { htmlFor: field.name, className: classes.label }, field.label, requiredMark && /* @__PURE__ */ import_react.default.createElement("span", { className: "rsf-required-mark" }, "*")) : null;
573
574
  const helpNode = renderDescription ? renderDescription(context) : field.description ? /* @__PURE__ */ import_react.default.createElement("p", { className: classes.help }, field.description) : null;
574
575
  const errorNode = canShowError ? renderError ? renderError(context) : /* @__PURE__ */ import_react.default.createElement("p", { className: classes.error, role: "alert" }, error) : null;
575
576
  const controlNode = field.renderControl?.(context) ?? renderControl?.(context) ?? renderDefaultControl(context);
@@ -583,7 +584,7 @@ var DynamicFields = ({
583
584
  }));
584
585
  }
585
586
  if (field.type === "checkbox") {
586
- return /* @__PURE__ */ import_react.default.createElement("div", { key: field.name, className: classes.field }, /* @__PURE__ */ import_react.default.createElement("label", { htmlFor: field.name, className: "inline-flex items-start gap-2 cursor-pointer" }, controlNode, /* @__PURE__ */ import_react.default.createElement("span", { className: "text-sm text-gray-800 dark:text-gray-200" }, field.label, requiredMark && /* @__PURE__ */ import_react.default.createElement("span", { className: "text-red-500 dark:text-red-400 ml-1" }, "*"))), helpNode, errorNode);
587
+ return /* @__PURE__ */ import_react.default.createElement("div", { key: field.name, className: classes.field }, /* @__PURE__ */ import_react.default.createElement("label", { htmlFor: field.name, className: "rsf-checkbox-item" }, controlNode, /* @__PURE__ */ import_react.default.createElement("span", { className: "rsf-checkbox-label" }, field.label, requiredMark && /* @__PURE__ */ import_react.default.createElement("span", { className: "rsf-required-mark" }, "*"))), helpNode, errorNode);
587
588
  }
588
589
  return /* @__PURE__ */ import_react.default.createElement("div", { key: field.name, className: classes.field }, labelNode, helpNode, controlNode, errorNode);
589
590
  })));
package/dist/index.js CHANGED
@@ -77,88 +77,88 @@ var buildInitialValues = (fields, defaultValues, controlledValues) => {
77
77
  };
78
78
  var baseTheme = {
79
79
  default: {
80
- wrapper: "w-full max-w-2xl mx-auto p-6 bg-white dark:bg-gray-900 text-gray-800 dark:text-gray-200 rounded-xl border border-gray-200 dark:border-gray-700 shadow-sm dark:shadow-2xl",
81
- title: "text-2xl font-semibold tracking-tight text-gray-900 dark:text-gray-100",
82
- description: "text-sm text-gray-500 dark:text-gray-400",
83
- fieldsContainer: "space-y-3",
84
- field: "w-full",
85
- label: "flex text-sm font-medium text-gray-800 dark:text-gray-200 mb-1.5",
86
- help: "text-xs text-gray-500 dark:text-gray-400",
87
- control: "w-full rounded-lg border border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-800 text-gray-800 dark:text-gray-200 focus:outline-none focus:ring-2 focus:ring-blue-500 dark:focus:ring-blue-400 focus:border-blue-500 dark:focus:border-blue-400 transition-colors",
88
- textarea: "w-full rounded-lg border border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-800 text-gray-800 dark:text-gray-200 focus:outline-none focus:ring-2 focus:ring-blue-500 dark:focus:ring-blue-400 focus:border-blue-500 dark:focus:border-blue-400 transition-colors min-h-24",
89
- select: "w-full rounded-lg border border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-800 text-gray-800 dark:text-gray-200 focus:outline-none focus:ring-2 focus:ring-blue-500 dark:focus:ring-blue-400 focus:border-blue-500 dark:focus:border-blue-400 transition-colors",
90
- option: "text-gray-800 dark:text-gray-200",
91
- checkbox: "h-4 w-4 rounded border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700 focus:outline-none",
92
- radio: "h-4 w-4 rounded-full border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700 focus:outline-none",
93
- error: "text-sm font-medium text-red-500 dark:text-red-400"
80
+ wrapper: "rsf-wrapper",
81
+ title: "rsf-title",
82
+ description: "rsf-description",
83
+ fieldsContainer: "rsf-fields-container",
84
+ field: "rsf-field",
85
+ label: "rsf-label",
86
+ help: "rsf-help",
87
+ control: "rsf-input",
88
+ textarea: "rsf-textarea",
89
+ select: "rsf-select",
90
+ option: "",
91
+ checkbox: "rsf-checkbox",
92
+ radio: "rsf-radio",
93
+ error: "rsf-error"
94
94
  },
95
95
  minimal: {
96
- wrapper: "w-full max-w-2xl mx-auto",
97
- title: "text-xl font-semibold text-gray-900 dark:text-gray-100",
98
- description: "text-sm text-gray-500 dark:text-gray-400",
99
- fieldsContainer: "space-y-3",
100
- field: "w-full",
101
- label: "text-sm font-medium text-gray-700 dark:text-gray-300 mb-1",
102
- help: "text-xs text-gray-500 dark:text-gray-400",
103
- control: "w-full rounded-md border border-gray-300 dark:border-gray-600 bg-transparent text-gray-900 dark:text-gray-100 focus:outline-none focus:ring-2 focus:ring-blue-500",
104
- textarea: "w-full rounded-md border border-gray-300 dark:border-gray-600 bg-transparent text-gray-900 dark:text-gray-100 focus:outline-none focus:ring-2 focus:ring-blue-500 min-h-24",
105
- select: "w-full rounded-md border border-gray-300 dark:border-gray-600 bg-transparent text-gray-900 dark:text-gray-100 focus:outline-none focus:ring-2 focus:ring-blue-500",
106
- option: "text-gray-900 dark:text-gray-100",
107
- checkbox: "h-4 w-4 rounded border border-gray-300 dark:border-gray-600 bg-transparent focus:outline-none",
108
- radio: "h-4 w-4 rounded-full border border-gray-300 dark:border-gray-600 bg-transparent focus:outline-none",
109
- error: "text-sm text-red-500"
96
+ wrapper: "rsf-wrapper rsf-wrapper--minimal",
97
+ title: "rsf-title",
98
+ description: "rsf-description",
99
+ fieldsContainer: "rsf-fields-container",
100
+ field: "rsf-field",
101
+ label: "rsf-label",
102
+ help: "rsf-help",
103
+ control: "rsf-input",
104
+ textarea: "rsf-textarea",
105
+ select: "rsf-select",
106
+ option: "",
107
+ checkbox: "rsf-checkbox",
108
+ radio: "rsf-radio",
109
+ error: "rsf-error"
110
110
  },
111
111
  filled: {
112
- wrapper: "w-full max-w-2xl mx-auto p-6 bg-gray-50 dark:bg-gray-900/50 text-gray-800 dark:text-gray-200 rounded-xl border border-gray-100 dark:border-gray-800",
113
- title: "text-2xl font-semibold text-gray-900 dark:text-gray-100",
114
- description: "text-sm text-gray-500 dark:text-gray-400",
115
- fieldsContainer: "space-y-3",
116
- field: "w-full",
117
- label: "text-sm font-medium text-gray-700 dark:text-gray-300 mb-1.5",
118
- help: "text-xs text-gray-500 dark:text-gray-400",
119
- control: "w-full rounded-lg border border-transparent bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 focus:outline-none focus:ring-2 focus:ring-blue-500",
120
- textarea: "w-full rounded-lg border border-transparent bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 focus:outline-none focus:ring-2 focus:ring-blue-500 min-h-24",
121
- select: "w-full rounded-lg border border-transparent bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 focus:outline-none focus:ring-2 focus:ring-blue-500",
122
- option: "text-gray-900 dark:text-gray-100",
123
- checkbox: "h-4 w-4 rounded border border-transparent bg-white dark:bg-gray-800 focus:outline-none",
124
- radio: "h-4 w-4 rounded-full border border-transparent bg-white dark:bg-gray-800 focus:outline-none",
125
- error: "text-sm text-red-500"
112
+ wrapper: "rsf-wrapper rsf-wrapper--filled",
113
+ title: "rsf-title",
114
+ description: "rsf-description",
115
+ fieldsContainer: "rsf-fields-container",
116
+ field: "rsf-field",
117
+ label: "rsf-label",
118
+ help: "rsf-help",
119
+ control: "rsf-input",
120
+ textarea: "rsf-textarea",
121
+ select: "rsf-select",
122
+ option: "",
123
+ checkbox: "rsf-checkbox",
124
+ radio: "rsf-radio",
125
+ error: "rsf-error"
126
126
  },
127
127
  underline: {
128
- wrapper: "w-full max-w-2xl mx-auto p-4",
129
- title: "text-xl font-semibold text-gray-900 dark:text-gray-100",
130
- description: "text-sm text-gray-500 dark:text-gray-400",
131
- fieldsContainer: "space-y-4",
132
- field: "w-full",
133
- label: "text-sm font-medium text-gray-700 dark:text-gray-300 mb-1",
134
- help: "text-xs text-gray-500 dark:text-gray-400",
135
- control: "w-full border-0 border-b border-gray-300 dark:border-gray-600 bg-transparent text-gray-900 dark:text-gray-100 rounded-none focus:outline-none focus:ring-0 focus:border-blue-500",
136
- textarea: "w-full border-0 border-b border-gray-300 dark:border-gray-600 bg-transparent text-gray-900 dark:text-gray-100 rounded-none focus:outline-none focus:ring-0 focus:border-blue-500 min-h-24",
137
- select: "w-full border-0 border-b border-gray-300 dark:border-gray-600 bg-transparent text-gray-900 dark:text-gray-100 rounded-none focus:outline-none focus:ring-0 focus:border-blue-500",
138
- option: "text-gray-900 dark:text-gray-100",
139
- checkbox: "h-4 w-4 rounded border border-gray-300 dark:border-gray-600",
140
- radio: "h-4 w-4 rounded-full border border-gray-300 dark:border-gray-600",
141
- error: "text-sm text-red-500"
128
+ wrapper: "rsf-wrapper rsf-wrapper--underline",
129
+ title: "rsf-title",
130
+ description: "rsf-description",
131
+ fieldsContainer: "rsf-fields-container",
132
+ field: "rsf-field",
133
+ label: "rsf-label",
134
+ help: "rsf-help",
135
+ control: "rsf-input",
136
+ textarea: "rsf-textarea",
137
+ select: "rsf-select",
138
+ option: "",
139
+ checkbox: "rsf-checkbox",
140
+ radio: "rsf-radio",
141
+ error: "rsf-error"
142
142
  }
143
143
  };
144
144
  var sizeMap = {
145
145
  sm: {
146
- control: "px-3 py-1.5 text-xs",
147
- label: "text-xs",
148
- help: "text-[11px]",
149
- error: "text-xs"
146
+ control: "rsf-input--sm",
147
+ label: "",
148
+ help: "",
149
+ error: ""
150
150
  },
151
151
  md: {
152
- control: "px-3.5 py-2 text-sm",
153
- label: "text-sm",
154
- help: "text-xs",
155
- error: "text-sm"
152
+ control: "",
153
+ label: "",
154
+ help: "",
155
+ error: ""
156
156
  },
157
157
  lg: {
158
- control: "px-4 py-2.5 text-base",
159
- label: "text-base",
160
- help: "text-sm",
161
- error: "text-sm"
158
+ control: "rsf-input--lg",
159
+ label: "",
160
+ help: "",
161
+ error: ""
162
162
  }
163
163
  };
164
164
  var DynamicFields = ({
@@ -381,7 +381,7 @@ var DynamicFields = ({
381
381
  error: cn(defaultUi.error, sizeClasses.error, errorClassName, field?.errorClassName, ui?.error, field?.ui?.error)
382
382
  });
383
383
  const buildStateClassName = (field, hasError, disabled, readOnly) => cn(
384
- hasError && stateClassNames?.invalid,
384
+ hasError && (stateClassNames?.invalid ?? "rsf-input--invalid"),
385
385
  disabled && stateClassNames?.disabled,
386
386
  readOnly && stateClassNames?.readonly,
387
387
  dirtyMap[field.name] && stateClassNames?.dirty,
@@ -398,7 +398,8 @@ var DynamicFields = ({
398
398
  };
399
399
  const renderDefaultControl = (context) => {
400
400
  const { field, value: value2, options, isLoadingOptions, classes, handleChange, handleBlur, disabled, readOnly, error } = context;
401
- const controlStateClass = buildStateClassName(field, Boolean(error), disabled, readOnly);
401
+ const showsError = Boolean(error) && shouldShowError(field.name);
402
+ const controlStateClass = buildStateClassName(field, showsError, disabled, readOnly);
402
403
  if (field.type === "textarea") {
403
404
  return /* @__PURE__ */ React.createElement(
404
405
  "textarea",
@@ -441,12 +442,12 @@ var DynamicFields = ({
441
442
  );
442
443
  }
443
444
  if (field.type === "radio") {
444
- return /* @__PURE__ */ React.createElement("div", { className: "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-3" }, options.map((option) => /* @__PURE__ */ React.createElement(
445
+ return /* @__PURE__ */ React.createElement("div", { className: "rsf-radio-group" }, options.map((option) => /* @__PURE__ */ React.createElement(
445
446
  "label",
446
447
  {
447
448
  key: `${field.name}-${String(option.value)}`,
448
449
  htmlFor: `${field.name}-${String(option.value)}`,
449
- className: "flex items-center gap-2 cursor-pointer"
450
+ className: "rsf-radio-item"
450
451
  },
451
452
  /* @__PURE__ */ React.createElement(
452
453
  "input",
@@ -463,7 +464,7 @@ var DynamicFields = ({
463
464
  className: cn(classes.radio, controlStateClass)
464
465
  }
465
466
  ),
466
- /* @__PURE__ */ React.createElement("span", { className: "text-sm text-gray-800 dark:text-gray-200" }, option.label)
467
+ /* @__PURE__ */ React.createElement("span", { className: "rsf-radio-label" }, option.label)
467
468
  )));
468
469
  }
469
470
  if (field.type === "checkbox") {
@@ -505,7 +506,7 @@ var DynamicFields = ({
505
506
  }
506
507
  );
507
508
  };
508
- return /* @__PURE__ */ React.createElement("div", { className: resolveUi().wrapper }, title && /* @__PURE__ */ React.createElement("div", { className: "mb-4" }, /* @__PURE__ */ React.createElement("h2", { className: resolveUi().title }, title), description && /* @__PURE__ */ React.createElement("p", { className: resolveUi().description }, description)), /* @__PURE__ */ React.createElement("div", { className: resolveUi().fieldsContainer }, visibleFields.map((field) => {
509
+ return /* @__PURE__ */ React.createElement("div", { className: resolveUi().wrapper }, title && /* @__PURE__ */ React.createElement("div", { className: "rsf-header" }, /* @__PURE__ */ React.createElement("h2", { className: resolveUi().title }, title), description && /* @__PURE__ */ React.createElement("p", { className: resolveUi().description }, description)), /* @__PURE__ */ React.createElement("div", { className: resolveUi().fieldsContainer }, visibleFields.map((field) => {
509
510
  const classes = resolveUi(field);
510
511
  const storedValue = getIn(values, field.name);
511
512
  const renderedValue = field.transformIn ? field.transformIn(storedValue, values) : storedValue;
@@ -533,7 +534,7 @@ var DynamicFields = ({
533
534
  handleBlur: () => handleFieldBlur(field)
534
535
  };
535
536
  const requiredMark = field.required || field.requiredWhen?.(values);
536
- const labelNode = field.type === "checkbox" ? null : renderLabel ? renderLabel(context) : field.label ? /* @__PURE__ */ React.createElement("label", { htmlFor: field.name, className: classes.label }, field.label, requiredMark && /* @__PURE__ */ React.createElement("span", { className: "text-red-500 dark:text-red-400 ml-1" }, "*")) : null;
537
+ const labelNode = field.type === "checkbox" ? null : renderLabel ? renderLabel(context) : field.label ? /* @__PURE__ */ React.createElement("label", { htmlFor: field.name, className: classes.label }, field.label, requiredMark && /* @__PURE__ */ React.createElement("span", { className: "rsf-required-mark" }, "*")) : null;
537
538
  const helpNode = renderDescription ? renderDescription(context) : field.description ? /* @__PURE__ */ React.createElement("p", { className: classes.help }, field.description) : null;
538
539
  const errorNode = canShowError ? renderError ? renderError(context) : /* @__PURE__ */ React.createElement("p", { className: classes.error, role: "alert" }, error) : null;
539
540
  const controlNode = field.renderControl?.(context) ?? renderControl?.(context) ?? renderDefaultControl(context);
@@ -547,7 +548,7 @@ var DynamicFields = ({
547
548
  }));
548
549
  }
549
550
  if (field.type === "checkbox") {
550
- return /* @__PURE__ */ React.createElement("div", { key: field.name, className: classes.field }, /* @__PURE__ */ React.createElement("label", { htmlFor: field.name, className: "inline-flex items-start gap-2 cursor-pointer" }, controlNode, /* @__PURE__ */ React.createElement("span", { className: "text-sm text-gray-800 dark:text-gray-200" }, field.label, requiredMark && /* @__PURE__ */ React.createElement("span", { className: "text-red-500 dark:text-red-400 ml-1" }, "*"))), helpNode, errorNode);
551
+ return /* @__PURE__ */ React.createElement("div", { key: field.name, className: classes.field }, /* @__PURE__ */ React.createElement("label", { htmlFor: field.name, className: "rsf-checkbox-item" }, controlNode, /* @__PURE__ */ React.createElement("span", { className: "rsf-checkbox-label" }, field.label, requiredMark && /* @__PURE__ */ React.createElement("span", { className: "rsf-required-mark" }, "*"))), helpNode, errorNode);
551
552
  }
552
553
  return /* @__PURE__ */ React.createElement("div", { key: field.name, className: classes.field }, labelNode, helpNode, controlNode, errorNode);
553
554
  })));
@@ -0,0 +1,468 @@
1
+ /* src/styles.css */
2
+ .rsf-wrapper *,
3
+ .rsf-wrapper *::before,
4
+ .rsf-wrapper *::after {
5
+ box-sizing: border-box;
6
+ }
7
+ .rsf-wrapper {
8
+ font-family: var(--font-sans, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif);
9
+ -webkit-font-smoothing: antialiased;
10
+ -moz-osx-font-smoothing: grayscale;
11
+ color: var(--foreground, hsl(240 10% 3.9%));
12
+ background-color: var(--card, hsl(0 0% 100%));
13
+ border-radius: var(--radius, 0.5rem);
14
+ border: 1px solid var(--border, hsl(240 5.9% 90%));
15
+ box-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.07), 0 1px 2px -1px rgb(0 0 0 / 0.07);
16
+ padding: 1.5rem;
17
+ width: 100%;
18
+ max-width: 42rem;
19
+ margin-left: auto;
20
+ margin-right: auto;
21
+ }
22
+ .rsf-header {
23
+ display: flex;
24
+ flex-direction: column;
25
+ gap: 0.375rem;
26
+ padding-bottom: 1.5rem;
27
+ margin-bottom: 1.5rem;
28
+ border-bottom: 1px solid var(--border, hsl(240 5.9% 90%));
29
+ }
30
+ .rsf-title {
31
+ font-size: 1.5rem;
32
+ font-weight: 600;
33
+ line-height: 1;
34
+ letter-spacing: -0.025em;
35
+ color: var(--card-foreground, hsl(240 10% 3.9%));
36
+ }
37
+ .rsf-description {
38
+ font-size: 0.875rem;
39
+ color: var(--muted-foreground, hsl(240 3.8% 46.1%));
40
+ line-height: 1.5;
41
+ }
42
+ .rsf-fields-container {
43
+ display: flex;
44
+ flex-direction: column;
45
+ gap: 1rem;
46
+ }
47
+ .rsf-field {
48
+ display: flex;
49
+ flex-direction: column;
50
+ gap: 0.5rem;
51
+ width: 100%;
52
+ }
53
+ .rsf-label {
54
+ font-size: 0.875rem;
55
+ font-weight: 500;
56
+ line-height: 1;
57
+ color: var(--foreground, hsl(240 10% 3.9%));
58
+ cursor: default;
59
+ display: flex;
60
+ align-items: center;
61
+ gap: 0;
62
+ }
63
+ .rsf-label[data-disabled=true] {
64
+ cursor: not-allowed;
65
+ opacity: 0.7;
66
+ }
67
+ .rsf-required-mark {
68
+ color: var(--destructive, hsl(0 84.2% 60.2%));
69
+ margin-left: 0.25rem;
70
+ }
71
+ .rsf-help {
72
+ font-size: 0.8rem;
73
+ color: var(--muted-foreground, hsl(240 3.8% 46.1%));
74
+ line-height: 1.5;
75
+ }
76
+ .rsf-error {
77
+ font-size: 0.8rem;
78
+ font-weight: 500;
79
+ color: var(--destructive, hsl(0 84.2% 60.2%));
80
+ line-height: 1.25;
81
+ }
82
+ .rsf-input {
83
+ display: flex;
84
+ height: 2.5rem;
85
+ width: 100%;
86
+ border-radius: calc(var(--radius, 0.5rem) - 2px);
87
+ border: 1px solid var(--input, hsl(240 5.9% 90%));
88
+ background-color: var(--background, hsl(0 0% 100%));
89
+ padding: 0.5rem 0.75rem;
90
+ font-size: 0.875rem;
91
+ font-family: inherit;
92
+ color: var(--foreground, hsl(240 10% 3.9%));
93
+ line-height: 1.25;
94
+ transition: border-color 150ms ease, box-shadow 150ms ease;
95
+ outline: none;
96
+ -webkit-appearance: none;
97
+ appearance: none;
98
+ }
99
+ .rsf-input::placeholder {
100
+ color: var(--muted-foreground, hsl(240 3.8% 46.1%));
101
+ }
102
+ .rsf-input:focus-visible {
103
+ outline: none;
104
+ box-shadow: 0 0 0 2px var(--background, hsl(0 0% 100%)), 0 0 0 4px var(--ring, hsl(240 10% 3.9%));
105
+ }
106
+ .rsf-input:disabled {
107
+ cursor: not-allowed;
108
+ opacity: 0.5;
109
+ background-color: var(--muted, hsl(240 4.8% 95.9%));
110
+ }
111
+ .rsf-input[readonly] {
112
+ cursor: default;
113
+ background-color: var(--muted, hsl(240 4.8% 95.9%));
114
+ }
115
+ .rsf-input--invalid {
116
+ border-color: var(--destructive, hsl(0 84.2% 60.2%));
117
+ }
118
+ .rsf-input--invalid:focus-visible {
119
+ box-shadow: 0 0 0 2px var(--background, hsl(0 0% 100%)), 0 0 0 4px var(--destructive, hsl(0 84.2% 60.2%));
120
+ }
121
+ .rsf-input--sm {
122
+ height: 2rem;
123
+ padding: 0.375rem 0.625rem;
124
+ font-size: 0.75rem;
125
+ }
126
+ .rsf-input--lg {
127
+ height: 2.75rem;
128
+ padding: 0.625rem 1rem;
129
+ font-size: 1rem;
130
+ }
131
+ .rsf-textarea {
132
+ display: flex;
133
+ min-height: 5rem;
134
+ width: 100%;
135
+ border-radius: calc(var(--radius, 0.5rem) - 2px);
136
+ border: 1px solid var(--input, hsl(240 5.9% 90%));
137
+ background-color: var(--background, hsl(0 0% 100%));
138
+ padding: 0.5rem 0.75rem;
139
+ font-size: 0.875rem;
140
+ font-family: inherit;
141
+ color: var(--foreground, hsl(240 10% 3.9%));
142
+ line-height: 1.5;
143
+ transition: border-color 150ms ease, box-shadow 150ms ease;
144
+ outline: none;
145
+ resize: none;
146
+ }
147
+ .rsf-textarea::placeholder {
148
+ color: var(--muted-foreground, hsl(240 3.8% 46.1%));
149
+ }
150
+ .rsf-textarea:focus-visible {
151
+ outline: none;
152
+ box-shadow: 0 0 0 2px var(--background, hsl(0 0% 100%)), 0 0 0 4px var(--ring, hsl(240 10% 3.9%));
153
+ }
154
+ .rsf-textarea:disabled {
155
+ cursor: not-allowed;
156
+ opacity: 0.5;
157
+ }
158
+ .rsf-textarea--invalid {
159
+ border-color: var(--destructive, hsl(0 84.2% 60.2%));
160
+ }
161
+ .rsf-textarea--invalid:focus-visible {
162
+ box-shadow: 0 0 0 2px var(--background, hsl(0 0% 100%)), 0 0 0 4px var(--destructive, hsl(0 84.2% 60.2%));
163
+ }
164
+ .rsf-select {
165
+ display: flex;
166
+ height: 2.5rem;
167
+ width: 100%;
168
+ border-radius: calc(var(--radius, 0.5rem) - 2px);
169
+ border: 1px solid var(--input, hsl(240 5.9% 90%));
170
+ background-color: var(--background, hsl(0 0% 100%));
171
+ padding: 0 0.75rem;
172
+ padding-right: 2rem;
173
+ font-size: 0.875rem;
174
+ font-family: inherit;
175
+ color: var(--foreground, hsl(240 10% 3.9%));
176
+ line-height: 1.25;
177
+ cursor: pointer;
178
+ transition: border-color 150ms ease, box-shadow 150ms ease;
179
+ outline: none;
180
+ -webkit-appearance: none;
181
+ appearance: none;
182
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%2371717a' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
183
+ background-repeat: no-repeat;
184
+ background-position: right 0.625rem center;
185
+ background-size: 1rem;
186
+ }
187
+ .rsf-select:focus-visible {
188
+ outline: none;
189
+ box-shadow: 0 0 0 2px var(--background, hsl(0 0% 100%)), 0 0 0 4px var(--ring, hsl(240 10% 3.9%));
190
+ }
191
+ .rsf-select:disabled {
192
+ cursor: not-allowed;
193
+ opacity: 0.5;
194
+ }
195
+ .rsf-select--invalid {
196
+ border-color: var(--destructive, hsl(0 84.2% 60.2%));
197
+ }
198
+ .rsf-select--invalid:focus-visible {
199
+ box-shadow: 0 0 0 2px var(--background, hsl(0 0% 100%)), 0 0 0 4px var(--destructive, hsl(0 84.2% 60.2%));
200
+ }
201
+ .rsf-select--sm {
202
+ height: 2rem;
203
+ font-size: 0.75rem;
204
+ }
205
+ .rsf-select--lg {
206
+ height: 2.75rem;
207
+ font-size: 1rem;
208
+ }
209
+ .rsf-radio-group {
210
+ display: flex;
211
+ flex-direction: column;
212
+ gap: 0.625rem;
213
+ }
214
+ .rsf-radio-item {
215
+ display: flex;
216
+ align-items: center;
217
+ gap: 0.5rem;
218
+ cursor: pointer;
219
+ user-select: none;
220
+ }
221
+ .rsf-radio-item:has(input:disabled) {
222
+ cursor: not-allowed;
223
+ opacity: 0.5;
224
+ }
225
+ .rsf-radio {
226
+ width: 1rem;
227
+ height: 1rem;
228
+ border-radius: 9999px;
229
+ border: 1px solid var(--primary, hsl(240 5.9% 10%));
230
+ background-color: var(--background, hsl(0 0% 100%));
231
+ flex-shrink: 0;
232
+ cursor: pointer;
233
+ transition: border-color 150ms ease, box-shadow 150ms ease;
234
+ outline: none;
235
+ -webkit-appearance: none;
236
+ appearance: none;
237
+ position: relative;
238
+ }
239
+ .rsf-radio:checked {
240
+ background-color: var(--primary, hsl(240 5.9% 10%));
241
+ border-color: var(--primary, hsl(240 5.9% 10%));
242
+ }
243
+ .rsf-radio:checked::after {
244
+ content: "";
245
+ position: absolute;
246
+ top: 50%;
247
+ left: 50%;
248
+ transform: translate(-50%, -50%);
249
+ width: 0.375rem;
250
+ height: 0.375rem;
251
+ border-radius: 9999px;
252
+ background-color: var(--primary-foreground, hsl(0 0% 98%));
253
+ }
254
+ .rsf-radio:focus-visible {
255
+ box-shadow: 0 0 0 2px var(--background, hsl(0 0% 100%)), 0 0 0 4px var(--ring, hsl(240 10% 3.9%));
256
+ }
257
+ .rsf-radio:disabled {
258
+ cursor: not-allowed;
259
+ opacity: 0.5;
260
+ }
261
+ .rsf-radio-label {
262
+ font-size: 0.875rem;
263
+ font-weight: 500;
264
+ line-height: 1;
265
+ color: var(--foreground, hsl(240 10% 3.9%));
266
+ }
267
+ .rsf-checkbox-item {
268
+ display: flex;
269
+ align-items: flex-start;
270
+ gap: 0.625rem;
271
+ cursor: pointer;
272
+ user-select: none;
273
+ }
274
+ .rsf-checkbox-item:has(input:disabled) {
275
+ cursor: not-allowed;
276
+ opacity: 0.5;
277
+ }
278
+ .rsf-checkbox {
279
+ width: 1rem;
280
+ height: 1rem;
281
+ flex-shrink: 0;
282
+ border-radius: 0.2rem;
283
+ border: 1px solid var(--primary, hsl(240 5.9% 10%));
284
+ background-color: var(--background, hsl(0 0% 100%));
285
+ cursor: pointer;
286
+ transition:
287
+ border-color 150ms ease,
288
+ background-color 150ms ease,
289
+ box-shadow 150ms ease;
290
+ outline: none;
291
+ -webkit-appearance: none;
292
+ appearance: none;
293
+ position: relative;
294
+ margin-top: 0.0625rem;
295
+ }
296
+ .rsf-checkbox:checked {
297
+ background-color: var(--primary, hsl(240 5.9% 10%));
298
+ border-color: var(--primary, hsl(240 5.9% 10%));
299
+ }
300
+ .rsf-checkbox:checked::after {
301
+ content: "";
302
+ position: absolute;
303
+ top: 50%;
304
+ left: 50%;
305
+ transform: translate(-50%, -55%) rotate(45deg);
306
+ width: 0.3rem;
307
+ height: 0.55rem;
308
+ border: 2px solid var(--primary-foreground, hsl(0 0% 98%));
309
+ border-top: none;
310
+ border-left: none;
311
+ }
312
+ .rsf-checkbox:focus-visible {
313
+ box-shadow: 0 0 0 2px var(--background, hsl(0 0% 100%)), 0 0 0 4px var(--ring, hsl(240 10% 3.9%));
314
+ }
315
+ .rsf-checkbox:disabled {
316
+ cursor: not-allowed;
317
+ opacity: 0.5;
318
+ }
319
+ .rsf-checkbox-label {
320
+ font-size: 0.875rem;
321
+ font-weight: 500;
322
+ line-height: 1.25;
323
+ color: var(--foreground, hsl(240 10% 3.9%));
324
+ }
325
+ @media (prefers-color-scheme: dark) {
326
+ .rsf-wrapper {
327
+ color: var(--foreground, hsl(0 0% 98%));
328
+ background-color: var(--card, hsl(240 10% 3.9%));
329
+ border-color: var(--border, hsl(240 3.7% 15.9%));
330
+ }
331
+ .rsf-header {
332
+ border-bottom-color: var(--border, hsl(240 3.7% 15.9%));
333
+ }
334
+ .rsf-title {
335
+ color: var(--card-foreground, hsl(0 0% 98%));
336
+ }
337
+ .rsf-description,
338
+ .rsf-help {
339
+ color: var(--muted-foreground, hsl(240 5% 64.9%));
340
+ }
341
+ .rsf-label,
342
+ .rsf-radio-label,
343
+ .rsf-checkbox-label {
344
+ color: var(--foreground, hsl(0 0% 98%));
345
+ }
346
+ .rsf-input,
347
+ .rsf-textarea,
348
+ .rsf-select {
349
+ background-color: var(--background, hsl(240 10% 3.9%));
350
+ border-color: var(--input, hsl(240 3.7% 15.9%));
351
+ color: var(--foreground, hsl(0 0% 98%));
352
+ }
353
+ .rsf-input::placeholder,
354
+ .rsf-textarea::placeholder {
355
+ color: var(--muted-foreground, hsl(240 5% 64.9%));
356
+ }
357
+ .rsf-input:focus-visible,
358
+ .rsf-textarea:focus-visible,
359
+ .rsf-select:focus-visible,
360
+ .rsf-radio:focus-visible,
361
+ .rsf-checkbox:focus-visible {
362
+ box-shadow: 0 0 0 2px var(--background, hsl(240 10% 3.9%)), 0 0 0 4px var(--ring, hsl(240 4.9% 83.9%));
363
+ }
364
+ .rsf-input:disabled,
365
+ .rsf-textarea:disabled,
366
+ .rsf-select:disabled {
367
+ background-color: var(--muted, hsl(240 3.7% 15.9%));
368
+ }
369
+ .rsf-radio {
370
+ border-color: var(--primary, hsl(0 0% 98%));
371
+ background-color: var(--background, hsl(240 10% 3.9%));
372
+ }
373
+ .rsf-radio:checked {
374
+ background-color: var(--primary, hsl(0 0% 98%));
375
+ border-color: var(--primary, hsl(0 0% 98%));
376
+ }
377
+ .rsf-radio:checked::after {
378
+ background-color: var(--primary-foreground, hsl(240 5.9% 10%));
379
+ }
380
+ .rsf-checkbox {
381
+ border-color: var(--primary, hsl(0 0% 98%));
382
+ background-color: var(--background, hsl(240 10% 3.9%));
383
+ }
384
+ .rsf-checkbox:checked {
385
+ background-color: var(--primary, hsl(0 0% 98%));
386
+ border-color: var(--primary, hsl(0 0% 98%));
387
+ }
388
+ .rsf-checkbox:checked::after {
389
+ border-color: var(--primary-foreground, hsl(240 5.9% 10%));
390
+ }
391
+ .rsf-select {
392
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%23a1a1aa' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
393
+ }
394
+ }
395
+ .rsf-wrapper--minimal {
396
+ background-color: transparent;
397
+ border: none;
398
+ box-shadow: none;
399
+ padding: 0;
400
+ border-radius: 0;
401
+ }
402
+ .rsf-wrapper--minimal .rsf-header {
403
+ border-bottom: none;
404
+ padding-bottom: 0.75rem;
405
+ margin-bottom: 0.75rem;
406
+ }
407
+ .rsf-wrapper--filled {
408
+ background-color: var(--muted, hsl(240 4.8% 95.9%));
409
+ border-color: transparent;
410
+ }
411
+ .rsf-wrapper--filled .rsf-input,
412
+ .rsf-wrapper--filled .rsf-textarea,
413
+ .rsf-wrapper--filled .rsf-select {
414
+ background-color: var(--background, hsl(0 0% 100%));
415
+ border-color: transparent;
416
+ }
417
+ @media (prefers-color-scheme: dark) {
418
+ .rsf-wrapper--filled {
419
+ background-color: var(--muted, hsl(240 3.7% 15.9%));
420
+ }
421
+ .rsf-wrapper--filled .rsf-input,
422
+ .rsf-wrapper--filled .rsf-textarea,
423
+ .rsf-wrapper--filled .rsf-select {
424
+ background-color: var(--card, hsl(240 10% 3.9%));
425
+ }
426
+ }
427
+ .rsf-wrapper--underline {
428
+ background-color: transparent;
429
+ border: none;
430
+ box-shadow: none;
431
+ padding-left: 0;
432
+ padding-right: 0;
433
+ border-radius: 0;
434
+ max-width: 42rem;
435
+ }
436
+ .rsf-wrapper--underline .rsf-input,
437
+ .rsf-wrapper--underline .rsf-textarea,
438
+ .rsf-wrapper--underline .rsf-select {
439
+ border-radius: 0;
440
+ border: none;
441
+ border-bottom: 1px solid var(--input, hsl(240 5.9% 90%));
442
+ background-color: transparent;
443
+ padding-left: 0;
444
+ padding-right: 0;
445
+ }
446
+ .rsf-wrapper--underline .rsf-input:focus-visible,
447
+ .rsf-wrapper--underline .rsf-textarea:focus-visible,
448
+ .rsf-wrapper--underline .rsf-select:focus-visible {
449
+ box-shadow: none;
450
+ border-bottom-color: var(--ring, hsl(240 10% 3.9%));
451
+ }
452
+ .rsf-wrapper--underline .rsf-input--invalid,
453
+ .rsf-wrapper--underline .rsf-textarea--invalid,
454
+ .rsf-wrapper--underline .rsf-select--invalid {
455
+ border-bottom-color: var(--destructive, hsl(0 84.2% 60.2%));
456
+ }
457
+ @media (prefers-color-scheme: dark) {
458
+ .rsf-wrapper--underline .rsf-input,
459
+ .rsf-wrapper--underline .rsf-textarea,
460
+ .rsf-wrapper--underline .rsf-select {
461
+ border-bottom-color: var(--input, hsl(240 3.7% 15.9%));
462
+ }
463
+ .rsf-wrapper--underline .rsf-input:focus-visible,
464
+ .rsf-wrapper--underline .rsf-textarea:focus-visible,
465
+ .rsf-wrapper--underline .rsf-select:focus-visible {
466
+ border-bottom-color: var(--ring, hsl(240 4.9% 83.9%));
467
+ }
468
+ }
@@ -0,0 +1,2 @@
1
+
2
+ export { }
@@ -0,0 +1,2 @@
1
+
2
+ export { }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-smart-fields",
3
- "version": "2.1.0",
3
+ "version": "2.3.0",
4
4
  "description": "A flexible and highly customizable dynamic form builder for React with validation, conditional fields, theming, and headless rendering.",
5
5
  "license": "MIT",
6
6
  "author": "Pratik Panchal",
@@ -13,14 +13,15 @@
13
13
  "types": "./dist/index.d.ts",
14
14
  "import": "./dist/index.js",
15
15
  "require": "./dist/index.cjs"
16
- }
16
+ },
17
+ "./styles.css": "./dist/styles.css"
17
18
  },
18
19
  "files": [
19
20
  "dist"
20
21
  ],
21
- "sideEffects": false,
22
+ "sideEffects": ["*.css"],
22
23
  "scripts": {
23
- "build": "tsup src/index.ts --format esm,cjs --dts --clean",
24
+ "build": "tsup src/index.ts src/styles.css --format esm,cjs --dts --clean",
24
25
  "build:types": "tsc --emitDeclarationOnly"
25
26
  },
26
27
  "repository": {