@algodomain/smart-forms 0.1.7 → 0.1.9

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.js CHANGED
@@ -1,13 +1,15 @@
1
- import { Button } from './chunk-UFRJXDAI.js';
2
- export { SmartCheckbox, SmartCombobox, SmartDatePicker, SmartRadioGroup, SmartSelect, SmartTags } from './chunk-UFRJXDAI.js';
3
- import { SmartFormProvider, useSmartForm, FieldDetectionContext, cn } from './chunk-RHECLW3K.js';
4
- export { SmartFormProvider, SmartInput, useFieldDetection, useFormField, useSmartForm } from './chunk-RHECLW3K.js';
5
- import React3, { createContext, isValidElement, useContext, useState, useMemo, useCallback, useRef, useEffect } from 'react';
1
+ import { Button } from './chunk-4XK6HAJ2.js';
2
+ export { SmartCheckbox, SmartCombobox, SmartDatePicker, SmartRadioGroup, SmartSelect, SmartTags } from './chunk-4XK6HAJ2.js';
3
+ import { SmartFormProvider, useSmartForm, FieldDetectionContext, useFormField, useFieldDetection, Label, TooltipProvider, Tooltip, TooltipTrigger, TooltipContent, Textarea, cn } from './chunk-6VKQ7EMR.js';
4
+ export { SmartFormProvider, SmartInput, useFieldDetection, useFormField, useSmartForm } from './chunk-6VKQ7EMR.js';
5
+ import * as React3 from 'react';
6
+ import React3__default, { createContext, isValidElement, useContext, useState, useMemo, useCallback, useEffect, useRef } from 'react';
6
7
  import { ToastContainer, Bounce } from 'react-toastify';
7
8
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
8
- import { ChevronLeft, ChevronRight, Check, X } from 'lucide-react';
9
+ import { ChevronLeft, ChevronRight, Check, X, InfoIcon } from 'lucide-react';
9
10
  import { z } from 'zod';
10
11
  import * as TabsPrimitive from '@radix-ui/react-tabs';
12
+ import { motion, AnimatePresence } from 'motion/react';
11
13
 
