react-form-dto 0.0.8 β 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +254 -31
- package/dist/components/Field.d.ts +1 -0
- package/dist/components/FormBuilder.d.ts +2 -0
- package/dist/components/Section.d.ts +2 -0
- package/dist/components/renderers/AutoComplete.d.ts +1 -0
- package/dist/components/renderers/CheckBoxInput.d.ts +1 -1
- package/dist/components/renderers/MultiAutoComplete.d.ts +1 -0
- package/dist/components/renderers/RadioInput.d.ts +1 -0
- package/dist/components/renderers/SelectInput.d.ts +1 -1
- package/dist/components/renderers/TextInput.d.ts +1 -1
- package/dist/components/renderers/TextareaInput.d.ts +1 -0
- package/dist/examples/profileForm.d.ts +1 -0
- package/dist/hooks/useFormBuilder.d.ts +1 -1
- package/dist/react-form-dto.es.js +408 -367
- package/dist/react-form-dto.umd.js +2 -2
- package/dist/stories/FormBuilder.stories.d.ts +1 -0
- package/dist/types/dto.d.ts +14 -9
- package/dist/utils/i18n.d.ts +18 -0
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/validation.d.ts +2 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,31 +1,43 @@
|
|
|
1
1
|
# React Form DTO
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+

|
|
4
|
+

|
|
5
|
+

|
|
6
|
+

