@syncfusion/ej2-react-form-renderer 0.1.2-beta → 34.2.3

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 (181) hide show
  1. package/README.md +88 -105
  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 -49
  149. package/src/ConditionalRuleEngine.d.ts +0 -295
  150. package/src/ConditionalRuleEngine.js +0 -566
  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 -147
  155. package/src/FormRenderer.d.ts +0 -84
  156. package/src/FormRenderer.js +0 -707
  157. package/src/FormValidator.d.ts +0 -479
  158. package/src/FormValidator.js +0 -579
  159. package/src/MinMaxRuleEngine.d.ts +0 -95
  160. package/src/MinMaxRuleEngine.js +0 -361
  161. package/src/StaticHtmlRenderer.d.ts +0 -8
  162. package/src/StaticHtmlRenderer.js +0 -21
  163. package/src/expressions/DependencyTracker.d.ts +0 -30
  164. package/src/expressions/DependencyTracker.js +0 -128
  165. package/src/expressions/ExpressionEngine.d.ts +0 -81
  166. package/src/expressions/ExpressionEngine.js +0 -503
  167. package/src/expressions/ExpressionParser.d.ts +0 -39
  168. package/src/expressions/ExpressionParser.js +0 -270
  169. package/src/json-converter.d.ts +0 -171
  170. package/src/json-converter.js +0 -1209
  171. package/src/parser.d.ts +0 -99
  172. package/src/parser.js +0 -753
  173. package/src/renderFormField.d.ts +0 -21
  174. package/src/renderFormField.js +0 -226
  175. package/src/types/FormSchema.d.ts +0 -211
  176. package/src/types/FormSchema.js +0 -1
  177. package/src/utils.js +0 -408
  178. package/styles/bootstrap5.3-dark.css +0 -26
  179. package/styles/fluent2-dark.css +0 -26
  180. package/styles/form-renderer.base.css +0 -499
  181. package/styles/tailwind3-dark.css +0 -10