12
14
  var ToastContainerWrapper = () => /* @__PURE__ */ jsx(
13
15
  ToastContainer,
@@ -124,7 +126,8 @@ var NavigationButtons = ({
124
126
  isDraftSaving,
125
127
  config,
126
128
  isFirstTab = false,
127
- isLastTab = false
129
+ isLastTab = false,
130
+ disabled = false
128
131
  }) => {
129
132
  const { formData, config: formConfig } = useSmartForm();
130
133
  const isSubmitDisabled = typeof formConfig.submitDisabled === "function" ? formConfig.submitDisabled(formData) : formConfig.submitDisabled || false;
@@ -139,7 +142,7 @@ var NavigationButtons = ({
139
142
  Button,
140
143
  {
141
144
  onClick: onPrevious,
142
- disabled: isFirstTab,
145
+ disabled: isFirstTab || disabled,
143
146
  variant: "secondary",
144
147
  children: [
145
148
  /* @__PURE__ */ jsx(ChevronLeft, { className: "h-4 w-4" }),
@@ -148,13 +151,13 @@ var NavigationButtons = ({
148
151
  }
149
152
  ) }),
150
153
  /* @__PURE__ */ jsxs("div", { className: isSingleButton ? "w-full" : "flex gap-4", children: [
151
- onReset && /* @__PURE__ */ jsx(ResetButton, { onClick: onReset }),
152
- config.allowSaveDraft && onSaveDraft && /* @__PURE__ */ jsx(DraftSaveButton, { onClick: onSaveDraft, disabled: isDraftSaving }),
154
+ onReset && /* @__PURE__ */ jsx(Button, { onClick: onReset, disabled, variant: "secondary", children: "Reset Form" }),
155
+ config.allowSaveDraft && onSaveDraft && /* @__PURE__ */ jsx(DraftSaveButton, { onClick: onSaveDraft, disabled: isDraftSaving || disabled }),
153
156
  isLastTab ? /* @__PURE__ */ jsxs(
154
157
  SubmitButton,
155
158
  {
156
159
  onClick: onSubmit,
157
- disabled: isLoading || isSubmitDisabled,
160
+ disabled: isLoading || isSubmitDisabled || disabled,
158
161
  isLoading,
159
162
  className: isSingleButton ? "w-full" : "",
160
163
  children: [
@@ -166,6 +169,7 @@ var NavigationButtons = ({
166
169
  Button,
167
170
  {
168
171
  onClick: onNext,
172
+ disabled,
169
173
  className: isSingleButton ? "w-full" : "",
170
174
  children: [
171
175
  "Next",
@@ -226,7 +230,7 @@ var SubmitButton2 = () => {
226
230
  };
227
231
  var SmartForm = (props) => {
228
232
  const { children, ...otherProps } = props;
229
- const childArray = React3.Children.toArray(children);
233
+ const childArray = React3__default.Children.toArray(children);
230
234
  const footerChildren = [];
231
235
  const regularChildren = [];
232
236
  childArray.forEach((child) => {
@@ -242,23 +246,466 @@ var SmartForm = (props) => {
242
246
  footerChildren.length > 0 && /* @__PURE__ */ jsx("div", { className: "space-y-4", children: footerChildren })
243
247
  ] });
244
248
  };
249
+ var MotionHighlightContext = React3.createContext(void 0);
250
+ function useMotionHighlight() {
251
+ const context = React3.useContext(MotionHighlightContext);
252
+ if (!context) {
253
+ throw new Error("useMotionHighlight must be used within a MotionHighlightProvider");
254
+ }
255
+ return context;
256
+ }
257
+ function MotionHighlight({ ref, ...props }) {
258
+ const {
259
+ children,
260
+ value,
261
+ defaultValue,
262
+ onValueChange,
263
+ className,
264
+ transition = { type: "spring", stiffness: 350, damping: 35 },
265
+ hover = false,
266
+ enabled = true,
267
+ controlledItems,
268
+ disabled = false,
269
+ exitDelay = 0.2,
270
+ mode = "children"
271
+ } = props;
272
+ const localRef = React3.useRef(null);
273
+ React3.useImperativeHandle(ref, () => localRef.current);
274
+ const [activeValue, setActiveValue] = React3.useState(value ?? defaultValue ?? null);
275
+ const [boundsState, setBoundsState] = React3.useState(null);
276
+ const [activeClassNameState, setActiveClassNameState] = React3.useState("");
277
+ const safeSetActiveValue = React3.useCallback(
278
+ (id2) => {
279
+ setActiveValue((prev) => prev === id2 ? prev : id2);
280
+ if (id2 !== activeValue) onValueChange?.(id2);
281
+ },
282
+ [activeValue, onValueChange]
283
+ );
284
+ const safeSetBounds = React3.useCallback(
285
+ (bounds) => {
286
+ if (!localRef.current) return;
287
+ const boundsOffset = props?.boundsOffset ?? {
288
+ top: 0,
289
+ left: 0,
290
+ width: 0,
291
+ height: 0
292
+ };
293
+ const containerRect = localRef.current.getBoundingClientRect();
294
+ const newBounds = {
295
+ top: bounds.top - containerRect.top + (boundsOffset.top ?? 0),
296
+ left: bounds.left - containerRect.left + (boundsOffset.left ?? 0),
297
+ width: bounds.width + (boundsOffset.width ?? 0),
298
+ height: bounds.height + (boundsOffset.height ?? 0)
299
+ };
300
+ setBoundsState((prev) => {
301
+ if (prev && prev.top === newBounds.top && prev.left === newBounds.left && prev.width === newBounds.width && prev.height === newBounds.height) {
302
+ return prev;
303
+ }
304
+ return newBounds;
305
+ });
306
+ },
307
+ [props]
308
+ );
309
+ const clearBounds = React3.useCallback(() => {
310
+ setBoundsState((prev) => prev === null ? prev : null);
311
+ }, []);
312
+ React3.useEffect(() => {
313
+ if (value !== void 0) setActiveValue(value);
314
+ else if (defaultValue !== void 0) setActiveValue(defaultValue);
315
+ }, [value, defaultValue]);
316
+ const id = React3.useId();
317
+ React3.useEffect(() => {
318
+ if (mode !== "parent") return;
319
+ const container = localRef.current;
320
+ if (!container) return;
321
+ const onScroll = () => {
322
+ if (!activeValue) return;
323
+ const activeEl = container.querySelector(`[data-value="${activeValue}"][data-highlight="true"]`);
324
+ if (activeEl) safeSetBounds(activeEl.getBoundingClientRect());
325
+ };
326
+ container.addEventListener("scroll", onScroll, { passive: true });
327
+ return () => container.removeEventListener("scroll", onScroll);
328
+ }, [mode, activeValue, safeSetBounds]);
329
+ const render = React3.useCallback(
330
+ (children2) => {
331
+ if (mode === "parent") {
332
+ return /* @__PURE__ */ jsxs(
333
+ "div",
334
+ {
335
+ ref: localRef,
336
+ "data-slot": "motion-highlight-container",
337
+ className: cn("relative", props?.containerClassName),
338
+ children: [
339
+ /* @__PURE__ */ jsx(AnimatePresence, { initial: false, children: boundsState && /* @__PURE__ */ jsx(
340
+ motion.div,
341
+ {
342
+ "data-slot": "motion-highlight",
343
+ animate: {
344
+ top: boundsState.top,
345
+ left: boundsState.left,
346
+ width: boundsState.width,
347
+ height: boundsState.height,
348
+ opacity: 1
349
+ },
350
+ initial: {
351
+ top: boundsState.top,
352
+ left: boundsState.left,
353
+ width: boundsState.width,
354
+ height: boundsState.height,
355
+ opacity: 0
356
+ },
357
+ exit: {
358
+ opacity: 0,
359
+ transition: {
360
+ ...transition,
361
+ delay: (transition?.delay ?? 0) + (exitDelay ?? 0)
362
+ }
363
+ },
364
+ transition,
365
+ className: cn("bg-muted absolute z-0", className, activeClassNameState)
366
+ }
367
+ ) }),
368
+ children2
369
+ ]
370
+ }
371
+ );
372
+ }
373
+ return children2;
374
+ },
375
+ [mode, props, boundsState, transition, exitDelay, className, activeClassNameState]
376
+ );
377
+ return /* @__PURE__ */ jsx(
378
+ MotionHighlightContext.Provider,
379
+ {
380
+ value: {
381
+ mode,
382
+ activeValue,
383
+ setActiveValue: safeSetActiveValue,
384
+ id,
385
+ hover,
386
+ className,
387
+ transition,
388
+ disabled,
389
+ enabled,
390
+ exitDelay,
391
+ setBounds: safeSetBounds,
392
+ clearBounds,
393
+ activeClassName: activeClassNameState,
394
+ setActiveClassName: setActiveClassNameState,
395
+ forceUpdateBounds: props?.forceUpdateBounds
396
+ },
397
+ children: enabled ? controlledItems ? render(children) : render(
398
+ React3.Children.map(children, (child, index) => /* @__PURE__ */ jsx(MotionHighlightItem, { className: props?.itemsClassName, children: child }, index))
399
+ ) : children
400
+ }
401
+ );
402
+ }
403
+ function getNonOverridingDataAttributes(element, dataAttributes) {
404
+ return Object.keys(dataAttributes).reduce((acc, key) => {
405
+ if (element.props[key] === void 0) {
406
+ acc[key] = dataAttributes[key];
407
+ }
408
+ return acc;
409
+ }, {});
410
+ }
411
+ function MotionHighlightItem({
412
+ ref,
413
+ children,
414
+ id,
415
+ value,
416
+ className,
417
+ transition,
418
+ disabled = false,
419
+ activeClassName,
420
+ exitDelay,
421
+ asChild = false,
422
+ forceUpdateBounds,
423
+ ...props
424
+ }) {
425
+ const itemId = React3.useId();
426
+ const {
427
+ activeValue,
428
+ setActiveValue,
429
+ mode,
430
+ setBounds,
431
+ clearBounds,
432
+ hover,
433
+ enabled,
434
+ className: contextClassName,
435
+ transition: contextTransition,
436
+ id: contextId,
437
+ disabled: contextDisabled,
438
+ exitDelay: contextExitDelay,
439
+ forceUpdateBounds: contextForceUpdateBounds,
440
+ setActiveClassName
441
+ } = useMotionHighlight();
442
+ const element = children;
443
+ const childValue = id ?? value ?? element.props?.["data-value"] ?? element.props?.id ?? itemId;
444
+ const isActive = activeValue === childValue;
445
+ const isDisabled = disabled === void 0 ? contextDisabled : disabled;
446
+ const itemTransition = transition ?? contextTransition;
447
+ const localRef = React3.useRef(null);
448
+ React3.useImperativeHandle(ref, () => localRef.current);
449
+ React3.useEffect(() => {
450
+ if (mode !== "parent") return;
451
+ let rafId;
452
+ let previousBounds = null;
453
+ const shouldUpdateBounds = forceUpdateBounds === true || contextForceUpdateBounds && forceUpdateBounds !== false;
454
+ const updateBounds = () => {
455
+ if (!localRef.current) return;
456
+ const bounds = localRef.current.getBoundingClientRect();
457
+ if (shouldUpdateBounds) {
458
+ if (previousBounds && previousBounds.top === bounds.top && previousBounds.left === bounds.left && previousBounds.width === bounds.width && previousBounds.height === bounds.height) {
459
+ rafId = requestAnimationFrame(updateBounds);
460
+ return;
461
+ }
462
+ previousBounds = bounds;
463
+ rafId = requestAnimationFrame(updateBounds);
464
+ }
465
+ setBounds(bounds);
466
+ };
467
+ if (isActive) {
468
+ updateBounds();
469
+ setActiveClassName(activeClassName ?? "");
470
+ } else if (!activeValue) clearBounds();
471
+ if (shouldUpdateBounds) return () => cancelAnimationFrame(rafId);
472
+ }, [
473
+ mode,
474
+ isActive,
475
+ activeValue,
476
+ setBounds,
477
+ clearBounds,
478
+ activeClassName,
479
+ setActiveClassName,
480
+ forceUpdateBounds,
481
+ contextForceUpdateBounds
482
+ ]);
483
+ if (!React3.isValidElement(children)) return children;
484
+ const dataAttributes = {
485
+ "data-active": isActive ? "true" : "false",
486
+ "aria-selected": isActive,
487
+ "data-disabled": isDisabled,
488
+ "data-value": childValue,
489
+ "data-highlight": true
490
+ };
491
+ const commonHandlers = hover ? {
492
+ onMouseEnter: (e) => {
493
+ setActiveValue(childValue);
494
+ element.props.onMouseEnter?.(e);
495
+ },
496
+ onMouseLeave: (e) => {
497
+ setActiveValue(null);
498
+ element.props.onMouseLeave?.(e);
499
+ }
500
+ } : {
501
+ onClick: (e) => {
502
+ setActiveValue(childValue);
503
+ element.props.onClick?.(e);
504
+ }
505
+ };
506
+ if (asChild) {
507
+ if (mode === "children") {
508
+ return React3.cloneElement(
509
+ element,
510
+ {
511
+ key: childValue,
512
+ ref: localRef,
513
+ className: cn("relative", element.props.className),
514
+ ...getNonOverridingDataAttributes(element, {
515
+ ...dataAttributes,
516
+ "data-slot": "motion-highlight-item-container"
517
+ }),
518
+ ...commonHandlers,
519
+ ...props
520
+ },
521
+ /* @__PURE__ */ jsxs(Fragment, { children: [
522
+ /* @__PURE__ */ jsx(AnimatePresence, { initial: false, children: isActive && !isDisabled && /* @__PURE__ */ jsx(
523
+ motion.div,
524
+ {
525
+ layoutId: `transition-background-${contextId}`,
526
+ "data-slot": "motion-highlight",
527
+ className: cn("bg-muted absolute inset-0 z-0", contextClassName, activeClassName),
528
+ transition: itemTransition,
529
+ initial: { opacity: 0 },
530
+ animate: { opacity: 1 },
531
+ exit: {
532
+ opacity: 0,
533
+ transition: {
534
+ ...itemTransition,
535
+ delay: (itemTransition?.delay ?? 0) + (exitDelay ?? contextExitDelay ?? 0)
536
+ }
537
+ },
538
+ ...dataAttributes
539
+ }
540
+ ) }),
541
+ /* @__PURE__ */ jsx("div", { "data-slot": "motion-highlight-item", className: cn("relative z-[1]", className), ...dataAttributes, children })
542
+ ] })
543
+ );
544
+ }
545
+ return React3.cloneElement(element, {
546
+ ref: localRef,
547
+ ...getNonOverridingDataAttributes(element, {
548
+ ...dataAttributes,
549
+ "data-slot": "motion-highlight-item"
550
+ }),
551
+ ...commonHandlers
552
+ });
553
+ }
554
+ return enabled ? /* @__PURE__ */ jsxs(
555
+ "div",
556
+ {
557
+ ref: localRef,
558
+ "data-slot": "motion-highlight-item-container",
559
+ className: cn(mode === "children" && "relative", className),
560
+ ...dataAttributes,
561
+ ...props,
562
+ ...commonHandlers,
563
+ children: [
564
+ mode === "children" && /* @__PURE__ */ jsx(AnimatePresence, { initial: false, children: isActive && !isDisabled && /* @__PURE__ */ jsx(
565
+ motion.div,
566
+ {
567
+ layoutId: `transition-background-${contextId}`,
568
+ "data-slot": "motion-highlight",
569
+ className: cn("bg-muted absolute inset-0 z-0", contextClassName, activeClassName),
570
+ transition: itemTransition,
571
+ initial: { opacity: 0 },
572
+ animate: { opacity: 1 },
573
+ exit: {
574
+ opacity: 0,
575
+ transition: {
576
+ ...itemTransition,
577
+ delay: (itemTransition?.delay ?? 0) + (exitDelay ?? contextExitDelay ?? 0)
578
+ }
579
+ },
580
+ ...dataAttributes
581
+ }
582
+ ) }),
583
+ React3.cloneElement(element, {
584
+ className: cn("relative z-[1]", element.props.className),
585
+ ...getNonOverridingDataAttributes(element, {
586
+ ...dataAttributes,
587
+ "data-slot": "motion-highlight-item"
588
+ })
589
+ })
590
+ ]
591
+ },
592
+ childValue
593
+ ) : children;
594
+ }
595
+ var TabsConfigContext = React3.createContext({});
596
+ function useTabsConfig() {
597
+ return React3.useContext(TabsConfigContext);
598
+ }
599
+ var TabsContext = React3.createContext(void 0);
600
+ function useTabs() {
601
+ const context = React3.useContext(TabsContext);
602
+ if (!context) {
603
+ throw new Error("useTabs must be used within a TabsProvider");
604
+ }
605
+ return context;
606
+ }
245
607
  function Tabs({
246
608
  className,
609
+ animate = false,
610
+ type = "default",
247
611
  ...props
248
612
  }) {
249
- return /* @__PURE__ */ jsx(
613
+ const config = React3.useMemo(() => ({ animate, type }), [animate, type]);
614
+ if (type === "default" && animate) {
615
+ const [activeValue, setActiveValue] = React3.useState(
616
+ props.defaultValue ?? void 0
617
+ );
618
+ const triggersRef = React3.useRef(/* @__PURE__ */ new Map());
619
+ const initialSet = React3.useRef(false);
620
+ const isControlled = props.value !== void 0;
621
+ React3.useEffect(() => {
622
+ if (!isControlled && activeValue === void 0 && triggersRef.current.size > 0 && !initialSet.current) {
623
+ const firstTab = Array.from(triggersRef.current.keys())[0];
624
+ setActiveValue(firstTab);
625
+ initialSet.current = true;
626
+ }
627
+ }, [activeValue, isControlled]);
628
+ const registerTrigger = (value, node) => {
629
+ if (node) {
630
+ triggersRef.current.set(value, node);
631
+ if (!isControlled && activeValue === void 0 && !initialSet.current) {
632
+ setActiveValue(value);
633
+ initialSet.current = true;
634
+ }
635
+ } else {
636
+ triggersRef.current.delete(value);
637
+ }
638
+ };
639
+ const handleValueChange = (val) => {
640
+ if (!isControlled) setActiveValue(val);
641
+ else props.onValueChange?.(val);
642
+ };
643
+ return /* @__PURE__ */ jsx(TabsConfigContext.Provider, { value: config, children: /* @__PURE__ */ jsx(
644
+ TabsContext.Provider,
645
+ {
646
+ value: {
647
+ activeValue: props.value ?? activeValue,
648
+ handleValueChange,
649
+ registerTrigger
650
+ },
651
+ children: /* @__PURE__ */ jsx("div", { "data-slot": "tabs", className: cn("flex flex-col gap-2", className), ...props, children: props.children })
652
+ }
653
+ ) });
654
+ }
655
+ return /* @__PURE__ */ jsx(TabsConfigContext.Provider, { value: config, children: /* @__PURE__ */ jsx(
250
656
  TabsPrimitive.Root,
251
657
  {
252
658
  "data-slot": "tabs",
253
659
  className: cn("flex flex-col gap-2", className),
254
660
  ...props
255
661
  }
256
- );
662
+ ) });
257
663
  }
258
664
  function TabsList({
259
665
  className,
666
+ activeClassName,
667
+ transition = {
668
+ type: "spring",
669
+ stiffness: 200,
670
+ damping: 25
671
+ },
260
672
  ...props
261
673
  }) {
674
+ const { animate, type } = useTabsConfig();
675
+ if (type === "default" && animate) {
676
+ const { activeValue } = useTabs();
677
+ return /* @__PURE__ */ jsx(
678
+ MotionHighlight,
679
+ {
680
+ controlledItems: true,
681
+ className: cn("bg-background rounded-sm shadow-sm", activeClassName),
682
+ value: activeValue,
683
+ transition,
684
+ children: /* @__PURE__ */ jsx(
685
+ "div",
686
+ {
687
+ role: "tablist",
688
+ "data-slot": "tabs-list",
689
+ className: cn(
690
+ "bg-muted text-muted-foreground inline-flex h-9 w-fit items-center justify-center rounded-lg p-[3px]",
691
+ className
692
+ ),
693
+ ...props,
694
+ children: props.children
695
+ }
696
+ )
697
+ }
698
+ );
699
+ }
700
+ if (type === "underline") {
701
+ return /* @__PURE__ */ jsx(
702
+ UnderlineTabsList,
703
+ {
704
+ className,
705
+ ...props
706
+ }
707
+ );
708
+ }
262
709
  return /* @__PURE__ */ jsx(
263
710
  TabsPrimitive.List,
264
711
  {
@@ -271,10 +718,198 @@ function TabsList({
271
718
  }
272
719
  );
273
720
  }
721
+ var UnderlineTabsContext = React3.createContext(void 0);
722
+ function useUnderlineTabs() {
723
+ const context = React3.useContext(UnderlineTabsContext);
724
+ if (!context) {
725
+ return { registerTrigger: () => {
726
+ }, activeValue: void 0 };
727
+ }
728
+ return context;
729
+ }
730
+ function UnderlineTabsList({
731
+ children,
732
+ className,
733
+ ...props
734
+ }) {
735
+ const { animate } = useTabsConfig();
736
+ const tabRefs = React3.useRef([]);
737
+ const [underlineStyle, setUnderlineStyle] = React3.useState({ left: 0, width: 0 });
738
+ const listRef = React3.useRef(null);
739
+ const registerTrigger = React3.useCallback((index, element) => {
740
+ tabRefs.current[index] = element;
741
+ }, []);
742
+ const updateUnderline = React3.useCallback(() => {
743
+ const activeElement = tabRefs.current.find((el) => {
744
+ if (!el) return false;
745
+ return el.getAttribute("data-state") === "active";
746
+ });
747
+ if (activeElement && listRef.current) {
748
+ const listRect = listRef.current.getBoundingClientRect();
749
+ const activeRect = activeElement.getBoundingClientRect();
750
+ const left = activeRect.left - listRect.left;
751
+ const width = activeRect.width;
752
+ setUnderlineStyle({ left, width });
753
+ }
754
+ }, []);
755
+ React3.useLayoutEffect(() => {
756
+ updateUnderline();
757
+ }, [updateUnderline]);
758
+ React3.useEffect(() => {
759
+ if (!listRef.current) return;
760
+ const observers = [];
761
+ const setupObservers = () => {
762
+ observers.forEach((obs) => obs.disconnect());
763
+ observers.length = 0;
764
+ tabRefs.current.forEach((el) => {
765
+ if (el) {
766
+ const observer = new MutationObserver(() => {
767
+ updateUnderline();
768
+ });
769
+ observer.observe(el, { attributes: true, attributeFilter: ["data-state"] });
770
+ observers.push(observer);
771
+ }
772
+ });
773
+ };
774
+ setupObservers();
775
+ const listObserver = new MutationObserver(() => {
776
+ setupObservers();
777
+ updateUnderline();
778
+ });
779
+ if (listRef.current) {
780
+ listObserver.observe(listRef.current, {
781
+ childList: true,
782
+ subtree: true
783
+ });
784
+ observers.push(listObserver);
785
+ }
786
+ return () => {
787
+ observers.forEach((obs) => obs.disconnect());
788
+ };
789
+ }, [updateUnderline]);
790
+ const contextValue = React3.useMemo(
791
+ () => ({ registerTrigger, activeValue: void 0 }),
792
+ [registerTrigger]
793
+ );
794
+ return /* @__PURE__ */ jsx(UnderlineTabsContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsxs("div", { ref: listRef, className: "relative", children: [
795
+ /* @__PURE__ */ jsx(
796
+ TabsPrimitive.List,
797
+ {
798
+ "data-slot": "tabs-list",
799
+ className: cn(
800
+ "bg-background relative rounded-none border-b p-0",
801
+ className
802
+ ),
803
+ ...props,
804
+ children
805
+ }
806
+ ),
807
+ animate && /* @__PURE__ */ jsx(
808
+ motion.div,
809
+ {
810
+ className: "bg-primary absolute bottom-0 z-20 h-0.5",
811
+ layoutId: "underline",
812
+ style: {
813
+ left: underlineStyle.left,
814
+ width: underlineStyle.width
815
+ },
816
+ transition: {
817
+ type: "spring",
818
+ stiffness: 400,
819
+ damping: 40
820
+ }
821
+ }
822
+ ),
823
+ !animate && underlineStyle.width > 0 && /* @__PURE__ */ jsx(
824
+ "div",
825
+ {
826
+ className: "bg-primary absolute bottom-0 z-20 h-0.5 transition-all duration-200",
827
+ style: {
828
+ left: underlineStyle.left,
829
+ width: underlineStyle.width
830
+ }
831
+ }
832
+ )
833
+ ] }) });
834
+ }
274
835
  function TabsTrigger({
275
836
  className,
276
837
  ...props
277
838
  }) {
839
+ const { animate, type } = useTabsConfig();
840
+ if (type === "default" && animate) {
841
+ const { activeValue, handleValueChange, registerTrigger } = useTabs();
842
+ const localRef = React3.useRef(null);
843
+ React3.useEffect(() => {
844
+ if (props.value) {
845
+ registerTrigger(props.value, localRef.current);
846
+ return () => registerTrigger(props.value, null);
847
+ }
848
+ }, [props.value, registerTrigger]);
849
+ const {
850
+ onDrag,
851
+ onDragStart,
852
+ onDragEnd,
853
+ onDragEnter,
854
+ onDragExit,
855
+ onDragLeave,
856
+ onDragOver,
857
+ onDrop,
858
+ onAnimationStart,
859
+ onAnimationEnd,
860
+ onAnimationIteration,
861
+ onTransitionEnd,
862
+ ...motionButtonProps
863
+ } = props;
864
+ return /* @__PURE__ */ jsx(MotionHighlightItem, { value: props.value, className: "size-full", children: /* @__PURE__ */ jsx(
865
+ motion.button,
866
+ {
867
+ ref: localRef,
868
+ "data-slot": "tabs-trigger",
869
+ role: "tab",
870
+ onClick: () => handleValueChange(props.value),
871
+ "data-state": activeValue === props.value ? "active" : "inactive",
872
+ className: cn(
873
+ "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",
874
+ className
875
+ ),
876
+ ...motionButtonProps,
877
+ children: props.children
878
+ }
879
+ ) });
880
+ }
881
+ if (type === "underline") {
882
+ const { registerTrigger } = useUnderlineTabs();
883
+ const [index, setIndex] = React3.useState(-1);
884
+ const localRef = React3.useRef(null);
885
+ React3.useEffect(() => {
886
+ if (localRef.current && localRef.current.parentElement) {
887
+ const siblings = Array.from(localRef.current.parentElement.children);
888
+ const idx = siblings.indexOf(localRef.current);
889
+ if (idx >= 0) {
890
+ setIndex(idx);
891
+ registerTrigger(idx, localRef.current);
892
+ }
893
+ }
894
+ return () => {
895
+ if (index >= 0) {
896
+ registerTrigger(index, null);
897
+ }
898
+ };
899
+ }, [registerTrigger, index]);
900
+ return /* @__PURE__ */ jsx(
901
+ TabsPrimitive.Trigger,
902
+ {
903
+ ref: localRef,
904
+ "data-slot": "tabs-trigger",
905
+ className: cn(
906
+ "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",
907
+ className
908
+ ),
909
+ ...props
910
+ }
911
+ );
912
+ }
278
913
  return /* @__PURE__ */ jsx(
279
914
  TabsPrimitive.Trigger,
280
915
  {
@@ -287,10 +922,63 @@ function TabsTrigger({
287
922
  }
288
923
  );
289
924
  }
925
+ var visitedTabsSet = /* @__PURE__ */ new Set();
290
926
  function TabsContent({
291
927
  className,
292
928
  ...props
293
929
  }) {
930
+ const { animate, type } = useTabsConfig();
931
+ if (type === "default" && animate) {
932
+ const { activeValue } = useTabs();
933
+ const isActive = activeValue === props.value;
934
+ const value = props.value;
935
+ React3.useEffect(() => {
936
+ if (value && isActive) {
937
+ visitedTabsSet.add(value);
938
+ }
939
+ }, [value, isActive]);
940
+ const shouldRender = visitedTabsSet.has(value) || isActive;
941
+ if (!shouldRender) {
942
+ return null;
943
+ }
944
+ const {
945
+ onDrag,
946
+ onDragStart,
947
+ onDragEnd,
948
+ onDragEnter,
949
+ onDragExit,
950
+ onDragLeave,
951
+ onDragOver,
952
+ onDrop,
953
+ onAnimationStart,
954
+ onAnimationEnd,
955
+ onAnimationIteration,
956
+ onTransitionEnd,
957
+ ...motionDivProps
958
+ } = props;
959
+ return /* @__PURE__ */ jsx(
960
+ motion.div,
961
+ {
962
+ role: "tabpanel",
963
+ "data-slot": "tabs-content",
964
+ className: cn("overflow-hidden", className),
965
+ initial: { filter: "blur(0px)" },
966
+ animate: { filter: isActive ? "blur(0px)" : "blur(2px)" },
967
+ exit: { filter: "blur(0px)" },
968
+ transition: { type: "spring", stiffness: 300, damping: 20 },
969
+ style: {
970
+ visibility: isActive ? "visible" : "hidden",
971
+ position: isActive ? "static" : "absolute",
972
+ width: isActive ? "100%" : "0",
973
+ height: isActive ? "auto" : "0",
974
+ overflow: isActive ? "visible" : "hidden"
975
+ },
976
+ "aria-hidden": !isActive,
977
+ ...motionDivProps,
978
+ children: props.children
979
+ }
980
+ );
981
+ }
294
982
  return /* @__PURE__ */ jsx(
295
983
  TabsPrimitive.Content,
296
984
  {
@@ -300,7 +988,7 @@ function TabsContent({
300
988
  }
301
989
  );
302
990
  }
303
- var TabIndexContext = React3.createContext(null);
991
+ var TabIndexContext = React3__default.createContext(null);
304
992
  var useTabIndex = () => {
305
993
  const context = useContext(TabIndexContext);
306
994
  return context;
@@ -325,30 +1013,47 @@ var NavigationButtonsWrapper = ({
325
1013
  onReset,
326
1014
  isLoading,
327
1015
  isDraftSaving,
328
- config
1016
+ config,
1017
+ isProcessing = false,
1018
+ processingError = null
329
1019
  }) => {
330
1020
  const isLastTab = activeTab === totalTabs - 1;
331
1021
  const isFirstTab = activeTab === 0;
332
- return /* @__PURE__ */ jsx(
333
- NavigationButtons,
334
- {
335
- onPrevious,
336
- onNext,
337
- onSubmit,
338
- onSaveDraft,
339
- onReset,
340
- isLoading,
341
- isDraftSaving,
342
- config,
343
- isFirstTab,
344
- isLastTab
345
- }
346
- );
1022
+ const handlePrevious = isProcessing ? () => {
1023
+ } : onPrevious;
1024
+ const handleNext = isProcessing ? () => {
1025
+ } : onNext;
1026
+ const handleSubmit = isProcessing ? () => {
1027
+ } : onSubmit;
1028
+ const handleSaveDraft = isProcessing ? void 0 : onSaveDraft;
1029
+ const handleReset = isProcessing ? void 0 : onReset;
1030
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
1031
+ /* @__PURE__ */ jsx(
1032
+ NavigationButtons,
1033
+ {
1034
+ onPrevious: handlePrevious,
1035
+ onNext: handleNext,
1036
+ onSubmit: handleSubmit,
1037
+ onSaveDraft: handleSaveDraft,
1038
+ onReset: handleReset,
1039
+ isLoading,
1040
+ isDraftSaving,
1041
+ config,
1042
+ isFirstTab,
1043
+ isLastTab,
1044
+ disabled: isProcessing
1045
+ }
1046
+ ),
1047
+ processingError && /* @__PURE__ */ jsx("div", { className: "mt-4 p-3 bg-red-50 border border-red-200 rounded-md text-red-700 text-sm", children: processingError })
1048
+ ] });
347
1049
  };
348
1050
  var MultiTabSmartForm = ({
349
1051
  children,
350
1052
  showProgressBar = true,
351
1053
  showTabNumbers = true,
1054
+ animateTabs = false,
1055
+ tabType = "default",
1056
+ disableManualTabSwitch = false,
352
1057
  ...baseProps
353
1058
  }) => {
354
1059
  const [activeTab, setActiveTab] = useState(0);
@@ -356,8 +1061,10 @@ var MultiTabSmartForm = ({
356
1061
  const [completedTabs, setCompletedTabs] = useState(/* @__PURE__ */ new Set());
357
1062
  const [validationErrorTabs, setValidationErrorTabs] = useState(/* @__PURE__ */ new Set());
358
1063
  const [externalTabFields, setExternalTabFields] = useState({});
1064
+ const [processingTab, setProcessingTab] = useState(null);
1065
+ const [processingError, setProcessingError] = useState(null);
359
1066
  const { footerChildren, regularChildren } = useMemo(() => {
360
- const childArray = React3.Children.toArray(children);
1067
+ const childArray = React3__default.Children.toArray(children);
361
1068
  const footerChildren2 = [];
362
1069
  const regularChildren2 = [];
363
1070
  childArray.forEach((child) => {
@@ -370,8 +1077,8 @@ var MultiTabSmartForm = ({
370
1077
  return { footerChildren: footerChildren2, regularChildren: regularChildren2 };
371
1078
  }, [children]);
372
1079
  const tabs = [];
373
- React3.Children.forEach(regularChildren, (child) => {
374
- if (React3.isValidElement(child) && child.type === Tab) {
1080
+ React3__default.Children.forEach(regularChildren, (child) => {
1081
+ if (React3__default.isValidElement(child) && child.type === Tab) {
375
1082
  const props = child.props;
376
1083
  if (props.title) {
377
1084
  tabs.push(props.title);
@@ -380,8 +1087,8 @@ var MultiTabSmartForm = ({
380
1087
  });
381
1088
  const findSmartInputs = useCallback((children2) => {
382
1089
  const fields = [];
383
- React3.Children.forEach(children2, (child) => {
384
- if (React3.isValidElement(child)) {
1090
+ React3__default.Children.forEach(children2, (child) => {
1091
+ if (React3__default.isValidElement(child)) {
385
1092
  const fieldProps = child.props;
386
1093
  if (fieldProps && typeof fieldProps === "object" && "field" in fieldProps && fieldProps.field) {
387
1094
  fields.push(fieldProps.field);
@@ -399,10 +1106,10 @@ var MultiTabSmartForm = ({
399
1106
  [tabIndex]: fields
400
1107
  }));
401
1108
  }, []);
402
- React3.useEffect(() => {
1109
+ React3__default.useEffect(() => {
403
1110
  const fields = [];
404
- React3.Children.forEach(regularChildren, (child) => {
405
- if (React3.isValidElement(child) && child.type === Tab) {
1111
+ React3__default.Children.forEach(regularChildren, (child) => {
1112
+ if (React3__default.isValidElement(child) && child.type === Tab) {
406
1113
  const tabFieldsInTab = findSmartInputs(child.props.children);
407
1114
  fields.push(tabFieldsInTab);
408
1115
  }
@@ -414,6 +1121,19 @@ var MultiTabSmartForm = ({
414
1121
  const externalFields = externalTabFields[tabIndex] || [];
415
1122
  return [...internalFields, ...externalFields];
416
1123
  }, [tabFields, externalTabFields]);
1124
+ const tabCallbacks = useMemo(() => {
1125
+ const callbacks = [];
1126
+ React3__default.Children.forEach(regularChildren, (child) => {
1127
+ if (React3__default.isValidElement(child) && child.type === Tab) {
1128
+ const props = child.props;
1129
+ callbacks.push({
1130
+ onNext: props.onNext,
1131
+ processingOverlay: props.processingOverlay
1132
+ });
1133
+ }
1134
+ });
1135
+ return callbacks;
1136
+ }, [regularChildren]);
417
1137
  const config = {
418
1138
  ...baseProps,
419
1139
  showProgressBar,
@@ -451,6 +1171,14 @@ var MultiTabSmartForm = ({
451
1171
  validationErrorTabs,
452
1172
  setValidationErrorTabs,
453
1173
  footerChildren,
1174
+ animateTabs,
1175
+ tabType,
1176
+ tabCallbacks,
1177
+ processingTab,
1178
+ setProcessingTab,
1179
+ processingError,
1180
+ setProcessingError,
1181
+ disableManualTabSwitch,
454
1182
  children: regularChildren
455
1183
  }
456
1184
  ) }) });
@@ -468,11 +1196,17 @@ var MultiTabFormContent = ({
468
1196
  validationErrorTabs,
469
1197
  setValidationErrorTabs,
470
1198
  footerChildren,
471
- children
1199
+ children,
1200
+ animateTabs,
1201
+ tabType,
1202
+ tabCallbacks,
1203
+ processingTab,
1204
+ setProcessingTab,
1205
+ processingError,
1206
+ setProcessingError,
1207
+ disableManualTabSwitch = false
472
1208
  }) => {
473
1209
  const { isLoading, isDraftSaving, submitForm, saveDraft, resetForm, validateFields, formData, validationRegistry, setErrors } = useSmartForm();
474
- const [maxContentHeight, setMaxContentHeight] = useState(0);
475
- const contentRefs = useRef([]);
476
1210
  const debounce = (func, wait) => {
477
1211
  let timeout;
478
1212
  return function executedFunction(...args) {
@@ -484,27 +1218,7 @@ var MultiTabFormContent = ({
484
1218
  timeout = setTimeout(later, wait);
485
1219
  };
486
1220
  };
487
- React3.useEffect(() => {
488
- const calculateMaxHeight = () => {
489
- let maxHeight = 0;
490
- contentRefs.current.forEach((ref) => {
491
- if (ref) {
492
- const height = ref.scrollHeight;
493
- maxHeight = Math.max(maxHeight, height);
494
- }
495
- });
496
- if (maxHeight > 0) {
497
- setMaxContentHeight(maxHeight);
498
- }
499
- };
500
- const timeoutId = setTimeout(calculateMaxHeight, 100);
501
- window.addEventListener("resize", calculateMaxHeight);
502
- return () => {
503
- clearTimeout(timeoutId);
504
- window.removeEventListener("resize", calculateMaxHeight);
505
- };
506
- }, [children, activeTab]);
507
- React3.useEffect(() => {
1221
+ React3__default.useEffect(() => {
508
1222
  const checkTabCompletion = debounce(() => {
509
1223
  tabs.forEach((_, tabIndex) => {
510
1224
  const tabFieldsInTab = getCombinedTabFields(tabIndex);
@@ -554,9 +1268,12 @@ var MultiTabFormContent = ({
554
1268
  checkTabCompletion();
555
1269
  }, [formData, validationRegistry, getCombinedTabFields, tabs, setCompletedTabs, setValidationErrorTabs]);
556
1270
  const handleTabChangeWithErrorCheck = useCallback((index) => {
1271
+ if (disableManualTabSwitch && index > activeTab) {
1272
+ return;
1273
+ }
557
1274
  onTabChange(index);
558
- }, [onTabChange]);
559
- const handleNextWithValidation = useCallback(() => {
1275
+ }, [onTabChange, disableManualTabSwitch, activeTab]);
1276
+ const handleNextWithValidation = useCallback(async () => {
560
1277
  const currentTabFields = getCombinedTabFields(activeTab);
561
1278
  if (currentTabFields.length > 0) {
562
1279
  const allErrors = {};
@@ -581,7 +1298,26 @@ var MultiTabFormContent = ({
581
1298
  newSet.delete(activeTab);
582
1299
  return newSet;
583
1300
  });
584
- onNext();
1301
+ const currentTabCallback = tabCallbacks[activeTab];
1302
+ if (currentTabCallback?.onNext) {
1303
+ try {
1304
+ setProcessingTab(activeTab);
1305
+ setProcessingError(null);
1306
+ const result = currentTabCallback.onNext();
1307
+ if (result instanceof Promise) {
1308
+ await result;
1309
+ }
1310
+ setProcessingTab(null);
1311
+ setProcessingError(null);
1312
+ onNext();
1313
+ } catch (error) {
1314
+ setProcessingTab(null);
1315
+ const errorMessage = error instanceof Error ? error.message : "An error occurred while processing";
1316
+ setProcessingError(errorMessage);
1317
+ }
1318
+ } else {
1319
+ onNext();
1320
+ }
585
1321
  } else {
586
1322
  setCompletedTabs((prev) => {
587
1323
  const newSet = new Set(prev);
@@ -602,9 +1338,28 @@ var MultiTabFormContent = ({
602
1338
  }
603
1339
  }
604
1340
  } else {
605
- onNext();
1341
+ const currentTabCallback = tabCallbacks[activeTab];
1342
+ if (currentTabCallback?.onNext) {
1343
+ try {
1344
+ setProcessingTab(activeTab);
1345
+ setProcessingError(null);
1346
+ const result = currentTabCallback.onNext();
1347
+ if (result instanceof Promise) {
1348
+ await result;
1349
+ }
1350
+ setProcessingTab(null);
1351
+ setProcessingError(null);
1352
+ onNext();
1353
+ } catch (error) {
1354
+ setProcessingTab(null);
1355
+ const errorMessage = error instanceof Error ? error.message : "An error occurred while processing";
1356
+ setProcessingError(errorMessage);
1357
+ }
1358
+ } else {
1359
+ onNext();
1360
+ }
606
1361
  }
607
- }, [activeTab, getCombinedTabFields, validateFields, onNext, setCompletedTabs, setValidationErrorTabs, validationRegistry, formData]);
1362
+ }, [activeTab, getCombinedTabFields, validateFields, onNext, setCompletedTabs, setValidationErrorTabs, validationRegistry, formData, tabCallbacks, setProcessingTab, setProcessingError]);
608
1363
  const handleSubmitWithValidation = useCallback(async () => {
609
1364
  const allErrors = {};
610
1365
  let isValid = true;
@@ -654,55 +1409,70 @@ var MultiTabFormContent = ({
654
1409
  }, [submitForm, getCombinedTabFields, onTabChange, tabs.length, validationRegistry, formData, setErrors, setValidationErrorTabs]);
655
1410
  const activeTabValue = tabs[activeTab] || tabs[0] || "";
656
1411
  return /* @__PURE__ */ jsxs(Fragment, { children: [
657
- /* @__PURE__ */ jsxs(Tabs, { value: activeTabValue, onValueChange: (value) => {
658
- const newIndex = tabs.indexOf(value);
659
- if (newIndex !== -1) {
660
- handleTabChangeWithErrorCheck(newIndex);
661
- }
662
- }, className: "w-full", children: [
663
- /* @__PURE__ */ jsx(TabsList, { className: `grid w-full mb-8`, style: { gridTemplateColumns: `repeat(${tabs.length}, 1fr)` }, children: tabs.map((tab, index) => /* @__PURE__ */ jsxs(TabsTrigger, { value: tab, className: "flex items-center gap-2", children: [
664
- config.showTabNumbers && /* @__PURE__ */ jsxs("span", { children: [
665
- index + 1,
666
- "."
667
- ] }),
668
- tab,
669
- completedTabs.has(index) && /* @__PURE__ */ jsx(Check, { className: "h-4 w-4 text-green-600" }),
670
- validationErrorTabs.has(index) && /* @__PURE__ */ jsx(X, { className: "h-4 w-4 text-red-600" })
671
- ] }, tab)) }),
672
- React3.Children.map(children, (child, index) => {
673
- if (React3.isValidElement(child) && child.type === Tab) {
674
- const tabProps = child.props;
675
- return /* @__PURE__ */ jsx(TabsContent, { value: tabProps.title, children: /* @__PURE__ */ jsx(TabIndexProvider, { tabIndex: index, children: /* @__PURE__ */ jsx(
676
- "div",
677
- {
678
- ref: (el) => {
679
- contentRefs.current[index] = el;
1412
+ /* @__PURE__ */ jsxs(
1413
+ Tabs,
1414
+ {
1415
+ value: activeTabValue,
1416
+ onValueChange: (value) => {
1417
+ const newIndex = tabs.indexOf(value);
1418
+ if (newIndex !== -1) {
1419
+ handleTabChangeWithErrorCheck(newIndex);
1420
+ }
1421
+ },
1422
+ className: "w-full",
1423
+ animate: animateTabs,
1424
+ type: tabType,
1425
+ children: [
1426
+ /* @__PURE__ */ jsx(TabsList, { className: `grid w-full mb-8`, style: { gridTemplateColumns: `repeat(${tabs.length}, 1fr)` }, children: tabs.map((tab, index) => {
1427
+ const isFutureTab = disableManualTabSwitch && index > activeTab;
1428
+ return /* @__PURE__ */ jsxs(
1429
+ TabsTrigger,
1430
+ {
1431
+ value: tab,
1432
+ disabled: isFutureTab,
1433
+ className: `flex items-center gap-2 ${isFutureTab ? "opacity-50 cursor-not-allowed" : ""}`,
1434
+ children: [
1435
+ config.showTabNumbers && /* @__PURE__ */ jsxs("span", { children: [
1436
+ index + 1,
1437
+ "."
1438
+ ] }),
1439
+ tab,
1440
+ completedTabs.has(index) && /* @__PURE__ */ jsx(Check, { className: "h-4 w-4 text-green-600" }),
1441
+ validationErrorTabs.has(index) && /* @__PURE__ */ jsx(X, { className: "h-4 w-4 text-red-600" })
1442
+ ]
680
1443
  },
681
- className: "space-y-6",
682
- style: { minHeight: maxContentHeight > 0 ? `${maxContentHeight}px` : void 0 },
683
- children: tabProps.children
1444
+ tab
1445
+ );
1446
+ }) }),
1447
+ React3__default.Children.map(children, (child, index) => {
1448
+ if (React3__default.isValidElement(child) && child.type === Tab) {
1449
+ const tabProps = child.props;
1450
+ const isCurrentlyProcessing = processingTab === index;
1451
+ const hasProcessingOverlay = tabCallbacks[index]?.processingOverlay;
1452
+ return /* @__PURE__ */ jsx(TabsContent, { value: tabProps.title, children: /* @__PURE__ */ jsx(TabIndexProvider, { tabIndex: index, children: /* @__PURE__ */ jsxs("div", { className: "space-y-6 relative", children: [
1453
+ tabProps.children,
1454
+ isCurrentlyProcessing && hasProcessingOverlay && /* @__PURE__ */ jsx(
1455
+ "div",
1456
+ {
1457
+ className: "absolute inset-0 bg-white/80 backdrop-blur-sm z-50 flex items-center justify-center pointer-events-none",
1458
+ style: { minHeight: "200px" },
1459
+ children: /* @__PURE__ */ jsx("div", { className: "pointer-events-auto", children: tabCallbacks[index].processingOverlay })
1460
+ }
1461
+ )
1462
+ ] }) }) }, index);
684
1463
  }
685
- ) }) }, index);
686
- }
687
- return null;
688
- }),
689
- /* @__PURE__ */ jsx("div", { style: { position: "absolute", left: "-9999px", top: "-9999px", visibility: "hidden" }, children: React3.Children.map(children, (child, index) => {
690
- if (React3.isValidElement(child) && child.type === Tab) {
691
- const tabProps = child.props;
692
- return /* @__PURE__ */ jsx(TabIndexProvider, { tabIndex: index, children: /* @__PURE__ */ jsx(
693
- "div",
694
- {
695
- ref: (el) => {
696
- contentRefs.current[index] = el;
697
- },
698
- className: "space-y-6",
699
- children: tabProps.children
1464
+ return null;
1465
+ }),
1466
+ /* @__PURE__ */ jsx("div", { style: { position: "absolute", left: "-9999px", top: "-9999px", visibility: "hidden" }, children: React3__default.Children.map(children, (child, index) => {
1467
+ if (React3__default.isValidElement(child) && child.type === Tab) {
1468
+ const tabProps = child.props;
1469
+ return /* @__PURE__ */ jsx(TabIndexProvider, { tabIndex: index, children: /* @__PURE__ */ jsx("div", { className: "space-y-6", children: tabProps.children }) }, `hidden-${index}`);
700
1470
  }
701
- ) }, `hidden-${index}`);
702
- }
703
- return null;
704
- }) })
705
- ] }),
1471
+ return null;
1472
+ }) })
1473
+ ]
1474
+ }
1475
+ ),
706
1476
  /* @__PURE__ */ jsx(
707
1477
  NavigationButtonsWrapper,
708
1478
  {
@@ -715,7 +1485,9 @@ var MultiTabFormContent = ({
715
1485
  onReset: config.showReset || config.enableLocalStorage ? resetForm : void 0,
716
1486
  isLoading,
717
1487
  isDraftSaving,
718
- config
1488
+ config,
1489
+ isProcessing: processingTab === activeTab,
1490
+ processingError
719
1491
  }
720
1492
  ),
721
1493
  footerChildren.length > 0 && /* @__PURE__ */ jsx("div", { className: "space-y-4", children: footerChildren }),
@@ -827,7 +1599,134 @@ var FormFieldGroup = ({
827
1599
  }) => {
828
1600
  return /* @__PURE__ */ jsx("div", { className: `flex flex-wrap gap-2 md:gap-4 mb-4 ${className}`, children });
829
1601
  };
1602
+ var SmartTextArea = ({
1603
+ field,
1604
+ label,
1605
+ rows = 4,
1606
+ placeholder,
1607
+ validation,
1608
+ className = "",
1609
+ required = false,
1610
+ defaultValue,
1611
+ syncValue,
1612
+ info,
1613
+ subLabel,
1614
+ disabled,
1615
+ hidden,
1616
+ charSize,
1617
+ autoFocus,
1618
+ autoComplete,
1619
+ autoCorrect,
1620
+ autoCapitalize,
1621
+ spellCheck,
1622
+ readOnly,
1623
+ wrap,
1624
+ cols,
1625
+ maxLength,
1626
+ minLength,
1627
+ name,
1628
+ dirName,
1629
+ form
1630
+ }) => {
1631
+ const { formData } = useSmartForm();
1632
+ const { value, error, onChange, fieldRef, registerValidation } = useFormField(field);
1633
+ const fieldDetection = useFieldDetection();
1634
+ const hasRegistered = useRef(false);
1635
+ const hasSetDefault = useRef(false);
1636
+ const isDisabled = typeof disabled === "function" ? disabled(formData) : disabled || false;
1637
+ const isHidden = typeof hidden === "function" ? hidden(formData) : hidden || false;
1638
+ if (isHidden) return null;
1639
+ useEffect(() => {
1640
+ if (validation && !hasRegistered.current) {
1641
+ hasRegistered.current = true;
1642
+ registerValidation(field, validation);
1643
+ }
1644
+ }, [validation, field, registerValidation]);
1645
+ useEffect(() => {
1646
+ if (fieldDetection?.registerField) {
1647
+ fieldDetection.registerField(field);
1648
+ }
1649
+ }, [field, fieldDetection]);
1650
+ useEffect(() => {
1651
+ if (defaultValue !== void 0 && !hasSetDefault.current && (value === void 0 || value === null || value === "")) {
1652
+ onChange(defaultValue);
1653
+ hasSetDefault.current = true;
1654
+ }
1655
+ }, [defaultValue, value, onChange]);
1656
+ const prevSyncValue = useRef(syncValue);
1657
+ useEffect(() => {
1658
+ if (syncValue !== void 0 && syncValue !== prevSyncValue.current) {
1659
+ onChange(syncValue);
1660
+ prevSyncValue.current = syncValue;
1661
+ }
1662
+ }, [syncValue, onChange]);
1663
+ const getPlaceholder = () => {
1664
+ if (placeholder) return placeholder;
1665
+ if (!label) return `Enter ${field}`;
1666
+ return `Enter ${label.toLowerCase()}`;
1667
+ };
1668
+ const currentLength = value ? String(value).length : 0;
1669
+ const maxChars = charSize || maxLength;
1670
+ const showCharCount = maxChars !== void 0;
1671
+ const handleChange = (e) => {
1672
+ const newValue = e.target.value;
1673
+ if (charSize && newValue.length > charSize) {
1674
+ return;
1675
+ }
1676
+ onChange(newValue);
1677
+ };
1678
+ return /* @__PURE__ */ jsxs("div", { className: `flex-1 min-w-0 ${className}`, children: [
1679
+ label && /* @__PURE__ */ jsxs("div", { className: "mb-1", children: [
1680
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-2", children: [
1681
+ /* @__PURE__ */ jsxs(Label, { className: "text-sm font-medium text-foreground", children: [
1682
+ label,
1683
+ " ",
1684
+ required && /* @__PURE__ */ jsx("span", { className: "text-destructive", children: "*" })
1685
+ ] }),
1686
+ info && /* @__PURE__ */ jsx(TooltipProvider, { children: /* @__PURE__ */ jsxs(Tooltip, { children: [
1687
+ /* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx(InfoIcon, { className: "h-4 w-4 text-muted-foreground cursor-pointer" }) }),
1688
+ /* @__PURE__ */ jsx(TooltipContent, { children: /* @__PURE__ */ jsx("p", { className: "max-w-xs", children: info }) })
1689
+ ] }) })
1690
+ ] }),
1691
+ subLabel && /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground mt-1", children: subLabel })
1692
+ ] }),
1693
+ /* @__PURE__ */ jsxs("div", { className: "relative", children: [
1694
+ /* @__PURE__ */ jsx(
1695
+ Textarea,
1696
+ {
1697
+ ref: fieldRef,
1698
+ value: value || "",
1699
+ onChange: handleChange,
1700
+ className: `w-full ${error ? "border-destructive" : ""} ${showCharCount ? "pb-8" : ""}`,
1701
+ placeholder: getPlaceholder(),
1702
+ rows,
1703
+ "data-field": field,
1704
+ disabled: isDisabled,
1705
+ autoFocus,
1706
+ autoComplete,
1707
+ autoCorrect,
1708
+ autoCapitalize,
1709
+ spellCheck,
1710
+ readOnly,
1711
+ wrap,
1712
+ cols,
1713
+ maxLength,
1714
+ minLength,
1715
+ name,
1716
+ dirName,
1717
+ form
1718
+ }
1719
+ ),
1720
+ showCharCount && /* @__PURE__ */ jsx("div", { className: "absolute bottom-2 right-2 pointer-events-none", children: /* @__PURE__ */ jsxs("span", { className: `text-xs bg-background/80 px-1.5 py-0.5 rounded ${currentLength > (maxChars || 0) ? "text-destructive" : currentLength > (maxChars || 0) * 0.9 ? "text-yellow-600" : "text-muted-foreground"}`, children: [
1721
+ currentLength,
1722
+ "/",
1723
+ maxChars
1724
+ ] }) })
1725
+ ] }),
1726
+ error && /* @__PURE__ */ jsx("p", { className: "text-destructive text-sm mt-1", children: error })
1727
+ ] });
1728
+ };
830
1729
 
831
- export { BaseSmartForm, DraftSaveButton, ExternalFieldProvider, Footer, FormFieldGroup, FormHeader, LoadingSpinner, MultiTabSmartForm, NavigationButtons, ResetButton, Section, SimpleFormButtons, SmartForm, SubmitButton, Tab, TabIndexProvider, ToastContainerWrapper, useAutoDetectFields, useExternalFormFields, useExternalFormRegistration, useExternalTab, useFormWrapper, useTabIndex };
1730
+ export { BaseSmartForm, DraftSaveButton, ExternalFieldProvider, Footer, FormFieldGroup, FormHeader, LoadingSpinner, MultiTabSmartForm, NavigationButtons, ResetButton, Section, SimpleFormButtons, SmartForm, SmartTextArea, SubmitButton, Tab, TabIndexProvider, ToastContainerWrapper, useAutoDetectFields, useExternalFormFields, useExternalFormRegistration, useExternalTab, useFormWrapper, useTabIndex };
832
1731
  //# sourceMappingURL=index.js.map
833
1732
  //# sourceMappingURL=index.js.map