@syncfusion/ej2-react-form-renderer 0.1.1-beta → 34.2.2

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 (173) hide show
  1. package/README.md +86 -110
  2. package/diConfig.json +85 -0
  3. package/dist/ej2-react-form-renderer.min.js +10 -0
  4. package/dist/ej2-react-form-renderer.umd.min.js +11 -0
  5. package/dist/ej2-react-form-renderer.umd.min.js.map +1 -0
  6. package/dist/es6/ej2-react-form-renderer.es2015.js +37 -0
  7. package/dist/es6/ej2-react-form-renderer.es2015.js.map +1 -0
  8. package/form-renderer.d.ts +4 -0
  9. package/form-renderer.js +4 -0
  10. package/index.d.ts +2 -4
  11. package/index.js +2 -4
  12. package/license +6 -13
  13. package/package.json +19 -38
  14. package/src/form-renderer/formrenderer.component.d.ts +34 -0
  15. package/src/form-renderer/formrenderer.component.js +49 -0
  16. package/src/form-renderer/index.d.ts +1 -0
  17. package/src/form-renderer/index.js +1 -0
  18. package/src/global.js +1 -0
  19. package/src/index.d.ts +2 -6
  20. package/src/index.js +2 -6
  21. package/styles/bds-lite.css +1 -0
  22. package/styles/bds-lite.scss +1 -0
  23. package/styles/bds.css +1 -0
  24. package/styles/bds.scss +1 -0
  25. package/styles/bootstrap-dark-lite.css +1 -0
  26. package/styles/bootstrap-dark-lite.scss +1 -0
  27. package/styles/bootstrap-dark.css +1 -26
  28. package/styles/bootstrap-dark.scss +1 -0
  29. package/styles/bootstrap-lite.css +1 -0
  30. package/styles/bootstrap-lite.scss +1 -0
  31. package/styles/bootstrap.css +1 -26
  32. package/styles/bootstrap.scss +1 -0
  33. package/styles/bootstrap4-lite.css +1 -0
  34. package/styles/bootstrap4-lite.scss +1 -0
  35. package/styles/bootstrap4.css +1 -26
  36. package/styles/bootstrap4.scss +1 -0
  37. package/styles/bootstrap5-dark-lite.css +1 -0
  38. package/styles/bootstrap5-dark-lite.scss +1 -0
  39. package/styles/bootstrap5-dark.css +1 -26
  40. package/styles/bootstrap5-dark.scss +1 -0
  41. package/styles/bootstrap5-lite.css +1 -0
  42. package/styles/bootstrap5-lite.scss +1 -0
  43. package/styles/bootstrap5.3-lite.css +1 -0
  44. package/styles/bootstrap5.3-lite.scss +1 -0
  45. package/styles/bootstrap5.3.css +1 -26
  46. package/styles/bootstrap5.3.scss +1 -0
  47. package/styles/bootstrap5.css +1 -26
  48. package/styles/bootstrap5.scss +1 -0
  49. package/styles/fabric-dark-lite.css +1 -0
  50. package/styles/fabric-dark-lite.scss +1 -0
  51. package/styles/fabric-dark.css +1 -0
  52. package/styles/fabric-dark.scss +1 -0
  53. package/styles/fabric-lite.css +1 -0
  54. package/styles/fabric-lite.scss +1 -0
  55. package/styles/fabric.css +1 -0
  56. package/styles/fabric.scss +1 -0
  57. package/styles/fluent-dark-lite.css +1 -0
  58. package/styles/fluent-dark-lite.scss +1 -0
  59. package/styles/fluent-dark.css +1 -26
  60. package/styles/fluent-dark.scss +1 -0
  61. package/styles/fluent-lite.css +1 -0
  62. package/styles/fluent-lite.scss +1 -0
  63. package/styles/fluent.css +1 -26
  64. package/styles/fluent.scss +1 -0
  65. package/styles/fluent2-lite.css +1 -0
  66. package/styles/fluent2-lite.scss +1 -0
  67. package/styles/fluent2.css +1 -26
  68. package/styles/fluent2.scss +1 -0
  69. package/styles/form-renderer/bds.css +1 -0
  70. package/styles/form-renderer/bds.scss +1 -0
  71. package/styles/form-renderer/bootstrap-dark.css +1 -0
  72. package/styles/form-renderer/bootstrap-dark.scss +1 -0
  73. package/styles/form-renderer/bootstrap.css +1 -0
  74. package/styles/form-renderer/bootstrap.scss +1 -0
  75. package/styles/form-renderer/bootstrap4.css +1 -0
  76. package/styles/form-renderer/bootstrap4.scss +1 -0
  77. package/styles/form-renderer/bootstrap5-dark.css +1 -0
  78. package/styles/form-renderer/bootstrap5-dark.scss +1 -0
  79. package/styles/form-renderer/bootstrap5.3.css +1 -0
  80. package/styles/form-renderer/bootstrap5.3.scss +1 -0
  81. package/styles/form-renderer/bootstrap5.css +1 -0
  82. package/styles/form-renderer/bootstrap5.scss +1 -0
  83. package/styles/form-renderer/fabric-dark.css +1 -0
  84. package/styles/form-renderer/fabric-dark.scss +1 -0
  85. package/styles/form-renderer/fabric.css +1 -0
  86. package/styles/form-renderer/fabric.scss +1 -0
  87. package/styles/form-renderer/fluent-dark.css +1 -0
  88. package/styles/form-renderer/fluent-dark.scss +1 -0
  89. package/styles/form-renderer/fluent.css +1 -0
  90. package/styles/form-renderer/fluent.scss +1 -0
  91. package/styles/form-renderer/fluent2.css +1 -0
  92. package/styles/form-renderer/fluent2.scss +1 -0
  93. package/styles/form-renderer/highcontrast-light.css +1 -0
  94. package/styles/form-renderer/highcontrast-light.scss +1 -0
  95. package/styles/form-renderer/highcontrast.css +1 -0
  96. package/styles/form-renderer/highcontrast.scss +1 -0
  97. package/styles/form-renderer/material-dark.css +1 -0
  98. package/styles/form-renderer/material-dark.scss +1 -0
  99. package/styles/form-renderer/material.css +1 -0
  100. package/styles/form-renderer/material.scss +1 -0
  101. package/styles/form-renderer/material3-dark.css +1 -0
  102. package/styles/form-renderer/material3-dark.scss +1 -0
  103. package/styles/form-renderer/material3.css +1 -0
  104. package/styles/form-renderer/material3.scss +1 -0
  105. package/styles/form-renderer/tailwind-dark.css +1 -0
  106. package/styles/form-renderer/tailwind-dark.scss +1 -0
  107. package/styles/form-renderer/tailwind.css +1 -0
  108. package/styles/form-renderer/tailwind.scss +1 -0
  109. package/styles/form-renderer/tailwind3.css +1 -0
  110. package/styles/form-renderer/tailwind3.scss +1 -0
  111. package/styles/highcontrast-light-lite.css +1 -0
  112. package/styles/highcontrast-light-lite.scss +1 -0
  113. package/styles/highcontrast-light.css +1 -0
  114. package/styles/highcontrast-light.scss +1 -0
  115. package/styles/highcontrast-lite.css +1 -0
  116. package/styles/highcontrast-lite.scss +1 -0
  117. package/styles/highcontrast.css +1 -0
  118. package/styles/highcontrast.scss +1 -0
  119. package/styles/material-dark-lite.css +1 -0
  120. package/styles/material-dark-lite.scss +1 -0
  121. package/styles/material-dark.css +1 -26
  122. package/styles/material-dark.scss +1 -0
  123. package/styles/material-lite.css +1 -0
  124. package/styles/material-lite.scss +1 -0
  125. package/styles/material.css +1 -26
  126. package/styles/material.scss +1 -0
  127. package/styles/material3-dark-lite.css +1 -0
  128. package/styles/material3-dark-lite.scss +1 -0
  129. package/styles/material3-dark.css +1 -26
  130. package/styles/material3-dark.scss +1 -0
  131. package/styles/material3-lite.css +1 -0
  132. package/styles/material3-lite.scss +1 -0
  133. package/styles/material3.css +1 -26
  134. package/styles/material3.scss +1 -0
  135. package/styles/tailwind-dark-lite.css +1 -0
  136. package/styles/tailwind-dark-lite.scss +1 -0
  137. package/styles/tailwind-dark.css +1 -26
  138. package/styles/tailwind-dark.scss +1 -0
  139. package/styles/tailwind-lite.css +1 -0
  140. package/styles/tailwind-lite.scss +1 -0
  141. package/styles/tailwind.css +1 -26
  142. package/styles/tailwind.scss +1 -0
  143. package/styles/tailwind3-lite.css +1 -0
  144. package/styles/tailwind3-lite.scss +1 -0
  145. package/styles/tailwind3.css +1 -26
  146. package/styles/tailwind3.scss +1 -0
  147. package/src/CheckboxGroup.d.ts +0 -12
  148. package/src/CheckboxGroup.js +0 -48
  149. package/src/ConditionalRuleEngine.d.ts +0 -253
  150. package/src/ConditionalRuleEngine.js +0 -489
  151. package/src/CustomTabComponent.d.ts +0 -13
  152. package/src/CustomTabComponent.js +0 -35
  153. package/src/DataGridComponent.d.ts +0 -28
  154. package/src/DataGridComponent.js +0 -144
  155. package/src/FormRenderer.d.ts +0 -90
  156. package/src/FormRenderer.js +0 -649
  157. package/src/FormValidator.d.ts +0 -479
  158. package/src/FormValidator.js +0 -579
  159. package/src/StaticHtmlRenderer.d.ts +0 -8
  160. package/src/StaticHtmlRenderer.js +0 -21
  161. package/src/json-converter.d.ts +0 -180
  162. package/src/json-converter.js +0 -1329
  163. package/src/parser.d.ts +0 -99
  164. package/src/parser.js +0 -750
  165. package/src/renderFormField.d.ts +0 -20
  166. package/src/renderFormField.js +0 -203
  167. package/src/types/FormSchema.d.ts +0 -205
  168. package/src/types/FormSchema.js +0 -1
  169. package/src/utils.js +0 -146
  170. package/styles/bootstrap5.3-dark.css +0 -26
  171. package/styles/fluent2-dark.css +0 -26
  172. package/styles/form-renderer.base.css +0 -489
  173. package/styles/tailwind3-dark.css +0 -10