@@ -1,270 +0,0 @@
1
- /**
2
- * ExpressionParser - Parse and compile expressions
3
- *
4
- * Converts string expressions into safe, compiled functions
5
- * Supports field references, operators, functions, and conditionals
6
- *
7
- * @spec Expression_Engine.md
8
- */
9
- export class ExpressionParser {
10
- supportedFunctions = [
11
- 'SUM', 'AVG', 'MIN', 'MAX', 'COUNT',
12
- 'ROUND', 'FLOOR', 'CEIL', 'ABS', 'SQRT',
13
- 'UPPER', 'LOWER', 'CONCAT', 'LENGTH', 'TRIM', 'SUBSTRING',
14
- 'TODAY', 'AGE', 'DATEFORMAT', 'DATEDIFF', 'ADDDAYS', 'SUBDAYS'
15
- ];
16
- availableFields = new Map();
17
- /**
18
- * Initialize parser with available fields for type validation
19
- */
20
- setAvailableFields(fields) {
21
- this.availableFields.clear();
22
- fields.forEach(field => {
23
- this.availableFields.set(field.name, field);
24
- });
25
- }
26
- validateFieldOperations(expression) {
27
- const errors = [];
28
- // Skip if no fields available
29
- if (this.availableFields.size === 0) {
30
- return errors;
31
- }
32
- // Invalid operators for string fields (allow only + for concatenation)
33
- const stringInvalidOps = ['-', '*', '/', '%', '^'];
34
- // All operators invalid for date fields
35
- const dateInvalidOps = ['-', '*', '/', '%', '^', '+'];
36
- // Track reported operator positions to avoid duplicates
37
- const reportedOperators = new Set();
38
- // Extract all field references and their surrounding operators
39
- const fieldRefPattern = /(\{[^}]+\})/g;
40
- let match;
41
- while ((match = fieldRefPattern.exec(expression)) !== null) {
42
- const fieldRef = match[0];
43
- const fieldName = fieldRef.slice(1, -1); // Remove { }
44
- const field = this.availableFields.get(fieldName);
45
- if (!field)
46
- continue; // Field not found in available fields, skip validation
47
- const fieldIndex = match.index;
48
- const fieldEndIndex = fieldIndex + fieldRef.length;
49
- // Get context around field reference (including spaces)
50
- const textBefore = expression.substring(Math.max(0, fieldIndex - 10), fieldIndex);
51
- const textAfter = expression.substring(fieldEndIndex, Math.min(expression.length, fieldEndIndex + 10));
52
- // Extract the operator if present (skip spaces)
53
- const operatorBefore = textBefore.trimEnd().slice(-1);
54
- const operatorAfter = textAfter.trimStart().charAt(0);
55
- // Calculate actual position of operators in the original expression
56
- const operatorBeforePos = fieldIndex - (textBefore.length - textBefore.trimEnd().length) - 1;
57
- const operatorAfterPos = fieldEndIndex + (textAfter.length - textAfter.trimStart().length);
58
- // For STRING fields: reject all operators except +
59
- if (field.type === 'string' && !field.format) {
60
- if (operatorBefore && stringInvalidOps.includes(operatorBefore)) {
61
- const key = `${operatorBeforePos}:${operatorBefore}`;
62
- if (!reportedOperators.has(key)) {
63
- errors.push(`Cannot perform '${operatorBefore}' operation on string field '{${fieldName}}'`);
64
- reportedOperators.add(key);
65
- }
66
- }
67
- if (operatorAfter && stringInvalidOps.includes(operatorAfter)) {
68
- const key = `${operatorAfterPos}:${operatorAfter}`;
69
- if (!reportedOperators.has(key)) {
70
- errors.push(`Cannot perform '${operatorAfter}' operation on string field '{${fieldName}}'`);
71
- reportedOperators.add(key);
72
- }
73
- }
74
- }
75
- // For DATE fields: reject ALL operators including +
76
- if (field.format === 'date' || field.format === 'date-time' || field.format === 'time') {
77
- if (operatorBefore && dateInvalidOps.includes(operatorBefore)) {
78
- const key = `${operatorBeforePos}:${operatorBefore}`;
79
- if (!reportedOperators.has(key)) {
80
- errors.push(`Cannot perform '${operatorBefore}' operation on date field '{${fieldName}}'`);
81
- reportedOperators.add(key);
82
- }
83
- }
84
- if (operatorAfter && dateInvalidOps.includes(operatorAfter)) {
85
- const key = `${operatorAfterPos}:${operatorAfter}`;
86
- if (!reportedOperators.has(key)) {
87
- errors.push(`Cannot perform '${operatorAfter}' operation on date field '{${fieldName}}'`);
88
- reportedOperators.add(key);
89
- }
90
- }
91
- }
92
- }
93
- return errors;
94
- }
95
- /**
96
- * Validate expression syntax
97
- */
98
- validate(expression) {
99
- const errors = [];
100
- if (!expression || expression.trim() === '') {
101
- return { valid: true, errors: [] };
102
- }
103
- // Check for unbalanced braces
104
- const openBraces = (expression.match(/\{/g) || []).length;
105
- const closeBraces = (expression.match(/\}/g) || []).length;
106
- if (openBraces !== closeBraces) {
107
- errors.push('Unbalanced braces in expression');
108
- }
109
- // Check for unbalanced parentheses
110
- const openParens = (expression.match(/\(/g) || []).length;
111
- const closeParens = (expression.match(/\)/g) || []).length;
112
- if (openParens !== closeParens) {
113
- errors.push('Unbalanced parentheses in expression');
114
- }
115
- // Check for invalid function calls
116
- const funcPattern = /(\w+)\s*\(/g;
117
- let match;
118
- while ((match = funcPattern.exec(expression)) !== null) {
119
- const funcName = match[1].toUpperCase();
120
- // Only validate uppercase-named functions
121
- if (funcName === funcName.toUpperCase() && !this.supportedFunctions.includes(funcName)) {
122
- errors.push(`Unknown function: ${funcName}`);
123
- }
124
- }
125
- // Validate field operations based on field types
126
- const fieldOpErrors = this.validateFieldOperations(expression);
127
- errors.push(...fieldOpErrors);
128
- return {
129
- valid: errors.length === 0,
130
- errors
131
- };
132
- }
133
- /**
134
- * Compile expression to executable function
135
- */
136
- compile(expression, options = {}) {
137
- try {
138
- // Set available fields for validation if provided
139
- if (options.availableFields && Array.isArray(options.availableFields)) {
140
- this.setAvailableFields(options.availableFields);
141
- }
142
- // Validate expression before compiling
143
- const validation = this.validate(expression);
144
- if (!validation.valid) {
145
- console.error('Expression validation errors:', validation.errors, { expression });
146
- return () => null;
147
- }
148
- // Replace field references with context lookups
149
- let compiled = expression;
150
- // Handle field references FIRST (this includes refs inside ${...})
151
- compiled = this.compileFieldReferences(compiled);
152
- // Handle bare function calls SECOND (e.g., SUM([...]) without braces)
153
- compiled = this.compileBareFunctionCalls(compiled);
154
- // Handle math expressions THIRD (now ${} and {} contain already-replaced refs)
155
- compiled = this.compileMatrixExpressions(compiled);
156
- // Create function that safely evaluates the expression
157
- return (context) => {
158
- try {
159
- // This uses Function constructor with controlled context binding
160
- // which is safer than eval() but still allows expressions
161
- // Note: compiled expression already uses context['field'] syntax
162
- const func = new Function('context', `
163
- try {
164
- return ${compiled};
165
- } catch (e) {
166
- return null;
167
- }
168
- `);
169
- return func(context);
170
- }
171
- catch (e) {
172
- console.error('Expression execution error:', e, { expression, compiled });
173
- return null;
174
- }
175
- };
176
- }
177
- catch (error) {
178
- console.error('Expression compilation error:', error, { expression });
179
- return () => null;
180
- }
181
- }
182
- // Private helpers
183
- compileMatrixExpressions(expression) {
184
- let compiled = expression;
185
- const keywords = ['and', 'or', 'in', 'new', 'typeof', 'instanceof', 'delete', 'void', 'this', 'super', 'async', 'await'];
186
- const constants = ['PI', 'TRUE', 'FALSE', 'NULL', 'UNDEFINED', 'Math'];
187
- const functions = [
188
- 'SUM', 'AVG', 'MIN', 'MAX', 'COUNT',
189
- 'ROUND', 'FLOOR', 'CEIL', 'ABS', 'SQRT',
190
- 'UPPER', 'LOWER', 'CONCAT', 'LENGTH', 'TRIM', 'SUBSTRING',
191
- 'TODAY', 'AGE', 'DATEFORMAT', 'DATEDIFF', 'ADDDAYS', 'SUBDAYS'
192
- ];
193
- // Create fresh regex each time to avoid lastIndex issues with g flag
194
- const mathExprPattern = /\$?\{([^}]+)\}/g;
195
- // Process ${...} and {...} blocks: replace bare identifiers with context lookups
196
- compiled = compiled.replace(mathExprPattern, (_match, content) => {
197
- let transformed = content;
198
- // STEP 1: Handle function calls first
199
- // Match function names followed by ( and prefix with context.
200
- // Use negative lookbehind to avoid double-replacing (e.g., context.SUM)
201
- functions.forEach(fn => {
202
- const funcCallRegex = new RegExp(`(?<!context\\.)\\b${fn}\\b(?=\\s*\\()`, 'g');
203
- transformed = transformed.replace(funcCallRegex, `context.${fn}`);
204
- });
205
- constants.forEach(constant => {
206
- const constantRegex = new RegExp(`\\b${constant}\\b`, 'g');
207
- transformed = transformed.replace(constantRegex, `context.${constant}`);
208
- });
209
- // STEP 2: Replace other bare identifiers with context lookups
210
- // Skip: operators, keywords, constants, and property/method access
211
- // First, protect string literals by temporarily replacing them
212
- const strings = [];
213
- let stringProtected = transformed;
214
- stringProtected = stringProtected.replace(/(['"`])(?:(?=(\\?))\2.)*?\1/g, (match) => {
215
- strings.push(match);
216
- return `__STRING_${strings.length - 1}__`;
217
- });
218
- // Now replace identifiers, but they won't match inside strings
219
- stringProtected = stringProtected.replace(/(?<!context\[')\b([a-zA-Z_][a-zA-Z0-9_]*)\b(?!\s*[(\.])/g, (word) => {
220
- // Skip keywords and constants
221
- if (keywords.includes(word.toLowerCase()) || constants.includes(word.toUpperCase())) {
222
- return word;
223
- }
224
- // Skip function names (already handled in step 1)
225
- if (functions.includes(word.toUpperCase())) {
226
- return word;
227
- }
228
- // Replace identifier with context access (but only if not already context['...'])
229
- if (!word.startsWith('context')) {
230
- return `context['${word}']`;
231
- }
232
- return word;
233
- });
234
- // Return as parenthesized expression
235
- return `(${transformed})`;
236
- });
237
- return compiled;
238
- }
239
- compileBareFunctionCalls(expression) {
240
- let compiled = expression;
241
- const functions = [
242
- 'SUM', 'AVG', 'MIN', 'MAX', 'COUNT',
243
- 'ROUND', 'FLOOR', 'CEIL', 'ABS', 'SQRT',
244
- 'UPPER', 'LOWER', 'CONCAT', 'LENGTH', 'TRIM', 'SUBSTRING',
245
- 'TODAY', 'AGE', 'DATEFORMAT', 'DATEDIFF', 'ADDDAYS', 'SUBDAYS'
246
- ];
247
- // Handle bare function calls like SUM([...]) that are not inside ${...} or {...}
248
- // Use negative lookbehind to avoid matching if already preceded by context.
249
- functions.forEach(fn => {
250
- const funcCallRegex = new RegExp(`(?<!context\\.)\\b${fn}\\b(?=\\s*\\()`, 'g');
251
- compiled = compiled.replace(funcCallRegex, `context.${fn}`);
252
- });
253
- return compiled;
254
- }
255
- compileFieldReferences(expression) {
256
- let compiled = expression;
257
- // Create fresh regex each time to avoid lastIndex issues with g flag
258
- const fieldRefPattern = /\{([^{}]+)\}/g;
259
- // Replace {fieldName} with context['fieldName'] or field access
260
- compiled = compiled.replace(fieldRefPattern, (match, ref) => {
261
- // Handle escaped braces
262
- if (ref.startsWith('\\') && ref.endsWith('\\')) {
263
- return match; // Keep as is
264
- }
265
- // Handle nested paths like {customer.name}
266
- return `context['${ref.replace(/\./g, '\'].[')}']`;
267
- });
268
- return compiled;
269
- }
270
- }
@@ -1,171 +0,0 @@
1
- import type { FormSchema, FormComponent } from '../FormBuilder/types/FormSchema';
2
- export declare const generateId: (type: string) => string;
3
- export declare const generateName: (type: string) => string;
4
- export interface UnifiedSchema {
5
- version: string;
6
- properties: Record<string, UnifiedField>;
7
- theme?: string;
8
- layout: LayoutNode[];
9
- settings?: any;
10
- }
11
- export interface UnifiedField extends DataField, UIField {
12
- }
13
- export interface DataSchema {
14
- version: string;
15
- properties: Record<string, DataField>;
16
- settings?: any;
17
- }
18
- export interface DataField {
19
- id: string;
20
- type: 'string' | 'number' | 'boolean' | 'array' | 'any' | 'button' | 'message' | 'sign' | 'image' | 'file' | 'color' | 'grid';
21
- name: string;
22
- label?: string;
23
- format?: 'date' | 'date-time' | 'time' | 'email' | 'url';
24
- defaultValue?: any;
25
- expressionValue?: string;
26
- content?: string;
27
- buttonType?: string;
28
- textboxType?: string;
29
- options?: string[] | any[];
30
- required?: boolean;
31
- minLength?: number;
32
- maxLength?: number;
33
- minValue?: number;
34
- maxValue?: number;
35
- minDate?: string;
36
- maxDate?: string;
37
- minTime?: string;
38
- maxTime?: string;
39
- pattern?: string;
40
- }
41
- export interface UISchema {
42
- properties: Record<string, UIField>;
43
- layout: LayoutNode[];
44
- }
45
- export interface UIField {
46
- widget: string;
47
- _configured?: boolean;
48
- [key: string]: any;
49
- }
50
- export interface SplitSchema {
51
- dataSchema: DataSchema;
52
- uiSchema: UISchema;
53
- }
54
- export type LayoutNode = FieldNode | TableNode | PanelNode | TabsNode | CardNode;
55
- export interface FieldNode {
56
- type: 'field';
57
- propertyId: string;
58
- }
59
- export interface TableNode {
60
- type: 'table';
61
- id: string;
62
- name: string;
63
- label?: string;
64
- cssClass?: string;
65
- hideBorders?: boolean;
66
- rows: number;
67
- cols: number;
68
- cells: TableCell[][];
69
- columnWidths?: {
70
- widths: (number | null)[];
71
- };
72
- conditions?: any;
73
- }
74
- export interface TableCell {
75
- row: number;
76
- col: number;
77
- children: LayoutNode[];
78
- }
79
- export interface PanelNode {
80
- type: 'panel';
81
- id: string;
82
- name: string;
83
- label?: string;
84
- cssClass?: string;
85
- hideBorders?: boolean;
86
- hideLabel?: boolean;
87
- children: LayoutNode[];
88
- conditions?: any;
89
- }
90
- export interface TabsNode {
91
- type: 'tabs';
92
- id: string;
93
- name: string;
94
- cssClass?: string;
95
- label?: string;
96
- tabOptions?: string[];
97
- tabs: TabItem[];
98
- conditions?: any;
99
- }
100
- export interface TabItem {
101
- header: string;
102
- children: LayoutNode[];
103
- }
104
- export interface CardNode {
105
- type: 'card';
106
- id: string;
107
- name: string;
108
- label?: string;
109
- cssClass?: string;
110
- hideLabel?: boolean;
111
- cardTitle?: string;
112
- cardSubtitle?: string;
113
- enableAction?: boolean;
114
- actionButtonLabel?: string;
115
- actionButtonType?: 'button' | 'submit';
116
- children: LayoutNode[];
117
- conditions?: any;
118
- }
119
- /**
120
- * Convert label to camelCase identifier
121
- * Examples:
122
- * "First Name" → "firstName"
123
- * "Email Address" → "emailAddress"
124
- * "Date of Birth" → "dateOfBirth"
125
- * "Phone Number (Mobile)" → "phoneNumberMobile"
126
- */
127
- export declare function labelToFieldKey(label: string, fallbackId?: string): string;
128
- /**
129
- * Ensure field key is unique by appending a number if needed
130
- */
131
- export declare function makeUniqueFieldKey(baseKey: string, existingKeys: Set<string>, originalId?: string): string;
132
- export declare const UI_TYPE_TO_SEMANTIC_TYPE: Record<string, {
133
- type: DataField['type'];
134
- format?: string;
135
- } | null>;
136
- export declare function splitSchema(heartSchema: FormSchema): UnifiedSchema;
137
- /**
138
- * Merge unified schema back into heart schema
139
- * Reconstructs FormComponent array from unified properties and layout
140
- */
141
- export declare function mergeSchema(unified: UnifiedSchema): FormSchema;
142
- /**
143
- * Infer widget type from semantic data type
144
- */
145
- export declare function inferWidgetFromType(type: string, format?: string, hasOptions?: boolean): string;
146
- export interface FieldMatchResult {
147
- existingId: string;
148
- newDataId: string;
149
- confidence: 'exact' | 'high' | 'medium' | 'low';
150
- method: 'id' | 'label-exact' | 'label-fuzzy' | 'new';
151
- similarity?: number;
152
- }
153
- /**
154
- * Match a new data field with existing UI schema field
155
- * Preserves existing ID for stability
156
- */
157
- export declare function matchFieldWithIDPreservation(newDataField: DataField, existingUISchema: UISchema): FieldMatchResult;
158
- /**
159
- * Merge with ID remapping for re-import scenarios
160
- * Preserves existing IDs to maintain layout stability
161
- */
162
- export declare function mergeWithIDRemapping(newDataSchema: DataSchema, existingUISchema: UISchema): FormSchema;
163
- /**
164
- * Extract all field IDs from layout tree
165
- */
166
- export declare function extractFieldIdsFromLayout(layout: LayoutNode[]): Set<string>;
167
- /**
168
- * Convert parser output (FormComponent[]) to DataSchema format
169
- * This allows parser results to be merged with existing UI schemas
170
- */
171
- export declare function convertComponentsToDataSchema(components: FormComponent[]): DataSchema;