extended-dynamic-forms 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. package/README.md +398 -1075
  2. package/dist/WizardForm.d.ts +4 -1
  3. package/dist/events/FormEventContext.d.ts +3 -0
  4. package/dist/events/FormEventHub.d.ts +19 -2
  5. package/dist/index.es.js +21051 -12923
  6. package/dist/index.umd.js +63 -36
  7. package/dist/style.css +1 -1
  8. package/dist/types/index.d.ts +6 -1
  9. package/dist/utils/fieldChangeDetector.d.ts +22 -0
  10. package/dist/widgets/base/index.d.ts +2 -0
  11. package/dist/widgets/base/types.d.ts +135 -0
  12. package/dist/widgets/base/utils.d.ts +63 -0
  13. package/dist/widgets/choice/ChoiceWidget.d.ts +30 -0
  14. package/dist/widgets/choice/ChoiceWidget.types.d.ts +496 -0
  15. package/dist/widgets/choice/examples/ChoiceWidget.example.d.ts +7 -0
  16. package/dist/widgets/choice/hooks/__tests__/useChoiceWidget.test.d.ts +1 -0
  17. package/dist/widgets/choice/hooks/__tests__/useDataSource.test.d.ts +1 -0
  18. package/dist/widgets/choice/hooks/examples/useChoiceWidget.example.d.ts +18 -0
  19. package/dist/widgets/choice/hooks/examples/useDataSourceExample.d.ts +22 -0
  20. package/dist/widgets/choice/hooks/index.d.ts +6 -0
  21. package/dist/widgets/choice/hooks/useChoiceWidget.d.ts +65 -0
  22. package/dist/widgets/choice/hooks/useDataSource.d.ts +69 -0
  23. package/dist/widgets/choice/index.d.ts +59 -0
  24. package/dist/widgets/choice/presenters/CheckboxPresenter.d.ts +70 -0
  25. package/dist/widgets/choice/presenters/DropdownPresenter.d.ts +37 -0
  26. package/dist/widgets/choice/presenters/PresenterStrategy.d.ts +230 -0
  27. package/dist/widgets/choice/presenters/RadioPresenter.d.ts +39 -0
  28. package/dist/widgets/choice/presenters/examples/RadioPresenterExample.d.ts +7 -0
  29. package/dist/widgets/choice/presenters/index.d.ts +20 -0
  30. package/dist/widgets/choice/providers/ApiDataSource.d.ts +241 -0
  31. package/dist/widgets/choice/providers/DataSourceProvider.d.ts +260 -0
  32. package/dist/widgets/choice/providers/StaticDataSource.d.ts +258 -0
  33. package/dist/widgets/choice/providers/WebSocketDataSource.d.ts +310 -0
  34. package/dist/widgets/choice/providers/index.d.ts +12 -0
  35. package/dist/widgets/choice/utils/index.d.ts +1 -0
  36. package/dist/widgets/choice/utils/responseMappers.d.ts +342 -0
  37. package/dist/widgets/date/DateTimeWidget.d.ts +26 -0
  38. package/dist/widgets/date/EnhancedDateWidget.d.ts +26 -0
  39. package/dist/widgets/date/index.d.ts +13 -0
  40. package/dist/widgets/file/FileUploadWidget.d.ts +40 -0
  41. package/dist/widgets/file/index.d.ts +2 -0
  42. package/dist/widgets/index.d.ts +33 -17
  43. package/dist/widgets/input/EmailWidget.d.ts +34 -0
  44. package/dist/widgets/input/NumberWidget.d.ts +39 -0
  45. package/dist/widgets/input/TelephoneWidget.d.ts +34 -0
  46. package/dist/widgets/input/URLWidget.d.ts +34 -0
  47. package/dist/widgets/input/index.d.ts +7 -0
  48. package/dist/widgets/text/PasswordWidget.d.ts +45 -0
  49. package/dist/widgets/text/TextWidget.d.ts +40 -0
  50. package/dist/widgets/text/TextareaWidget.d.ts +38 -0
  51. package/dist/widgets/text/index.d.ts +20 -0
  52. package/package.json +8 -8
  53. package/dist/vanilla-entry.d.ts +0 -204
  54. package/dist/widgets/enhanced/EnhancedWidgets.d.ts +0 -37
  55. package/examples/conditional-v2-example.tsx +0 -64
  56. package/examples/dynamic-array-items-example.tsx +0 -211
  57. package/examples/form-devtools-example.tsx +0 -384
  58. package/examples/global-ui-rules-example.tsx +0 -371
  59. package/examples/vanilla-js/README.md +0 -212
  60. package/examples/vanilla-js/basic-form.html +0 -142
  61. package/examples/vanilla-js/conditional-form.html +0 -159
  62. package/examples/vanilla-js/wizard-form.html +0 -185
package/README.md CHANGED
@@ -1,1220 +1,543 @@
1
1
  # Extended Dynamic Forms
2
2
 
3
- ## 🚨 BREAKING CHANGE: v0.2.0 - JsonLogic Only Conditions
3
+ ## BREAKING CHANGE: v0.2.0
4
4
 
5
- > **⚠️ IMPORTANT**: Starting with v0.2.0, Extended Dynamic Forms **ONLY** supports JsonLogic for conditional logic. Function-based conditions are no longer supported. This is a breaking change that improves security, performance, and maintainability.
6
- >
7
- > **Migration Required**: If you are using function-based conditions like `condition: (formData) => ...`, you must migrate to JsonLogic format: `condition: { "==": [{ "var": "fieldName" }, "value"] }`
5
+ All conditional logic now uses **JsonLogic rules only** for conditions. Function-based conditions have been removed for security and portability. Note that validation effects may still use functions. See migration examples below.
8
6
 
9
- ## ⚠️ Project Status: Active Development & Documentation Refinement
7
+ ## Project Status
10
8
 
11
- **Important Notice**: This project is currently undergoing significant documentation updates to better reflect the actual implementation. Some features described in this README may not be fully implemented or may differ from the documentation. We are actively working to align the documentation with the codebase.
9
+ **Important Notes:**
10
+ - Requires RJSF source in sibling directory for development
11
+ - Cannot be installed from npm due to local file dependencies
12
+ - JSON logic conditions don't work with vanilla JavaScript builds
13
+ - Array drag-and-drop is not implemented
14
+ - Limited test coverage for UI components and event system
15
+ - JSON Patch implementation supports add/remove/replace only (not move/copy/test)
12
16
 
13
- **Known Issues**:
14
- - The project currently uses local file dependencies that require a specific directory structure to build
15
- - The project requires RJSF packages from a sibling directory (../react-jsonschema-form/)
16
- - Some playground demos use deprecated v1 conditional patterns (01-simple-conditionals.demo.tsx)
17
- - Array drag-and-drop functionality mentioned in documentation is not implemented
18
- - Test coverage is limited for UI components and event systems
19
- - Several documented features have incomplete implementations
20
- - Significant dead code: 76% of utility functions are unused (13 out of 17 functions)
21
- - JSON Patch implementation in v2 doesn't fully comply with RFC 6902 (no move/copy/test operations)
17
+ ## Overview
22
18
 