|
|
4
7
|
|
|
5
|
-
|
|
8
|
+
**Schema-first, DTO-driven form framework for React and Material UI (MUI v7)**
|
|
9
|
+
|
|
10
|
+
React Form DTO is a **high-level form framework** for building complex, dynamic, and enterprise-scale forms using declarative JSON or TypeScript DTOsβrather than verbose, repetitive JSX.
|
|
11
|
+
|
|
12
|
+
It is designed for **schema-driven UIs**, backend-configured workflows, admin panels, and internal tools where forms must be **configurable, scalable, and predictable**.
|
|
6
13
|
|
|
7
14
|
---
|
|
8
15
|
|
|
9
16
|
## Why React Form DTO?
|
|
10
17
|
|
|
11
|
-
Most form libraries
|
|
18
|
+
Most form libraries solve **state management**.
|
|
19
|
+
React Form DTO solves **form architecture**.
|
|
20
|
+
|
|
21
|
+
It operates at a higher abstraction level where **layout, validation, rendering, and behavior** are defined in a single schema.
|
|
12
22
|
|
|
13
|
-
|
|
23
|
+
### Use this library when:
|
|
14
24
|
|
|
15
|
-
-
|
|
16
|
-
-
|
|
17
|
-
-
|
|
18
|
-
-
|
|
25
|
+
- Forms are generated from backend schemas or configuration APIs
|
|
26
|
+
- UI logic must be reused across multiple applications
|
|
27
|
+
- Forms are large, dynamic, or conditional
|
|
28
|
+
- You need imperative control (wizards, modals, async flows)
|
|
29
|
+
- Your design system is based on Material UI
|
|
19
30
|
|
|
20
|
-
|
|
31
|
+
### Key Advantages
|
|
21
32
|
|
|
22
33
|
- π **DTO-first design** β define forms entirely in JSON or TypeScript
|
|
23
|
-
- π¨ **Material UI v7 native** β
|
|
24
|
-
- π§± **Composable
|
|
25
|
-
- π― **Imperative API** β programmatic
|
|
26
|
-
- π **Conditional rendering** β
|
|
27
|
-
- π§© **
|
|
28
|
-
- π‘οΈ **Strong TypeScript typing** β
|
|
34
|
+
- π¨ **Material UI v7 native** β accessibility and consistency by default
|
|
35
|
+
- π§± **Composable structure** β Form β Section β Field
|
|
36
|
+
- π― **Imperative API** β programmatic control via refs
|
|
37
|
+
- π **Conditional rendering** β dynamic visibility and logic
|
|
38
|
+
- π§© **Extensible renderers** β plug in custom components
|
|
39
|
+
- π‘οΈ **Strong TypeScript typing** β safe, predictable APIs
|
|
40
|
+
- π **Enterprise-ready** β optimized for large, config-driven forms
|
|
29
41
|
|
|
30
42
|
---
|
|
31
43
|
|
|
@@ -33,22 +45,43 @@ Most form libraries focus on low-level state management. React Form DTO operates
|
|
|
33
45
|
|
|
34
46
|
| Feature | React Form DTO | React Hook Form | Formik |
|
|
35
47
|
|------|---------------|----------------|--------|
|
|
36
|
-
| Schema/DTO driven | β
Native | β Manual | β Manual |
|
|
48
|
+
| Schema / DTO driven | β
Native | β Manual | β Manual |
|
|
37
49
|
| MUI-first | β
Yes | β οΈ Partial | β οΈ Partial |
|
|
38
50
|
| Imperative API | β
First-class | β οΈ Limited | β οΈ Limited |
|
|
39
51
|
| Large dynamic forms | β
Excellent | β οΈ Medium | β Poor |
|
|
40
52
|
| Boilerplate | β
Minimal | β High | β High |
|
|
41
53
|
|
|
42
|
-
> React Form DTO is **not a replacement** for React Hook Form.
|
|
54
|
+
> **Note:** React Form DTO is **not a replacement** for React Hook Form.
|
|
55
|
+
> It is a **higher-level abstraction** for schema-driven UI generation.
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
## What This Library Is Not
|
|
60
|
+
|
|
61
|
+
- β A low-level form state library
|
|
62
|
+
- β A visual form builder
|
|
63
|
+
- β A replacement for small hand-crafted forms
|
|
64
|
+
- β A design system
|
|
65
|
+
|
|
66
|
+
React Form DTO excels when **forms are data, not components**.
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
## Documentation & Demo
|
|
71
|
+
|
|
72
|
+
- π **Documentation:** See full DTO reference, APIs, and advanced examples [Documentation](https://shakir-afridi.github.io/react-form-dto/docs)
|
|
73
|
+
- π **Storybook:** Interactive component playground and live demos [Live Demo](https://shakir-afridi.github.io/react-form-dto/storybook)
|
|
43
74
|
|
|
44
75
|
---
|
|
45
76
|
|
|
46
77
|
## Installation
|
|
47
78
|
|
|
48
79
|
```bash
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
80
|
+
npm install react-form-dto
|
|
81
|
+
# or
|
|
82
|
+
yarn add react-form-dto
|
|
83
|
+
# or
|
|
84
|
+
pnpm add react-form-dto
|
|
52
85
|
```
|
|
53
86
|
|
|
54
87
|
### Requirements
|
|
@@ -59,7 +92,25 @@ npm install
|
|
|
59
92
|
|
|
60
93
|
---
|
|
61
94
|
|
|
62
|
-
##
|
|
95
|
+
## Core Concepts
|
|
96
|
+
|
|
97
|
+
### DTO as Source of Truth
|
|
98
|
+
|
|
99
|
+
All structure, layout, validation, and behavior live in a single schema.
|
|
100
|
+
|
|
101
|
+
### Stateless Rendering
|
|
102
|
+
|
|
103
|
+
The UI is derived entirely from the DTO and internal state.
|
|
104
|
+
|
|
105
|
+
### Imperative Escape Hatch
|
|
106
|
+
|
|
107
|
+
Refs enable workflows that declarative-only approaches struggle with.
|
|
108
|
+
|
|
109
|
+
### Renderer Isolation
|
|
110
|
+
|
|
111
|
+
Field logic is decoupled from presentation, enabling customization.
|
|
112
|
+
|
|
113
|
+
## Quick Start
|
|
63
114
|
|
|
64
115
|
```tsx
|
|
65
116
|
import { FormBuilder, type FormBuilderHandle } from 'react-form-dto';
|
|
@@ -201,12 +252,14 @@ const profileForm: FormDTO = {
|
|
|
201
252
|
- `date`
|
|
202
253
|
- `email`
|
|
203
254
|
- `password`
|
|
255
|
+
- `textarea`
|
|
204
256
|
|
|
205
257
|
### Selection Inputs
|
|
206
258
|
|
|
207
259
|
- `select`
|
|
208
260
|
- `autocomplete`
|
|
209
261
|
- `multi-autocomplete`
|
|
262
|
+
- `radio`
|
|
210
263
|
|
|
211
264
|
### Boolean Inputs
|
|
212
265
|
|
|
@@ -214,6 +267,143 @@ const profileForm: FormDTO = {
|
|
|
214
267
|
|
|
215
268
|
---
|
|
216
269
|
|
|
270
|
+
## π Internationalization (I18n)
|
|
271
|
+
|
|
272
|
+
React Form DTO has built-in support for multi-language forms through `I18String` and `I18nOption` types.
|
|
273
|
+
|
|
274
|
+
### Using I18String
|
|
275
|
+
|
|
276
|
+
Any text property (`label`, `placeholder`, `title`, `description`, validation messages) can be either a plain string or a locale map:
|
|
277
|
+
|
|
278
|
+
```tsx
|
|
279
|
+
// Simple string (single language)
|
|
280
|
+
{
|
|
281
|
+
label: "First Name"
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
// Multi-language support
|
|
285
|
+
{
|
|
286
|
+
label: {
|
|
287
|
+
en: "First Name",
|
|
288
|
+
fr: "PrΓ©nom",
|
|
289
|
+
es: "Nombre",
|
|
290
|
+
de: "Vorname"
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
### Using I18nOption for Selections
|
|
296
|
+
|
|
297
|
+
For select, autocomplete, and multi-autocomplete fields, you can use `I18nOption` objects to provide translatable labels while maintaining stable values:
|
|
298
|
+
|
|
299
|
+
```tsx
|
|
300
|
+
{
|
|
301
|
+
id: "country",
|
|
302
|
+
type: "select",
|
|
303
|
+
label: { en: "Country", fr: "Pays" },
|
|
304
|
+
options: [
|
|
305
|
+
{
|
|
306
|
+
value: "us",
|
|
307
|
+
label: { en: "United States", fr: "Γtats-Unis" }
|
|
308
|
+
},
|
|
309
|
+
{
|
|
310
|
+
value: "fr",
|
|
311
|
+
label: { en: "France", fr: "France" }
|
|
312
|
+
},
|
|
313
|
+
{
|
|
314
|
+
value: "de",
|
|
315
|
+
label: { en: "Germany", fr: "Allemagne" }
|
|
316
|
+
}
|
|
317
|
+
]
|
|
318
|
+
}
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
**Backward Compatibility:** Simple string arrays still work:
|
|
322
|
+
|
|
323
|
+
```tsx
|
|
324
|
+
options: ["USA", "France", "Germany"] // Still supported
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
### I18n Validation Messages
|
|
328
|
+
|
|
329
|
+
Validation messages also support I18n:
|
|
330
|
+
|
|
331
|
+
```tsx
|
|
332
|
+
validations: {
|
|
333
|
+
required: {
|
|
334
|
+
en: "This field is required",
|
|
335
|
+
fr: "Ce champ est obligatoire",
|
|
336
|
+
es: "Este campo es obligatorio"
|
|
337
|
+
},
|
|
338
|
+
validate: (value) => value.length < 2
|
|
339
|
+
? {
|
|
340
|
+
en: "Minimum 2 characters",
|
|
341
|
+
fr: "Minimum 2 caractères"
|
|
342
|
+
}
|
|
343
|
+
: null
|
|
344
|
+
}
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
### Complete I18n Example
|
|
348
|
+
|
|
349
|
+
```tsx
|
|
350
|
+
const multilingualForm: FormDTO = {
|
|
351
|
+
title: {
|
|
352
|
+
en: "User Registration",
|
|
353
|
+
fr: "Inscription de l'utilisateur",
|
|
354
|
+
es: "Registro de Usuario"
|
|
355
|
+
},
|
|
356
|
+
description: {
|
|
357
|
+
en: "Please fill in your details",
|
|
358
|
+
fr: "Veuillez remplir vos coordonnΓ©es",
|
|
359
|
+
es: "Por favor complete sus datos"
|
|
360
|
+
},
|
|
361
|
+
sections: [
|
|
362
|
+
{
|
|
363
|
+
id: "personal",
|
|
364
|
+
heading: {
|
|
365
|
+
en: "Personal Information",
|
|
366
|
+
fr: "Informations personnelles",
|
|
367
|
+
es: "InformaciΓ³n Personal"
|
|
368
|
+
},
|
|
369
|
+
fields: [
|
|
370
|
+
{
|
|
371
|
+
id: "title",
|
|
372
|
+
type: "select",
|
|
373
|
+
label: { en: "Title", fr: "Titre", es: "TΓtulo" },
|
|
374
|
+
options: [
|
|
375
|
+
{ value: "mr", label: { en: "Mr", fr: "M.", es: "Sr." } },
|
|
376
|
+
{ value: "ms", label: { en: "Ms", fr: "Mme", es: "Sra." } },
|
|
377
|
+
{ value: "dr", label: { en: "Dr", fr: "Dr", es: "Dr." } }
|
|
378
|
+
]
|
|
379
|
+
},
|
|
380
|
+
{
|
|
381
|
+
id: "firstName",
|
|
382
|
+
type: "text",
|
|
383
|
+
label: { en: "First Name", fr: "PrΓ©nom", es: "Nombre" },
|
|
384
|
+
placeholder: {
|
|
385
|
+
en: "Enter your first name",
|
|
386
|
+
fr: "Entrez votre prΓ©nom",
|
|
387
|
+
es: "Ingrese su nombre"
|
|
388
|
+
},
|
|
389
|
+
validations: {
|
|
390
|
+
required: {
|
|
391
|
+
en: "First name is required",
|
|
392
|
+
fr: "Le prΓ©nom est obligatoire",
|
|
393
|
+
es: "El nombre es obligatorio"
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
]
|
|
398
|
+
}
|
|
399
|
+
]
|
|
400
|
+
};
|
|
401
|
+
```
|
|
402
|
+
|
|
403
|
+
> **Note:** The library provides the I18n structure. You'll need to implement locale selection and text resolution in your application layer.
|
|
404
|
+
|
|
405
|
+
---
|
|
406
|
+
|
|
217
407
|
## Custom Field Renderers
|
|
218
408
|
|
|
219
409
|
Override any default renderer by supplying your own component:
|
|
@@ -258,14 +448,23 @@ validations: {
|
|
|
258
448
|
|
|
259
449
|
---
|
|
260
450
|
|
|
261
|
-
##
|
|
451
|
+
## Real-World Enterprise Usage
|
|
262
452
|
|
|
263
|
-
|
|
264
|
-
|
|
453
|
+
```text
|
|
454
|
+
Backend β returns FormDTO
|
|
455
|
+
Frontend β renders form dynamically
|
|
456
|
+
Backend updates β UI changes without redeploy
|
|
457
|
+
```
|
|
458
|
+
|
|
459
|
+
This enables:
|
|
460
|
+
|
|
461
|
+
- Backend-driven workflows
|
|
462
|
+
- Feature flags via schemas
|
|
463
|
+
- Faster iteration without frontend releases
|
|
265
464
|
|
|
266
465
|
---
|
|
267
466
|
|
|
268
|
-
##
|
|
467
|
+
## Other Use Cases
|
|
269
468
|
|
|
270
469
|
- Admin dashboards
|
|
271
470
|
- Internal enterprise tools
|
|
@@ -275,6 +474,23 @@ validations: {
|
|
|
275
474
|
|
|
276
475
|
---
|
|
277
476
|
|
|
477
|
+
## Performance Characteristics
|
|
478
|
+
|
|
479
|
+
- Independent field rendering
|
|
480
|
+
- Section-level isolation
|
|
481
|
+
- Optimized for 100+ field forms
|
|
482
|
+
- No unnecessary re-renders across sections
|
|
483
|
+
|
|
484
|
+
---
|
|
485
|
+
|
|
486
|
+
## Incremental Adoption Strategy
|
|
487
|
+
|
|
488
|
+
- Use React Form DTO for large dynamic forms
|
|
489
|
+
- Keep React Hook Form for small custom forms
|
|
490
|
+
- Share validation logic between both
|
|
491
|
+
|
|
492
|
+
---
|
|
493
|
+
|
|
278
494
|
## Roadmap (Suggested)
|
|
279
495
|
|
|
280
496
|
- Field registry API (`registerFieldType`)
|
|
@@ -286,11 +502,18 @@ validations: {
|
|
|
286
502
|
|
|
287
503
|
## π€ Contributing
|
|
288
504
|
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
505
|
+
Contributions are welcome and encouraged.
|
|
506
|
+
|
|
507
|
+
1. Fork the repository
|
|
508
|
+
2. Create a feature branch
|
|
509
|
+
`git checkout -b feature/my-feature`
|
|
510
|
+
3. Commit your changes
|
|
511
|
+
`git commit -m "Add my feature"`
|
|
512
|
+
4. Push to the branch
|
|
513
|
+
`git push origin feature/my-feature`
|
|
514
|
+
5. Open a Pull Request
|
|
515
|
+
|
|
516
|
+
Please keep changes focused and well-documented.
|
|
294
517
|
|
|
295
518
|
---
|
|
296
519
|
|
|
@@ -300,4 +523,4 @@ MIT
|
|
|
300
523
|
|
|
301
524
|
---
|
|
302
525
|
|
|
303
|
-
**React Form DTO β Schema-first forms for Material UI**
|
|
526
|
+
**React Form DTO β Schema-first forms for Material UI**
|
|
@@ -23,6 +23,8 @@ type FormBuilderProps = {
|
|
|
23
23
|
dto: FormDTO;
|
|
24
24
|
/** Optional custom renderers for specific field types */
|
|
25
25
|
renderers?: Record<string, React.ComponentType<any>>;
|
|
26
|
+
/** Current locale for i18n string resolution (default: 'en') */
|
|
27
|
+
locale?: string;
|
|
26
28
|
};
|
|
27
29
|
/**
|
|
28
30
|
* FormBuilder component that dynamically renders a form based on a FormDTO definition.
|
|
@@ -13,6 +13,8 @@ type SectionProps = {
|
|
|
13
13
|
/** Optional custom renderers for specific field types */
|
|
14
14
|
renderers?: Record<string, React.ComponentType<any>>;
|
|
15
15
|
validateField: (id: string) => string[];
|
|
16
|
+
/** Current locale for i18n string resolution (default: 'en') */
|
|
17
|
+
locale?: string;
|
|
16
18
|
};
|
|
17
19
|
/**
|
|
18
20
|
* Section component that renders a form section with its heading, description, and fields.
|
|
@@ -13,4 +13,4 @@ import { FieldRendererProps } from '../../components/Field';
|
|
|
13
13
|
* onChange={handleChange}
|
|
14
14
|
* />
|
|
15
15
|
*/
|
|
16
|
-
export declare function CheckBoxInput({ field, value, onChange, error, }: FieldRendererProps): import("react/jsx-runtime").JSX.Element;
|
|
16
|
+
export declare function CheckBoxInput({ field, value, onChange, error, locale, }: FieldRendererProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -13,4 +13,4 @@ import { FieldRendererProps } from '../../components/Field';
|
|
|
13
13
|
* onChange={handleChange}
|
|
14
14
|
* />
|
|
15
15
|
*/
|
|
16
|
-
export declare function SelectInput({ field, value, onChange, error, }: FieldRendererProps): import("react/jsx-runtime").JSX.Element;
|
|
16
|
+
export declare function SelectInput({ field, value, onChange, error, locale, }: FieldRendererProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -13,4 +13,4 @@ import { FieldRendererProps } from '../../components/Field';
|
|
|
13
13
|
* onChange={handleChange}
|
|
14
14
|
* />
|
|
15
15
|
*/
|
|
16
|
-
export declare function TextInput({ field, value, onChange, error, }: FieldRendererProps): import("react/jsx-runtime").JSX.Element;
|
|
16
|
+
export declare function TextInput({ field, value, onChange, error, locale, }: FieldRendererProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -12,7 +12,7 @@ type Errors = Record<string, string | null>;
|
|
|
12
12
|
* form.handleChange('email', 'user@example.com');
|
|
13
13
|
* const errors = form.validateAll();
|
|
14
14
|
*/
|
|
15
|
-
export declare function useFormBuilder(dto: FormDTO): {
|
|
15
|
+
export declare function useFormBuilder(dto: FormDTO, locale?: string): {
|
|
16
16
|
/** Current form values for all fields */
|
|
17
17
|
values: Record<string, any>;
|
|
18
18
|
/** Function to update a field value */
|