@@ -1,489 +0,0 @@
1
- /**
2
- * ConditionalRuleEngine - Core rule evaluation engine for conditional behaviors
3
- *
4
- * Evaluates declarative condition rules (from QueryBuilder or manual JSON) against
5
- * form state to determine field visibility, read-only state, disabled state, and
6
- * which validators should apply.
7
- *
8
- * @spec CONDITIONAL-VALIDATION.md
9
- * @requirement Tasks 3.1-3.12: ConditionalRuleEngine implementation
10
- *
11
- * Features:
12
- * - Simple rule evaluation (field operator value)
13
- * - Composite rules (AND/OR combinations with nesting)
14
- * - Conditional validators (apply validator only when condition met)
15
- * - Relationship validators (cross-field validation with safe expression eval)
16
- * - Behavioral flags (visibility, readOnly, disabled)
17
- * - Error handling with safe defaults
18
- *
19
- * Security:
20
- * - Uses expr-eval for safe expression evaluation (no eval())
21
- * - Defaults to safe behavior on errors (visible, not disabled, not read-only)
22
- *
23
- * @example
24
- * ```typescript
25
- * const isVisible = ConditionalRuleEngine.isFieldVisible(
26
- * component.conditions,
27
- * { country: 'US', age: 25 }
28
- * );
29
- *
30
- * const behaviors = ConditionalRuleEngine.applyConditionalBehaviors(
31
- * component.conditions,
32
- * formValues
33
- * );
34
- * ```
35
- */
36
- import { Internationalization } from '@syncfusion/ej2-base';
37
- /**
38
- * ConditionalRuleEngine class
39
- *
40
- * @spec CONDITIONAL-VALIDATION.md - Core rule evaluation engine
41
- * @requirement Phase 1: Conditional visibility, readOnly, disabled behaviors
42
- */
43
- export class ConditionalRuleEngine {
44
- /**
45
- * Evaluate a conditional rule against form values
46
- *
47
- * Handles both simple rules (field operator value) and composite rules (AND/OR).
48
- * Returns false for malformed rules.
49
- *
50
- * @spec CONDITIONAL-VALIDATION.md - evaluateCondition method
51
- * @requirement Task 3.2: Implement evaluateCondition with simple and composite handling
52
- *
53
- * @param rule - ConditionalRule or CompositeConditionalRule
54
- * @param formValues - Current form field values (key = field name, value = field value)
55
- * @returns true if condition met, false otherwise
56
- *
57
- * @example
58
- * ```typescript
59
- * const rule = { field: 'age', operator: 'greaterThan', value: 18 };
60
- * const isAdult = ConditionalRuleEngine.evaluateCondition(rule, { age: 25 });
61
- * // isAdult = true
62
- * ```
63
- */
64
- static evaluateCondition(rule, formValues) {
65
- try {
66
- // Handle simple rule (field operator value)
67
- if ('field' in rule && 'operator' in rule && 'value' in rule) {
68
- return this.evaluateSimpleRule(rule, formValues);
69
- }
70
- // Handle composite rule (AND/OR)
71
- if ('condition' in rule && 'rules' in rule) {
72
- return this.evaluateCompositeRule(rule, formValues);
73
- }
74
- // Malformed rule - default to false (safe default)
75
- console.warn('ConditionalRuleEngine: Malformed rule detected', rule);
76
- return false;
77
- }
78
- catch (error) {
79
- console.error('ConditionalRuleEngine: Error evaluating condition', error);
80
- return false; // Safe default on error
81
- }
82
- }
83
- /**
84
- * Evaluate simple field comparison rule
85
- *
86
- * Supports operators: equal, notEqual, greaterThan, lessThan, greaterThanOrEqual,
87
- * lessThanOrEqual, in, notIn, contains, notContains.
88
- *
89
- * Handles both camelCase (greaterThan) and lowercase (greaterthan) operator formats
90
- * for compatibility with QueryBuilder output.
91
- *
92
- * @spec CONDITIONAL-VALIDATION.md - evaluateSimpleRule method
93
- * @requirement Task 3.3: Implement evaluateSimpleRule supporting all operators
94
- *
95
- * @param rule - Simple conditional rule with field, operator, value
96
- * @param formValues - Current form field values
97
- * @returns true if comparison is true, false otherwise
98
- *
99
- * @example
100
- * ```typescript
101
- * const rule = { field: 'email', operator: 'contains', value: '@' };
102
- * const hasAt = evaluateSimpleRule(rule, { email: 'test@example.com' });
103
- * // hasAt = true
104
- * ```
105
- */
106
- static evaluateSimpleRule(rule, formValues) {
107
- try {
108
- const fieldValue = formValues[rule.field];
109
- const operator = rule.operator.toLowerCase();
110
- // Allow evaluation for operators that make sense when value is undefined/empty
111
- if (fieldValue === undefined) {
112
- const allowedForUndefined = ['equal', 'equals', 'notequal', 'notequals', 'isempty', 'isnotempty'];
113
- if (!allowedForUndefined.includes(operator)) {
114
- return false;
115
- }
116
- }
117
- // Check if field value is an array (for multiselect, checkboxGroup)
118
- const isFieldArray = Array.isArray(fieldValue);
119
- const intl = new Internationalization();
120
- switch (operator) {
121
- case 'equal':
122
- case 'equals':
123
- return fieldValue === rule.value;
124
- case 'notequal':
125
- case 'notequals':
126
- return fieldValue !== rule.value;
127
- case 'startswith': return fieldValue.startsWith(rule.value);
128
- case 'doesnotstartswith': return !fieldValue.startsWith(rule.value);
129
- case 'greaterthan':
130
- case 'lessthan':
131
- case 'greaterthanorequal':
132
- case 'lessthanorequal': {
133
- const ln = Number(fieldValue);
134
- const rn = Number(rule.value);
135
- if (!Number.isNaN(ln) && !Number.isNaN(rn)) {
136
- if (operator === 'greaterthan')
137
- return ln > rn;
138
- if (operator === 'lessthan')
139
- return ln < rn;
140
- if (operator === 'greaterthanorequal')
141
- return ln >= rn;
142
- return ln <= rn;
143
- }
144
- return false;
145
- }
146
- case 'dategreaterthan':
147
- case 'datelessthan': {
148
- // try date comparison first
149
- const leftTs = intl.parseDate(fieldValue, { format: 'MM/dd/yyyy' });
150
- const rightTs = intl.parseDate(rule.value, { format: 'MM/dd/yyyy' });
151
- if (leftTs !== null && rightTs !== null) {
152
- if (operator === 'dategreaterthan')
153
- return leftTs > rightTs;
154
- if (operator === 'datelessthan')
155
- return leftTs < rightTs;
156
- return leftTs <= rightTs;
157
- }
158
- return false;
159
- }
160
- case 'timegreaterthan':
161
- case 'timelessthan': {
162
- // Parse time strings (format: hh:mm a)
163
- const leftTime = intl.parseDate(fieldValue, { format: 'hh:mm a', type: 'time' });
164
- const rightTime = intl.parseDate(rule.value, { format: 'hh:mm a', type: 'time' });
165
- if (leftTime !== null && rightTime !== null) {
166
- if (operator === 'timegreaterthan')
167
- return leftTime > rightTime;
168
- if (operator === 'timelessthan')
169
- return leftTime < rightTime;
170
- }
171
- return false;
172
- }
173
- case 'datetimegreaterthan':
174
- case 'datetimelessthan': {
175
- // Parse datetime strings (format: MM/dd/yyyy hh:mm a)
176
- const leftDateTime = intl.parseDate(fieldValue, { format: 'MM/dd/yyyy hh:mm a', type: 'dateTime' });
177
- const rightDateTime = intl.parseDate(rule.value, { format: 'MM/dd/yyyy hh:mm a', type: 'dateTime' });
178
- if (leftDateTime !== null && rightDateTime !== null) {
179
- if (operator === 'datetimegreaterthan')
180
- return leftDateTime > rightDateTime;
181
- if (operator === 'datetimelessthan')
182
- return leftDateTime < rightDateTime;
183
- }
184
- return false;
185
- }
186
- case 'contains':
187
- // If field value is array, check if array contains the specific value(s)
188
- if (isFieldArray) {
189
- // Parse comma-separated values in rule.value if it's a string
190
- if (typeof rule.value === 'string' && rule.value.includes(',')) {
191
- const searchValues = rule.value.split(',').map(v => v.trim());
192
- // Check if array contains ANY of the search values
193
- return searchValues.some(searchVal => fieldValue.includes(searchVal));
194
- }
195
- return fieldValue.includes(rule.value);
196
- }
197
- // Otherwise, check string contains
198
- return String(fieldValue).includes(String(rule.value));
199
- case 'notcontains':
200
- // If field value is array, check if array does NOT contain the specific value(s)
201
- if (isFieldArray) {
202
- // Parse comma-separated values in rule.value if it's a string
203
- if (typeof rule.value === 'string' && rule.value.includes(',')) {
204
- const searchValues = rule.value.split(',').map(v => v.trim());
205
- // Check if array contains NONE of the search values
206
- return !searchValues.some(searchVal => fieldValue.includes(searchVal));
207
- }
208
- return !fieldValue.includes(rule.value);
209
- }
210
- // Otherwise, check string does not contain
211
- return !String(fieldValue).includes(String(rule.value));
212
- case 'isempty':
213
- // Check if array is empty
214
- if (isFieldArray) {
215
- return fieldValue.length === 0;
216
- }
217
- // For non-arrays, check if falsy or empty string
218
- return !fieldValue || String(fieldValue).length === 0;
219
- case 'isnotempty':
220
- // Check if array has items
221
- if (isFieldArray) {
222
- return fieldValue.length > 0;
223
- }
224
- // For non-arrays, check if truthy and not empty string
225
- return !!fieldValue && String(fieldValue).length > 0;
226
- default:
227
- console.warn(`ConditionalRuleEngine: Unknown operator "${rule.operator}"`);
228
- return false;
229
- }
230
- }
231
- catch (error) {
232
- console.error('ConditionalRuleEngine: Error in evaluateSimpleRule', error);
233
- return false;
234
- }
235
- }
236
- /**
237
- * Evaluate composite rule with AND/OR logic
238
- *
239
- * Recursively evaluates nested rules with AND (all must be true) or OR
240
- * (at least one must be true) logic.
241
- *
242
- * @spec CONDITIONAL-VALIDATION.md - evaluateCompositeRule method
243
- * @requirement Task 3.4: Implement evaluateCompositeRule for AND/OR logic
244
- *
245
- * @param rule - Composite rule with condition ('and'|'or') and rules array
246
- * @param formValues - Current form field values
247
- * @returns true if composite condition met, false otherwise
248
- *
249
- * @example
250
- * ```typescript
251
- * const rule = {
252
- * condition: 'and',
253
- * rules: [
254
- * { field: 'age', operator: 'greaterThan', value: 18 },
255
- * { field: 'country', operator: 'equal', value: 'US' }
256
- * ]
257
- * };
258
- * const isEligible = evaluateCompositeRule(rule, { age: 25, country: 'US' });
259
- * // isEligible = true
260
- * ```
261
- */
262
- static evaluateCompositeRule(rule, formValues) {
263
- try {
264
- if (!Array.isArray(rule.rules) || rule.rules.length === 0) {
265
- console.warn('ConditionalRuleEngine: Composite rule has no rules');
266
- return false;
267
- }
268
- const condition = rule.condition.toLowerCase();
269
- if (condition === 'and') {
270
- // All rules must be true
271
- return rule.rules.every((childRule) => this.evaluateCondition(childRule, formValues));
272
- }
273
- else if (condition === 'or') {
274
- // At least one rule must be true
275
- return rule.rules.some((childRule) => this.evaluateCondition(childRule, formValues));
276
- }
277
- else {
278
- console.warn(`ConditionalRuleEngine: Unknown composite condition "${rule.condition}"`);
279
- return false;
280
- }
281
- }
282
- catch (error) {
283
- console.error('ConditionalRuleEngine: Error in evaluateCompositeRule', error);
284
- return false;
285
- }
286
- }
287
- /**
288
- * Check if field should be visible
289
- *
290
- * Evaluates visibleWhen condition. Defaults to true (visible) if no condition
291
- * is defined or on error.
292
- *
293
- * @spec CONDITIONAL-VALIDATION.md - isFieldVisible method
294
- * @requirement Task 3.8: Implement isFieldVisible (defaults to true if no condition)
295
- *
296
- * @param conditions - FormComponentConditions containing visibleWhen rule
297
- * @param formValues - Current form field values
298
- * @returns true if field should be visible, false if hidden
299
- *
300
- * @example
301
- * ```typescript
302
- * const conditions = {
303
- * visibleWhen: { field: 'showEmail', operator: 'equal', value: true }
304
- * };
305
- * const visible = isFieldVisible(conditions, { showEmail: true });
306
- * // visible = true
307
- * ```
308
- */
309
- static isFieldVisible(conditions, formValues) {
310
- try {
311
- if (!conditions?.visibleWhen) {
312
- return true; // Default: visible if no condition
313
- }
314
- return this.evaluateCondition(conditions.visibleWhen, formValues);
315
- }
316
- catch (error) {
317
- console.error('ConditionalRuleEngine: Error in isFieldVisible', error);
318
- return true; // Safe default: visible on error
319
- }
320
- }
321
- /**
322
- * Check if field should be read-only
323
- *
324
- * Evaluates readOnlyWhen condition. Defaults to false (editable) if no
325
- * condition is defined or on error.
326
- *
327
- * @spec CONDITIONAL-VALIDATION.md - isFieldReadOnly method
328
- * @requirement Task 3.9: Implement isFieldReadOnly (defaults to false if no condition)
329
- *
330
- * @param conditions - FormComponentConditions containing readOnlyWhen rule
331
- * @param formValues - Current form field values
332
- * @returns true if field should be read-only, false if editable
333
- *
334
- * @example
335
- * ```typescript
336
- * const conditions = {
337
- * readOnlyWhen: { field: 'isVerified', operator: 'equal', value: true }
338
- * };
339
- * const readOnly = isFieldReadOnly(conditions, { isVerified: true });
340
- * // readOnly = true
341
- * ```
342
- */
343
- static isFieldReadOnly(conditions, formValues) {
344
- try {
345
- if (!conditions?.readOnlyWhen) {
346
- return false; // Default: not read-only if no condition
347
- }
348
- return this.evaluateCondition(conditions.readOnlyWhen, formValues);
349
- }
350
- catch (error) {
351
- console.error('ConditionalRuleEngine: Error in isFieldReadOnly', error);
352
- return false; // Safe default: not read-only on error
353
- }
354
- }
355
- /**
356
- * Check if field should be disabled
357
- *
358
- * Evaluates disabledWhen condition. Defaults to false (enabled) if no
359
- * condition is defined or on error.
360
- *
361
- * @spec CONDITIONAL-VALIDATION.md - isFieldDisabled method
362
- * @requirement Task 3.10: Implement isFieldDisabled (defaults to false if no condition)
363
- *
364
- * @param conditions - FormComponentConditions containing disabledWhen rule
365
- * @param formValues - Current form field values
366
- * @returns true if field should be disabled, false if enabled
367
- *
368
- * @example
369
- * ```typescript
370
- * const conditions = {
371
- * disabledWhen: { field: 'orderStatus', operator: 'equal', value: 'completed' }
372
- * };
373
- * const disabled = isFieldDisabled(conditions, { orderStatus: 'completed' });
374
- * // disabled = true
375
- * ```
376
- */
377
- static isFieldDisabled(conditions, formValues) {
378
- try {
379
- if (!conditions?.disabledWhen) {
380
- return false; // Default: not disabled if no condition
381
- }
382
- return this.evaluateCondition(conditions.disabledWhen, formValues);
383
- }
384
- catch (error) {
385
- console.error('ConditionalRuleEngine: Error in isFieldDisabled', error);
386
- return false; // Safe default: not disabled on error
387
- }
388
- }
389
- /**
390
- * Check if field should be hidden
391
- *
392
- * Evaluates hideWhen condition. Defaults to false (visible) if no condition
393
- * is defined or on error.
394
- *
395
- * @param conditions - FormComponentConditions containing hideWhen rule
396
- * @param formValues - Current form field values
397
- * @returns true if field should be hidden, false if visible
398
- *
399
- * @example
400
- * ```typescript
401
- * const conditions = {
402
- * hideWhen: { field: 'hideEmail', operator: 'equal', value: true }
403
- * };
404
- * const hidden = isFieldHidden(conditions, { hideEmail: true });
405
- * // hidden = true
406
- * ```
407
- */
408
- static isFieldHidden(conditions, formValues) {
409
- try {
410
- if (!conditions?.hideWhen) {
411
- return false; // Default: not hidden if no condition
412
- }
413
- return this.evaluateCondition(conditions.hideWhen, formValues);
414
- }
415
- catch (error) {
416
- console.error('ConditionalRuleEngine: Error in isFieldHidden', error);
417
- return false; // Safe default: not hidden on error
418
- }
419
- }
420
- /**
421
- * Check if field should be required
422
- *
423
- * Evaluates requiredWhen condition. Defaults to false (not required) if no condition
424
- * is defined or on error.
425
- *
426
- * @param conditions - FormComponentConditions containing requiredWhen rule
427
- * @param formValues - Current form field values
428
- * @returns true if field should be required, false if optional
429
- *
430
- * @example
431
- * ```typescript
432
- * const conditions = {
433
- * requiredWhen: { field: 'requireDetails', operator: 'equal', value: true }
434
- * };
435
- * const required = isFieldRequired(conditions, { requireDetails: true });
436
- * // required = true
437
- * ```
438
- */
439
- static isFieldRequired(conditions, formValues) {
440
- try {
441
- if (!conditions?.requiredWhen) {
442
- return false; // Default: not required if no condition
443
- }
444
- return this.evaluateCondition(conditions.requiredWhen, formValues);
445
- }
446
- catch (error) {
447
- console.error('ConditionalRuleEngine: Error in isFieldRequired', error);
448
- return false; // Safe default: not required on error
449
- }
450
- }
451
- /**
452
- * Get value to set for field if condition is met
453
- *
454
- * Evaluates setValueWhen condition and returns the value to assign if true.
455
- * Returns undefined if no condition is defined, condition not met, or on error.
456
- *
457
- * @param conditions - FormComponentConditions containing setValueWhen rule
458
- * @param formValues - Current form field values
459
- * @returns The value to set if condition met, undefined otherwise
460
- *
461
- * @example
462
- * ```typescript
463
- * const conditions = {
464
- * setValueWhen: {
465
- * condition: { field: 'country', operator: 'equal', value: 'US' },
466
- * value: 'United States'
467
- * }
468
- * };
469
- * const value = getConditionalValue(conditions, { country: 'US' });
470
- * // value = 'United States'
471
- * ```
472
- */
473
- static getConditionalValue(conditions, formValues) {
474
- try {
475
- if (!conditions?.setValueWhen) {
476
- return undefined;
477
- }
478
- const isMet = this.evaluateCondition(conditions.setValueWhen.condition, formValues);
479
- if (isMet) {
480
- return conditions.setValueWhen.value;
481
- }
482
- return undefined;
483
- }
484
- catch (error) {
485
- console.error('ConditionalRuleEngine: Error in getConditionalValue', error);
486
- return undefined;
487
- }
488
- }
489
- }
@@ -1,13 +0,0 @@
1
- import React from 'react';
2
- interface TabItem {
3
- header: string;
4
- content: React.ReactNode;
5
- }
6
- interface CustomTabComponentProps {
7
- tabs: TabItem[];
8
- selectedIndex?: number;
9
- onTabSelect?: (index: number) => void;
10
- className?: string;
11
- }
12
- export declare const CustomTabComponent: React.FC<CustomTabComponentProps>;
13
- export {};
@@ -1,35 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { useState, useEffect, useRef } from 'react';
3
- export const CustomTabComponent = ({ tabs, selectedIndex = 0, onTabSelect, className = '' }) => {
4
- const [activeIndex, setActiveIndex] = useState(selectedIndex);
5
- const [indicatorStyle, setIndicatorStyle] = useState({ left: 0, right: 0 });
6
- const tabRefs = useRef([]);
7
- useEffect(() => {
8
- setActiveIndex(selectedIndex);
9
- }, [selectedIndex]);
10
- useEffect(() => {
11
- // Update indicator position
12
- const activeTab = tabRefs.current[activeIndex];
13
- if (activeTab) {
14
- const container = activeTab.parentElement;
15
- if (container) {
16
- const containerWidth = container.offsetWidth;
17
- const tabLeft = activeTab.offsetLeft;
18
- const tabWidth = activeTab.offsetWidth;
19
- setIndicatorStyle({
20
- left: tabLeft,
21
- right: containerWidth - tabLeft - tabWidth
22
- });
23
- }
24
- }
25
- }, [activeIndex, tabs]);
26
- const handleTabClick = (index) => {
27
- setActiveIndex(index);
28
- onTabSelect?.(index);
29
- };
30
- return (_jsxs("div", { className: `form-tabs e-control e-tab e-lib e-keyboard ${className}`, "aria-disabled": "false", style: { width: '100%', height: 'auto' }, children: [_jsx("div", { className: "e-tab-header e-control e-toolbar e-lib e-keyboard", role: "tablist", "aria-disabled": "false", "aria-orientation": "horizontal", style: { height: 'auto', width: '100%' }, children: _jsxs("div", { className: "e-toolbar-items", "data-ripple": "true", children: [_jsx("div", { className: "e-indicator e-ignore", style: {
31
- left: `${indicatorStyle.left}px`,
32
- right: `${indicatorStyle.right}px`,
33
- transition: 'left 0.3s ease, right 0.3s ease'
34
- } }), tabs.map((tab, index) => (_jsx("div", { ref: el => { tabRefs.current[index] = el; }, className: `e-toolbar-item e-template ${activeIndex === index ? 'e-active' : ''}`, id: `e-item-tab_${index}`, "data-id": `tabitem_${index}`, children: _jsx("div", { className: "e-tab-wrap", tabIndex: activeIndex === index ? 0 : -1, "data-tabindex": "-1", role: "tab", "aria-selected": activeIndex === index, "aria-disabled": "false", "aria-controls": `e-content-tab_${index}`, onClick: () => handleTabClick(index), style: { cursor: 'pointer' }, children: _jsx("div", { className: "e-text-wrap", children: _jsx("div", { className: "e-tab-text", role: "presentation", children: tab.header }) }) }) }, index)))] }) }), _jsx("div", { className: "e-content e-lib e-touch", style: { height: 'auto' }, children: tabs.map((tab, index) => (_jsx("div", { className: `e-item ${activeIndex === index ? 'e-active' : ''}`, id: `e-content-tab_${index}`, role: "tabpanel", "aria-labelledby": `e-item-tab_${index}`, style: { display: activeIndex === index ? 'block' : 'none' }, children: _jsx("div", { children: tab.content }) }, index))) })] }));
35
- };
@@ -1,28 +0,0 @@
1
- import React from 'react';
2
- import type { GridComponentSchema } from '../FormBuilder/types/FormSchema';
3
- /**
4
- * DataGridRef: Public API exposed via forwardRef
5
- * - getGridData(): Returns current grid data array for form submission
6
- */
7
- export interface DataGridRef {
8
- getGridData: () => Record<string, any>[];
9
- }
10
- /**
11
- * DataGridComponentProps: Component props extending GridComponentSchema
12
- * - onDataChange: Optional callback when grid data changes
13
- * - isPreviewMode: Whether to refresh grid on column changes (for preview/renderer only)
14
- */
15
- export interface DataGridComponentProps extends GridComponentSchema {
16
- onDataChange?: (data: Record<string, any>[]) => void;
17
- }
18
- /**
19
- * DataGridComponent: Wrapper around Syncfusion GridComponent
20
- *
21
- * Responsibilities:
22
- * - Manages internal _currentData state (initialized from dataSource)
23
- * - Exposes getGridData() via useImperativeHandle for form submission
24
- * - Handles actionComplete events (add/edit/delete operations)
25
- * - Maps GridColumn.validationRules to ColumnDirective.validationRules
26
- * - Renders Syncfusion toolbar with CRUD actions based on allowAdding/Editing/Deleting
27
- */
28
- export declare const DataGridComponent: React.ForwardRefExoticComponent<DataGridComponentProps & React.RefAttributes<DataGridRef>>;