@syncfusion/ej2-form-renderer 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 (214) hide show
  1. package/README.md +60 -0
  2. package/common.d.ts +4 -0
  3. package/common.js +4 -0
  4. package/dist/ej2-form-renderer.umd.min.js +11 -0
  5. package/dist/ej2-form-renderer.umd.min.js.map +1 -0
  6. package/dist/es6/ej2-form-renderer.es2015.js +6787 -0
  7. package/dist/es6/ej2-form-renderer.es2015.js.map +1 -0
  8. package/dist/es6/ej2-form-renderer.es5.js +7055 -0
  9. package/dist/es6/ej2-form-renderer.es5.js.map +1 -0
  10. package/dist/global/ej2-form-renderer.min.js +11 -0
  11. package/dist/global/ej2-form-renderer.min.js.map +1 -0
  12. package/dist/global/index.d.ts +14 -0
  13. package/form-renderer.d.ts +4 -0
  14. package/form-renderer.js +4 -0
  15. package/index.d.ts +4 -0
  16. package/index.js +4 -0
  17. package/license +10 -0
  18. package/package.json +41 -0
  19. package/src/common/checkbox-group.d.ts +55 -0
  20. package/src/common/checkbox-group.js +241 -0
  21. package/src/common/conditional-rule-engine.d.ts +241 -0
  22. package/src/common/conditional-rule-engine.js +505 -0
  23. package/src/common/custom-validation-engine.d.ts +57 -0
  24. package/src/common/custom-validation-engine.js +152 -0
  25. package/src/common/datagrid-component.d.ts +156 -0
  26. package/src/common/datagrid-component.js +410 -0
  27. package/src/common/expressions/dependency-tracker.d.ts +29 -0
  28. package/src/common/expressions/dependency-tracker.js +137 -0
  29. package/src/common/expressions/expression-engine.d.ts +94 -0
  30. package/src/common/expressions/expression-engine.js +514 -0
  31. package/src/common/expressions/expression-parser.d.ts +40 -0
  32. package/src/common/expressions/expression-parser.js +270 -0
  33. package/src/common/expressions/grid-expressions.d.ts +24 -0
  34. package/src/common/expressions/grid-expressions.js +92 -0
  35. package/src/common/expressions/index.d.ts +4 -0
  36. package/src/common/expressions/index.js +4 -0
  37. package/src/common/index.d.ts +10 -0
  38. package/src/common/index.js +10 -0
  39. package/src/common/json-converter.d.ts +945 -0
  40. package/src/common/json-converter.js +1110 -0
  41. package/src/common/minmax-rule-engine.d.ts +105 -0
  42. package/src/common/minmax-rule-engine.js +380 -0
  43. package/src/common/option-fetcher.d.ts +30 -0
  44. package/src/common/option-fetcher.js +139 -0
  45. package/src/common/parser.d.ts +98 -0
  46. package/src/common/parser.js +788 -0
  47. package/src/common/static-html-renderer.d.ts +45 -0
  48. package/src/common/static-html-renderer.js +77 -0
  49. package/src/common/utils.d.ts +116 -0
  50. package/src/common/utils.js +484 -0
  51. package/src/form-renderer/form-renderer-model.d.ts +65 -0
  52. package/src/form-renderer/form-renderer.d.ts +425 -0
  53. package/src/form-renderer/form-renderer.js +2277 -0
  54. package/src/form-renderer/index.d.ts +6 -0
  55. package/src/form-renderer/index.js +5 -0
  56. package/src/form-renderer/render-form-field.d.ts +31 -0
  57. package/src/form-renderer/render-form-field.js +816 -0
  58. package/src/form-renderer/types/form-schema.d.ts +452 -0
  59. package/src/form-renderer/types/form-schema.js +32 -0
  60. package/src/global.js +1 -0
  61. package/src/index.d.ts +4 -0
  62. package/src/index.js +4 -0
  63. package/styles/bds-lite.css +599 -0
  64. package/styles/bds-lite.scss +2 -0
  65. package/styles/bds.css +599 -0
  66. package/styles/bds.scss +2 -0
  67. package/styles/bootstrap-dark-lite.css +608 -0
  68. package/styles/bootstrap-dark-lite.scss +2 -0
  69. package/styles/bootstrap-dark.css +608 -0
  70. package/styles/bootstrap-dark.scss +2 -0
  71. package/styles/bootstrap-lite.css +595 -0
  72. package/styles/bootstrap-lite.scss +2 -0
  73. package/styles/bootstrap.css +595 -0
  74. package/styles/bootstrap.scss +2 -0
  75. package/styles/bootstrap4-lite.css +595 -0
  76. package/styles/bootstrap4-lite.scss +2 -0
  77. package/styles/bootstrap4.css +595 -0
  78. package/styles/bootstrap4.scss +2 -0
  79. package/styles/bootstrap5-dark-lite.css +595 -0
  80. package/styles/bootstrap5-dark-lite.scss +2 -0
  81. package/styles/bootstrap5-dark.css +595 -0
  82. package/styles/bootstrap5-dark.scss +2 -0
  83. package/styles/bootstrap5-lite.css +595 -0
  84. package/styles/bootstrap5-lite.scss +2 -0
  85. package/styles/bootstrap5.3-lite.css +679 -0
  86. package/styles/bootstrap5.3-lite.scss +2 -0
  87. package/styles/bootstrap5.3.css +679 -0
  88. package/styles/bootstrap5.3.scss +2 -0
  89. package/styles/bootstrap5.css +595 -0
  90. package/styles/bootstrap5.scss +2 -0
  91. package/styles/fabric-dark-lite.css +608 -0
  92. package/styles/fabric-dark-lite.scss +2 -0
  93. package/styles/fabric-dark.css +608 -0
  94. package/styles/fabric-dark.scss +2 -0
  95. package/styles/fabric-lite.css +595 -0
  96. package/styles/fabric-lite.scss +2 -0
  97. package/styles/fabric.css +595 -0
  98. package/styles/fabric.scss +2 -0
  99. package/styles/fluent-dark-lite.css +595 -0
  100. package/styles/fluent-dark-lite.scss +2 -0
  101. package/styles/fluent-dark.css +595 -0
  102. package/styles/fluent-dark.scss +2 -0
  103. package/styles/fluent-lite.css +595 -0
  104. package/styles/fluent-lite.scss +2 -0
  105. package/styles/fluent.css +595 -0
  106. package/styles/fluent.scss +2 -0
  107. package/styles/fluent2-lite.css +681 -0
  108. package/styles/fluent2-lite.scss +2 -0
  109. package/styles/fluent2.css +681 -0
  110. package/styles/fluent2.scss +2 -0
  111. package/styles/form-renderer/_all.scss +2 -0
  112. package/styles/form-renderer/_bds-definition.scss +8 -0
  113. package/styles/form-renderer/_bootstrap-dark-definition.scss +8 -0
  114. package/styles/form-renderer/_bootstrap-definition.scss +8 -0
  115. package/styles/form-renderer/_bootstrap4-definition.scss +8 -0
  116. package/styles/form-renderer/_bootstrap5-dark-definition.scss +8 -0
  117. package/styles/form-renderer/_bootstrap5-definition.scss +8 -0
  118. package/styles/form-renderer/_bootstrap5.3-definition.scss +8 -0
  119. package/styles/form-renderer/_fabric-dark-definition.scss +8 -0
  120. package/styles/form-renderer/_fabric-definition.scss +8 -0
  121. package/styles/form-renderer/_fluent-dark-definition.scss +8 -0
  122. package/styles/form-renderer/_fluent-definition.scss +8 -0
  123. package/styles/form-renderer/_fluent2-definition.scss +8 -0
  124. package/styles/form-renderer/_highcontrast-definition.scss +8 -0
  125. package/styles/form-renderer/_highcontrast-light-definition.scss +8 -0
  126. package/styles/form-renderer/_layout.scss +480 -0
  127. package/styles/form-renderer/_material-dark-definition.scss +8 -0
  128. package/styles/form-renderer/_material-definition.scss +8 -0
  129. package/styles/form-renderer/_material3-dark-definition.scss +8 -0
  130. package/styles/form-renderer/_material3-definition.scss +8 -0
  131. package/styles/form-renderer/_mixin.scss +26 -0
  132. package/styles/form-renderer/_tailwind-dark-definition.scss +8 -0
  133. package/styles/form-renderer/_tailwind-definition.scss +8 -0
  134. package/styles/form-renderer/_tailwind3-definition.scss +8 -0
  135. package/styles/form-renderer/_theme.scss +69 -0
  136. package/styles/form-renderer/_variables.scss +2 -0
  137. package/styles/form-renderer/bds.css +599 -0
  138. package/styles/form-renderer/bds.scss +2 -0
  139. package/styles/form-renderer/bootstrap-dark.css +608 -0
  140. package/styles/form-renderer/bootstrap-dark.scss +2 -0
  141. package/styles/form-renderer/bootstrap.css +595 -0
  142. package/styles/form-renderer/bootstrap.scss +2 -0
  143. package/styles/form-renderer/bootstrap4.css +595 -0
  144. package/styles/form-renderer/bootstrap4.scss +2 -0
  145. package/styles/form-renderer/bootstrap5-dark.css +595 -0
  146. package/styles/form-renderer/bootstrap5-dark.scss +2 -0
  147. package/styles/form-renderer/bootstrap5.3.css +679 -0
  148. package/styles/form-renderer/bootstrap5.3.scss +2 -0
  149. package/styles/form-renderer/bootstrap5.css +595 -0
  150. package/styles/form-renderer/bootstrap5.scss +2 -0
  151. package/styles/form-renderer/fabric-dark.css +608 -0
  152. package/styles/form-renderer/fabric-dark.scss +2 -0
  153. package/styles/form-renderer/fabric.css +595 -0
  154. package/styles/form-renderer/fabric.scss +2 -0
  155. package/styles/form-renderer/fluent-dark.css +595 -0
  156. package/styles/form-renderer/fluent-dark.scss +2 -0
  157. package/styles/form-renderer/fluent.css +595 -0
  158. package/styles/form-renderer/fluent.scss +2 -0
  159. package/styles/form-renderer/fluent2.css +681 -0
  160. package/styles/form-renderer/fluent2.scss +2 -0
  161. package/styles/form-renderer/highcontrast-light.css +595 -0
  162. package/styles/form-renderer/highcontrast-light.scss +2 -0
  163. package/styles/form-renderer/highcontrast.css +608 -0
  164. package/styles/form-renderer/highcontrast.scss +2 -0
  165. package/styles/form-renderer/material-dark.css +608 -0
  166. package/styles/form-renderer/material-dark.scss +2 -0
  167. package/styles/form-renderer/material.css +595 -0
  168. package/styles/form-renderer/material.scss +2 -0
  169. package/styles/form-renderer/material3-dark.css +677 -0
  170. package/styles/form-renderer/material3-dark.scss +2 -0
  171. package/styles/form-renderer/material3.css +679 -0
  172. package/styles/form-renderer/material3.scss +2 -0
  173. package/styles/form-renderer/tailwind-dark.css +595 -0
  174. package/styles/form-renderer/tailwind-dark.scss +2 -0
  175. package/styles/form-renderer/tailwind.css +595 -0
  176. package/styles/form-renderer/tailwind.scss +2 -0
  177. package/styles/form-renderer/tailwind3.css +669 -0
  178. package/styles/form-renderer/tailwind3.scss +2 -0
  179. package/styles/highcontrast-light-lite.css +595 -0
  180. package/styles/highcontrast-light-lite.scss +2 -0
  181. package/styles/highcontrast-light.css +595 -0
  182. package/styles/highcontrast-light.scss +2 -0
  183. package/styles/highcontrast-lite.css +608 -0
  184. package/styles/highcontrast-lite.scss +2 -0
  185. package/styles/highcontrast.css +608 -0
  186. package/styles/highcontrast.scss +2 -0
  187. package/styles/material-dark-lite.css +608 -0
  188. package/styles/material-dark-lite.scss +2 -0
  189. package/styles/material-dark.css +608 -0
  190. package/styles/material-dark.scss +2 -0
  191. package/styles/material-lite.css +595 -0
  192. package/styles/material-lite.scss +2 -0
  193. package/styles/material.css +595 -0
  194. package/styles/material.scss +2 -0
  195. package/styles/material3-dark-lite.css +677 -0
  196. package/styles/material3-dark-lite.scss +2 -0
  197. package/styles/material3-dark.css +677 -0
  198. package/styles/material3-dark.scss +2 -0
  199. package/styles/material3-lite.css +679 -0
  200. package/styles/material3-lite.scss +2 -0
  201. package/styles/material3.css +679 -0
  202. package/styles/material3.scss +2 -0
  203. package/styles/tailwind-dark-lite.css +595 -0
  204. package/styles/tailwind-dark-lite.scss +2 -0
  205. package/styles/tailwind-dark.css +595 -0
  206. package/styles/tailwind-dark.scss +2 -0
  207. package/styles/tailwind-lite.css +595 -0
  208. package/styles/tailwind-lite.scss +2 -0
  209. package/styles/tailwind.css +595 -0
  210. package/styles/tailwind.scss +2 -0
  211. package/styles/tailwind3-lite.css +669 -0
  212. package/styles/tailwind3-lite.scss +2 -0
  213. package/styles/tailwind3.css +669 -0
  214. package/styles/tailwind3.scss +2 -0