23
- **A revolutionary extension library for [React JSON Schema Form (RJSF)](https://github.com/rjsf-team/react-jsonschema-form)** that transforms schema-driven forms into sophisticated, enterprise-ready applications with O(N) performance and professional UI components.
19
+ Extended Dynamic Forms is an extension library for React JSON Schema Form (RJSF) v6 that adds:
24
20
 
25
- Built on top of the excellent RJSF v6 foundation, this library introduces the **Three Pillars v2 Architecture** for conditional logic, multi-step wizard orchestration, central event systems with webhook integration, and a comprehensive suite of 25+ Ant Design components.
26
-
27
- [![npm version](https://img.shields.io/npm/v/extended-dynamic-forms.svg)](https://www.npmjs.com/package/extended-dynamic-forms)
28
- [![MIT License](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/user/extended-dynamic-forms/blob/main/LICENSE)
29
- [![Built on RJSF](https://img.shields.io/badge/built%20on-RJSF%20v6-brightgreen)](https://github.com/rjsf-team/react-jsonschema-form)
30
- [![TypeScript](https://img.shields.io/badge/TypeScript-Ready-blue.svg)](https://www.typescriptlang.org/)
31
- [![Standalone JS](https://img.shields.io/badge/Vanilla%20JS-Supported-orange.svg)](#standalone-javascript-support)
32
-
33
- ## Why Extended Dynamic Forms?
34
-
35
- While [RJSF](https://github.com/rjsf-team/react-jsonschema-form) provides an excellent foundation for generating forms from JSON Schema, enterprise applications demand more sophisticated capabilities:
36
-
37
- ### 🚀 **Performance Revolution**
38
- - **O(N) Conditional Logic**: Advanced Three Pillars v2 architecture vs traditional O(M×N) systems
39
- - **Optimized Array Processing**: Per-item evaluation with dynamic array conditionals
40
- - **Memory Efficient**: Immutable schema processing with intelligent caching
41
-
42
- ### 🎯 **Enterprise-Grade Features**
43
- - **Complex Conditional Logic**: Multi-field dependencies, nested conditions, and dynamic validation
44
- - **Multi-Step Workflows**: Automatic wizard detection with step-aware conditional logic
45
- - **Real-Time Integration**: Production-ready webhooks with retry logic and error isolation
46
- - **Professional UI**: Comprehensive suite of enhanced Ant Design components with consistent styling
47
-
48
- ### 🔄 **Developer Experience**
49
- - **Dual Architecture Support**: Modern React hooks + vanilla JavaScript compatibility
50
- - **Type-Safe Throughout**: Comprehensive TypeScript interfaces and validation
51
- - **Rich Ecosystem**: Interactive playground with comprehensive real-world demos
52
- - **Migration Ready**: Automated v1-to-v2 conversion utilities
53
-
54
- This library transforms RJSF from a simple form generator into a complete enterprise form solution while preserving its declarative approach.
55
-
56
- ## Core Features
57
-
58
- ### 🚀 Three Pillars v2 Architecture with JsonLogic
59
- - **UI Logic Pillar**: Control form appearance with JsonLogic conditions and JSON Patch operations
60
- - **Schema Logic Pillar**: Modify data structure with JsonLogic rules when truly needed
61
- - **Validation Logic Pillar**: Dynamic validation rules with JsonLogic conditions
62
- - **O(N) Performance**: Superior array handling vs v1's O(M×N)
63
- - **JsonLogic-Only**: Secure, data-driven conditions without code execution
64
- - **React Hooks**: Modern, declarative API with `useConditionalUi`, `useConditionalSchema`, `useConditionalValidation`
65
-
66
- ### 🎯 Declarative Conditional Logic with JsonLogic
67
- - Define complex form behavior with secure JsonLogic rules
68
- - Dynamic array support with per-item evaluation
69
- - No code execution - all conditions are data-driven
70
- - Type-safe with comprehensive TypeScript support
71
-
72
- ```tsx
73
- import { UiRule, JsonLogicRule } from 'extended-dynamic-forms/conditionals/v2';
74
-
75
- const uiRules: UiRule[] = [{
76
- name: 'Show premium features for premium users',
77
- condition: {
78
- "==": [{ "var": "accountType" }, "premium"]
79
- } as JsonLogicRule,
80
- effect: [
81
- { op: 'remove', path: '/premiumFeatures/ui:widget' }
82
- ]
83
- }];
84
- ```
85
-
86
- ### 🧙‍♂️ Multi-Step Wizard Forms
87
- - Automatic step detection from schema structure
88
- - **Full conditional logic support** with step-aware rule processing
89
- - Built-in progress indicators and navigation
90
- - Per-step validation
91
- - Supports both v1 conditions (deprecated) and v2 Three Pillars architecture
92
-
93
- **Step-Aware Conditional Logic**
94
-
95
- The `WizardForm` automatically filters and transforms conditional rules to work within the current step's context. This means you can define conditions that reference fields across different steps, and the wizard will intelligently apply only the relevant rules for the active step:
96
-
97
- ```tsx
98
- // Define steps with prefixed field names to avoid collisions
99
- const schema = {
100
- type: 'object',
101
- properties: {
102
- STEP_PERSONAL: {
103
- type: 'object',
104
- title: 'Personal Information',
105
- properties: {
106
- isUSCitizen: { type: 'boolean', title: 'Are you a US Citizen?' },
107
- ssn: { type: 'string', title: 'Social Security Number' }
108
- }
109
- }
110
- // ... other steps
111
- }
112
- };
113
-
114
- // Use v2 UiRules with JsonLogic to handle step-aware conditionals
115
- const uiRules: UiRule[] = [{
116
- name: 'Show SSN only for US Citizens in Personal step',
117
- condition: {
118
- "!": { "var": "STEP_PERSONAL.isUSCitizen" }
119
- } as JsonLogicRule,
120
- effect: [
121
- { op: 'add', path: '/STEP_PERSONAL/properties/ssn/ui:widget', value: 'hidden' }
122
- ]
123
- }];
124
-
125
- // The WizardForm handles the step isolation automatically
126
- ```
127
-
128
- ### 🔗 Central Event Orchestration
129
- - Unified event system for all field interactions
130
- - Webhook integration with retry logic
131
- - Real-time form analytics capabilities
132
- - Debounced event processing
133
-
134
- ### 🎨 Ant Design Components
135
- - Complete widget suite built with Ant Design v5
136
- - Enhanced standard widgets with event integration
137
- - Custom widgets: Rating, Color Picker, Range Slider
138
- - Professional field components: Address, Phone, Currency
139
-
140
- ### ⚡ Form Lifecycle Hooks
141
- - Intercept and modify form data at key stages
142
- - `beforeSubmit`, `afterSubmit`, `beforeValidation`, `afterValidation`
143
- - Ideal for data transformation, logging, or triggering side effects
144
-
145
- ### 📦 Additional Features
146
- - **TypeScript**: Full type safety and IntelliSense with comprehensive interface definitions
147
- - **Performance**: Optimized re-renders and memoization with intelligent caching
148
- - **Extensible**: Add custom widgets, fields, and actions with clean APIs
149
- - **Test Coverage**: Focused on conditional logic and wizard forms (UI components have limited coverage)
150
- - **Developer Experience**: Interactive playground with real-world demos (note: some deprecated)
151
-
152
- ### 🌐 Standalone JavaScript Support
153
-
154
- **Complete vanilla JavaScript compatibility** with a production-ready UMD bundle that includes React, Ant Design, and all dependencies:
155
-
156
- ```html
157
- <!DOCTYPE html>
158
- <html>
159
- <head>
160
- <script src="https://unpkg.com/extended-dynamic-forms/dist/standalone.umd.js"></script>
161
- <link rel="stylesheet" href="https://unpkg.com/extended-dynamic-forms/dist/style.css">
162
- </head>
163
- <body>
164
- <div id="form-container"></div>
165
-
166
- <script>
167
- const { createForm, createWizard } = ExtendedDynamicForms;
168
-
169
- // Create a complete form without React knowledge
170
- const form = createForm({
171
- schema: {
172
- type: 'object',
173
- properties: {
174
- name: { type: 'string', title: 'Full Name' },
175
- email: { type: 'string', format: 'email', title: 'Email' }
176
- }
177
- },
178
- container: document.getElementById('form-container'),
179
- onSubmit: (data) => console.log('Form submitted:', data)
180
- });
181
- </script>
182
- </body>
183
- </html>
184
- ```
185
-
186
- **Important Notes on Conditional Logic in Vanilla JS:**
187
- - **JsonLogic is NOT supported in vanilla JS** - The JsonLogic runtime requires React hooks
188
- - Only v1 conditions are supported with the `conditionals` prop
189
- - Subject to v1's O(M×N) performance for array conditionals
190
- - For JsonLogic and v2 benefits, you must use the React-based API
191
-
192
- ```javascript
193
- // Vanilla JS supports only v1 conditionals
194
- ExtendedDynamicForms.createForm({
195
- container: '#my-form',
196
- schema: schema,
197
- conditionals: {
198
- rules: [
199
- {
200
- conditions: { showField: true },
201
- event: { type: 'show', params: { field: 'conditionalField' } }
202
- }
203
- ]
204
- }
205
- });
206
- ```
207
-
208
- **Perfect for:**
209
- - WordPress/Drupal integrations
210
- - Legacy applications
211
- - CMS form builders
212
- - No-build environments
213
- - PHP/ASP.NET applications
214
-
215
- ## Credits & Acknowledgments
216
-
217
- This library is built on top of [React JSON Schema Form (RJSF)](https://github.com/rjsf-team/react-jsonschema-form), an amazing open-source project that provides the core form generation engine. We extend RJSF's capabilities while maintaining full compatibility with its ecosystem.
218
-
219
- Special thanks to the RJSF team and contributors for creating such a flexible and well-architected foundation.
21
+ - **Three Pillars Architecture** for conditional logic with O(N) performance (where N is the number of conditional rules/array items)
22
+ - **Multi-step wizard forms** with automatic step detection
23
+ - **Central event orchestration** with webhook support
24
+ - **25+ Ant Design components** for professional UI
25
+ - **TypeScript-first** development with full type safety
220
26
 
221
27
  ## Installation
222
28
 
223
- > ⚠️ **Important Note**: This library currently uses local file dependencies for RJSF packages (pointing to `../react-jsonschema-form/`). This means:
224
- > - The library cannot be installed directly from npm without modifications
225
- > - You need the RJSF source code in a sibling directory for development
226
- > - Consider using a monorepo structure or git submodules for proper dependency management
227
-
228
- ### React Projects
29
+ **Note:** This library currently requires local development setup and cannot be installed via npm due to local file dependencies.
229
30
 
230
31
  ```bash
231
- npm install extended-dynamic-forms
232
- # or
233
- yarn add extended-dynamic-forms
234
- # or
235
- pnpm add extended-dynamic-forms
236
- ```
237
-
238
- ### Standalone JavaScript (No Build Required)
239
-
240
- ```html
241
- <!-- Production CDN -->
242
- <script src="https://unpkg.com/extended-dynamic-forms@latest/dist/standalone.umd.js"></script>
243
- <link rel="stylesheet" href="https://unpkg.com/extended-dynamic-forms@latest/dist/style.css">
32
+ # Clone RJSF as sibling directory (required)
33
+ cd ..
34
+ git clone https://github.com/rjsf-team/react-jsonschema-form.git
244
35
 
245
- <!-- Or download and host locally -->
246
- <script src="./path/to/extended-dynamic-forms-standalone.js"></script>
247
- ```
248
-
249
- ### Peer Dependencies
250
-
251
- **Current Version**: `0.2.0` - Built for **RJSF v6** with Three Pillars v2 architecture (JsonLogic-only).
252
-
253
- ```json
254
- {
255
- "react": "^18.0.0 || ^19.0.0",
256
- "react-dom": "^18.0.0 || ^19.0.0",
257
- "antd": "^5.24.0"
258
- }
36
+ # Setup Extended Dynamic Forms
37
+ cd extended-dynamic-forms
38
+ npm install
39
+ npm run dev
259
40
  ```
260
41
 
261
- > **React 19 Support**: This library supports both React 18 and React 19. See [REACT-19-COMPATIBILITY.md](./REACT-19-COMPATIBILITY.md) for migration details.
262
-
263
- **RJSF Dependencies** (automatically handled):
264
- - `@rjsf/core`: ^6.0.0+
265
- - `@rjsf/utils`: ^6.0.0+
266
- - `@rjsf/validator-ajv8`: ^6.0.0+
267
- - `@rjsf/antd`: ^6.0.0+
42
+ **Important:** The library is currently designed for internal use or as part of a monorepo setup. Standalone npm package distribution is not yet supported.
268
43
 
269
- > **Development Note**: This library is currently developed against RJSF v6 and includes all necessary RJSF dependencies. No additional RJSF packages need to be installed separately.
44
+ ## Core Architecture
270
45
 
271
- **Additional Dependencies**:
272
- - `dayjs`: ^1.11.13 (Date handling)
273
- - `json-rules-engine-simplified`: ^0.2.0 (v1 conditional logic)
46
+ ### Three Pillars Conditional System
274
47
 
275
- > **Note**: This library is specifically built for RJSF v6 to leverage the latest performance improvements and API enhancements. All examples and documentation assume RJSF v6.
48
+ The conditional logic system is divided into three independent pillars:
276
49
 
277
- ## Setup
50
+ #### 1. UI Logic Pillar
51
+ Controls form appearance using JsonLogic conditions and JSON Patch operations:
278
52
 
279
- ### CSS Requirements
280
-
281
- This package uses Ant Design components. Import the CSS in your application:
53
+ ```typescript
54
+ import { useConditionalUi, UiRule } from 'extended-dynamic-forms/conditionals/v2';
282
55
 
283
- ```tsx
284
- // In your main entry file (e.g., App.tsx or index.tsx)
285
- import 'extended-dynamic-forms/dist/style.css'; // Or your specific CSS entry point
286
- ```
56
+ const uiRules: UiRule[] = [{
57
+ name: 'Show license number when has license',
58
+ condition: { "==": [{ "var": "hasDriversLicense" }, true] },
59
+ effect: [{ op: 'remove', path: '/licenseNumber/ui:widget' }]
60
+ }];
287
61
 
288
- ### Theming & Customization
289
-
290
- Since Extended Dynamic Forms uses Ant Design components, you can customize the appearance using Ant Design's powerful theming system:
291
-
292
- ```tsx
293
- import { ConfigProvider, theme } from 'antd';
294
- import { ExtendedForm, WizardForm } from 'extended-dynamic-forms';
295
-
296
- function App() {
297
- return (
298
- <ConfigProvider
299
- theme={{
300
- token: {
301
- colorPrimary: '#00b96b',
302
- borderRadius: 8,
303
- fontSize: 16,
304
- },
305
- algorithm: theme.darkAlgorithm, // Optional: Use dark theme
306
- }}
307
- >
308
- <WizardForm
309
- schema={schema}
310
- uiSchema={uiSchema}
311
- conditionals={conditionals}
312
- />
313
- </ConfigProvider>
314
- );
315
- }
62
+ const conditionalUiSchema = useConditionalUi(uiRules, baseUiSchema, formData);
316
63
  ```
317
64
 
318
- ## Three Pillars v2 Architecture with JsonLogic (Required Approach)
319
-
320
- > ⚠️ **BREAKING CHANGE**: As of v0.2.0, the Three Pillars v2 system ONLY supports JsonLogic conditions. Function-based conditions are no longer supported for security and maintainability reasons.
321
-
322
- The Three Pillars v2 system with JsonLogic provides superior performance, cleaner separation of concerns, and better security. It consists of three independent pillars:
323
-
324
- ### 1. UI Logic Pillar (`useConditionalUi`)
325
-
326
- Controls form appearance using JSON Patch operations with JsonLogic conditions:
327
-
328
- ```tsx
329
- // Note: v2 conditionals require deep import for optimal tree-shaking
330
- import { useConditionalUi, UiRule, JsonLogicRule } from 'extended-dynamic-forms/conditionals/v2';
331
-
332
- // Define UI rules with JsonLogic conditions and JSON Patch operations
333
- const uiRules: UiRule[] = [
334
- {
335
- name: 'Show shipping address when required',
336
- condition: {
337
- "==": [{ "var": "requiresShipping" }, true]
338
- } as JsonLogicRule,
339
- effect: [{ op: 'remove', path: '/shippingAddress/ui:widget' }],
340
- order: 1
341
- },
342
- {
343
- name: 'Dynamic country fields',
344
- condition: {
345
- "==": [{ "var": "shippingAddress.country" }, "USA"]
346
- } as JsonLogicRule,
347
- effect: [
348
- { op: 'remove', path: '/shippingAddress/state/ui:widget' },
349
- { op: 'add', path: '/shippingAddress/province/ui:widget', value: 'hidden' }
350
- ],
351
- order: 2
352
- }
353
- ];
354
-
355
- const baseUiSchema = {
356
- shippingAddress: {
357
- 'ui:widget': 'hidden', // Initially hidden
358
- state: { 'ui:widget': 'text' },
359
- province: { 'ui:widget': 'hidden' } // Initially hidden
360
- }
361
- };
65
+ #### 2. Schema Logic Pillar
66
+ Modifies JSON Schema structure dynamically (use sparingly):
362
67
 
363
- // In your component
364
- function MyForm() {
365
- const [formData, setFormData] = useState({});
366
-
367
- // IMPORTANT: Define rules outside render or memoize them!
368
- const conditionalUiSchema = useConditionalUi(uiRules, baseUiSchema, formData);
369
-
370
- return (
371
- <ExtendedForm
372
- schema={schema}
373
- uiSchema={conditionalUiSchema}
374
- formData={formData}
375
- onChange={({ formData }) => setFormData(formData)}
376
- />
377
- );
378
- }
68
+ ```typescript
69
+ const schemaRules: SchemaRule[] = [{
70
+ name: 'Add premium fields',
71
+ condition: { "==": [{ "var": "accountType" }, "premium"] },
72
+ effect: [{ op: 'add', path: '/properties/premiumFeatures', value: {...} }]
73
+ }];
379
74
  ```
380
75
 
381
- ### 2. Schema Logic Pillar (`useConditionalSchema`)
382
-
383
- Modifies JSON Schema structure (use sparingly - prefer UI or Validation pillars):
384
-
385
- ```tsx
386
- import { useConditionalSchema, SchemaRule, JsonLogicRule } from 'extended-dynamic-forms/conditionals/v2';
387
-
388
- const schemaRules: SchemaRule[] = [
389
- {
390
- name: 'Add premium fields',
391
- condition: {
392
- "==": [{ "var": "accountType" }, "premium"]
393
- } as JsonLogicRule,
394
- effect: [
395
- {
396
- op: 'add',
397
- path: '/properties/premiumFeatures',
398
- value: {
399
- type: 'object',
400
- properties: {
401
- priority: { type: 'string', enum: ['high', 'medium', 'low'] }
402
- }
403
- }
404
- }
405
- ]
406
- }
407
- ];
76
+ #### 3. Validation Logic Pillar
77
+ Adds conditional validation rules:
408
78
 
409
- const conditionalSchema = useConditionalSchema(schemaRules, baseSchema, formData);
410
- ```
411
-
412
- ### 3. Validation Logic Pillar (`useConditionalValidation`)
413
-
414
- Adds conditional validation without modifying schema:
415
-
416
- ```tsx
417
- import { useMemo } from 'react';
418
- import { useConditionalValidation, ValidationRule, JsonLogicRule, createCustomValidate } from 'extended-dynamic-forms/conditionals/v2';
419
-
420
- const validationRules: ValidationRule[] = [
421
- {
422
- name: 'Require consent for minors',
423
- condition: {
424
- "<": [{ "var": "age" }, 18]
425
- } as JsonLogicRule,
426
- effect: {
427
- type: 'validation',
428
- validate: (errors, formData) => {
429
- if (!formData.parentConsent) {
430
- errors.parentConsent.addError('Parent consent is required for minors');
431
- }
79
+ ```typescript
80
+ const validationRules: ValidationRule[] = [{
81
+ name: 'Require consent for minors',
82
+ condition: { "<": [{ "var": "age" }, 18] },
83
+ effect: {
84
+ name: 'Parent consent validation',
85
+ isActive: { "<": [{ "var": "age" }, 18] },
86
+ validate: (errors, formData) => {
87
+ if (!formData.parentConsent) {
88
+ errors.parentConsent.__errors = ['Parent consent required'];
432
89
  }
433
90
  }
434
91
  }
435
- ];
436
-
437
- // In your component
438
- function MyForm({ schema }) {
439
- const [formData, setFormData] = useState({});
440
-
441
- // 1. Get the conditional validation configuration
442
- const conditionalValidationConfig = useConditionalValidation(validationRules, {}, formData);
443
-
444
- // 2. Create the memoized validate function
445
- const customValidate = useMemo(
446
- () => createCustomValidate(conditionalValidationConfig),
447
- [conditionalValidationConfig]
448
- );
449
-
450
- // 3. Use with ExtendedForm
451
- return (
452
- <ExtendedForm
453
- schema={schema}
454
- formData={formData}
455
- onChange={({ formData }) => setFormData(formData)}
456
- customValidate={customValidate}
457
- />
458
- );
459
- }
92
+ }];
460
93
  ```
461
94
 
462
95
  ### Dynamic Arrays with O(N) Performance
463
96
 
464
- #### **The Performance Revolution: `createDynamicArrayItemsUiSchema`**
465
-
466
- One of the most significant breakthroughs in v2 is the `createDynamicArrayItemsUiSchema` function, which enables **true O(N) performance** for array conditionals. This is a fundamental improvement over traditional form libraries that struggle with dynamic array logic.
467
-
468
- **How It Works:**
469
- - **Per-Item Evaluation**: Each array item's conditionals are evaluated independently during render
470
- - **No Rule Explosion**: Unlike v1's wildcard expansion, no rules are multiplied by array size
471
- - **React-Optimized**: Leverages React's rendering cycle for optimal performance
97
+ Provides efficient handling of conditional logic within arrays, where N is the number of array items:
472
98
 
473
- > **Note**: `createDynamicArrayItemsUiSchema` still supports function-based conditions as it evaluates per-item during render. This is not a security risk as the functions are defined in your code, not from user input.
474
-
475
- ```tsx
99
+ ```typescript
476
100
  import { createDynamicArrayItemsUiSchema } from 'extended-dynamic-forms/conditionals/v2';
477
101
 
478
- // Define per-item conditional logic - this function runs for each array item
479
- const directorItemConditions = (director, index) => ({
480
- shareholdingPercentage: {
481
- 'ui:widget': director.hasShareholding ? 'percentage' : 'hidden'
482
- },
483
- tfn: {
484
- 'ui:widget': director.isAustralianResident ? 'text' : 'hidden'
485
- },
486
- passport: {
487
- 'ui:widget': !director.isAustralianResident ? 'text' : 'hidden'
488
- },
489
- // Add visual indicator for the chairman
490
- 'ui:classNames': index === 0 ? 'chairman-director' : 'regular-director'
491
- });
492
-
493
- // Apply to your array field
494
102
  const uiSchema = {
495
103
  directors: {
496
- 'ui:title': 'Company Directors',
497
- 'ui:description': 'Add all company directors and their details',
498
- items: createDynamicArrayItemsUiSchema(directorItemConditions)
104
+ items: createDynamicArrayItemsUiSchema((director, index) => ({
105
+ shareholdingPercentage: {
106
+ 'ui:widget': director.hasShareholding ? 'percentage' : 'hidden'
107
+ }
108
+ }))
499
109
  }
500
110
  };
501
111
  ```
502
112
 
503
- **Performance Comparison:**
113
+ ## Multi-Step Wizard Forms
114
+
115
+ Create wizard forms with automatic step detection:
116
+
504
117
  ```typescript
505
- // ❌ Traditional approach: O(M×N) - Rules × Array Items
506
- // With 10 rules and 50 directors = 500 evaluations
118
+ import { WizardForm } from 'extended-dynamic-forms';
507
119
 
508
- // ✅ v2 approach: O(N) - Per-item evaluation
509
- // With 50 directors = 50 evaluations (regardless of rule complexity)
120
+ <WizardForm
121
+ schema={wizardSchema}
122
+ uiSchema={conditionalUiSchema}
123
+ formData={formData}
124
+ onStepChange={(fromStep, toStep) => {
125
+ console.log(`Step ${fromStep} → ${toStep}`);
126
+ }}
127
+ />
510
128
  ```
511
129
 
512
- **Advanced Patterns:**
513
- ```tsx
514
- // Complex business logic with multiple conditions
515
- const productItemConditions = (product, index) => {
516
- const baseConfig = {
517
- price: { 'ui:widget': 'currency' },
518
- quantity: { 'ui:widget': 'number' }
519
- };
520
-
521
- // Category-specific fields
522
- if (product.category === 'software') {
523
- baseConfig.licenseType = { 'ui:widget': 'select' };
524
- baseConfig.maintenancePeriod = { 'ui:widget': 'hidden' };
525
- }
130
+ **Important:** Wizard forms flatten nested step data. Use flat paths in conditions:
526
131
 
527
- // Subscription-specific logic
528
- if (product.billingType === 'subscription') {
529
- baseConfig.recurringPrice = { 'ui:widget': 'currency' };
530
- baseConfig.billingCycle = { 'ui:widget': 'select' };
132
+ ```typescript
133
+ // Schema uses STEP_ prefixes
134
+ const schema = {
135
+ properties: {
136
+ STEP_PERSONAL: {
137
+ properties: {
138
+ hasDriversLicense: { type: 'boolean' }
139
+ }
140
+ }
531
141
  }
532
-
533
- return baseConfig;
534
142
  };
535
- ```
536
143
 
537
- ### Performance Best Practices
144
+ // Conditions use flat paths (no STEP_ prefix)
145
+ condition: { "==": [{ "var": "hasDriversLicense" }, true] }
146
+ ```
538
147
 
539
- > ⚠️ **Critical**: Always define rules and base schemas outside render or memoize them!
148
+ ## Event System & Webhooks
540
149
 
541
- ```tsx
542
- // ❌ BAD - Creates new objects every render
543
- function MyForm() {
544
- const conditionalUiSchema = useConditionalUi(
545
- [{ condition: () => true, effect: [...] }], // New array every render!
546
- { field: { 'ui:widget': 'text' } }, // New object every render!
547
- formData
548
- );
549
- }
150
+ Central event orchestration for all form interactions:
550
151
 
551
- // ✅ GOOD - Stable references
552
- const rules = [{ condition: () => true, effect: [...] }];
553
- const baseUiSchema = { field: { 'ui:widget': 'text' } };
554
-
555
- function MyForm() {
556
- const conditionalUiSchema = useConditionalUi(rules, baseUiSchema, formData);
557
- }
152
+ ```typescript
153
+ <ExtendedForm
154
+ schema={schema}
155
+ uiSchema={uiSchema}
156
+ webhooks={[{
157
+ url: 'https://api.example.com/events',
158
+ events: ['change', 'blur'],
159
+ debounceMs: 500,
160
+ retries: 3
161
+ }]}
162
+ onFieldChange={(event) => console.log(event.fieldId, event.fieldValue)}
163
+ />
558
164
  ```
559
165
 
560
- ### JsonLogic Conditions (Required)
166
+ **Event Types:**
167
+ - `focus` - Field focus
168
+ - `blur` - Field blur
169
+ - `change` - Value changes
170
+ - `submit` - Form submission
171
+ - `stepChange` - Wizard navigation
172
+ - `validationError` - Validation failures
561
173
 
562
- As of v0.2.0, v2 ONLY supports JsonLogic conditions for security and maintainability:
174
+ ## Custom Widgets
563
175
 
564
- ```tsx
565
- import { JsonLogicRule, UiRule } from 'extended-dynamic-forms/conditionals/v2';
176
+ All widgets must integrate with the event system:
566
177
 
567
- // JsonLogic rule examples
568
- const simpleRule: UiRule = {
569
- name: 'Show field B when A is true',
570
- condition: { "==": [{ "var": "fieldA" }, true] } as JsonLogicRule,
571
- effect: [{ op: 'remove', path: '/fieldB/ui:widget' }]
572
- };
178
+ ```typescript
179
+ import { WidgetProps } from '@rjsf/utils';
180
+ import { useFieldEventHandlers } from 'extended-dynamic-forms/events';
573
181
 
574
- const complexRule: UiRule = {
575
- name: 'Complex business logic',
576
- condition: {
577
- "and": [
578
- { "==": [{ "var": "accountType" }, "premium"] },
579
- { ">": [{ "var": "revenue" }, 100000] },
580
- { "in": [{ "var": "country" }, ["USA", "Canada", "UK"]] }
581
- ]
582
- } as JsonLogicRule,
583
- effect: [{ op: 'remove', path: '/advancedFeatures/ui:widget' }]
182
+ export const CustomWidget: FC<WidgetProps> = ({ id, value, onChange, schema }) => {
183
+ const fieldEventHandlers = useFieldEventHandlers(id, schema);
184
+
185
+ const handleChange = async (newValue) => {
186
+ onChange(newValue); // RJSF update
187
+ await fieldEventHandlers.onChange(newValue); // Event system
188
+ };
189
+
190
+ return <Input value={value} onChange={(e) => handleChange(e.target.value)} />;
584
191
  };
585
192
  ```
586
193
 
587
- ## Quick Start
194
+ ## JsonLogic Migration Examples
588
195
 
589
- ### Simple Wizard Form (Recommended)
196
+ Common patterns for migrating from function-based conditions:
590
197
 
591
- The `WizardForm` component automatically detects multi-step forms and handles navigation. It fully supports conditional logic through either v1 conditions (deprecated) or the recommended Three Pillars v2 architecture:
198
+ ```typescript
199
+ // Equality
200
+ // Before: (formData) => formData.field === "value"
201
+ // After: { "==": [{ "var": "field" }, "value"] }
592
202
 
593
- ```tsx
594
- import { useState } from 'react';
595
- import { WizardForm } from 'extended-dynamic-forms';
596
- import { useConditionalUi, UiRule } from 'extended-dynamic-forms/conditionals/v2';
597
- import schema from './schema.json';
598
- import baseUiSchema from './ui-schema.json';
599
- import webhooks from './webhooks.json';
600
-
601
- // Example: v2 Three Pillars approach with JsonLogic (required)
602
- const uiRules: UiRule[] = [
603
- {
604
- name: 'Show tax ID in company step when listed',
605
- condition: {
606
- "==": [{ "var": "STEP_COMPANY.isListedCompany" }, true]
607
- } as JsonLogicRule,
608
- effect: [{ op: 'remove', path: '/STEP_COMPANY/taxId/ui:widget' }]
609
- },
610
- {
611
- name: 'Show shareholding percentage for directors with shares',
612
- condition: {
613
- "some": [
614
- { "var": "STEP_DIRECTORS.directors" },
615
- { "var": "hasShareholding" }
616
- ]
617
- } as JsonLogicRule,
618
- effect: [{ op: 'remove', path: '/STEP_DIRECTORS/directors/items/shareholdingPercentage/ui:widget' }]
619
- }
620
- ];
621
-
622
- function App() {
623
- const [formData, setFormData] = useState({});
624
- const conditionalUiSchema = useConditionalUi(uiRules, baseUiSchema, formData);
625
-
626
- return (
627
- <WizardForm
628
- schema={schema}
629
- uiSchema={conditionalUiSchema}
630
- formData={formData}
631
- onChange={({ formData }) => setFormData(formData)}
632
- webhooks={webhooks}
633
- onSubmit={(data) => console.log('Submitted:', data.formData)}
634
- />
635
- );
636
- }
203
+ // Boolean check
204
+ // Before: (formData) => formData.isEnabled
205
+ // After: { "var": "isEnabled" }
637
206
 
638
- // Alternative: v1 conditions approach (deprecated but still supported)
639
- const v1Conditions = [
640
- {
641
- conditions: { "STEP_COMPANY.isListedCompany": true },
642
- event: { type: "show", params: { field: "STEP_COMPANY.taxId" } }
643
- },
644
- {
645
- conditions: { "STEP_DIRECTORS.directors[*].hasShareholding": true },
646
- event: { type: "show", params: { field: "STEP_DIRECTORS.directors[*].shareholdingPercentage" } }
647
- }
648
- ];
207
+ // AND condition
208
+ // Before: (formData) => formData.a && formData.b
209
+ // After: { "and": [{ "var": "a" }, { "var": "b" }] }
649
210
 
650
- // Pass v1 conditions directly to WizardForm
651
- <WizardForm
652
- schema={schema}
653
- uiSchema={uiSchema}
654
- conditions={v1Conditions} // WizardForm handles step-aware transformation
655
- onSubmit={(data) => console.log('Submitted:', data.formData)}
656
- />
211
+ // Array contains
212
+ // Before: (formData) => formData.roles?.includes("admin")
213
+ // After: { "in": ["admin", { "var": "roles" }] }
657
214
  ```
658
215
 
659
- ### Basic Form with Three Pillars v2
660
-
661
- ```tsx
662
- import { ExtendedForm } from 'extended-dynamic-forms';
663
- import { useConditionalUi, UiRule, JsonLogicRule } from 'extended-dynamic-forms/conditionals/v2';
664
-
665
- const schema = {
666
- type: 'object',
667
- properties: {
668
- isStudent: { type: 'boolean', title: 'Are you a student?' },
669
- studentId: { type: 'string', title: 'Student ID' },
670
- school: { type: 'string', title: 'School Name' }
671
- }
672
- };
216
+ ## Available Widgets
673
217
 
674
- const baseUiSchema = {
675
- studentId: { 'ui:widget': 'text' },
676
- school: { 'ui:widget': 'text' }
677
- };
218
+ ### Complete Widget List
678
219
 
679
- // Define UI rules outside component with JsonLogic
680
- const uiRules: UiRule[] = [
681
- {
682
- name: 'Show student fields when student',
683
- condition: {
684
- "!": { "var": "isStudent" }
685
- } as JsonLogicRule,
686
- effect: [
687
- { op: 'add', path: '/studentId/ui:widget', value: 'hidden' },
688
- { op: 'add', path: '/school/ui:widget', value: 'hidden' }
689
- ]
690
- }
691
- ];
220
+ #### Choice Widget (Unified Selection)
221
+ - **ChoiceWidget** - Intelligent widget that automatically adapts based on schema:
222
+ - Renders as dropdown/select for regular choices
223
+ - Renders as radio group when `ui:widget` is "radio"
224
+ - Renders as checkbox group for multi-select arrays
225
+ - Supports static and dynamic data sources (API, WebSocket)
692
226
 
693
- function App() {
694
- const [formData, setFormData] = useState({});
695
- const conditionalUiSchema = useConditionalUi(uiRules, baseUiSchema, formData);
696
-
697
- return (
698
- <ExtendedForm
699
- schema={schema}
700
- uiSchema={conditionalUiSchema}
701
- formData={formData}
702
- onChange={({ formData }) => setFormData(formData)}
703
- />
704
- );
705
- }
706
- ```
227
+ #### Text Input Widgets
228
+ - **TextWidget** - Standard text input with Ant Design styling
229
+ - **TextareaWidget** - Multi-line text input
230
+ - **PasswordWidget** - Password input with visibility toggle
707
231
 
708
- ## Custom Widgets
232
+ #### Specialized Input Widgets
233
+ - **ColorWidget** - Color picker using HTML5 color input
234
+ - **EmailWidget** - Email input with validation
235
+ - **URLWidget** - URL input with validation
236
+ - **TelephoneWidget** - Phone number input
237
+ - **NumberWidget** - Numeric input with increment/decrement controls
709
238
 
710
- ### Available Widgets
239
+ #### Visual Input Widgets
240
+ - **RangeWidget** / **SliderWidget** - Slider for numeric ranges
241
+ - **RatingWidget** - Star rating component
711
242
 
712
- The library includes enhanced versions of all standard RJSF widgets plus custom ones:
243
+ #### Date & Time Widgets
244
+ - **DateWidget** / **EnhancedDateWidget** - Date picker with Ant Design DatePicker
245
+ - **DateTimeWidget** - Combined date and time picker
713
246
 
714
- #### Custom Widgets
247
+ #### File Upload Widgets
248
+ - **FileWidget** - Basic file input
249
+ - **FileUploadWidget** - Enhanced upload with progress, preview, and base64 support
715
250
 
716
- ```tsx
717
- // Color Picker
718
- const uiSchema = {
719
- favoriteColor: {
720
- 'ui:widget': 'color'
721
- }
722
- };
251
+ ### Widget Configuration Examples
723
252
 
724
- // Rating Widget
725
- const uiSchema = {
726
- satisfaction: {
727
- 'ui:widget': 'rating',
728
- 'ui:options': {
729
- max: 10 // default is 5
730
- }
253
+ #### Basic Text Input
254
+ ```json
255
+ {
256
+ "schema": {
257
+ "type": "string",
258
+ "title": "Full Name"
259
+ },
260
+ "uiSchema": {
261
+ "ui:widget": "text",
262
+ "ui:placeholder": "Enter your full name"
731
263
  }
732
- };
264
+ }
265
+ ```
733
266
 
734
- // Range Slider
735
- const schema = {
736
- volume: {
737
- type: 'number',
738
- minimum: 0,
739
- maximum: 100
740
- }
741
- };
742
- const uiSchema = {
743
- volume: {
744
- 'ui:widget': 'range'
267
+ #### Number Input with Range
268
+ ```json
269
+ {
270
+ "schema": {
271
+ "type": "number",
272
+ "title": "Age",
273
+ "minimum": 0,
274
+ "maximum": 120
275
+ },
276
+ "uiSchema": {
277
+ "ui:widget": "number"
745
278
  }
746
- };
279
+ }
280
+ ```
747
281
 
748
- // File Upload
749
- const uiSchema = {
750
- documents: {
751
- 'ui:widget': 'file',
752
- 'ui:options': {
753
- accept: '.pdf,.doc,.docx',
754
- multiple: true
282
+ #### Rating Widget
283
+ ```json
284
+ {
285
+ "schema": {
286
+ "type": "number",
287
+ "title": "Rate your experience",
288
+ "minimum": 0,
289
+ "maximum": 5
290
+ },
291
+ "uiSchema": {
292
+ "ui:widget": "rating",
293
+ "ui:options": {
294
+ "count": 5,
295
+ "allowHalf": true
755
296
  }
756
297
  }
757
- };
298
+ }
758
299
  ```
759
300
 
760
- #### Enhanced Standard Widgets
761
-
762
- All standard RJSF widgets are enhanced with:
763
- - **Event Integration**: Automatic integration with the central event system
764
- - **Ant Design Styling**: Modern, consistent appearance
765
- - **Error States**: Proper error indication and messaging
766
- - **Accessibility**: Enhanced ARIA support
767
-
768
- ### Array Templates
769
-
770
- The library provides Ant Design Card-based array templates for better visual organization:
771
- - **ArrayFieldTemplate**: Card container with proper spacing and visual hierarchy
772
- - **ArrayFieldItemTemplate**: Individual array items with integrated add/remove buttons
773
- - **Visual Design**: Clean card-based layout for array management
774
- - **Note**: Drag-and-drop reordering is not currently implemented
775
-
776
- ## Central Event Orchestration System
777
-
778
- ### Field-Level Event Handling
779
-
780
- ```tsx
781
- import { ExtendedForm, type FormFieldEvent } from 'extended-dynamic-forms';
782
-
783
- <ExtendedForm
784
- schema={schema}
785
- uiSchema={uiSchema}
786
- formData={formData}
787
-
788
- // Field-level event handlers
789
- onFieldFocus={(event: FormFieldEvent) => {
790
- console.log(`Field ${event.fieldId} focused:`, event.fieldValue);
791
- }}
792
-
793
- onFieldChange={(event: FormFieldEvent) => {
794
- console.log(`Field ${event.fieldId} changed:`, event.fieldValue);
795
- // Real-time validation or processing
796
- }}
797
-
798
- onFieldBlur={(event: FormFieldEvent) => {
799
- console.log(`Field ${event.fieldId} blurred:`, event.fieldValue);
800
- }}
801
- />
301
+ #### Choice Widget (Dropdown)
302
+ ```json
303
+ {
304
+ "schema": {
305
+ "type": "string",
306
+ "title": "Country",
307
+ "enum": ["us", "uk", "au", "ca"],
308
+ "enumNames": ["United States", "United Kingdom", "Australia", "Canada"]
309
+ },
310
+ "uiSchema": {
311
+ "ui:widget": "choice"
312
+ }
313
+ }
802
314
  ```
803
315
 
804
- ### Webhook Integration
805
-
806
- Configure multiple webhook endpoints to receive real-time form events:
807
-
808
- ```tsx
809
- import { ExtendedForm, type WebhookConfig } from 'extended-dynamic-forms';
810
-
811
- const webhookConfigs: WebhookConfig[] = [
812
- {
813
- url: 'https://api.yourapp.com/form-events',
814
- method: 'POST',
815
- events: ['change', 'blur'], // Only trigger on change and blur
816
- debounceMs: 500, // Wait 500ms before sending
817
- retries: 3, // Retry failed requests
818
- timeout: 5000, // 5 second timeout
819
- headers: {
820
- 'Authorization': 'Bearer your-api-token',
821
- 'X-Form-ID': 'contact-form'
316
+ #### Choice Widget (Radio Group)
317
+ ```json
318
+ {
319
+ "schema": {
320
+ "type": "string",
321
+ "title": "Gender",
322
+ "enum": ["male", "female", "other"]
323
+ },
324
+ "uiSchema": {
325
+ "ui:widget": "choice",
326
+ "ui:options": {
327
+ "presenter": "radio"
822
328
  }
823
329
  }
824
- ];
825
-
826
- <ExtendedForm
827
- schema={schema}
828
- uiSchema={uiSchema}
829
- webhooks={webhookConfigs}
830
- />
330
+ }
831
331
  ```
832
332
 
833
- ## V1 Conditional System (Deprecated)
834
-
835
- > ⚠️ **DEPRECATED**: The v1 conditional system is deprecated and will be removed in a future version. Use the Three Pillars v2 system for all new implementations.
836
-
837
- The v1 system uses imperative engines with O(M×N) performance for arrays. While still functional, it has significant limitations compared to v2.
838
-
839
- ### Basic V1 Usage (Not Recommended)
840
-
841
- ```tsx
842
- import { ExtendedForm } from 'extended-dynamic-forms';
843
-
844
- const conditionals = {
845
- rules: [
846
- {
847
- conditions: { isStudent: true },
848
- event: { type: "require", params: { field: ["studentId", "school"] } }
333
+ #### Choice Widget (Checkbox Group - Multi-select)
334
+ ```json
335
+ {
336
+ "schema": {
337
+ "type": "array",
338
+ "title": "Interests",
339
+ "items": {
340
+ "type": "string",
341
+ "enum": ["sports", "music", "reading", "travel"]
849
342
  },
850
- {
851
- conditions: { isStudent: false },
852
- event: { type: "remove", params: { field: ["studentId", "school"] } }
343
+ "uniqueItems": true
344
+ },
345
+ "uiSchema": {
346
+ "ui:widget": "choice",
347
+ "ui:options": {
348
+ "presenter": "checkbox"
853
349
  }
854
- ]
855
- };
856
-
857
- <ExtendedForm
858
- schema={schema}
859
- uiSchema={uiSchema}
860
- conditionals={conditionals}
861
- />
862
- ```
863
-
864
- ### Why Migrate to v2?
865
-
866
- - **Performance**: O(N) vs O(M×N) for arrays
867
- - **Maintainability**: Clear separation of concerns
868
- - **Type Safety**: Full TypeScript support
869
- - **Predictability**: No complex rule interactions
870
- - **Modern React**: Hooks-based architecture
871
-
872
- ## API Reference
873
-
874
- ### ExtendedFormProps
875
-
876
- ```typescript
877
- interface ExtendedFormProps<T = any, S extends RJSFSchema = RJSFSchema, F = any> extends FormProps<T, S, F> {
878
- // Standard RJSF props
879
- schema: S;
880
- uiSchema?: UiSchema<T, S, F>;
881
- formData?: T;
882
- onSubmit?: (data: IChangeEvent<T, S, F>, event?: React.FormEvent<HTMLFormElement>) => void;
883
- onChange?: (data: IChangeEvent<T, S, F>) => void;
884
-
885
- // Field-level event handlers
886
- onFieldFocus?: (event: FormFieldEvent) => Promise<void> | void;
887
- onFieldBlur?: (event: FormFieldEvent) => Promise<void> | void;
888
- onFieldChange?: (event: FormFieldEvent) => Promise<void> | void;
889
-
890
- // Webhook configuration
891
- webhooks?: WebhookConfig[];
892
-
893
- // Conditional logic (v1 - deprecated)
894
- conditionals?: ConditionalConfig;
895
-
896
- // Form lifecycle events
897
- beforeSubmit?: (data: T) => Promise<T> | T;
898
- afterSubmit?: (data: T) => Promise<void> | void;
899
- beforeValidation?: (data: T) => Promise<T> | T;
900
- afterValidation?: (data: T, errors: RJSFValidationError[]) => Promise<void> | void;
350
+ }
901
351
  }
902
352
  ```
903
353
 
904
- ### Three Pillars v2 Hooks
905
-
906
- ```typescript
907
- // UI Logic Pillar
908
- function useConditionalUi(
909
- rules: UiRule[],
910
- baseUiSchema: UiSchema,
911
- formData: any
912
- ): UiSchema
913
-
914
- // Schema Logic Pillar
915
- function useConditionalSchema(
916
- rules: SchemaRule[],
917
- baseSchema: RJSFSchema,
918
- formData: any
919
- ): RJSFSchema
920
-
921
- // Validation Logic Pillar
922
- function useConditionalValidation(
923
- rules: ValidationRule[],
924
- baseConfig: ValidationConfig,
925
- formData: any
926
- ): ValidationConfig
927
- ```
928
-
929
- ## Real-World Use Cases
930
-
931
- ### 🏢 Enterprise Business Applications
932
-
933
- **Australian Company Registration** (Featured Demo)
934
- ```tsx
935
- // Complete 5-step wizard with dynamic conditionals
936
- const companyOnboardingSchema = {
937
- STEP_COMPANY: { /* Company details */ },
938
- STEP_DIRECTORS: { /* Dynamic director array */ },
939
- STEP_ADDRESS: { /* Address with postal logic */ },
940
- STEP_FINANCIAL: { /* Banking with international support */ },
941
- STEP_COMPLIANCE: { /* Regulatory requirements */ }
942
- };
943
-
944
- // Per-director conditionals with O(N) performance
945
- const uiSchema = {
946
- STEP_DIRECTORS: {
947
- directors: {
948
- items: createDynamicArrayItemsUiSchema((director) => ({
949
- tfn: { 'ui:widget': director.isAustralianResident ? 'text' : 'hidden' },
950
- passport: { 'ui:widget': !director.isAustralianResident ? 'text' : 'hidden' }
951
- }))
354
+ #### Date Picker
355
+ ```json
356
+ {
357
+ "schema": {
358
+ "type": "string",
359
+ "title": "Date of Birth",
360
+ "format": "date"
361
+ },
362
+ "uiSchema": {
363
+ "ui:widget": "date",
364
+ "ui:options": {
365
+ "format": "DD/MM/YYYY",
366
+ "picker": "date"
952
367
  }
953
368
  }
954
- };
369
+ }
955
370
  ```
956
371
 
957
- ### 💼 Multi-Step Workflows
958
-
959
- **Loan Applications**
960
- - Conditional document requirements based on loan type
961
- - Income verification with employment status logic
962
- - Asset declaration with property type conditionals
963
-
964
- **Employee Onboarding**
965
- - Role-based form sections (technical vs. non-technical)
966
- - Security clearance workflows
967
- - Benefits enrollment with eligibility rules
968
-
969
- **Grant Applications**
970
- - Multi-stage submissions with validation gates
971
- - Budget calculations with category-based rules
972
- - Compliance checks based on funding type
973
-
974
- ### 🔄 Dynamic Array Management
975
-
976
- **Board of Directors Management**
977
- ```tsx
978
- // Professional-grade array handling with O(N) performance
979
- import { createDynamicArrayItemsUiSchema } from 'extended-dynamic-forms';
980
-
981
- const uiSchema = {
982
- STEP_DIRECTORS: {
983
- directors: {
984
- items: createDynamicArrayItemsUiSchema((director, index) => ({
985
- shareholdingPercentage: {
986
- 'ui:widget': director.hasShareholding ? 'percentage' : 'hidden'
987
- },
988
- tfn: {
989
- 'ui:widget': director.isAustralianResident ? 'text' : 'hidden'
990
- },
991
- passport: {
992
- 'ui:widget': !director.isAustralianResident ? 'text' : 'hidden'
993
- }
994
- }))
372
+ #### File Upload
373
+ ```json
374
+ {
375
+ "schema": {
376
+ "type": "string",
377
+ "title": "Resume",
378
+ "format": "data-url"
379
+ },
380
+ "uiSchema": {
381
+ "ui:widget": "FileUploadWidget",
382
+ "ui:options": {
383
+ "accept": ".pdf,.doc,.docx",
384
+ "maxSize": 5242880,
385
+ "multiple": false
995
386
  }
996
387
  }
997
- };
388
+ }
998
389
  ```
999
390
 
1000
- **Product Configurations**
1001
- - Dynamic product options based on category
1002
- - Pricing calculations with quantity breaks
1003
- - Feature availability by subscription tier
1004
-
1005
- **Address Management**
1006
- - International vs. domestic address formats
1007
- - State/province selection based on country
1008
- - Postal code validation by region
1009
-
1010
- ### 🌐 CMS & Integration Use Cases
391
+ #### Color Picker
392
+ ```json
393
+ {
394
+ "schema": {
395
+ "type": "string",
396
+ "title": "Favorite Color",
397
+ "format": "color"
398
+ },
399
+ "uiSchema": {
400
+ "ui:widget": "color"
401
+ }
402
+ }
403
+ ```
1011
404
 
1012
- **WordPress/Drupal Forms**
1013
- ```html
1014
- <!-- Standalone JavaScript integration -->
1015
- <script>
1016
- const { createWizard } = ExtendedDynamicForms;
1017
-
1018
- createWizard({
1019
- schema: wpFormSchema,
1020
- container: '#wp-form-container',
1021
- onSubmit: (data) => {
1022
- // Submit to WordPress REST API
1023
- wp.apiRequest({ path: '/wp/v2/forms', method: 'POST', data });
405
+ #### Range/Slider Widget
406
+ ```json
407
+ {
408
+ "schema": {
409
+ "type": "number",
410
+ "title": "Volume",
411
+ "minimum": 0,
412
+ "maximum": 100
413
+ },
414
+ "uiSchema": {
415
+ "ui:widget": "range",
416
+ "ui:options": {
417
+ "marks": {
418
+ "0": "Mute",
419
+ "50": "50%",
420
+ "100": "Max"
421
+ }
1024
422
  }
1025
- });
1026
- </script>
423
+ }
424
+ }
1027
425
  ```
1028
426
 
1029
- **Legacy System Modernization**
1030
- - Drop-in replacement for static HTML forms
1031
- - Progressive enhancement of existing forms
1032
- - No-build deployment to production environments
1033
-
1034
- ## Architecture
1035
-
1036
- Extended Dynamic Forms uses a layered architecture that cleanly extends RJSF:
1037
-
1038
- ```
1039
- ┌─────────────────────────────────────────────────┐
1040
- │ Three Pillars v2 (Conditional System) │
1041
- ├─────────────────────────────────────────────────┤
1042
- │ Application Layer (WizardForm) │
1043
- ├─────────────────────────────────────────────────┤
1044
- │ Event Layer (FormEventHub) │
1045
- ├─────────────────────────────────────────────────┤
1046
- │ Component Layer (Widgets/Fields/Templates) │
1047
- ├─────────────────────────────────────────────────┤
1048
- │ Base Layer (@rjsf/antd) │
1049
- └─────────────────────────────────────────────────┘
427
+ #### Hidden Field
428
+ ```json
429
+ {
430
+ "schema": {
431
+ "type": "string",
432
+ "title": "User ID"
433
+ },
434
+ "uiSchema": {
435
+ "ui:widget": "hidden"
436
+ }
437
+ }
1050
438
  ```
1051
439
 
1052
- ## Feature Comparison
1053
-
1054
- | Feature | Basic RJSF | Extended Dynamic Forms |
1055
- |---------|------------|----------------------|
1056
- | **Form Generation** | ✅ JSON Schema | ✅ Enhanced JSON Schema |
1057
- | **UI Components** | Basic HTML | ✅ Comprehensive Ant Design Suite |
1058
- | **Conditional Logic** | ❌ Manual | ✅ Three Pillars v2 (O(N)) |
1059
- | **Multi-Step Forms** | ❌ Manual | ✅ Automatic Wizard Detection |
1060
- | **Event System** | Basic onChange | ✅ Central Event Orchestration |
1061
- | **Webhook Integration** | ❌ None | ✅ Production-Ready with Retry |
1062
- | **Array Conditionals** | ❌ None | ✅ Per-Item O(N) Performance |
1063
- | **TypeScript** | Partial | ✅ Comprehensive Type Definitions |
1064
- | **Standalone JS** | ❌ React Only | ✅ Complete UMD Bundle |
1065
- | **Testing** | Basic | ⚠️ Focused on Conditionals/Wizards |
1066
- | **Performance** | Standard | ✅ Optimized with Caching |
1067
- | **Validation** | Basic | ✅ Dynamic + Custom Rules |
1068
- | **Developer Tools** | Limited | ✅ Interactive Playground |
440
+ ### Widget Registration
1069
441
 
1070
- ## Development
1071
-
1072
- ### 🚀 Quick Start
1073
-
1074
- > **Development Setup Note**: Due to local file dependencies, you need:
1075
- > 1. Clone RJSF repository in a sibling directory: `../react-jsonschema-form/`
1076
- > 2. Ensure the RJSF packages are built and available
442
+ Register custom widgets with ExtendedForm:
1077
443
 
1078
- ```bash
1079
- # Clone and setup (requires specific directory structure)
1080
- git clone https://github.com/user/extended-dynamic-forms.git
1081
- cd extended-dynamic-forms
1082
- npm install # Note: Will fail without ../react-jsonschema-form/ directory
444
+ ```typescript
445
+ import { ExtendedForm, customWidgets } from 'extended-dynamic-forms';
1083
446
 
1084
- # Start development with playground
1085
- npm run dev # Launches interactive playground
1086
- npm run playground # Alternative playground command
447
+ // Use all built-in widgets
448
+ <ExtendedForm
449
+ widgets={customWidgets}
450
+ schema={schema}
451
+ uiSchema={uiSchema}
452
+ />
1087
453
 
1088
- # Development workflow
1089
- npm run test # Run complete test suite
1090
- npm run test:ui # Visual test runner
1091
- npm run lint # ESLint validation
1092
- npm run format # Prettier formatting
454
+ // Or register specific widgets
455
+ <ExtendedForm
456
+ widgets={{
457
+ text: customWidgets.text,
458
+ date: customWidgets.date,
459
+ choice: customWidgets.choice
460
+ }}
461
+ />
1093
462
  ```
1094
463
 
1095
- ### 📦 Build Commands
464
+ ## Development
1096
465
 
1097
466
  ```bash
1098
- # Library builds
1099
- npm run build # TypeScript + Vite library build
1100
- npm run build:vanilla # Standalone UMD bundle
1101
- npm run build:all # Both library and standalone
1102
-
1103
- # Production validation
1104
- npm run preview # Preview library build
1105
- npm run serve:examples # Serve vanilla JS examples
1106
- ```
467
+ # Development
468
+ npm run dev # Start playground
469
+ npm run test # Run tests
470
+ npm run test:ui # Test with UI
1107
471
 
1108
- ### 🧪 Testing
472
+ # Building
473
+ npm run build # Build library
474
+ npm run build:vanilla # Build standalone (currently broken - JsonLogic incompatible)
475
+ npm run preview # Preview build
1109
476
 
1110
- **Test Coverage**: Test suite focuses primarily on:
1111
- - **Conditional Logic**: Comprehensive coverage for v1 and v2 systems (16+ test files)
1112
- - **Wizard Forms**: Step navigation and validation
1113
- - **Performance**: Array conditional optimization
1114
- - **Note**: Limited coverage for UI components, event system, and utility functions
1115
-
1116
- ```bash
1117
- npm run test # Run complete test suite
1118
- npm run test -- --grep "conditional" # Test conditional logic
1119
- npm run test -- --grep "wizard" # Test wizard forms
1120
- npm run test -- --grep "array" # Test array handling
477
+ # Code Quality
478
+ npm run lint # ESLint
479
+ npm run format # Prettier
1121
480
  ```
1122
481
 
1123
- ### 🏗️ Architecture
482
+ ## Project Structure
1124
483
 
1125
- **Build Configuration**:
1126
- - **Library**: ES + UMD via Vite with TypeScript declarations
1127
- - **Standalone**: Complete UMD bundle with React/antd included
1128
- - **External Dependencies**: React, antd marked as externals in library build
1129
- - **Type Generation**: `vite-plugin-dts` for .d.ts files
1130
-
1131
- **File Structure**:
1132
484
  ```
1133
485
  src/
1134
- ├── ExtendedForm.tsx # Main form wrapper
1135
- ├── WizardForm.tsx # Multi-step orchestrator
1136
- ├── conditionals/ # v1 + v2 conditional systems
1137
- │ ├── v2/ # Three Pillars architecture
1138
- │ └── DynamicArrayConditionalEngine.ts
1139
- ├── events/ # Central event orchestration
1140
- ├── widgets/ # Enhanced component suite
1141
- ├── components/ # Field and template components
1142
- └── utils/ # Utilities (Note: 76% are unused)
1143
- ```
1144
-
1145
- ## Examples & Demos
1146
-
1147
- ### 🎮 Interactive Playground
1148
-
1149
- The library includes a comprehensive **interactive playground** with extensive real-world demos demonstrating all features:
1150
-
1151
- ```bash
1152
- # Run the playground locally
1153
- npm run dev
1154
- # or
1155
- npm run playground
486
+ ├── components/ # Core form components
487
+ ├── conditionals/ # Three Pillars system
488
+ │ └── v2/ # Current implementation
489
+ ├── events/ # Event orchestration
490
+ ├── layouts/ # Layout systems
491
+ │ └── wizard/ # Wizard form components
492
+ ├── widgets/ # Input widgets
493
+ └── utils/ # Utilities
1156
494
  ```
1157
495
 
1158
- ### 📚 Demo Categories
496
+ ## Examples
1159
497
 
1160
- > **Note**: Some playground demos may be outdated. The v1 conditional demo (`/playground/src/demos/conditionals/01-deprecated-v1-conditions.demo.tsx`) is deprecated and should not be used as a reference for new implementations.
498
+ Interactive examples available at `/playground/src/demos/`:
1161
499
 
1162
- #### **Three Pillars v2 Demonstrations**
1163
- - **Global UI Rules**: Dynamic show/hide with JSON Patch operations
1164
- - **Dynamic Array Items**: Per-item conditional logic with O(N) performance
1165
- - **Conditional Validation**: Custom validation rules without schema changes
1166
- - **Migration Examples**: Automated v1-to-v2 rule conversion
500
+ - **Wizard Forms**: Australian Company Onboarding, Employee Onboarding
501
+ - **Conditionals**: Dynamic visibility, validation, array handling
502
+ - **Events**: Webhook integration, field tracking
503
+ - **Widgets**: All available components
1167
504
 
1168
- #### **🧙‍♂️ Wizard Form Showcases**
1169
- - **Australian Company Onboarding**: 5-step enterprise form with:
1170
- - Dynamic director arrays with per-item conditionals
1171
- - Real-time fee calculations based on business rules
1172
- - Complex validation (ABN/ACN numbers, postcodes)
1173
- - Step-aware conditional logic
1174
- - Professional business workflow
505
+ Run `npm run dev` to explore examples.
1175
506
 
1176
- #### **🔗 Event System Demos**
1177
- - **Real-time Form Analytics**: Webhook integration with retry logic
1178
- - **Field-Level Event Handling**: Focus/blur/change event orchestration
1179
- - **Webhook Configuration**: Multiple endpoints with custom headers
507
+ ## Known Limitations
1180
508
 
1181
- #### **🎨 Widget Showcase**
1182
- - **Enhanced Standard Widgets**: All RJSF widgets with Ant Design styling
1183
- - **Custom Widgets**: Color picker, rating, range slider, file upload
1184
- - **Professional Fields**: Address, currency, phone number components
509
+ 1. **Dependencies**: Requires RJSF source in sibling directory
510
+ 2. **Installation**: Cannot install from npm
511
+ 3. **Vanilla JS**: JsonLogic not supported in standalone builds
512
+ 4. **Arrays**: No drag-and-drop functionality
513
+ 5. **JSON Patch**: Only supports add/remove/replace operations
514
+ 6. **Test Coverage**: Limited for UI components and events
1185
515
 
1186
- ### 📱 Vanilla JavaScript Examples
516
+ ## TypeScript
1187
517
 
1188
- Complete standalone examples in `/examples/vanilla-js/`:
518
+ Full TypeScript support with exported types:
1189
519
 
1190
- ```html
1191
- <!-- Basic Form -->
1192
- basic-form.html <!-- Simple contact form -->
1193
- conditional-form.html <!-- Dynamic field visibility -->
1194
- wizard-form.html <!-- Multi-step onboarding -->
520
+ ```typescript
521
+ import {
522
+ ExtendedForm,
523
+ WizardForm,
524
+ UiRule,
525
+ SchemaRule,
526
+ ValidationRule,
527
+ JsonLogicRule,
528
+ FormEvent,
529
+ WebhookConfig
530
+ } from 'extended-dynamic-forms';
1195
531
  ```
1196
532
 
1197
- ### 🔗 Live Demo Links
1198
-
1199
- - **[Playground](https://extended-dynamic-forms-playground.vercel.app)** - Interactive demo environment
1200
- - **[Australian Company Onboarding](https://extended-dynamic-forms-playground.vercel.app/wizard/australian-company)** - Full enterprise form showcase
1201
- - **[Three Pillars v2 Demo](https://extended-dynamic-forms-playground.vercel.app/conditionals/three-pillars)** - Modern conditional logic patterns
1202
-
1203
533
  ## Contributing
1204
534
 
1205
- We welcome contributions! Please see our [Contributing Guide](CONTRIBUTING.md) for details.
1206
-
1207
- ## Community & Support
1208
-
1209
- - 📚 [Documentation](https://extended-dynamic-forms.dev)
1210
- - 🐛 [Issue Tracker](https://github.com/user/extended-dynamic-forms/issues)
1211
- - 💬 [Discussions](https://github.com/user/extended-dynamic-forms/discussions)
1212
- - 📧 [Email Support](mailto:support@extended-dynamic-forms.dev)
1213
-
1214
-
535
+ 1. Fork the repository
536
+ 2. Create your feature branch
537
+ 3. Add tests for new functionality
538
+ 4. Ensure all tests pass
539
+ 5. Submit a pull request
1215
540
 
1216
- ---
541
+ ## License
1217
542
 
1218
- <p align="center">
1219
- Built with ❤️ on top of <a href="https://github.com/rjsf-team/react-jsonschema-form">React JSON Schema Form</a>
1220
- </p>
543
+ MIT License - see LICENSE file for details.