@algodomain/smart-forms 0.1.8 → 0.1.10

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
@@ -19,8 +19,11 @@ Built with TypeScript, Tailwind CSS, Zod validation, and shadcn/ui components.
19
19
  - [Opinionated Fields](#-opinionated-fields)
20
20
  - [Configuration Reference](#-configuration-reference)
21
21
  - [Advanced Features](#-advanced-features)
22
+ - [UI Components](#-ui-components)
23
+ - [Button Components](#-button-components)
22
24
  - [Theming](#-theming--customization)
23
25
  - [Hooks & Context](#-hooks--context)
26
+ - [Context Providers](#-context-providers)
24
27
  - [Examples](#-examples)
25
28
  - [Troubleshooting](#-troubleshooting)
26
29
  - [Contributing](#-contributing)
@@ -199,16 +202,35 @@ Multi-step form with tabs and progress tracking.
199
202
  api="/api/submit"
200
203
  showProgressBar={true}
201
204
  showTabNumbers={true}
205
+ animateTabs={false}
206
+ tabType="default"
202
207
  >
203
- <Tab title="Step 1">
208
+ <Tab title="Step 1" onNext={async () => { /* custom logic */ }}>
204
209
  {/* Fields */}
205
210
  </Tab>
206
- <Tab title="Step 2">
211
+ <Tab title="Step 2" processingOverlay={<LoadingSpinner />}>
207
212
  {/* Fields */}
208
213
  </Tab>
209
214
  </MultiTabSmartForm>
210
215
  ```
211
216
 
217
+ **Additional Props:**
218
+
219
+ | Prop | Type | Default | Description |
220
+ |------|------|---------|-------------|
221
+ | `animateTabs` | `boolean` | `false` | Enable tab transition animations |
222
+ | `tabType` | `'underline' \| 'default'` | `'default'` | Tab styling variant |
223
+ | `disableManualTabSwitch` | `boolean` | `false` | Prevent manual clicking on future tabs. Users can still navigate forward via Next button and go back to previous tabs. |
224
+
225
+ **Tab Component Props:**
226
+
227
+ | Prop | Type | Description |
228
+ |------|------|-------------|
229
+ | `title` | `string` | **Required.** Tab title |
230
+ | `children` | `ReactNode` | Tab content |
231
+ | `onNext` | `() => Promise<void> \| void` | Callback executed before moving to next tab. Can be async. If it throws, navigation is prevented. |
232
+ | `processingOverlay` | `ReactNode` | Overlay shown while `onNext` is processing |
233
+
212
234
  ### BaseSmartForm
213
235
 
214
236
  Low-level form component for custom layouts.
@@ -224,6 +246,63 @@ Low-level form component for custom layouts.
224
246
  </BaseSmartForm>
225
247
  ```
226
248
 
249
+ ### FormFieldGroup
250
+
251
+ A layout component for grouping form fields horizontally with responsive spacing. Fields automatically wrap to multiple rows on smaller screens.
252
+
253
+ **Usage:**
254
+
255
+ ```tsx
256
+ import { FormFieldGroup } from '@algodomain/smart-forms'
257
+ import { SmartInput, SmartSelect } from '@algodomain/smart-forms/fields'
258
+
259
+ <SmartForm api="/api/submit">
260
+ <FormFieldGroup>
261
+ <SmartInput field="firstName" label="First Name" />
262
+ <SmartInput field="lastName" label="Last Name" />
263
+ </FormFieldGroup>
264
+
265
+ <FormFieldGroup>
266
+ <SmartInput field="city" label="City" />
267
+ <SmartSelect field="state" label="State" options={stateOptions} />
268
+ <SmartInput field="zipCode" label="Zip Code" />
269
+ </FormFieldGroup>
270
+ </SmartForm>
271
+ ```
272
+
273
+ **Props:**
274
+
275
+ | Prop | Type | Default | Description |
276
+ |------|------|---------|-------------|
277
+ | `children` | `ReactNode` | - | **Required.** Form field components to group |
278
+ | `className` | `string` | `''` | Additional CSS classes to apply |
279
+
280
+ **Features:**
281
+ - Responsive flex layout with automatic wrapping
282
+ - Spacing: `gap-2` on mobile, `gap-4` on medium screens and above
283
+ - Bottom margin: `mb-4` for consistent spacing between groups
284
+
285
+ **Example: Address Form with Grouped Fields**
286
+
287
+ ```tsx
288
+ <SmartForm api="/api/submit">
289
+ <FormFieldGroup>
290
+ <SmartInput field="streetAddress" label="Street Address" required />
291
+ </FormFieldGroup>
292
+
293
+ <FormFieldGroup>
294
+ <SmartInput field="city" label="City" required />
295
+ <SmartSelect field="state" label="State" options={states} required />
296
+ <SmartInput field="zipCode" label="Zip Code" required />
297
+ </FormFieldGroup>
298
+
299
+ <FormFieldGroup className="gap-6">
300
+ <SmartInput field="country" label="Country" required />
301
+ <SmartSelect field="phoneCode" label="Phone Code" options={phoneCodes} />
302
+ </FormFieldGroup>
303
+ </SmartForm>
304
+ ```
305
+
227
306
  ---
228
307
 
229
308
  ## 🎯 Field Components
@@ -477,6 +556,9 @@ All form components (`SmartForm`, `MultiTabSmartForm`, `BaseSmartForm`) support
477
556
  | `showReset` | `boolean` | `false` | Show reset button |
478
557
  | `showProgressBar` | `boolean` | `true` | Display progress bar (MultiTab only) |
479
558
  | `showTabNumbers` | `boolean` | `true` | Show tab numbers (MultiTab only) |
559
+ | `animateTabs` | `boolean` | `false` | Enable tab animations (MultiTab only) |
560
+ | `tabType` | `'underline' \| 'default'` | `'default'` | Tab styling variant (MultiTab only) |
561
+ | `disableManualTabSwitch` | `boolean` | `false` | Prevent manual clicking on future tabs (MultiTab only) |
480
562
  | `authentication` | `AuthenticationConfig` | - | Authentication configuration |
481
563
  | `includeQueryParams` | `boolean` | `false` | Include URL query parameters |
482
564
  | `queryParamsToInclude` | `string[]` | - | Filter specific query params |
@@ -598,6 +680,214 @@ All field components support these props:
598
680
 
599
681
  ## 🚀 Advanced Features
600
682
 
683
+ ### Disable Manual Tab Switching
684
+
685
+ Control whether users can manually click on future tabs. When enabled, users must complete each step sequentially using the Next button, but can still go back to previous tabs.
686
+
687
+ **Usage:**
688
+
689
+ ```tsx
690
+ <MultiTabSmartForm
691
+ api="/api/submit"
692
+ disableManualTabSwitch={true}
693
+ >
694
+ <Tab title="Step 1">
695
+ <SmartInput field="name" label="Name" required />
696
+ </Tab>
697
+
698
+ <Tab title="Step 2">
699
+ <SmartInput field="email" label="Email" required />
700
+ </Tab>
701
+
702
+ <Tab title="Step 3">
703
+ <SmartInput field="phone" label="Phone" required />
704
+ </Tab>
705
+ </MultiTabSmartForm>
706
+ ```
707
+
708
+ **Behavior:**
709
+ - When `disableManualTabSwitch={true}`:
710
+ - Users **cannot** click on tabs ahead of the current tab
711
+ - Future tabs appear disabled (grayed out)
712
+ - Users **can** click on previous tabs to go back
713
+ - Users **can** navigate forward using the Next button (after validation)
714
+ - When `disableManualTabSwitch={false}` (default):
715
+ - Users can freely click on any tab
716
+ - All tabs are clickable
717
+
718
+ **Use Cases:**
719
+ - Enforce sequential completion of multi-step forms
720
+ - Ensure users complete each step before proceeding
721
+ - Prevent skipping validation steps
722
+ - Guide users through a structured workflow
723
+
724
+ ### Tab Callbacks and Processing Overlays
725
+
726
+ In MultiTabSmartForm, you can add custom logic before moving to the next tab using the `onNext` callback. This is useful for async operations like API calls or data processing.
727
+
728
+ **Basic Usage:**
729
+
730
+ ```tsx
731
+ <MultiTabSmartForm api="/api/submit">
732
+ <Tab
733
+ title="Step 1"
734
+ onNext={async () => {
735
+ // Custom validation or API call
736
+ const response = await fetch('/api/validate-step1')
737
+ if (!response.ok) {
738
+ throw new Error('Validation failed')
739
+ }
740
+ }}
741
+ >
742
+ <SmartInput field="name" label="Name" required />
743
+ </Tab>
744
+
745
+ <Tab title="Step 2">
746
+ <SmartInput field="email" label="Email" required />
747
+ </Tab>
748
+ </MultiTabSmartForm>
749
+ ```
750
+
751
+ **With Processing Overlay:**
752
+
753
+ ```tsx
754
+ import { LoadingSpinner } from '@algodomain/smart-forms'
755
+
756
+ <MultiTabSmartForm api="/api/submit">
757
+ <Tab
758
+ title="Processing Step"
759
+ onNext={async () => {
760
+ // Long-running operation
761
+ await processData()
762
+ }}
763
+ processingOverlay={
764
+ <div className="flex flex-col items-center gap-2">
765
+ <LoadingSpinner className="h-8 w-8" />
766
+ <p>Processing your data...</p>
767
+ </div>
768
+ }
769
+ >
770
+ <SmartInput field="data" label="Data" required />
771
+ </Tab>
772
+ </MultiTabSmartForm>
773
+ ```
774
+
775
+ **Error Handling:**
776
+
777
+ If `onNext` throws an error, navigation to the next tab is prevented and the error message is displayed:
778
+
779
+ ```tsx
780
+ <Tab
781
+ title="Step 1"
782
+ onNext={async () => {
783
+ const result = await validateData()
784
+ if (!result.valid) {
785
+ throw new Error(result.message) // Navigation prevented, error shown
786
+ }
787
+ }}
788
+ >
789
+ {/* Fields */}
790
+ </Tab>
791
+ ```
792
+
793
+ ### External Forms Integration
794
+
795
+ You can integrate external forms (forms outside the MultiTabSmartForm component) with the tab system for validation and navigation.
796
+
797
+ **Method 1: Manual Registration (Recommended for known fields)**
798
+
799
+ ```tsx
800
+ import { useExternalFormFields } from '@algodomain/smart-forms'
801
+
802
+ function ExternalForm() {
803
+ // Register fields for tab index 0
804
+ useExternalFormFields(['name', 'email', 'phone'], 0)
805
+
806
+ return (
807
+ <div>
808
+ <input name="name" />
809
+ <input name="email" />
810
+ <input name="phone" />
811
+ </div>
812
+ )
813
+ }
814
+
815
+ // In your MultiTabSmartForm
816
+ <MultiTabSmartForm api="/api/submit">
817
+ <Tab title="Step 1">
818
+ <ExternalForm />
819
+ </Tab>
820
+ </MultiTabSmartForm>
821
+ ```
822
+
823
+ **Method 2: Auto-Detection (Recommended for dynamic fields)**
824
+
825
+ ```tsx
826
+ import { useExternalTab, ExternalFieldProvider } from '@algodomain/smart-forms'
827
+ import { SmartInput } from '@algodomain/smart-forms/fields'
828
+
829
+ function ExternalForm() {
830
+ const { registerField, ExternalFieldProvider } = useExternalTab()
831
+
832
+ return (
833
+ <ExternalFieldProvider registerField={registerField}>
834
+ <SmartInput field="name" label="Name" />
835
+ <SmartInput field="email" label="Email" />
836
+ </ExternalFieldProvider>
837
+ )
838
+ }
839
+ ```
840
+
841
+ **Method 3: Using TabIndexProvider**
842
+
843
+ ```tsx
844
+ import { TabIndexProvider, useExternalFormFields } from '@algodomain/smart-forms'
845
+
846
+ function ExternalForm() {
847
+ const tabIndexContext = useTabIndex()
848
+ const tabIndex = tabIndexContext?.tabIndex ?? 0
849
+
850
+ useExternalFormFields(['field1', 'field2'], tabIndex)
851
+
852
+ return <div>{/* Your form */}</div>
853
+ }
854
+
855
+ // Wrap with TabIndexProvider
856
+ <TabIndexProvider tabIndex={0}>
857
+ <ExternalForm />
858
+ </TabIndexProvider>
859
+ ```
860
+
861
+ ### Submit Hooks
862
+
863
+ Register custom hooks to execute before form submission. Useful for file uploads or other async operations.
864
+
865
+ ```tsx
866
+ import { useSmartForm } from '@algodomain/smart-forms'
867
+
868
+ function FileUploadField() {
869
+ const { registerSubmitHook, unregisterSubmitHook } = useSmartForm()
870
+ const field = 'resume'
871
+
872
+ useEffect(() => {
873
+ const key = `upload-${field}`
874
+
875
+ const uploadHook = async () => {
876
+ // Upload file before form submission
877
+ await uploadFile(file)
878
+ }
879
+
880
+ registerSubmitHook(key, uploadHook)
881
+
882
+ return () => {
883
+ unregisterSubmitHook(key)
884
+ }
885
+ }, [field, file])
886
+
887
+ return <input type="file" />
888
+ }
889
+ ```
890
+
601
891
  ### Conditional Field Disabling
602
892
 
603
893
  Disable fields or submit buttons based on form data values. Supports both static boolean values and dynamic functions.
@@ -946,6 +1236,146 @@ The library will:
946
1236
 
947
1237
  ---
948
1238
 
1239
+ ## 🧩 UI Components
1240
+
1241
+ ### FormHeader
1242
+
1243
+ Display form title, subtitle, and logo.
1244
+
1245
+ ```tsx
1246
+ import { FormHeader } from '@algodomain/smart-forms'
1247
+
1248
+ <FormHeader
1249
+ title="Registration Form"
1250
+ subTitle="Please fill in your details"
1251
+ logo={<img src="/logo.png" alt="Logo" />}
1252
+ />
1253
+ ```
1254
+
1255
+ ### Section
1256
+
1257
+ Section divider with optional text.
1258
+
1259
+ ```tsx
1260
+ import { Section } from '@algodomain/smart-forms'
1261
+
1262
+ <Section text="Personal Information" />
1263
+ ```
1264
+
1265
+ ### Footer
1266
+
1267
+ Footer component for form content.
1268
+
1269
+ ```tsx
1270
+ import { Footer } from '@algodomain/smart-forms'
1271
+
1272
+ <Footer>
1273
+ <p className="text-sm text-gray-500">
1274
+ By submitting, you agree to our terms and conditions.
1275
+ </p>
1276
+ </Footer>
1277
+ ```
1278
+
1279
+ ### ToastContainerWrapper
1280
+
1281
+ Toast notification container (automatically included in forms).
1282
+
1283
+ ```tsx
1284
+ import { ToastContainerWrapper } from '@algodomain/smart-forms'
1285
+
1286
+ <ToastContainerWrapper />
1287
+ ```
1288
+
1289
+ ## 🔘 Button Components
1290
+
1291
+ ### LoadingSpinner
1292
+
1293
+ Loading spinner component.
1294
+
1295
+ ```tsx
1296
+ import { LoadingSpinner } from '@algodomain/smart-forms'
1297
+
1298
+ <LoadingSpinner className="h-6 w-6" />
1299
+ ```
1300
+
1301
+ ### SubmitButton
1302
+
1303
+ Submit button with loading state.
1304
+
1305
+ ```tsx
1306
+ import { SubmitButton } from '@algodomain/smart-forms'
1307
+
1308
+ <SubmitButton
1309
+ onClick={handleSubmit}
1310
+ disabled={isLoading}
1311
+ isLoading={isLoading}
1312
+ >
1313
+ Submit Form
1314
+ </SubmitButton>
1315
+ ```
1316
+
1317
+ ### DraftSaveButton
1318
+
1319
+ Draft save button.
1320
+
1321
+ ```tsx
1322
+ import { DraftSaveButton } from '@algodomain/smart-forms'
1323
+
1324
+ <DraftSaveButton
1325
+ onClick={handleSaveDraft}
1326
+ disabled={isDraftSaving}
1327
+ />
1328
+ ```
1329
+
1330
+ ### ResetButton
1331
+
1332
+ Reset form button.
1333
+
1334
+ ```tsx
1335
+ import { ResetButton } from '@algodomain/smart-forms'
1336
+
1337
+ <ResetButton onClick={handleReset} />
1338
+ ```
1339
+
1340
+ ### NavigationButtons
1341
+
1342
+ Navigation buttons for multi-tab forms.
1343
+
1344
+ ```tsx
1345
+ import { NavigationButtons } from '@algodomain/smart-forms'
1346
+
1347
+ <NavigationButtons
1348
+ onPrevious={handlePrevious}
1349
+ onNext={handleNext}
1350
+ onSubmit={handleSubmit}
1351
+ onSaveDraft={handleSaveDraft}
1352
+ onReset={handleReset}
1353
+ isLoading={isLoading}
1354
+ isDraftSaving={isDraftSaving}
1355
+ config={config}
1356
+ isFirstTab={false}
1357
+ isLastTab={false}
1358
+ disabled={false}
1359
+ />
1360
+ ```
1361
+
1362
+ ### SimpleFormButtons
1363
+
1364
+ Simple button group for single-page forms.
1365
+
1366
+ ```tsx
1367
+ import { SimpleFormButtons } from '@algodomain/smart-forms'
1368
+
1369
+ <SimpleFormButtons
1370
+ onSubmit={handleSubmit}
1371
+ onSaveDraft={handleSaveDraft}
1372
+ onReset={handleReset}
1373
+ isLoading={isLoading}
1374
+ isDraftSaving={isDraftSaving}
1375
+ config={config}
1376
+ />
1377
+ ```
1378
+
949
1379
  ## 🎨 Theming & Customization
950
1380
 
951
1381
  ### CSS Variables
@@ -1025,21 +1455,36 @@ import { useSmartForm } from '@algodomain/smart-forms'
1025
1455
 
1026
1456
  function MyComponent() {
1027
1457
  const {
1028
- formData, // Current form values
1029
- errors, // Validation errors
1030
- isLoading, // Submission loading state
1031
- isDraftSaving, // Draft saving state
1032
- submitForm, // Submit function
1033
- saveDraft, // Save draft function
1034
- resetForm, // Reset to initial values
1035
- updateField, // Update specific field
1036
- config // Form configuration
1458
+ formData, // Current form values
1459
+ errors, // Validation errors
1460
+ isLoading, // Submission loading state
1461
+ isDraftSaving, // Draft saving state
1462
+ submitForm, // Submit function
1463
+ saveDraft, // Save draft function
1464
+ resetForm, // Reset to initial values
1465
+ updateField, // Update specific field
1466
+ validateField, // Validate a single field
1467
+ validateFields, // Validate multiple fields
1468
+ validateFormAndGetResult, // Validate entire form and return boolean
1469
+ registerSubmitHook, // Register a hook to run before submission
1470
+ unregisterSubmitHook, // Unregister a submit hook
1471
+ setErrors, // Manually set validation errors
1472
+ config // Form configuration
1037
1473
  } = useSmartForm()
1038
1474
 
1039
1475
  return <button onClick={submitForm}>Submit</button>
1040
1476
  }
1041
1477
  ```
1042
1478
 
1479
+ **Methods:**
1480
+
1481
+ - `validateField(field: string, value: any): boolean` - Validate a single field
1482
+ - `validateFields(fields: string[]): boolean` - Validate multiple fields
1483
+ - `validateFormAndGetResult(): boolean` - Validate entire form and return result
1484
+ - `registerSubmitHook(key: string, hook: () => Promise<void>): void` - Register a hook to execute before form submission
1485
+ - `unregisterSubmitHook(key: string): void` - Unregister a submit hook
1486
+ - `setErrors(errors: Record<string, string>): void` - Manually set validation errors
1487
+
1043
1488
  ### useFormField
1044
1489
 
1045
1490
  Access individual field state (used internally by field components).
@@ -1059,6 +1504,170 @@ function CustomField({ field }) {
1059
1504
  }
1060
1505
  ```
1061
1506
 
1507
+ ### useFormWrapper
1508
+
1509
+ Alias for `useSmartForm` (for convenience).
1510
+
1511
+ ```tsx
1512
+ import { useFormWrapper } from '@algodomain/smart-forms'
1513
+
1514
+ function MyComponent() {
1515
+ const { formData, submitForm } = useFormWrapper()
1516
+ // Same as useSmartForm
1517
+ }
1518
+ ```
1519
+
1520
+ ### useTabIndex
1521
+
1522
+ Get the current tab index in a MultiTabSmartForm.
1523
+
1524
+ ```tsx
1525
+ import { useTabIndex } from '@algodomain/smart-forms'
1526
+
1527
+ function MyComponent() {
1528
+ const tabIndexContext = useTabIndex()
1529
+ const tabIndex = tabIndexContext?.tabIndex ?? 0
1530
+
1531
+ return <div>Current tab: {tabIndex + 1}</div>
1532
+ }
1533
+ ```
1534
+
1535
+ ### useExternalFormRegistration
1536
+
1537
+ Register external forms with MultiTabSmartForm for validation and tab navigation.
1538
+
1539
+ ```tsx
1540
+ import { useExternalFormRegistration } from '@algodomain/smart-forms'
1541
+
1542
+ function ExternalForm() {
1543
+ const { registerTabFields, currentTabIndex } = useExternalFormRegistration()
1544
+
1545
+ useEffect(() => {
1546
+ registerTabFields(currentTabIndex, ['field1', 'field2'])
1547
+ }, [])
1548
+
1549
+ return <div>{/* Your form fields */}</div>
1550
+ }
1551
+ ```
1552
+
1553
+ ### useExternalFormFields
1554
+
1555
+ Register fields from external forms with a specific tab index.
1556
+
1557
+ ```tsx
1558
+ import { useExternalFormFields } from '@algodomain/smart-forms'
1559
+
1560
+ function ExternalForm() {
1561
+ useExternalFormFields(['field1', 'field2'], 0) // Register fields for tab 0
1562
+
1563
+ return <div>{/* Your form fields */}</div>
1564
+ }
1565
+ ```
1566
+
1567
+ ### useAutoDetectFields
1568
+
1569
+ Automatically detect and register fields in external forms.
1570
+
1571
+ ```tsx
1572
+ import { useAutoDetectFields, ExternalFieldProvider } from '@algodomain/smart-forms'
1573
+
1574
+ function ExternalForm() {
1575
+ const { registerField, ExternalFieldProvider } = useAutoDetectFields(0)
1576
+
1577
+ return (
1578
+ <ExternalFieldProvider registerField={registerField}>
1579
+ <SmartInput field="name" label="Name" />
1580
+ <SmartInput field="email" label="Email" />
1581
+ </ExternalFieldProvider>
1582
+ )
1583
+ }
1584
+ ```
1585
+
1586
+ ### useExternalTab
1587
+
1588
+ Automatically detect both tab index and fields in external forms (recommended).
1589
+
1590
+ ```tsx
1591
+ import { useExternalTab, ExternalFieldProvider } from '@algodomain/smart-forms'
1592
+
1593
+ function ExternalForm() {
1594
+ const { registerField, ExternalFieldProvider } = useExternalTab()
1595
+
1596
+ return (
1597
+ <ExternalFieldProvider registerField={registerField}>
1598
+ <SmartInput field="name" label="Name" />
1599
+ <SmartInput field="email" label="Email" />
1600
+ </ExternalFieldProvider>
1601
+ )
1602
+ }
1603
+ ```
1604
+
1605
+ ### useFieldDetection
1606
+
1607
+ Access field detection context (used internally by field components).
1608
+
1609
+ ```tsx
1610
+ import { useFieldDetection } from '@algodomain/smart-forms'
1611
+
1612
+ function CustomField({ field }) {
1613
+ const context = useFieldDetection()
1614
+
1615
+ useEffect(() => {
1616
+ if (context) {
1617
+ context.registerField(field)
1618
+ }
1619
+ }, [field, context])
1620
+
1621
+ return <input />
1622
+ }
1623
+ ```
1624
+
1625
+ ## 🔌 Context Providers
1626
+
1627
+ ### TabIndexProvider
1628
+
1629
+ Provide tab index context to child components.
1630
+
1631
+ ```tsx
1632
+ import { TabIndexProvider, useTabIndex } from '@algodomain/smart-forms'
1633
+
1634
+ function MyComponent() {
1635
+ return (
1636
+ <TabIndexProvider tabIndex={0}>
1637
+ <ChildComponent />
1638
+ </TabIndexProvider>
1639
+ )
1640
+ }
1641
+
1642
+ function ChildComponent() {
1643
+ const context = useTabIndex()
1644
+ const tabIndex = context?.tabIndex ?? 0
1645
+ return <div>Tab: {tabIndex}</div>
1646
+ }
1647
+ ```
1648
+
1649
+ ### ExternalFieldProvider
1650
+
1651
+ Provider for automatic field detection in external forms.
1652
+
1653
+ ```tsx
1654
+ import { ExternalFieldProvider } from '@algodomain/smart-forms'
1655
+
1656
+ function ExternalForm() {
1657
+ const registerField = (fieldName: string) => {
1658
+ // Register field with parent form
1659
+ console.log('Registering field:', fieldName)
1660
+ }
1661
+
1662
+ return (
1663
+ <ExternalFieldProvider registerField={registerField}>
1664
+ <SmartInput field="name" label="Name" />
1665
+ <SmartInput field="email" label="Email" />
1666
+ </ExternalFieldProvider>
1667
+ )
1668
+ }
1669
+ ```
1670
+
1062
1671
  ---
1063
1672
 
1064
1673
  ## 💡 Examples
@@ -1066,7 +1675,7 @@ function CustomField({ field }) {
1066
1675
  ### Complete Registration Form
1067
1676
 
1068
1677
  ```tsx
1069
- import { SmartForm } from '@algodomain/smart-forms'
1678
+ import { SmartForm, FormHeader, Section, Footer } from '@algodomain/smart-forms'
1070
1679
  import { SmartInput, SmartSelect, SmartCheckbox, SmartDatePicker } from '@algodomain/smart-forms/fields'
1071
1680
  import { FieldEmail, FieldPassword } from '@algodomain/smart-forms/opinionated'
1072
1681
  import { z } from 'zod'
@@ -1086,6 +1695,13 @@ export function RegistrationForm() {
1086
1695
  toast.error('Registration failed.')
1087
1696
  }}
1088
1697
  >
1698
+ <FormHeader
1699
+ title="Create Your Account"
1700
+ subTitle="Join us today and get started"
1701
+ />
1702
+
1703
+ <Section text="Personal Information" />
1704
+
1089
1705
  <SmartInput
1090
1706
  field="fullName"
1091
1707
  label="Full Name"
@@ -1096,6 +1712,8 @@ export function RegistrationForm() {
1096
1712
  <FieldEmail field="email" required />
1097
1713
  <FieldPassword field="password" required />
1098
1714
 
1715
+ <Section text="Location" />
1716
+
1099
1717
  <SmartSelect
1100
1718
  field="country"
1101
1719
  label="Country"
@@ -1121,12 +1739,20 @@ export function RegistrationForm() {
1121
1739
  required
1122
1740
  />
1123
1741
 
1742
+ <Section text="Agreements" />
1743
+
1124
1744
  <SmartCheckbox
1125
1745
  field="terms"
1126
1746
  label="I agree to the Terms and Conditions"
1127
1747
  validation={z.boolean().refine(val => val === true)}
1128
1748
  required
1129
1749
  />
1750
+
1751
+ <Footer>
1752
+ <p className="text-sm text-gray-500 text-center">
1753
+ By submitting, you agree to our terms and conditions.
1754
+ </p>
1755
+ </Footer>
1130
1756
  </SmartForm>
1131
1757
  )
1132
1758
  }
@@ -1135,7 +1761,7 @@ export function RegistrationForm() {
1135
1761
  ### Multi-Tab Job Application
1136
1762
 
1137
1763
  ```tsx
1138
- import { MultiTabSmartForm, Tab } from '@algodomain/smart-forms'
1764
+ import { MultiTabSmartForm, Tab, LoadingSpinner } from '@algodomain/smart-forms'
1139
1765
  import { SmartInput, SmartTags, SmartDualRangeSlider } from '@algodomain/smart-forms/fields'
1140
1766
  import { FieldEmail, FieldPhone } from '@algodomain/smart-forms/opinionated'
1141
1767
  import { z } from 'zod'
@@ -1147,11 +1773,23 @@ export function JobApplicationForm() {
1147
1773
  method="POST"
1148
1774
  showProgressBar={true}
1149
1775
  showTabNumbers={true}
1776
+ animateTabs={true}
1777
+ tabType="underline"
1778
+ disableManualTabSwitch={true}
1150
1779
  allowSaveDraft={true}
1151
1780
  enableLocalStorage={true}
1152
1781
  storageKey="job-application"
1153
1782
  >
1154
- <Tab title="Personal Info">
1783
+ <Tab
1784
+ title="Personal Info"
1785
+ onNext={async () => {
1786
+ // Validate with external API before proceeding
1787
+ const response = await fetch('/api/validate-personal-info')
1788
+ if (!response.ok) {
1789
+ throw new Error('Personal information validation failed')
1790
+ }
1791
+ }}
1792
+ >
1155
1793
  <SmartInput
1156
1794
  field="fullName"
1157
1795
  label="Full Name"
@@ -1162,7 +1800,15 @@ export function JobApplicationForm() {
1162
1800
  <FieldPhone field="phone" required />
1163
1801
  </Tab>
1164
1802
 
1165
- <Tab title="Experience">
1803
+ <Tab
1804
+ title="Experience"
1805
+ processingOverlay={
1806
+ <div className="flex flex-col items-center gap-2">
1807
+ <LoadingSpinner className="h-8 w-8" />
1808
+ <p>Processing experience data...</p>
1809
+ </div>
1810
+ }
1811
+ >
1166
1812
  <SmartDualRangeSlider
1167
1813
  minField="minExperience"
1168
1814
  maxField="maxExperience"
@@ -1183,6 +1829,41 @@ export function JobApplicationForm() {
1183
1829
  }
1184
1830
  ```
1185
1831
 
1832
+ ### Form with External Components
1833
+
1834
+ ```tsx
1835
+ import { MultiTabSmartForm, Tab, useExternalTab, ExternalFieldProvider } from '@algodomain/smart-forms'
1836
+ import { SmartInput } from '@algodomain/smart-forms/fields'
1837
+
1838
+ // External form component
1839
+ function ExternalAddressForm() {
1840
+ const { registerField, ExternalFieldProvider } = useExternalTab()
1841
+
1842
+ return (
1843
+ <ExternalFieldProvider registerField={registerField}>
1844
+ <SmartInput field="street" label="Street" required />
1845
+ <SmartInput field="city" label="City" required />
1846
+ <SmartInput field="zipCode" label="Zip Code" required />
1847
+ </ExternalFieldProvider>
1848
+ )
1849
+ }
1850
+
1851
+ // Main form
1852
+ export function FormWithExternalComponents() {
1853
+ return (
1854
+ <MultiTabSmartForm api="/api/submit">
1855
+ <Tab title="Basic Info">
1856
+ <SmartInput field="name" label="Name" required />
1857
+ </Tab>
1858
+
1859
+ <Tab title="Address">
1860
+ <ExternalAddressForm />
1861
+ </Tab>
1862
+ </MultiTabSmartForm>
1863
+ )
1864
+ }
1865
+ ```
1866
+
1186
1867
  ### Form with Query Parameters
1187
1868
 
1188
1869
  ```tsx