@@ -0,0 +1,788 @@
1
+ var __assign = (this && this.__assign) || function () {
2
+ __assign = Object.assign || function(t) {
3
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
4
+ s = arguments[i];
5
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
6
+ t[p] = s[p];
7
+ }
8
+ return t;
9
+ };
10
+ return __assign.apply(this, arguments);
11
+ };
12
+ import { sanitizeId, VALIDATION_REGEX } from './utils';
13
+ /**
14
+ * @private
15
+ */
16
+ var DEFAULT_CONFIG = {
17
+ strict: false,
18
+ maxInputSize: 5 * 1024 * 1024,
19
+ defaultTextType: 'textbox',
20
+ inferTypeFromValue: true,
21
+ generateIds: true,
22
+ includeMetadata: true,
23
+ customTypeMap: {},
24
+ validateUnknownFields: false
25
+ };
26
+ /**
27
+ * @private
28
+ */
29
+ var UniversalJsonParser = /** @class */ (function () {
30
+ function UniversalJsonParser(customConfig) {
31
+ this.config = __assign({}, DEFAULT_CONFIG, customConfig);
32
+ }
33
+ UniversalJsonParser.prototype.parse = function (input) {
34
+ var errors = [];
35
+ var warnings = [];
36
+ // Handle string input
37
+ if (typeof input === 'string') {
38
+ if (input.length > this.config.maxInputSize) {
39
+ return this.formatError(errors, warnings, "Input exceeds maximum size of " + this.config.maxInputSize + " bytes");
40
+ }
41
+ var jsonValidation = validateJSON(input);
42
+ if (!jsonValidation.valid) {
43
+ return this.formatError(errors, warnings, (jsonValidation.errors && jsonValidation.errors[0]) || 'Invalid JSON');
44
+ }
45
+ try {
46
+ input = JSON.parse(input);
47
+ }
48
+ catch (error) {
49
+ return this.formatError(errors, warnings, "Failed to parse JSON: " + error.message);
50
+ }
51
+ }
52
+ // Detect format
53
+ var detection = this.detectFormat(input);
54
+ // Add warnings for ambiguous format detection
55
+ if (detection.ambiguousFormats && detection.ambiguousFormats.length > 0) {
56
+ warnings.push("Ambiguous format detected.");
57
+ warnings.push("Using " + detection.format + " format (" + (detection.format === 'json-schema' ? 'properties priority' : 'pages priority') + ")");
58
+ }
59
+ // Parse based on format
60
+ var components = [];
61
+ switch (detection.format) {
62
+ case 'configured-schema':
63
+ // Already in our standard format, just use directly
64
+ components = input.properties || [];
65
+ break;
66
+ case 'json-schema': {
67
+ var jsonSchemaResult = this.parseJsonSchema(input);
68
+ components = jsonSchemaResult.components;
69
+ if (jsonSchemaResult.warnings) {
70
+ warnings.push.apply(warnings, jsonSchemaResult.warnings);
71
+ }
72
+ break;
73
+ }
74
+ case 'surveyjs':
75
+ components = this.parseSurveyJS(input);
76
+ break;
77
+ case 'openapi':
78
+ components = this.parseOpenAPI(input);
79
+ break;
80
+ case 'data-inference':
81
+ components = this.parseDataInference(input);
82
+ // Only warn about inferred types if components were actually created
83
+ if (components.length > 0) {
84
+ warnings.push('Field types inferred from data; please verify');
85
+ }
86
+ break;
87
+ default:
88
+ errors.push('Could not determine input format');
89
+ }
90
+ if (components.length === 0) {
91
+ errors.push('No form fields could be extracted from input');
92
+ }
93
+ // Add default submit button if not already present
94
+ var hasSubmitButton = components.some(function (comp) { return comp.type === 'button' && comp.buttonType === 'submit'; });
95
+ if (!hasSubmitButton && components.length > 0) {
96
+ components.push({
97
+ id: this.generateComponentId('button'),
98
+ type: 'button',
99
+ label: 'Submit',
100
+ style: 'primary',
101
+ buttonType: 'submit',
102
+ });
103
+ }
104
+ var schema = {
105
+ version: input.version || "0.1.0",
106
+ components: components
107
+ };
108
+ var schemaValidation = validateFormSchema(schema);
109
+ if (!schemaValidation.valid && schemaValidation.errors) {
110
+ errors.push.apply(errors, schemaValidation.errors);
111
+ }
112
+ if (schemaValidation.warnings) {
113
+ warnings.push.apply(warnings, schemaValidation.warnings);
114
+ }
115
+ if (this.config.strict && warnings.length > 0) {
116
+ errors.push.apply(errors, warnings);
117
+ warnings.length = 0;
118
+ }
119
+ var sanitized = sanitizeFormSchema(schema);
120
+ return {
121
+ success: errors.length === 0,
122
+ schema: sanitized,
123
+ errors: errors,
124
+ warnings: warnings,
125
+ metadata: {
126
+ detectedFormat: detection.format,
127
+ confidence: detection.confidence,
128
+ sourceHints: detection.hints
129
+ }
130
+ };
131
+ };
132
+ UniversalJsonParser.prototype.formatError = function (errors, warnings, message) {
133
+ errors.push(message);
134
+ return {
135
+ success: false,
136
+ schema: null,
137
+ errors: errors,
138
+ warnings: warnings,
139
+ metadata: {
140
+ detectedFormat: 'unknown',
141
+ confidence: 'low',
142
+ sourceHints: []
143
+ }
144
+ };
145
+ };
146
+ UniversalJsonParser.prototype.detectFormat = function (input) {
147
+ var hints = [];
148
+ var ambiguousFormats = [];
149
+ if (!input || typeof input !== 'object') {
150
+ return {
151
+ format: 'unknown',
152
+ confidence: 'low',
153
+ hints: ['Input is not a valid object']
154
+ };
155
+ }
156
+ // Check for JSON Schema indicators
157
+ if (input.$schema && typeof input.$schema === 'string' && input.$schema.includes('json-schema')) {
158
+ hints.push('$schema property detected');
159
+ return { format: 'json-schema', confidence: 'high', hints: hints };
160
+ }
161
+ // Detect ambiguous formats (Test Case 8)
162
+ var hasProperties = input.properties && typeof input.properties === 'object';
163
+ var hasPages = input.pages && Array.isArray(input.pages);
164
+ var hasElements = input.elements && Array.isArray(input.elements);
165
+ if (hasProperties && hasPages) {
166
+ hints.push('Multiple format patterns detected');
167
+ hints.push('Selected based on priority rules');
168
+ ambiguousFormats.push('properties format', 'pages format');
169
+ // JSON Schema has priority
170
+ return {
171
+ format: 'json-schema',
172
+ confidence: 'medium',
173
+ hints: hints,
174
+ ambiguousFormats: ambiguousFormats
175
+ };
176
+ }
177
+ // Check for SurveyJS with pages
178
+ if (hasPages) {
179
+ hints.push('pages array detected');
180
+ if (input.pages[0] && input.pages[0].elements)
181
+ hints.push('elements structure matched');
182
+ return { format: 'surveyjs', confidence: 'high', hints: hints };
183
+ }
184
+ // Check for SurveyJS with elements at root
185
+ if (hasElements && !hasProperties) {
186
+ hints.push('elements array at root level');
187
+ return { format: 'surveyjs', confidence: 'medium', hints: hints };
188
+ }
189
+ // Check for JSON Schema with properties
190
+ if (hasProperties) {
191
+ hints.push('properties object detected');
192
+ if (input.type === 'object')
193
+ hints.push('type: object matched');
194
+ if (input.required && Array.isArray(input.required))
195
+ hints.push('required array found');
196
+ // Check for API schema indicators (example fields pattern)
197
+ if (this.hasExampleFields(input.properties)) {
198
+ hints.push('example fields detected (API schema pattern)');
199
+ return { format: 'openapi', confidence: 'high', hints: hints };
200
+ }
201
+ return { format: 'json-schema', confidence: 'high', hints: hints };
202
+ }
203
+ // Check for Data Inference
204
+ if (this.isDataInferenceCandidate(input)) {
205
+ hints.push('Simple object with primitive values');
206
+ hints.push('No schema indicators found');
207
+ return { format: 'data-inference', confidence: 'medium', hints: hints };
208
+ }
209
+ return {
210
+ format: 'unknown',
211
+ confidence: 'low',
212
+ hints: ['Could not identify format']
213
+ };
214
+ };
215
+ UniversalJsonParser.prototype.hasExampleFields = function (properties) {
216
+ if (!properties || typeof properties !== 'object')
217
+ return false;
218
+ var keys = Object.keys(properties);
219
+ for (var _i = 0, keys_1 = keys; _i < keys_1.length; _i++) {
220
+ var key = keys_1[_i];
221
+ var prop = properties[key];
222
+ if (prop && 'example' in prop) {
223
+ return true;
224
+ }
225
+ }
226
+ return false;
227
+ };
228
+ UniversalJsonParser.prototype.isDataInferenceCandidate = function (input) {
229
+ if (!input || typeof input !== 'object')
230
+ return false;
231
+ if (input.$schema || input.properties || input.pages || input.elements)
232
+ return false;
233
+ var inputKeys = Object.keys(input);
234
+ return inputKeys.every(function (k) {
235
+ var val = input[k];
236
+ if (val === null || val === undefined)
237
+ return true;
238
+ if (typeof val === 'string' || typeof val === 'number' || typeof val === 'boolean')
239
+ return true;
240
+ if (Array.isArray(val)) {
241
+ return val.every(function (item) {
242
+ return typeof item === 'string' || typeof item === 'number' || typeof item === 'boolean';
243
+ });
244
+ }
245
+ return false;
246
+ });
247
+ };
248
+ UniversalJsonParser.prototype.inferComponentType = function (fieldName, value) {
249
+ var valueType = this.inferTypeFromValue(fieldName, value);
250
+ if (valueType.type) {
251
+ return __assign({}, valueType, { confidence: 'high', method: 'value-type' });
252
+ }
253
+ var patternMatch = this.matchFieldNamePattern(fieldName);
254
+ if (patternMatch.type) {
255
+ return __assign({}, patternMatch, { confidence: 'high', method: 'name-pattern' });
256
+ }
257
+ return {
258
+ type: this.config.defaultTextType,
259
+ confidence: 'low',
260
+ method: 'fallback'
261
+ };
262
+ };
263
+ UniversalJsonParser.prototype.inferTypeFromValue = function (fieldName, value) {
264
+ if (!this.config.inferTypeFromValue)
265
+ return { type: 'textbox' };
266
+ if (value === null || value === undefined) {
267
+ // Even with null/undefined values, check field name patterns
268
+ return this.matchFieldNamePattern(fieldName);
269
+ }
270
+ if (typeof value === 'string') {
271
+ // Check value-based patterns first (highest confidence)
272
+ if (value.includes('@') && value.includes('.')) {
273
+ return { type: 'textbox', textboxType: 'email' };
274
+ }
275
+ // eslint-disable-next-line security/detect-unsafe-regex
276
+ if (/^(https?:\/\/)?(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}/.test(value)) {
277
+ return { type: 'textbox', textboxType: 'url' };
278
+ }
279
+ if (/^\d{4}-\d{2}-\d{2}/.test(value)) {
280
+ return { type: 'date' };
281
+ }
282
+ // For generic strings, check field name patterns
283
+ var fieldNameMatch = this.matchFieldNamePattern(fieldName);
284
+ if (fieldNameMatch.type !== 'textbox' || fieldNameMatch.textboxType) {
285
+ return fieldNameMatch;
286
+ }
287
+ return { type: this.config.defaultTextType };
288
+ }
289
+ if (typeof value === 'number') {
290
+ return { type: 'number' };
291
+ }
292
+ if (typeof value === 'boolean') {
293
+ return { type: 'checkbox' };
294
+ }
295
+ if (Array.isArray(value)) {
296
+ return { type: 'multiselect' };
297
+ }
298
+ return { type: 'textbox' };
299
+ };
300
+ UniversalJsonParser.prototype.matchFieldNamePattern = function (fieldName) {
301
+ if (this.config.customTypeMap) {
302
+ var customType = this.config.customTypeMap[fieldName.toLowerCase()];
303
+ if (customType)
304
+ return { type: customType };
305
+ }
306
+ var lower = fieldName.toLowerCase();
307
+ var normalized = lower.replace(/[_\-\s]+/g, ' ');
308
+ if (/email|mail|e-?mail/.test(normalized))
309
+ return { type: 'textbox', textboxType: 'email' };
310
+ if (/date|birth|birthday|dob|created|updated/.test(normalized))
311
+ return { type: 'date' };
312
+ if (/phone|tel|mobile|cell|cellphone|msisdn/.test(normalized))
313
+ return { type: 'textbox', textboxType: 'number' };
314
+ if (/url|link|uri|website/.test(normalized))
315
+ return { type: 'textbox', textboxType: 'url' };
316
+ if (/password|pwd|pass|security|secret|key|token/.test(normalized))
317
+ return { type: 'textbox', textboxType: 'password' };
318
+ if (/\b(?:age|count|qty|quantity|amount|price|cost|salary|fee|rate|number|num)\b/.test(normalized))
319
+ return { type: 'number' };
320
+ if (/active|enabled|visible|deleted|archived|approved|confirmed/.test(normalized))
321
+ return { type: 'checkbox' };
322
+ if (/select|choice|option|type|status|category|kind/.test(normalized))
323
+ return { type: 'dropdown' };
324
+ if (/description|comment|note|bio|biography|about|message|content|summary|details/.test(normalized))
325
+ return { type: 'textarea' };
326
+ return { type: 'textbox' };
327
+ };
328
+ UniversalJsonParser.prototype.parseJsonSchema = function (schema) {
329
+ var components = [];
330
+ var warnings = [];
331
+ if (!schema.properties || typeof schema.properties !== 'object')
332
+ return { components: components, warnings: warnings };
333
+ var flattenedProperties = this.flattenNestedProperties(schema.properties, '', warnings);
334
+ var flatKeys = Object.keys(flattenedProperties);
335
+ for (var _i = 0, flatKeys_1 = flatKeys; _i < flatKeys_1.length; _i++) {
336
+ var key = flatKeys_1[_i];
337
+ var propDef = flattenedProperties[key];
338
+ var typeInfo = this.mapJsonSchemaType(propDef);
339
+ var requiredArr = schema.required || [];
340
+ var isRequired = requiredArr.indexOf(key) !== -1;
341
+ components.push(this.createComponent(key, propDef, typeInfo, { required: isRequired }));
342
+ }
343
+ return { components: components, warnings: warnings };
344
+ };
345
+ UniversalJsonParser.prototype.flattenNestedProperties = function (properties, prefix, warnings) {
346
+ var flattened = {};
347
+ var hasNested = false;
348
+ var propKeys = Object.keys(properties);
349
+ for (var _i = 0, propKeys_1 = propKeys; _i < propKeys_1.length; _i++) {
350
+ var key = propKeys_1[_i];
351
+ var propDef = properties[key];
352
+ var fullKey = prefix ? prefix + "_" + key : key;
353
+ // Check if this is a nested object (Test Case 9)
354
+ if (propDef.type === 'object' && propDef.properties && typeof propDef.properties === 'object') {
355
+ hasNested = true;
356
+ var nestedFlattened = this.flattenNestedProperties(propDef.properties, fullKey, warnings);
357
+ Object.assign(flattened, nestedFlattened);
358
+ }
359
+ else {
360
+ flattened[fullKey] = propDef;
361
+ }
362
+ }
363
+ // Add warnings for nested objects
364
+ if (hasNested && !prefix) {
365
+ warnings.push('NESTED_OBJECTS_FLATTENED: Nested objects converted to flat structure');
366
+ var outerKeys = Object.keys(properties);
367
+ for (var _a = 0, outerKeys_1 = outerKeys; _a < outerKeys_1.length; _a++) {
368
+ var key = outerKeys_1[_a];
369
+ var propDef = properties[key];
370
+ if (propDef.type === 'object' && propDef.properties) {
371
+ this.collectFlattenedFieldNames(propDef.properties, key, warnings);
372
+ }
373
+ }
374
+ }
375
+ return flattened;
376
+ };
377
+ UniversalJsonParser.prototype.collectFlattenedFieldNames = function (properties, prefix, warnings) {
378
+ var collKeys = Object.keys(properties);
379
+ for (var _i = 0, collKeys_1 = collKeys; _i < collKeys_1.length; _i++) {
380
+ var key = collKeys_1[_i];
381
+ var propDef = properties[key];
382
+ var fullKey = prefix + "_" + key;
383
+ warnings.push("Field '" + prefix + "." + key + "' flattened to '" + fullKey + "'");
384
+ if (propDef.type === 'object' && propDef.properties) {
385
+ this.collectFlattenedFieldNames(propDef.properties, fullKey, warnings);
386
+ }
387
+ }
388
+ };
389
+ UniversalJsonParser.prototype.parseSurveyJS = function (schema) {
390
+ var _this = this;
391
+ var components = [];
392
+ if (schema.pages && Array.isArray(schema.pages)) {
393
+ schema.pages.forEach(function (page) {
394
+ if (page.elements && Array.isArray(page.elements)) {
395
+ page.elements.forEach(function (element) {
396
+ components.push(_this.createComponentFromSurveyJS(element));
397
+ });
398
+ }
399
+ });
400
+ }
401
+ if (!components.length && schema.elements && Array.isArray(schema.elements)) {
402
+ schema.elements.forEach(function (element) {
403
+ components.push(_this.createComponentFromSurveyJS(element));
404
+ });
405
+ }
406
+ return components;
407
+ };
408
+ UniversalJsonParser.prototype.createComponentFromSurveyJS = function (element) {
409
+ var type = this.mapSurveyJSType(element.type || 'text');
410
+ var validation = {};
411
+ // Only add required if explicitly true
412
+ if (element.isRequired === true) {
413
+ validation.required = true;
414
+ }
415
+ if (element.validators && Array.isArray(element.validators)) {
416
+ element.validators.forEach(function (validator) {
417
+ if (validator.type === 'numeric') {
418
+ if (validator.minValue !== undefined)
419
+ validation.minValue = validator.minValue;
420
+ if (validator.maxValue !== undefined)
421
+ validation.maxValue = validator.maxValue;
422
+ }
423
+ if (validator.type === 'text') {
424
+ if (validator.minLength !== undefined)
425
+ validation.minLength = validator.minLength;
426
+ if (validator.maxLength !== undefined)
427
+ validation.maxLength = validator.maxLength;
428
+ }
429
+ });
430
+ }
431
+ var component = __assign({ id: this.generateComponentId(type), type: type, label: element.title || element.label || this.humanizeFieldName(element.name), defaultValue: element.defaultValue, expressionValue: element.expressionValue }, Object.keys(validation).length > 0 ? validation : undefined);
432
+ if (type === 'dropdown' || type === 'multiselect' || type === 'radio' || type === 'splitButton') {
433
+ if (element.choices && Array.isArray(element.choices)) {
434
+ component.options = element.choices;
435
+ }
436
+ }
437
+ return component;
438
+ };
439
+ UniversalJsonParser.prototype.mapSurveyJSType = function (surveyType) {
440
+ var typeMap = {
441
+ text: 'textbox',
442
+ email: 'email',
443
+ number: 'number',
444
+ checkbox: 'checkbox',
445
+ radiogroup: 'radio',
446
+ dropdown: 'dropdown',
447
+ tagbox: 'multiselect',
448
+ multiselect: 'multiselect',
449
+ rating: 'number',
450
+ comment: 'textarea',
451
+ date: 'date'
452
+ };
453
+ return typeMap[surveyType] || 'textbox';
454
+ };
455
+ UniversalJsonParser.prototype.parseOpenAPI = function (schema) {
456
+ var components = [];
457
+ if (!schema.properties || typeof schema.properties !== 'object')
458
+ return components;
459
+ var openAPIKeys = Object.keys(schema.properties);
460
+ var requiredArr = schema.required || [];
461
+ for (var _i = 0, openAPIKeys_1 = openAPIKeys; _i < openAPIKeys_1.length; _i++) {
462
+ var key = openAPIKeys_1[_i];
463
+ var propDef = schema.properties[key];
464
+ var typeInfo = this.mapJsonSchemaType(propDef);
465
+ var isRequired = requiredArr.indexOf(key) !== -1;
466
+ components.push(this.createComponent(key, propDef, typeInfo, { required: isRequired }));
467
+ }
468
+ return components;
469
+ };
470
+ UniversalJsonParser.prototype.parseDataInference = function (data) {
471
+ var components = [];
472
+ var dataKeys = Object.keys(data);
473
+ for (var _i = 0, dataKeys_1 = dataKeys; _i < dataKeys_1.length; _i++) {
474
+ var key = dataKeys_1[_i];
475
+ var value = data[key];
476
+ var typeInference = this.inferComponentType(key, value);
477
+ var component = {
478
+ id: this.generateComponentId(typeInference.type),
479
+ type: typeInference.type,
480
+ label: this.humanizeFieldName(key),
481
+ defaultValue: value,
482
+ expressionValue: undefined
483
+ };
484
+ if (typeInference.textboxType) {
485
+ component.textboxType = typeInference.textboxType;
486
+ // Add default regex patterns for email and url
487
+ if (typeInference.textboxType === 'email') {
488
+ component.regex = VALIDATION_REGEX['EMAIL'];
489
+ }
490
+ else if (typeInference.textboxType === 'url') {
491
+ component.regex = VALIDATION_REGEX['URL'];
492
+ }
493
+ }
494
+ if (typeInference.type === 'date' && component.defaultValue !== undefined && component.defaultValue !== null) {
495
+ var formatted = this.formatDateTimeValue(component.defaultValue);
496
+ if (formatted)
497
+ component.defaultValue = formatted;
498
+ }
499
+ if (Array.isArray(value) && value.length > 0) {
500
+ component.options = value;
501
+ }
502
+ components.push(component);
503
+ }
504
+ return components;
505
+ };
506
+ UniversalJsonParser.prototype.createComponent = function (fieldName, propDef, typeInfo, context) {
507
+ var validation = {};
508
+ // Only add required if explicitly true
509
+ var isRequired = propDef.required !== undefined ? propDef.required : context.required;
510
+ if (isRequired === true) {
511
+ validation.required = true;
512
+ }
513
+ if (propDef.minLength)
514
+ validation.minLength = propDef.minLength;
515
+ if (propDef.maxLength)
516
+ validation.maxLength = propDef.maxLength;
517
+ if (propDef.minDate)
518
+ validation.minDate = propDef.minDate;
519
+ if (propDef.maxDate)
520
+ validation.maxDate = propDef.maxDate;
521
+ if (propDef.minTime)
522
+ validation.minTime = propDef.minTime;
523
+ if (propDef.minValue)
524
+ validation.minValue = propDef.minValue;
525
+ if (propDef.maxValue)
526
+ validation.maxValue = propDef.maxValue;
527
+ if (propDef.pattern) {
528
+ validation.pattern = propDef.pattern;
529
+ }
530
+ var rawId = propDef.id || this.generateComponentId(typeInfo.type);
531
+ var safeGeneratedId = sanitizeId(rawId, this.generateComponentId(typeInfo.type));
532
+ var component = __assign({ id: safeGeneratedId, name: propDef.name, type: typeInfo.type, label: propDef.title || propDef.label || this.humanizeFieldName(fieldName), defaultValue: propDef.default || propDef.defaultValue || undefined, expressionValue: propDef.expressionValue || undefined, content: propDef.content, buttonType: propDef.buttonType, textboxType: propDef.textboxType }, Object.keys(validation).length > 0 ? validation : undefined);
533
+ if (typeInfo.textboxType) {
534
+ component.textboxType = typeInfo.textboxType;
535
+ // Add default regex patterns for email and url
536
+ if (typeInfo.textboxType === 'email') {
537
+ if (!validation.pattern) {
538
+ validation.regex = '^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$'; // Standard email regex
539
+ validation.validationMessage = 'Please enter a valid email address';
540
+ }
541
+ }
542
+ else if (typeInfo.textboxType === 'url') {
543
+ if (!validation.pattern) {
544
+ validation.regex = '^(https?:\\/\\/)?(www\\.)?[-a-zA-Z0-9@:%._\\+~#=]{1,256}\\.[a-zA-Z0-9()]{1,6}\\b([-a-zA-Z0-9()@:%_\\+.~#?&//=]*)$';
545
+ validation.validationMessage = 'Please enter a valid URL';
546
+ }
547
+ }
548
+ }
549
+ if (typeInfo.type === 'date' && component.defaultValue !== undefined && component.defaultValue !== null) {
550
+ var formatted = this.formatDateTimeValue(component.defaultValue);
551
+ if (formatted)
552
+ component.defaultValue = formatted;
553
+ }
554
+ if ((typeInfo.type === 'splitButton' || typeInfo.type === 'dropdown' || typeInfo.type === 'multiselect' || typeInfo.type === 'radio') && (propDef.enum || propDef.options)) {
555
+ component.options = propDef.enum || propDef.options;
556
+ }
557
+ return component;
558
+ };
559
+ UniversalJsonParser.prototype.parseDateFromValue = function (value) {
560
+ if (value == null)
561
+ return null;
562
+ // numeric timestamps
563
+ if (typeof value === 'number') {
564
+ // assume seconds if small
565
+ if (value < 1e12)
566
+ return new Date(value * 1000);
567
+ return new Date(value);
568
+ }
569
+ if (typeof value === 'string') {
570
+ var s = value.trim();
571
+ // Try ISO / RFC parse
572
+ var dIso = new Date(s);
573
+ if (!isNaN(dIso.getTime()))
574
+ return dIso;
575
+ // yyyy-mm-dd[ T hh:mm(:ss)]
576
+ // eslint-disable-next-line security/detect-unsafe-regex
577
+ var m = s.match(/^(\d{4})-(\d{2})-(\d{2})(?:[T ](\d{2}):(\d{2})(?::(\d{2}))?)?/);
578
+ if (m)
579
+ return new Date(Number(m[1]), Number(m[2]) - 1, Number(m[3]), Number(m[4] || 0), Number(m[5] || 0), Number(m[6] || 0));
580
+ // mm/dd/yyyy or m/d/yyyy
581
+ // eslint-disable-next-line security/detect-unsafe-regex
582
+ var m2 = s.match(/^(\d{1,2})\/(\d{1,2})\/(\d{4})(?:[ T](\d{1,2}):(\d{2})(?:[:](\d{2}))?)?/);
583
+ if (m2)
584
+ return new Date(Number(m2[3]), Number(m2[1]) - 1, Number(m2[2]), Number(m2[4] || 0), Number(m2[5] || 0), Number(m2[6] || 0));
585
+ }
586
+ return null;
587
+ };
588
+ UniversalJsonParser.prototype.formatDate = function (d) {
589
+ var monthNum = d.getMonth() + 1;
590
+ var dayNum = d.getDate();
591
+ var mm = monthNum < 10 ? '0' + monthNum : String(monthNum);
592
+ var dd = dayNum < 10 ? '0' + dayNum : String(dayNum);
593
+ var yyyy = d.getFullYear();
594
+ return mm + "/" + dd + "/" + yyyy;
595
+ };
596
+ // private formatTime(d: Date): string {
597
+ // let hours = d.getHours();
598
+ // const minutes = d.getMinutes().toString().padStart(2, '0');
599
+ // const ampm = hours >= 12 ? 'PM' : 'AM';
600
+ // hours = hours % 12;
601
+ // if (hours === 0) hours = 12;
602
+ // return `${hours.toString().padStart(2, '0')}:${minutes} ${ampm}`;
603
+ // }
604
+ UniversalJsonParser.prototype.formatDateTimeValue = function (value) {
605
+ var d = this.parseDateFromValue(value);
606
+ if (!d)
607
+ return undefined;
608
+ var datePart = this.formatDate(d);
609
+ var hasTime = d.getHours() !== 0 || d.getMinutes() !== 0 || /\dT\d{2}:\d{2}/.test(String(value));
610
+ if (hasTime)
611
+ return "" + datePart;
612
+ return datePart;
613
+ };
614
+ UniversalJsonParser.prototype.mapJsonSchemaType = function (propDef) {
615
+ var schemaType = propDef.type;
616
+ if (schemaType === 'string') {
617
+ var fmt = (propDef.format || '').toString().toLowerCase();
618
+ var text = ((propDef.title || propDef.label || '') + ' ' + (propDef.description || '')).toLowerCase();
619
+ if (/email|mail|e-?mail/.test(fmt) || /email|mail|e-?mail/.test(text))
620
+ return { type: 'textbox', textboxType: 'email' };
621
+ if (/uri|url|link|website/.test(fmt) || /uri|url|link|website/.test(text))
622
+ return { type: 'textbox', textboxType: 'url' };
623
+ if (/phone|tel|mobile|cell|msisdn/.test(fmt) || /phone|tel|mobile|cell|msisdn/.test(text))
624
+ return { type: 'textbox', textboxType: 'number' };
625
+ if (/password|pwd|pass|security|secret|key/.test(fmt) || /password|pwd|pass|security|secret|key/.test(text))
626
+ return { type: 'textbox', textboxType: 'password' };
627
+ if (fmt === 'date' || fmt === 'date-time' || /date|birthday|dob/.test(text))
628
+ return { type: 'date' };
629
+ if (propDef.enum)
630
+ return { type: 'dropdown' };
631
+ if (propDef.options)
632
+ return { type: 'dropdown' };
633
+ return { type: this.config.defaultTextType };
634
+ }
635
+ if (schemaType === 'number' || schemaType === 'integer')
636
+ return { type: 'number' };
637
+ if (schemaType === 'boolean')
638
+ return { type: 'checkbox' };
639
+ if (schemaType === 'array')
640
+ return { type: 'multiselect' };
641
+ // Presentation / custom widget types
642
+ if (schemaType === 'message')
643
+ return { type: 'message' };
644
+ if (schemaType === 'button')
645
+ return { type: 'button' };
646
+ if (schemaType === 'signature' || schemaType === 'sign')
647
+ return { type: 'signature' };
648
+ if (schemaType === 'image' || schemaType === 'imageEditor')
649
+ return { type: 'imageEditor' };
650
+ if (schemaType === 'file' || schemaType === 'fileUpload')
651
+ return { type: 'fileUpload' };
652
+ if (schemaType === 'color' || schemaType === 'colorPicker')
653
+ return { type: 'colorPicker' };
654
+ if (schemaType === 'splitButton')
655
+ return { type: 'splitButton' };
656
+ return { type: this.config.defaultTextType };
657
+ };
658
+ UniversalJsonParser.prototype.generateComponentId = function (type) {
659
+ if (!this.config.generateIds)
660
+ return '';
661
+ var timestamp = Date.now();
662
+ var random = Math.floor(Math.random() * 1000);
663
+ return type + "_" + timestamp + "_" + random;
664
+ };
665
+ UniversalJsonParser.prototype.humanizeFieldName = function (fieldName) {
666
+ var result = fieldName.replace(/_/g, ' ');
667
+ result = result.replace(/([a-z])([A-Z])/g, '$1 $2');
668
+ return result;
669
+ };
670
+ return UniversalJsonParser;
671
+ }());
672
+ export { UniversalJsonParser };
673
+ /**
674
+ * @private
675
+ */
676
+ export var validateJSON = function (jsonString) {
677
+ try {
678
+ JSON.parse(jsonString);
679
+ return { valid: true };
680
+ }
681
+ catch (error) {
682
+ return {
683
+ valid: false,
684
+ errors: ["Invalid JSON syntax: " + error.message]
685
+ };
686
+ }
687
+ };
688
+ /**
689
+ * @private
690
+ */
691
+ export var validateFormSchema = function (schema) {
692
+ var errors = [];
693
+ var warnings = [];
694
+ if (!schema.components) {
695
+ errors.push('Missing required property: components');
696
+ }
697
+ else if (!Array.isArray(schema.components)) {
698
+ errors.push('Property "components" must be an array');
699
+ }
700
+ // Validate component structure
701
+ if (Array.isArray(schema.components)) {
702
+ var componentIds_1 = new Set();
703
+ var validateComponent_1 = function (comp, path) {
704
+ if (path === void 0) { path = 'root'; }
705
+ if (!comp.id) {
706
+ errors.push("Component at " + path + " is missing \"id\" property");
707
+ }
708
+ else {
709
+ if (componentIds_1.has(comp.id)) {
710
+ errors.push("Duplicate component ID found: " + comp.id);
711
+ }
712
+ componentIds_1.add(comp.id);
713
+ }
714
+ if (!comp.type) {
715
+ errors.push("Component \"" + (comp.id || 'unknown') + "\" is missing \"type\" property");
716
+ }
717
+ if (comp.children && Array.isArray(comp.children)) {
718
+ comp.children.forEach(function (child, index) {
719
+ validateComponent_1(child, path + ".children[" + index + "]");
720
+ });
721
+ }
722
+ if (comp.tabItems && Array.isArray(comp.tabItems)) {
723
+ comp.tabItems.forEach(function (tab, tabIndex) {
724
+ if (tab.content && Array.isArray(tab.content)) {
725
+ tab.content.forEach(function (child, index) {
726
+ validateComponent_1(child, path + ".tabItems[" + tabIndex + "].content[" + index + "]");
727
+ });
728
+ }
729
+ });
730
+ }
731
+ if (comp.tableCells && Array.isArray(comp.tableCells)) {
732
+ comp.tableCells.forEach(function (row, rowIndex) {
733
+ if (Array.isArray(row)) {
734
+ row.forEach(function (cell, colIndex) {
735
+ if (Array.isArray(cell)) {
736
+ cell.forEach(function (child, index) {
737
+ validateComponent_1(child, path + ".tableCells[" + rowIndex + "][" + colIndex + "][" + index + "]");
738
+ });
739
+ }
740
+ });
741
+ }
742
+ });
743
+ }
744
+ };
745
+ schema.components.forEach(function (comp, index) {
746
+ validateComponent_1(comp, "components[" + index + "]");
747
+ });
748
+ }
749
+ return {
750
+ valid: errors.length === 0,
751
+ errors: errors.length > 0 ? errors : undefined,
752
+ warnings: warnings.length > 0 ? warnings : undefined
753
+ };
754
+ };
755
+ /**
756
+ * @private
757
+ */
758
+ export var sanitizeFormSchema = function (schema) {
759
+ var sanitized = {
760
+ version: schema.version || "0.1.0",
761
+ components: schema.components || []
762
+ };
763
+ var sanitizeComponent = function (comp) {
764
+ var sanitizedComp = __assign({}, comp, { _configured: true });
765
+ if (comp.children && Array.isArray(comp.children)) {
766
+ sanitizedComp.children = comp.children.map(sanitizeComponent);
767
+ }
768
+ if (comp.tabItems && Array.isArray(comp.tabItems)) {
769
+ sanitizedComp.tabItems = comp.tabItems.map(function (tab) { return (__assign({}, tab, { content: tab.content ? tab.content.map(sanitizeComponent) : [] })); });
770
+ }
771
+ if (comp.tableCells && Array.isArray(comp.tableCells)) {
772
+ sanitizedComp.tableCells = comp.tableCells.map(function (row) {
773
+ return row.map(function (cell) {
774
+ return Array.isArray(cell) ? cell.map(sanitizeComponent) : [];
775
+ });
776
+ });
777
+ }
778
+ return sanitizedComp;
779
+ };
780
+ sanitized.components = sanitized.components.map(sanitizeComponent);
781
+ return sanitized;
782
+ };
783
+ /**
784
+ * @private
785
+ */
786
+ export var exportFormSchema = function (schema) {
787
+ return JSON.stringify(schema, null, 2);
788
+ };