@algodomain/smart-forms 0.1.9 → 0.1.11

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.cjs CHANGED
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
- var chunkDRMVY7TX_cjs = require('./chunk-DRMVY7TX.cjs');
4
- var chunkWUYS7DMR_cjs = require('./chunk-WUYS7DMR.cjs');
3
+ var chunkTX7JD2XS_cjs = require('./chunk-TX7JD2XS.cjs');
4
+ var chunkAEN4A4ST_cjs = require('./chunk-AEN4A4ST.cjs');
5
5
  var React3 = require('react');
6
6
  var reactToastify = require('react-toastify');
7
7
  var jsxRuntime = require('react/jsx-runtime');
@@ -79,7 +79,7 @@ var BaseSmartForm = ({
79
79
  onSuccess,
80
80
  onError,
81
81
  transformData,
82
- className = "max-w-2xl mx-auto p-6 bg-white",
82
+ className = "p-6 bg-white",
83
83
  title,
84
84
  subTitle,
85
85
  logo,
@@ -119,7 +119,7 @@ var BaseSmartForm = ({
119
119
  queryParamsToInclude,
120
120
  submitDisabled
121
121
  };
122
- return /* @__PURE__ */ jsxRuntime.jsx(chunkWUYS7DMR_cjs.SmartFormProvider, { config, initialData, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className, children: [
122
+ return /* @__PURE__ */ jsxRuntime.jsx(chunkAEN4A4ST_cjs.SmartFormProvider, { config, initialData, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className, children: [
123
123
  /* @__PURE__ */ jsxRuntime.jsx(ToastContainerWrapper, {}),
124
124
  /* @__PURE__ */ jsxRuntime.jsx(FormHeader, { title, subTitle, logo }),
125
125
  children,
@@ -127,15 +127,15 @@ var BaseSmartForm = ({
127
127
  ] }) });
128
128
  };
129
129
  var LoadingSpinner = ({ className = "h-4 w-4" }) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: `animate-spin rounded-full border-b-2 border-current ${className}` });
130
- var SubmitButton = ({ onClick, disabled, isLoading, children, className }) => /* @__PURE__ */ jsxRuntime.jsx(chunkDRMVY7TX_cjs.Button, { onClick, disabled, className, children: isLoading ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
130
+ var SubmitButton = ({ onClick, disabled, isLoading, children, className }) => /* @__PURE__ */ jsxRuntime.jsx(chunkTX7JD2XS_cjs.Button, { onClick, disabled, className, children: isLoading ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
131
131
  /* @__PURE__ */ jsxRuntime.jsx(LoadingSpinner, {}),
132
132
  "Submitting..."
133
133
  ] }) : children });
134
- var DraftSaveButton = ({ onClick, disabled }) => /* @__PURE__ */ jsxRuntime.jsx(chunkDRMVY7TX_cjs.Button, { onClick, disabled, variant: "secondary", children: disabled ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
134
+ var DraftSaveButton = ({ onClick, disabled }) => /* @__PURE__ */ jsxRuntime.jsx(chunkTX7JD2XS_cjs.Button, { onClick, disabled, variant: "secondary", children: disabled ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
135
135
  /* @__PURE__ */ jsxRuntime.jsx(LoadingSpinner, {}),
136
136
  "Saving..."
137
137
  ] }) : "Save Draft" });
138
- var ResetButton = ({ onClick }) => /* @__PURE__ */ jsxRuntime.jsx(chunkDRMVY7TX_cjs.Button, { onClick, variant: "secondary", children: "Reset Form" });
138
+ var ResetButton = ({ onClick }) => /* @__PURE__ */ jsxRuntime.jsx(chunkTX7JD2XS_cjs.Button, { onClick, variant: "secondary", children: "Reset Form" });
139
139
  var NavigationButtons = ({
140
140
  onPrevious,
141
141
  onNext,
@@ -149,7 +149,7 @@ var NavigationButtons = ({
149
149
  isLastTab = false,
150
150
  disabled = false
151
151
  }) => {
152
- const { formData, config: formConfig } = chunkWUYS7DMR_cjs.useSmartForm();
152
+ const { formData, config: formConfig } = chunkAEN4A4ST_cjs.useSmartForm();
153
153
  const isSubmitDisabled = typeof formConfig.submitDisabled === "function" ? formConfig.submitDisabled(formData) : formConfig.submitDisabled || false;
154
154
  const hasResetButton = !!onReset;
155
155
  const hasDraftButton = config.allowSaveDraft && !!onSaveDraft;
@@ -159,7 +159,7 @@ var NavigationButtons = ({
159
159
  const isSingleButton = rightSectionButtons === 1 && !hasPreviousButton;
160
160
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-between items-center mt-8 pt-6 border-t border-gray-200", children: [
161
161
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex gap-4", children: onPrevious && /* @__PURE__ */ jsxRuntime.jsxs(
162
- chunkDRMVY7TX_cjs.Button,
162
+ chunkTX7JD2XS_cjs.Button,
163
163
  {
164
164
  onClick: onPrevious,
165
165
  disabled: isFirstTab || disabled,
@@ -171,7 +171,7 @@ var NavigationButtons = ({
171
171
  }
172
172
  ) }),
173
173
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: isSingleButton ? "w-full" : "flex gap-4", children: [
174
- onReset && /* @__PURE__ */ jsxRuntime.jsx(chunkDRMVY7TX_cjs.Button, { onClick: onReset, disabled, variant: "secondary", children: "Reset Form" }),
174
+ onReset && /* @__PURE__ */ jsxRuntime.jsx(chunkTX7JD2XS_cjs.Button, { onClick: onReset, disabled, variant: "secondary", children: "Reset Form" }),
175
175
  config.allowSaveDraft && onSaveDraft && /* @__PURE__ */ jsxRuntime.jsx(DraftSaveButton, { onClick: onSaveDraft, disabled: isDraftSaving || disabled }),
176
176
  isLastTab ? /* @__PURE__ */ jsxRuntime.jsxs(
177
177
  SubmitButton,
@@ -186,7 +186,7 @@ var NavigationButtons = ({
186
186
  ]
187
187
  }
188
188
  ) : onNext && /* @__PURE__ */ jsxRuntime.jsxs(
189
- chunkDRMVY7TX_cjs.Button,
189
+ chunkTX7JD2XS_cjs.Button,
190
190
  {
191
191
  onClick: onNext,
192
192
  disabled,
@@ -208,7 +208,7 @@ var SimpleFormButtons = ({
208
208
  isDraftSaving,
209
209
  config
210
210
  }) => {
211
- const { formData, config: formConfig } = chunkWUYS7DMR_cjs.useSmartForm();
211
+ const { formData, config: formConfig } = chunkAEN4A4ST_cjs.useSmartForm();
212
212
  const isSubmitDisabled = typeof formConfig.submitDisabled === "function" ? formConfig.submitDisabled(formData) : formConfig.submitDisabled || false;
213
213
  const hasResetButton = !!onReset;
214
214
  const hasDraftButton = config.allowSaveDraft && !!onSaveDraft;
@@ -234,7 +234,7 @@ var SimpleFormButtons = ({
234
234
  ] }) });
235
235
  };
236
236
  var SubmitButton2 = () => {
237
- const { isLoading, isDraftSaving, submitForm, saveDraft, resetForm, config } = chunkWUYS7DMR_cjs.useSmartForm();
237
+ const { isLoading, isDraftSaving, submitForm, saveDraft, resetForm, config } = chunkAEN4A4ST_cjs.useSmartForm();
238
238
  const shouldShowReset = config.showReset || config.enableLocalStorage;
239
239
  return /* @__PURE__ */ jsxRuntime.jsx(
240
240
  SimpleFormButtons,
@@ -354,7 +354,7 @@ function MotionHighlight({ ref, ...props }) {
354
354
  {
355
355
  ref: localRef,
356
356
  "data-slot": "motion-highlight-container",
357
- className: chunkWUYS7DMR_cjs.cn("relative", props?.containerClassName),
357
+ className: chunkAEN4A4ST_cjs.cn("relative", props?.containerClassName),
358
358
  children: [
359
359
  /* @__PURE__ */ jsxRuntime.jsx(react.AnimatePresence, { initial: false, children: boundsState && /* @__PURE__ */ jsxRuntime.jsx(
360
360
  react.motion.div,
@@ -382,7 +382,7 @@ function MotionHighlight({ ref, ...props }) {
382
382
  }
383
383
  },
384
384
  transition,
385
- className: chunkWUYS7DMR_cjs.cn("bg-muted absolute z-0", className, activeClassNameState)
385
+ className: chunkAEN4A4ST_cjs.cn("bg-muted absolute z-0", className, activeClassNameState)
386
386
  }
387
387
  ) }),
388
388
  children2
@@ -510,16 +510,16 @@ function MotionHighlightItem({
510
510
  };
511
511
  const commonHandlers = hover ? {
512
512
  onMouseEnter: (e) => {
513
- setActiveValue(childValue);
513
+ if (!isDisabled) setActiveValue(childValue);
514
514
  element.props.onMouseEnter?.(e);
515
515
  },
516
516
  onMouseLeave: (e) => {
517
- setActiveValue(null);
517
+ if (!isDisabled) setActiveValue(null);
518
518
  element.props.onMouseLeave?.(e);
519
519
  }
520
520
  } : {
521
521
  onClick: (e) => {
522
- setActiveValue(childValue);
522
+ if (!isDisabled) setActiveValue(childValue);
523
523
  element.props.onClick?.(e);
524
524
  }
525
525
  };
@@ -530,7 +530,7 @@ function MotionHighlightItem({
530
530
  {
531
531
  key: childValue,
532
532
  ref: localRef,
533
- className: chunkWUYS7DMR_cjs.cn("relative", element.props.className),
533
+ className: chunkAEN4A4ST_cjs.cn("relative", element.props.className),
534
534
  ...getNonOverridingDataAttributes(element, {
535
535
  ...dataAttributes,
536
536
  "data-slot": "motion-highlight-item-container"
@@ -544,7 +544,7 @@ function MotionHighlightItem({
544
544
  {
545
545
  layoutId: `transition-background-${contextId}`,
546
546
  "data-slot": "motion-highlight",
547
- className: chunkWUYS7DMR_cjs.cn("bg-muted absolute inset-0 z-0", contextClassName, activeClassName),
547
+ className: chunkAEN4A4ST_cjs.cn("bg-muted absolute inset-0 z-0", contextClassName, activeClassName),
548
548
  transition: itemTransition,
549
549
  initial: { opacity: 0 },
550
550
  animate: { opacity: 1 },
@@ -558,7 +558,7 @@ function MotionHighlightItem({
558
558
  ...dataAttributes
559
559
  }
560
560
  ) }),
561
- /* @__PURE__ */ jsxRuntime.jsx("div", { "data-slot": "motion-highlight-item", className: chunkWUYS7DMR_cjs.cn("relative z-[1]", className), ...dataAttributes, children })
561
+ /* @__PURE__ */ jsxRuntime.jsx("div", { "data-slot": "motion-highlight-item", className: chunkAEN4A4ST_cjs.cn("relative z-[1]", className), ...dataAttributes, children })
562
562
  ] })
563
563
  );
564
564
  }
@@ -576,7 +576,7 @@ function MotionHighlightItem({
576
576
  {
577
577
  ref: localRef,
578
578
  "data-slot": "motion-highlight-item-container",
579
- className: chunkWUYS7DMR_cjs.cn(mode === "children" && "relative", className),
579
+ className: chunkAEN4A4ST_cjs.cn(mode === "children" && "relative", className),
580
580
  ...dataAttributes,
581
581
  ...props,
582
582
  ...commonHandlers,
@@ -586,7 +586,7 @@ function MotionHighlightItem({
586
586
  {
587
587
  layoutId: `transition-background-${contextId}`,
588
588
  "data-slot": "motion-highlight",
589
- className: chunkWUYS7DMR_cjs.cn("bg-muted absolute inset-0 z-0", contextClassName, activeClassName),
589
+ className: chunkAEN4A4ST_cjs.cn("bg-muted absolute inset-0 z-0", contextClassName, activeClassName),
590
590
  transition: itemTransition,
591
591
  initial: { opacity: 0 },
592
592
  animate: { opacity: 1 },
@@ -601,7 +601,7 @@ function MotionHighlightItem({
601
601
  }
602
602
  ) }),
603
603
  React3__namespace.cloneElement(element, {
604
- className: chunkWUYS7DMR_cjs.cn("relative z-[1]", element.props.className),
604
+ className: chunkAEN4A4ST_cjs.cn("relative z-[1]", element.props.className),
605
605
  ...getNonOverridingDataAttributes(element, {
606
606
  ...dataAttributes,
607
607
  "data-slot": "motion-highlight-item"
@@ -668,7 +668,7 @@ function Tabs({
668
668
  handleValueChange,
669
669
  registerTrigger
670
670
  },
671
- children: /* @__PURE__ */ jsxRuntime.jsx("div", { "data-slot": "tabs", className: chunkWUYS7DMR_cjs.cn("flex flex-col gap-2", className), ...props, children: props.children })
671
+ children: /* @__PURE__ */ jsxRuntime.jsx("div", { "data-slot": "tabs", className: chunkAEN4A4ST_cjs.cn("flex flex-col gap-2", className), ...props, children: props.children })
672
672
  }
673
673
  ) });
674
674
  }
@@ -676,7 +676,7 @@ function Tabs({
676
676
  TabsPrimitive__namespace.Root,
677
677
  {
678
678
  "data-slot": "tabs",
679
- className: chunkWUYS7DMR_cjs.cn("flex flex-col gap-2", className),
679
+ className: chunkAEN4A4ST_cjs.cn("flex flex-col gap-2", className),
680
680
  ...props
681
681
  }
682
682
  ) });
@@ -698,7 +698,7 @@ function TabsList({
698
698
  MotionHighlight,
699
699
  {
700
700
  controlledItems: true,
701
- className: chunkWUYS7DMR_cjs.cn("bg-background rounded-sm shadow-sm", activeClassName),
701
+ className: chunkAEN4A4ST_cjs.cn("bg-background rounded-sm shadow-sm", activeClassName),
702
702
  value: activeValue,
703
703
  transition,
704
704
  children: /* @__PURE__ */ jsxRuntime.jsx(
@@ -706,7 +706,7 @@ function TabsList({
706
706
  {
707
707
  role: "tablist",
708
708
  "data-slot": "tabs-list",
709
- className: chunkWUYS7DMR_cjs.cn(
709
+ className: chunkAEN4A4ST_cjs.cn(
710
710
  "bg-muted text-muted-foreground inline-flex h-9 w-fit items-center justify-center rounded-lg p-[3px]",
711
711
  className
712
712
  ),
@@ -730,7 +730,7 @@ function TabsList({
730
730
  TabsPrimitive__namespace.List,
731
731
  {
732
732
  "data-slot": "tabs-list",
733
- className: chunkWUYS7DMR_cjs.cn(
733
+ className: chunkAEN4A4ST_cjs.cn(
734
734
  "bg-muted text-muted-foreground inline-flex h-9 w-fit items-center justify-center rounded-lg p-[3px]",
735
735
  className
736
736
  ),
@@ -816,7 +816,7 @@ function UnderlineTabsList({
816
816
  TabsPrimitive__namespace.List,
817
817
  {
818
818
  "data-slot": "tabs-list",
819
- className: chunkWUYS7DMR_cjs.cn(
819
+ className: chunkAEN4A4ST_cjs.cn(
820
820
  "bg-background relative rounded-none border-b p-0",
821
821
  className
822
822
  ),
@@ -879,17 +879,19 @@ function TabsTrigger({
879
879
  onAnimationEnd,
880
880
  onAnimationIteration,
881
881
  onTransitionEnd,
882
+ disabled,
882
883
  ...motionButtonProps
883
884
  } = props;
884
- return /* @__PURE__ */ jsxRuntime.jsx(MotionHighlightItem, { value: props.value, className: "size-full", children: /* @__PURE__ */ jsxRuntime.jsx(
885
+ return /* @__PURE__ */ jsxRuntime.jsx(MotionHighlightItem, { value: props.value, className: "size-full", disabled, children: /* @__PURE__ */ jsxRuntime.jsx(
885
886
  react.motion.button,
886
887
  {
887
888
  ref: localRef,
888
889
  "data-slot": "tabs-trigger",
889
890
  role: "tab",
890
- onClick: () => handleValueChange(props.value),
891
+ onClick: () => !disabled && handleValueChange(props.value),
891
892
  "data-state": activeValue === props.value ? "active" : "inactive",
892
- className: chunkWUYS7DMR_cjs.cn(
893
+ disabled,
894
+ className: chunkAEN4A4ST_cjs.cn(
893
895
  "ring-offset-background focus-visible:ring-ring data-[state=active]:text-foreground z-10 inline-flex size-full cursor-pointer items-center justify-center rounded-sm px-2 py-1 text-sm font-medium whitespace-nowrap transition-transform focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-none disabled:pointer-events-none disabled:opacity-50",
894
896
  className
895
897
  ),
@@ -922,7 +924,7 @@ function TabsTrigger({
922
924
  {
923
925
  ref: localRef,
924
926
  "data-slot": "tabs-trigger",
925
- className: chunkWUYS7DMR_cjs.cn(
927
+ className: chunkAEN4A4ST_cjs.cn(
926
928
  "bg-background dark:data-[state=active]:bg-background relative z-10 pl-10 pr-10 rounded-none border-0 data-[state=active]:shadow-none cursor-pointer",
927
929
  className
928
930
  ),
@@ -934,7 +936,7 @@ function TabsTrigger({
934
936
  TabsPrimitive__namespace.Trigger,
935
937
  {
936
938
  "data-slot": "tabs-trigger",
937
- className: chunkWUYS7DMR_cjs.cn(
939
+ className: chunkAEN4A4ST_cjs.cn(
938
940
  "data-[state=active]:bg-background dark:data-[state=active]:text-foreground focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:outline-ring dark:data-[state=active]:border-input dark:data-[state=active]:bg-input/30 text-foreground dark:text-muted-foreground inline-flex h-[calc(100%-1px)] flex-1 items-center justify-center gap-1.5 rounded-md border border-transparent px-2 py-1 text-sm font-medium whitespace-nowrap transition-[color,box-shadow] focus-visible:ring-[3px] focus-visible:outline-1 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:shadow-sm [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
939
941
  className
940
942
  ),
@@ -981,7 +983,7 @@ function TabsContent({
981
983
  {
982
984
  role: "tabpanel",
983
985
  "data-slot": "tabs-content",
984
- className: chunkWUYS7DMR_cjs.cn("overflow-hidden", className),
986
+ className: chunkAEN4A4ST_cjs.cn("overflow-hidden", className),
985
987
  initial: { filter: "blur(0px)" },
986
988
  animate: { filter: isActive ? "blur(0px)" : "blur(2px)" },
987
989
  exit: { filter: "blur(0px)" },
@@ -1003,7 +1005,7 @@ function TabsContent({
1003
1005
  TabsPrimitive__namespace.Content,
1004
1006
  {
1005
1007
  "data-slot": "tabs-content",
1006
- className: chunkWUYS7DMR_cjs.cn("flex-1 outline-none", className),
1008
+ className: chunkAEN4A4ST_cjs.cn("flex-1 outline-none", className),
1007
1009
  ...props
1008
1010
  }
1009
1011
  );
@@ -1083,6 +1085,7 @@ var MultiTabSmartForm = ({
1083
1085
  const [externalTabFields, setExternalTabFields] = React3.useState({});
1084
1086
  const [processingTab, setProcessingTab] = React3.useState(null);
1085
1087
  const [processingError, setProcessingError] = React3.useState(null);
1088
+ const [maxUnlockedTab, setMaxUnlockedTab] = React3.useState(0);
1086
1089
  const { footerChildren, regularChildren } = React3.useMemo(() => {
1087
1090
  const childArray = React3__namespace.default.Children.toArray(children);
1088
1091
  const footerChildren2 = [];
@@ -1199,6 +1202,8 @@ var MultiTabSmartForm = ({
1199
1202
  processingError,
1200
1203
  setProcessingError,
1201
1204
  disableManualTabSwitch,
1205
+ maxUnlockedTab,
1206
+ setMaxUnlockedTab,
1202
1207
  children: regularChildren
1203
1208
  }
1204
1209
  ) }) });
@@ -1224,9 +1229,11 @@ var MultiTabFormContent = ({
1224
1229
  setProcessingTab,
1225
1230
  processingError,
1226
1231
  setProcessingError,
1227
- disableManualTabSwitch = false
1232
+ disableManualTabSwitch = false,
1233
+ maxUnlockedTab,
1234
+ setMaxUnlockedTab
1228
1235
  }) => {
1229
- const { isLoading, isDraftSaving, submitForm, saveDraft, resetForm, validateFields, formData, validationRegistry, setErrors } = chunkWUYS7DMR_cjs.useSmartForm();
1236
+ const { isLoading, isDraftSaving, submitForm, saveDraft, resetForm, validateFields, formData, validationRegistry, setErrors, getValidationErrorMessage } = chunkAEN4A4ST_cjs.useSmartForm();
1230
1237
  const debounce = (func, wait) => {
1231
1238
  let timeout;
1232
1239
  return function executedFunction(...args) {
@@ -1288,11 +1295,11 @@ var MultiTabFormContent = ({
1288
1295
  checkTabCompletion();
1289
1296
  }, [formData, validationRegistry, getCombinedTabFields, tabs, setCompletedTabs, setValidationErrorTabs]);
1290
1297
  const handleTabChangeWithErrorCheck = React3.useCallback((index) => {
1291
- if (disableManualTabSwitch && index > activeTab) {
1298
+ if (disableManualTabSwitch && index > maxUnlockedTab) {
1292
1299
  return;
1293
1300
  }
1294
1301
  onTabChange(index);
1295
- }, [onTabChange, disableManualTabSwitch, activeTab]);
1302
+ }, [onTabChange, disableManualTabSwitch, maxUnlockedTab]);
1296
1303
  const handleNextWithValidation = React3.useCallback(async () => {
1297
1304
  const currentTabFields = getCombinedTabFields(activeTab);
1298
1305
  if (currentTabFields.length > 0) {
@@ -1305,7 +1312,8 @@ var MultiTabFormContent = ({
1305
1312
  validation.parse(formData[field]);
1306
1313
  } catch (error) {
1307
1314
  if (error instanceof zod.z.ZodError) {
1308
- allErrors[field] = error.issues[0]?.message || `Invalid ${field}`;
1315
+ const msg = error.issues[0]?.message ?? "";
1316
+ allErrors[field] = getValidationErrorMessage(field, msg);
1309
1317
  isValid = false;
1310
1318
  }
1311
1319
  }
@@ -1329,6 +1337,7 @@ var MultiTabFormContent = ({
1329
1337
  }
1330
1338
  setProcessingTab(null);
1331
1339
  setProcessingError(null);
1340
+ setMaxUnlockedTab((prev) => Math.max(prev, activeTab + 1));
1332
1341
  onNext();
1333
1342
  } catch (error) {
1334
1343
  setProcessingTab(null);
@@ -1336,6 +1345,7 @@ var MultiTabFormContent = ({
1336
1345
  setProcessingError(errorMessage);
1337
1346
  }
1338
1347
  } else {
1348
+ setMaxUnlockedTab((prev) => Math.max(prev, activeTab + 1));
1339
1349
  onNext();
1340
1350
  }
1341
1351
  } else {
@@ -1369,6 +1379,7 @@ var MultiTabFormContent = ({
1369
1379
  }
1370
1380
  setProcessingTab(null);
1371
1381
  setProcessingError(null);
1382
+ setMaxUnlockedTab((prev) => Math.max(prev, activeTab + 1));
1372
1383
  onNext();
1373
1384
  } catch (error) {
1374
1385
  setProcessingTab(null);
@@ -1376,10 +1387,11 @@ var MultiTabFormContent = ({
1376
1387
  setProcessingError(errorMessage);
1377
1388
  }
1378
1389
  } else {
1390
+ setMaxUnlockedTab((prev) => Math.max(prev, activeTab + 1));
1379
1391
  onNext();
1380
1392
  }
1381
1393
  }
1382
- }, [activeTab, getCombinedTabFields, validateFields, onNext, setCompletedTabs, setValidationErrorTabs, validationRegistry, formData, tabCallbacks, setProcessingTab, setProcessingError]);
1394
+ }, [activeTab, getCombinedTabFields, validateFields, onNext, setCompletedTabs, setValidationErrorTabs, validationRegistry, formData, tabCallbacks, setProcessingTab, setProcessingError, setMaxUnlockedTab, getValidationErrorMessage]);
1383
1395
  const handleSubmitWithValidation = React3.useCallback(async () => {
1384
1396
  const allErrors = {};
1385
1397
  let isValid = true;
@@ -1390,7 +1402,8 @@ var MultiTabFormContent = ({
1390
1402
  validation.parse(formData[field]);
1391
1403
  } catch (error) {
1392
1404
  if (error instanceof zod.z.ZodError) {
1393
- allErrors[field] = error.issues[0]?.message || `Invalid ${field}`;
1405
+ const msg = error.issues[0]?.message ?? "";
1406
+ allErrors[field] = getValidationErrorMessage(field, msg);
1394
1407
  isValid = false;
1395
1408
  }
1396
1409
  }
@@ -1426,7 +1439,7 @@ var MultiTabFormContent = ({
1426
1439
  }, 100);
1427
1440
  }
1428
1441
  }
1429
- }, [submitForm, getCombinedTabFields, onTabChange, tabs.length, validationRegistry, formData, setErrors, setValidationErrorTabs]);
1442
+ }, [submitForm, getCombinedTabFields, onTabChange, tabs.length, validationRegistry, formData, setErrors, setValidationErrorTabs, getValidationErrorMessage]);
1430
1443
  const activeTabValue = tabs[activeTab] || tabs[0] || "";
1431
1444
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1432
1445
  /* @__PURE__ */ jsxRuntime.jsxs(
@@ -1443,8 +1456,8 @@ var MultiTabFormContent = ({
1443
1456
  animate: animateTabs,
1444
1457
  type: tabType,
1445
1458
  children: [
1446
- /* @__PURE__ */ jsxRuntime.jsx(TabsList, { className: `grid w-full mb-8`, style: { gridTemplateColumns: `repeat(${tabs.length}, 1fr)` }, children: tabs.map((tab, index) => {
1447
- const isFutureTab = disableManualTabSwitch && index > activeTab;
1459
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full mb-8", children: /* @__PURE__ */ jsxRuntime.jsx(TabsList, { className: `grid w-full`, style: { gridTemplateColumns: `repeat(${tabs.length}, 1fr)` }, children: tabs.map((tab, index) => {
1460
+ const isFutureTab = disableManualTabSwitch && index > maxUnlockedTab;
1448
1461
  return /* @__PURE__ */ jsxRuntime.jsxs(
1449
1462
  TabsTrigger,
1450
1463
  {
@@ -1463,7 +1476,7 @@ var MultiTabFormContent = ({
1463
1476
  },
1464
1477
  tab
1465
1478
  );
1466
- }) }),
1479
+ }) }) }),
1467
1480
  React3__namespace.default.Children.map(children, (child, index) => {
1468
1481
  if (React3__namespace.default.isValidElement(child) && child.type === Tab) {
1469
1482
  const tabProps = child.props;
@@ -1471,14 +1484,7 @@ var MultiTabFormContent = ({
1471
1484
  const hasProcessingOverlay = tabCallbacks[index]?.processingOverlay;
1472
1485
  return /* @__PURE__ */ jsxRuntime.jsx(TabsContent, { value: tabProps.title, children: /* @__PURE__ */ jsxRuntime.jsx(TabIndexProvider, { tabIndex: index, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-6 relative", children: [
1473
1486
  tabProps.children,
1474
- isCurrentlyProcessing && hasProcessingOverlay && /* @__PURE__ */ jsxRuntime.jsx(
1475
- "div",
1476
- {
1477
- className: "absolute inset-0 bg-white/80 backdrop-blur-sm z-50 flex items-center justify-center pointer-events-none",
1478
- style: { minHeight: "200px" },
1479
- children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pointer-events-auto", children: tabCallbacks[index].processingOverlay })
1480
- }
1481
- )
1487
+ isCurrentlyProcessing && hasProcessingOverlay && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "fixed inset-0 bg-black/70 z-50 flex items-center justify-center pointer-events-none", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pointer-events-auto", children: tabCallbacks[index].processingOverlay }) })
1482
1488
  ] }) }) }, index);
1483
1489
  }
1484
1490
  return null;
@@ -1532,7 +1538,7 @@ var MultiTabFormContent = ({
1532
1538
 
1533
1539
  // src/hooks/useFormWrapper.ts
1534
1540
  var useFormWrapper = () => {
1535
- return chunkWUYS7DMR_cjs.useSmartForm();
1541
+ return chunkAEN4A4ST_cjs.useSmartForm();
1536
1542
  };
1537
1543
  var useExternalFormRegistration = () => {
1538
1544
  const context = React3.useContext(ExternalFormContext);
@@ -1554,7 +1560,7 @@ var ExternalFieldProvider = ({
1554
1560
  children,
1555
1561
  registerField
1556
1562
  }) => {
1557
- return /* @__PURE__ */ jsxRuntime.jsx(chunkWUYS7DMR_cjs.FieldDetectionContext.Provider, { value: { registerField }, children });
1563
+ return /* @__PURE__ */ jsxRuntime.jsx(chunkAEN4A4ST_cjs.FieldDetectionContext.Provider, { value: { registerField }, children });
1558
1564
  };
1559
1565
 
1560
1566
  // src/useAutoDetectFields.tsx
@@ -1648,20 +1654,33 @@ var SmartTextArea = ({
1648
1654
  dirName,
1649
1655
  form
1650
1656
  }) => {
1651
- const { formData } = chunkWUYS7DMR_cjs.useSmartForm();
1652
- const { value, error, onChange, fieldRef, registerValidation } = chunkWUYS7DMR_cjs.useFormField(field);
1653
- const fieldDetection = chunkWUYS7DMR_cjs.useFieldDetection();
1657
+ const { formData } = chunkAEN4A4ST_cjs.useSmartForm();
1658
+ const { value, error, onChange, fieldRef, registerValidation } = chunkAEN4A4ST_cjs.useFormField(field);
1659
+ const fieldDetection = chunkAEN4A4ST_cjs.useFieldDetection();
1654
1660
  const hasRegistered = React3.useRef(false);
1655
1661
  const hasSetDefault = React3.useRef(false);
1656
1662
  const isDisabled = typeof disabled === "function" ? disabled(formData) : disabled || false;
1657
1663
  const isHidden = typeof hidden === "function" ? hidden(formData) : hidden || false;
1658
1664
  if (isHidden) return null;
1665
+ const displayName = label || field;
1666
+ const builtinValidation = React3.useMemo(() => {
1667
+ if (validation) return void 0;
1668
+ const preprocess = (v) => v === void 0 || v === null ? "" : v;
1669
+ if (minLength != null) {
1670
+ return zod.z.preprocess(preprocess, zod.z.string().min(minLength, `${displayName} must be at least ${minLength} characters`));
1671
+ }
1672
+ if (required) {
1673
+ return zod.z.preprocess(preprocess, zod.z.string().min(1, `${displayName} is required`));
1674
+ }
1675
+ return void 0;
1676
+ }, [validation, minLength, required, displayName]);
1677
+ const schemaToRegister = validation ?? builtinValidation;
1659
1678
  React3.useEffect(() => {
1660
- if (validation && !hasRegistered.current) {
1679
+ if (schemaToRegister && !hasRegistered.current) {
1661
1680
  hasRegistered.current = true;
1662
- registerValidation(field, validation);
1681
+ registerValidation(field, schemaToRegister, { label: displayName });
1663
1682
  }
1664
- }, [validation, field, registerValidation]);
1683
+ }, [schemaToRegister, field, registerValidation, displayName]);
1665
1684
  React3.useEffect(() => {
1666
1685
  if (fieldDetection?.registerField) {
1667
1686
  fieldDetection.registerField(field);
@@ -1698,21 +1717,21 @@ var SmartTextArea = ({
1698
1717
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `flex-1 min-w-0 ${className}`, children: [
1699
1718
  label && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mb-1", children: [
1700
1719
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between gap-2", children: [
1701
- /* @__PURE__ */ jsxRuntime.jsxs(chunkWUYS7DMR_cjs.Label, { className: "text-sm font-medium text-foreground", children: [
1720
+ /* @__PURE__ */ jsxRuntime.jsxs(chunkAEN4A4ST_cjs.Label, { className: "text-sm font-medium text-foreground", children: [
1702
1721
  label,
1703
1722
  " ",
1704
1723
  required && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-destructive", children: "*" })
1705
1724
  ] }),
1706
- info && /* @__PURE__ */ jsxRuntime.jsx(chunkWUYS7DMR_cjs.TooltipProvider, { children: /* @__PURE__ */ jsxRuntime.jsxs(chunkWUYS7DMR_cjs.Tooltip, { children: [
1707
- /* @__PURE__ */ jsxRuntime.jsx(chunkWUYS7DMR_cjs.TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.InfoIcon, { className: "h-4 w-4 text-muted-foreground cursor-pointer" }) }),
1708
- /* @__PURE__ */ jsxRuntime.jsx(chunkWUYS7DMR_cjs.TooltipContent, { children: /* @__PURE__ */ jsxRuntime.jsx("p", { className: "max-w-xs", children: info }) })
1725
+ info && /* @__PURE__ */ jsxRuntime.jsx(chunkAEN4A4ST_cjs.TooltipProvider, { children: /* @__PURE__ */ jsxRuntime.jsxs(chunkAEN4A4ST_cjs.Tooltip, { children: [
1726
+ /* @__PURE__ */ jsxRuntime.jsx(chunkAEN4A4ST_cjs.TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.InfoIcon, { className: "h-4 w-4 text-muted-foreground cursor-pointer" }) }),
1727
+ /* @__PURE__ */ jsxRuntime.jsx(chunkAEN4A4ST_cjs.TooltipContent, { children: /* @__PURE__ */ jsxRuntime.jsx("p", { className: "max-w-xs", children: info }) })
1709
1728
  ] }) })
1710
1729
  ] }),
1711
1730
  subLabel && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground mt-1", children: subLabel })
1712
1731
  ] }),
1713
1732
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", children: [
1714
1733
  /* @__PURE__ */ jsxRuntime.jsx(
1715
- chunkWUYS7DMR_cjs.Textarea,
1734
+ chunkAEN4A4ST_cjs.Textarea,
1716
1735
  {
1717
1736
  ref: fieldRef,
1718
1737
  value: value || "",
@@ -1749,47 +1768,47 @@ var SmartTextArea = ({
1749
1768
 
1750
1769
  Object.defineProperty(exports, "SmartCheckbox", {
1751
1770
  enumerable: true,
1752
- get: function () { return chunkDRMVY7TX_cjs.SmartCheckbox; }
1771
+ get: function () { return chunkTX7JD2XS_cjs.SmartCheckbox; }
1753
1772
  });
1754
1773
  Object.defineProperty(exports, "SmartCombobox", {
1755
1774
  enumerable: true,
1756
- get: function () { return chunkDRMVY7TX_cjs.SmartCombobox; }
1775
+ get: function () { return chunkTX7JD2XS_cjs.SmartCombobox; }
1757
1776
  });
1758
1777
  Object.defineProperty(exports, "SmartDatePicker", {
1759
1778
  enumerable: true,
1760
- get: function () { return chunkDRMVY7TX_cjs.SmartDatePicker; }
1779
+ get: function () { return chunkTX7JD2XS_cjs.SmartDatePicker; }
1761
1780
  });
1762
1781
  Object.defineProperty(exports, "SmartRadioGroup", {
1763
1782
  enumerable: true,
1764
- get: function () { return chunkDRMVY7TX_cjs.SmartRadioGroup; }
1783
+ get: function () { return chunkTX7JD2XS_cjs.SmartRadioGroup; }
1765
1784
  });
1766
1785
  Object.defineProperty(exports, "SmartSelect", {
1767
1786
  enumerable: true,
1768
- get: function () { return chunkDRMVY7TX_cjs.SmartSelect; }
1787
+ get: function () { return chunkTX7JD2XS_cjs.SmartSelect; }
1769
1788
  });
1770
1789
  Object.defineProperty(exports, "SmartTags", {
1771
1790
  enumerable: true,
1772
- get: function () { return chunkDRMVY7TX_cjs.SmartTags; }
1791
+ get: function () { return chunkTX7JD2XS_cjs.SmartTags; }
1773
1792
  });
1774
1793
  Object.defineProperty(exports, "SmartFormProvider", {
1775
1794
  enumerable: true,
1776
- get: function () { return chunkWUYS7DMR_cjs.SmartFormProvider; }
1795
+ get: function () { return chunkAEN4A4ST_cjs.SmartFormProvider; }
1777
1796
  });
1778
1797
  Object.defineProperty(exports, "SmartInput", {
1779
1798
  enumerable: true,
1780
- get: function () { return chunkWUYS7DMR_cjs.SmartInput; }
1799
+ get: function () { return chunkAEN4A4ST_cjs.SmartInput; }
1781
1800
  });
1782
1801
  Object.defineProperty(exports, "useFieldDetection", {
1783
1802
  enumerable: true,
1784
- get: function () { return chunkWUYS7DMR_cjs.useFieldDetection; }
1803
+ get: function () { return chunkAEN4A4ST_cjs.useFieldDetection; }
1785
1804
  });
1786
1805
  Object.defineProperty(exports, "useFormField", {
1787
1806
  enumerable: true,
1788
- get: function () { return chunkWUYS7DMR_cjs.useFormField; }
1807
+ get: function () { return chunkAEN4A4ST_cjs.useFormField; }
1789
1808
  });
1790
1809
  Object.defineProperty(exports, "useSmartForm", {
1791
1810
  enumerable: true,
1792
- get: function () { return chunkWUYS7DMR_cjs.useSmartForm; }
1811
+ get: function () { return chunkAEN4A4ST_cjs.useSmartForm; }
1793
1812
  });
1794
1813
  exports.BaseSmartForm = BaseSmartForm;
1795
1814
  exports.DraftSaveButton = DraftSaveButton;