@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,514 @@
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 { ExpressionParser } from './expression-parser';
13
+ import { DependencyTracker } from './dependency-tracker';
14
+ import { Internationalization } from '@syncfusion/ej2-base';
15
+ /**
16
+ * ExpressionEngine - Core evaluation engine
17
+ *
18
+ * Safely evaluates user-defined expressions against form state
19
+ * Supports field references, math operations, functions, and conditionals
20
+ * @private
21
+ */
22
+ var ExpressionEngine = /** @class */ (function () {
23
+ function ExpressionEngine() {
24
+ this.evaluationCache = new Map();
25
+ this.compiledFunctions = new Map();
26
+ this.parser = new ExpressionParser();
27
+ this.dependencyTracker = new DependencyTracker();
28
+ }
29
+ /**
30
+ * Evaluate expression against form values
31
+ */
32
+ ExpressionEngine.prototype.evaluate = function (expression, formValues, options, isCustomValidation) {
33
+ if (options === void 0) { options = {}; }
34
+ if (isCustomValidation === void 0) { isCustomValidation = false; }
35
+ try {
36
+ if (!expression || expression.trim() === '') {
37
+ return null;
38
+ }
39
+ var _a = options.timeout, timeout = _a === void 0 ? 5000 : _a, _b = options.maxDepth, maxDepth = _b === void 0 ? 10 : _b, _c = options.locale, locale = _c === void 0 ? 'en-US' : _c, _d = options.throwOnError, throwOnError = _d === void 0 ? false : _d;
40
+ // Check cache
41
+ var cacheKey = this.getCacheKey(expression, formValues);
42
+ if (!isCustomValidation && this.evaluationCache.has(cacheKey)) {
43
+ return this.evaluationCache.get(cacheKey);
44
+ }
45
+ // Get or compile function
46
+ var fn = this.compiledFunctions.get(expression);
47
+ if (!fn) {
48
+ fn = this.parser.compile(expression, {
49
+ timeout: timeout,
50
+ maxDepth: maxDepth,
51
+ locale: locale,
52
+ isCustomValidation: isCustomValidation
53
+ });
54
+ this.compiledFunctions.set(expression, fn);
55
+ }
56
+ // Execute with context
57
+ var context = this.buildContext(formValues);
58
+ var startTime = Date.now();
59
+ var result = fn(context);
60
+ // Validate timeout
61
+ if (Date.now() - startTime > timeout) {
62
+ var error = new Error("Expression evaluation exceeded timeout of " + timeout + "ms");
63
+ if (throwOnError)
64
+ throw error;
65
+ return null;
66
+ }
67
+ // Cache result
68
+ this.evaluationCache.set(cacheKey, result);
69
+ return result;
70
+ }
71
+ catch (error) {
72
+ if (options.throwOnError) {
73
+ throw error;
74
+ }
75
+ return null;
76
+ }
77
+ };
78
+ /**
79
+ * Extract field names referenced in expression
80
+ */
81
+ ExpressionEngine.prototype.extractDependencies = function (expression) {
82
+ if (!expression)
83
+ return [];
84
+ return this.dependencyTracker.extractFieldReferences(expression);
85
+ };
86
+ /**
87
+ * Build dependency graph for all expressions
88
+ */
89
+ ExpressionEngine.prototype.buildDependencyGraph = function (components) {
90
+ var _this = this;
91
+ var graph = {};
92
+ components.forEach(function (comp) {
93
+ if (comp.expressionValue) {
94
+ var deps = _this.extractDependencies(comp.expressionValue);
95
+ graph[comp.name] = deps;
96
+ }
97
+ });
98
+ return graph;
99
+ };
100
+ /**
101
+ * Detect circular dependencies
102
+ */
103
+ ExpressionEngine.prototype.detectCircularDependencies = function (graph) {
104
+ var visited = new Set();
105
+ var recursionStack = new Set();
106
+ var cycles = [];
107
+ var visit = function (node, path) {
108
+ visited.add(node);
109
+ recursionStack.add(node);
110
+ path.push(node);
111
+ var deps = graph[node] || [];
112
+ for (var _i = 0, deps_1 = deps; _i < deps_1.length; _i++) {
113
+ var dep = deps_1[_i];
114
+ if (!visited.has(dep)) {
115
+ visit(dep, path.slice());
116
+ }
117
+ else if (recursionStack.has(dep)) {
118
+ var cycleStart = path.indexOf(dep);
119
+ cycles.push(path.slice(cycleStart).concat([dep]));
120
+ }
121
+ }
122
+ recursionStack.delete(node);
123
+ };
124
+ for (var _i = 0, _a = Object.keys(graph); _i < _a.length; _i++) {
125
+ var node = _a[_i];
126
+ if (!visited.has(node)) {
127
+ visit(node, []);
128
+ }
129
+ }
130
+ return cycles;
131
+ };
132
+ /**
133
+ * Get topological order for evaluation
134
+ */
135
+ ExpressionEngine.prototype.getTopologicalOrder = function (graph) {
136
+ var visited = new Set();
137
+ var order = [];
138
+ var visit = function (node) {
139
+ if (visited.has(node))
140
+ return;
141
+ visited.add(node);
142
+ var deps = graph[node] || [];
143
+ for (var _i = 0, deps_2 = deps; _i < deps_2.length; _i++) {
144
+ var dep = deps_2[_i];
145
+ visit(dep);
146
+ }
147
+ order.push(node);
148
+ };
149
+ for (var _i = 0, _a = Object.keys(graph); _i < _a.length; _i++) {
150
+ var node = _a[_i];
151
+ visit(node);
152
+ }
153
+ return order;
154
+ };
155
+ /**
156
+ * Clear internal caches
157
+ */
158
+ ExpressionEngine.prototype.clearCache = function () {
159
+ this.evaluationCache.clear();
160
+ this.compiledFunctions.clear();
161
+ };
162
+ // Private helper methods
163
+ ExpressionEngine.prototype.getCacheKey = function (expression, formValues) {
164
+ // Simple cache key (in production, use better hashing)
165
+ return expression + ":" + JSON.stringify(formValues);
166
+ };
167
+ ExpressionEngine.prototype.buildContext = function (formValues) {
168
+ var intl = new Internationalization();
169
+ var dFormatter = intl.getDateFormat({
170
+ format: 'MM/dd/yyyy',
171
+ type: 'date'
172
+ });
173
+ return __assign({}, formValues, {
174
+ // Constants
175
+ PI: Math.PI, TRUE: true, FALSE: false, NULL: null, UNDEFINED: undefined, Math: Math,
176
+ // Aggregate Functions
177
+ SUM: function (values) { return Array.isArray(values) ? values.reduce(function (a, b) { return Number(a) + Number(b); }, 0) : 0; }, AVG: function (values) {
178
+ if (!Array.isArray(values) || values.length === 0)
179
+ return 0;
180
+ var sum = values.reduce(function (a, b) { return Number(a) + Number(b); }, 0);
181
+ return sum / values.length;
182
+ }, MIN: function (values) { return Array.isArray(values) && values.length > 0 ? Math.min.apply(Math, values.map(Number)) : 0; }, MAX: function (values) { return Array.isArray(values) && values.length > 0 ? Math.max.apply(Math, values.map(Number)) : 0; }, COUNT: function (values) { return Array.isArray(values) ? values.length : 0; },
183
+ // Math Functions
184
+ ROUND: function (value, decimals) {
185
+ if (decimals === void 0) { decimals = 0; }
186
+ return Math.round(value * Math.pow(10, decimals)) / Math.pow(10, decimals);
187
+ }, FLOOR: Math.floor, CEIL: Math.ceil, ABS: Math.abs, SQRT: Math.sqrt,
188
+ // String Functions
189
+ UPPER: function (text) { return String(text).toUpperCase(); }, LOWER: function (text) { return String(text).toLowerCase(); }, CONCAT: function () {
190
+ var strings = [];
191
+ for (var _i = 0; _i < arguments.length; _i++) {
192
+ strings[_i] = arguments[_i];
193
+ }
194
+ return strings.map(String).join('');
195
+ }, LENGTH: function (text) { return String(text).length; }, TRIM: function (text) { return String(text).trim(); }, SUBSTRING: function (text, start, length) {
196
+ return length !== undefined
197
+ ? String(text).substr(start, length)
198
+ : String(text).substr(start);
199
+ },
200
+ // Date Functions
201
+ TODAY: function () {
202
+ var value = dFormatter(new Date());
203
+ return value;
204
+ }, AGE: function (birthDate) {
205
+ var birth = typeof birthDate === 'string' ? new Date(birthDate) : birthDate;
206
+ var today = new Date();
207
+ var age = today.getFullYear() - birth.getFullYear();
208
+ var monthDiff = today.getMonth() - birth.getMonth();
209
+ if (monthDiff < 0 || (monthDiff === 0 && today.getDate() < birth.getDate())) {
210
+ age--;
211
+ }
212
+ return age;
213
+ }, DATEFORMAT: function (date, format) {
214
+ var d = typeof date === 'string' ? new Date(date) : date;
215
+ var formatter = intl.getDateFormat({
216
+ format: format,
217
+ type: 'date'
218
+ });
219
+ // Simple date format implementation
220
+ return formatter(d);
221
+ }, DATEDIFF: function (date1, date2) {
222
+ var d1 = typeof date1 === 'string' ? new Date(date1) : date1;
223
+ var d2 = typeof date2 === 'string' ? new Date(date2) : date2;
224
+ return Math.floor((d2.getTime() - d1.getTime()) / (1000 * 60 * 60 * 24));
225
+ },
226
+ // Add days to a date (for date arithmetic like {date} + 5)
227
+ ADDDAYS: function (date, days) {
228
+ var d = typeof date === 'string' ? new Date(date) : new Date(date);
229
+ d.setDate(d.getDate() + Number(days));
230
+ return dFormatter(d);
231
+ },
232
+ // Add days to a date (for date arithmetic like {date} + 5)
233
+ SUBDAYS: function (date, days) {
234
+ var d = typeof date === 'string' ? new Date(date) : new Date(date);
235
+ d.setDate(d.getDate() - Number(days));
236
+ return dFormatter(d);
237
+ } });
238
+ };
239
+ return ExpressionEngine;
240
+ }());
241
+ export { ExpressionEngine };
242
+ /**
243
+ * ExpressionValidator - Validates expressions before runtime
244
+ *
245
+ * Checks syntax, validates field references, and detects circular dependencies
246
+ * @private
247
+ */
248
+ var ExpressionValidator = /** @class */ (function () {
249
+ function ExpressionValidator() {
250
+ this.supportedFunctions = [
251
+ 'SUM', 'AVG', 'MIN', 'MAX', 'COUNT',
252
+ 'ROUND', 'FLOOR', 'CEIL', 'ABS', 'SQRT',
253
+ 'UPPER', 'LOWER', 'CONCAT', 'LENGTH', 'TRIM', 'SUBSTRING',
254
+ 'TODAY', 'AGE', 'DATEFORMAT', 'DATEDIFF', 'ADDDAYS', 'SUBDAYS'
255
+ ];
256
+ this.keywords = ['PI', 'TRUE', 'FALSE', 'NULL', 'UNDEFINED', 'and', 'or', 'in'];
257
+ }
258
+ /**
259
+ * Validate expression against available fields
260
+ */
261
+ ExpressionValidator.prototype.validate = function (expression, availableFields) {
262
+ var errors = [];
263
+ if (!expression || expression.trim() === '') {
264
+ return errors; // Empty expression is valid
265
+ }
266
+ // Check syntax
267
+ var syntaxErrors = this.validateSyntax(expression);
268
+ errors.push.apply(errors, syntaxErrors);
269
+ // Check field references
270
+ var fieldErrors = this.validateFieldReferences(expression, availableFields);
271
+ errors.push.apply(errors, fieldErrors);
272
+ // Check function calls
273
+ var funcErrors = this.validateFunctionCalls(expression);
274
+ errors.push.apply(errors, funcErrors);
275
+ // Check field operations based on types
276
+ var opErrors = this.validateFieldOperations(expression, availableFields);
277
+ errors.push.apply(errors, opErrors);
278
+ return errors;
279
+ };
280
+ /**
281
+ * Validate field operations - check for invalid operators on string/date types
282
+ */
283
+ ExpressionValidator.prototype.validateFieldOperations = function (expression, availableFields) {
284
+ var errors = [];
285
+ // Skip if not field objects with type info
286
+ if (!Array.isArray(availableFields) || availableFields.length === 0) {
287
+ return errors;
288
+ }
289
+ var firstField = availableFields[0];
290
+ if (typeof firstField === 'string') {
291
+ return errors; // No type information available
292
+ }
293
+ // Build field map from objects
294
+ var fieldMap = new Map();
295
+ availableFields.forEach(function (field) {
296
+ if (field && typeof field === 'object' && field.name) {
297
+ fieldMap.set(field.name, field);
298
+ }
299
+ });
300
+ if (fieldMap.size === 0)
301
+ return errors;
302
+ // Track reported operator positions to avoid duplicates
303
+ var reportedOperators = new Set();
304
+ // Check each field reference for invalid operations
305
+ var fieldRefPattern = /(\{[^}]+\})/g;
306
+ var match;
307
+ // Invalid operators for string fields (allow only + for concatenation)
308
+ var stringInvalidOps = ['-', '*', '/', '%', '^'];
309
+ // Operators invalid for date fields (allow + for date arithmetic with numbers)
310
+ var dateInvalidOps = ['-', '*', '/', '%', '^', '+'];
311
+ while ((match = fieldRefPattern.exec(expression)) !== null) {
312
+ var fieldRef = match[0];
313
+ var fieldName = fieldRef.slice(1, -1); // Remove { }
314
+ var field = fieldMap.get(fieldName);
315
+ if (!field)
316
+ continue;
317
+ var fieldIndex = match.index;
318
+ var fieldEndIndex = fieldIndex + fieldRef.length;
319
+ // Get context around field reference (including spaces)
320
+ var textBefore = expression.substring(Math.max(0, fieldIndex - 10), fieldIndex);
321
+ var textAfter = expression.substring(fieldEndIndex, Math.min(expression.length, fieldEndIndex + 10));
322
+ // Extract the operator if present (skip spaces)
323
+ var operatorBefore = textBefore.replace(/\s+$/, '').slice(-1);
324
+ var operatorAfter = textAfter.replace(/^\s+/, '').charAt(0);
325
+ // Calculate actual position of operators in the original expression
326
+ var textBeforeTrimmed = textBefore.replace(/\s+$/, '');
327
+ var textAfterTrimmed = textAfter.replace(/^\s+/, '');
328
+ var operatorBeforePos = fieldIndex - (textBefore.length - textBeforeTrimmed.length) - 1;
329
+ var operatorAfterPos = fieldEndIndex + (textAfter.length - textAfterTrimmed.length);
330
+ // For STRING fields (without format)
331
+ if (field.type === 'string' && !field.format) {
332
+ if (operatorBefore && stringInvalidOps.indexOf(operatorBefore) !== -1) {
333
+ var key = operatorBeforePos + ":" + operatorBefore;
334
+ if (!reportedOperators.has(key)) {
335
+ errors.push({
336
+ type: 'InvalidOperation',
337
+ message: "Cannot perform '" + operatorBefore + "' operation on string field '{" + fieldName + "}'"
338
+ });
339
+ reportedOperators.add(key);
340
+ }
341
+ }
342
+ if (operatorAfter && stringInvalidOps.indexOf(operatorAfter) !== -1) {
343
+ var key = operatorAfterPos + ":" + operatorAfter;
344
+ if (!reportedOperators.has(key)) {
345
+ errors.push({
346
+ type: 'InvalidOperation',
347
+ message: "Cannot perform '" + operatorAfter + "' operation on string field '{" + fieldName + "}'"
348
+ });
349
+ reportedOperators.add(key);
350
+ }
351
+ }
352
+ }
353
+ // For DATE fields - allow + with numbers, reject other operators
354
+ if (field.format === 'date' || field.format === 'date-time' || field.format === 'time') {
355
+ if (operatorBefore && dateInvalidOps.indexOf(operatorBefore) !== -1) {
356
+ var key = operatorBeforePos + ":" + operatorBefore;
357
+ if (!reportedOperators.has(key)) {
358
+ errors.push({
359
+ type: 'InvalidOperation',
360
+ message: "Cannot perform '" + operatorBefore + "' operation on date field '{" + fieldName + "}'"
361
+ });
362
+ reportedOperators.add(key);
363
+ }
364
+ }
365
+ if (operatorAfter && dateInvalidOps.indexOf(operatorAfter) !== -1) {
366
+ var key = operatorAfterPos + ":" + operatorAfter;
367
+ if (!reportedOperators.has(key)) {
368
+ errors.push({
369
+ type: 'InvalidOperation',
370
+ message: "Cannot perform '" + operatorAfter + "' operation on date field '{" + fieldName + "}'"
371
+ });
372
+ reportedOperators.add(key);
373
+ }
374
+ }
375
+ // Allow + only when combined with numbers or number fields
376
+ if (operatorAfter === '+') {
377
+ var operandAfter = textAfter.replace(/^\s+/, '').substring(1).trim();
378
+ var isNumberField = /^\{[^}]+\}/.test(operandAfter) && fieldMap.get(operandAfter.slice(1, -1)) && fieldMap.get(operandAfter.slice(1, -1)).type === 'number';
379
+ var isNumberLiteral = /^\d+/.test(operandAfter);
380
+ if (!isNumberField && !isNumberLiteral) {
381
+ var key = operatorAfterPos + ":" + operatorAfter;
382
+ if (!reportedOperators.has(key)) {
383
+ errors.push({
384
+ type: 'InvalidOperation',
385
+ message: "Date field '{" + fieldName + "}' can only be used with +number or +{numberField}, not '" + operatorAfter + operandAfter.substring(0, 10) + "'"
386
+ });
387
+ reportedOperators.add(key);
388
+ }
389
+ }
390
+ }
391
+ if (operatorBefore === '+') {
392
+ var trimmedBefore = textBefore.replace(/\s+$/, '');
393
+ var operandBefore = trimmedBefore.substring(0, trimmedBefore.length - 1).trim();
394
+ var isNumberField = /\{[^}]+\}$/.test(operandBefore) && fieldMap.get(operandBefore.slice(operandBefore.lastIndexOf('{') + 1, -1)) && fieldMap.get(operandBefore.slice(operandBefore.lastIndexOf('{') + 1, -1)).type === 'number';
395
+ var isNumberLiteral = /\d+$/.test(operandBefore);
396
+ if (!isNumberField && !isNumberLiteral) {
397
+ var key = operatorBeforePos + ":" + operatorBefore;
398
+ if (!reportedOperators.has(key)) {
399
+ errors.push({
400
+ type: 'InvalidOperation',
401
+ message: "Date field '{" + fieldName + "}' can only be used with +number or +{numberField}"
402
+ });
403
+ reportedOperators.add(key);
404
+ }
405
+ }
406
+ }
407
+ }
408
+ }
409
+ return errors;
410
+ };
411
+ ExpressionValidator.prototype.validateSyntax = function (expression) {
412
+ var errors = [];
413
+ // Check balanced braces
414
+ var openBraces = (expression.match(/\{/g) || []).length;
415
+ var closeBraces = (expression.match(/\}/g) || []).length;
416
+ if (openBraces !== closeBraces) {
417
+ errors.push({
418
+ type: 'SyntaxError',
419
+ message: 'Unbalanced braces in expression'
420
+ });
421
+ }
422
+ // Check balanced parentheses
423
+ var openParens = (expression.match(/\(/g) || []).length;
424
+ var closeParens = (expression.match(/\)/g) || []).length;
425
+ if (openParens !== closeParens) {
426
+ errors.push({
427
+ type: 'SyntaxError',
428
+ message: 'Unbalanced parentheses in expression'
429
+ });
430
+ }
431
+ // Check balanced $ brackets
432
+ var openDollar = (expression.match(/\$\{/g) || []).length;
433
+ var closeDollar = (expression.match(/\}/g) || []).length;
434
+ if (openDollar > closeDollar) {
435
+ errors.push({
436
+ type: 'SyntaxError',
437
+ message: 'Unbalanced ${ } in expression'
438
+ });
439
+ }
440
+ return errors;
441
+ };
442
+ /**
443
+ * @private
444
+ */
445
+ ExpressionValidator.prototype.validateFieldReferences = function (expression, availableFields) {
446
+ var errors = [];
447
+ // Skip field validation if availableFields is not properly populated
448
+ // This allows expressions to work at runtime even if we can't validate field names at editor time
449
+ if (!availableFields || availableFields.length === 0) {
450
+ return errors;
451
+ }
452
+ var fieldRefPattern = /\{([^{}]+)\}/g;
453
+ var match;
454
+ // Handle both string[] and AvailableField[] formats
455
+ var availableFieldsSet;
456
+ if (typeof availableFields[0] === 'string') {
457
+ availableFieldsSet = new Set(availableFields);
458
+ }
459
+ else {
460
+ availableFieldsSet = new Set(availableFields.map(function (f) { return f.name; }));
461
+ }
462
+ while ((match = fieldRefPattern.exec(expression)) !== null) {
463
+ var ref = match[1].trim();
464
+ // Skip if it's a function call
465
+ if (this.isFunctionCall(ref))
466
+ continue;
467
+ // Skip if it's a math expression (contains operators or numbers)
468
+ // This distinguishes between {fieldName} and ${5 + 3}
469
+ if (this.isMathExpression(ref))
470
+ continue;
471
+ // Extract field name from nested paths (e.g., "customer.name" -> "customer")
472
+ var fieldName = ref.split(/[.\[\]]/)[0].trim();
473
+ // Check if field exists
474
+ if (fieldName && this.keywords.indexOf(fieldName.toUpperCase()) === -1) {
475
+ if (!availableFieldsSet.has(fieldName)) {
476
+ errors.push({
477
+ type: 'UndefinedField',
478
+ message: "Field '" + fieldName + "' is not defined in the form",
479
+ field: fieldName
480
+ });
481
+ }
482
+ }
483
+ }
484
+ return errors;
485
+ };
486
+ ExpressionValidator.prototype.validateFunctionCalls = function (expression) {
487
+ var errors = [];
488
+ var funcPattern = /(\w+)\s*\(/g;
489
+ var match;
490
+ while ((match = funcPattern.exec(expression)) !== null) {
491
+ var funcName = match[1];
492
+ // Only validate uppercase functions (user-defined lowercase functions might be allowed)
493
+ if (funcName === funcName.toUpperCase() && this.supportedFunctions.indexOf(funcName) === -1) {
494
+ errors.push({
495
+ type: 'InvalidFunction',
496
+ message: "Unknown function: '" + funcName + "'. Supported functions: " + this.supportedFunctions.join(', ')
497
+ });
498
+ }
499
+ }
500
+ return errors;
501
+ };
502
+ ExpressionValidator.prototype.isFunctionCall = function (ref) {
503
+ return /^\w+\s*\(/.test(ref);
504
+ };
505
+ ExpressionValidator.prototype.isMathExpression = function (ref) {
506
+ // Check if the expression contains math operators, numbers, or other non-field-name patterns
507
+ // Math expressions like: "5 + 3", "qty * 2", "age > 18", "sum([1,2,3])"
508
+ // should be skipped, while field references like "fieldName" or "customer.name" should be validated
509
+ var mathOperatorPattern = /[\+\-\*\/\%\=\<\>\!\&\|\^\~\s\d]/;
510
+ return mathOperatorPattern.test(ref);
511
+ };
512
+ return ExpressionValidator;
513
+ }());
514
+ export { ExpressionValidator };
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Field type information for validation
3
+ * @private
4
+ */
5
+ export interface AvailableField {
6
+ name: string;
7
+ type: string;
8
+ format?: string;
9
+ }
10
+ /**
11
+ * ExpressionParser - Parse and compile expressions
12
+ *
13
+ * Converts string expressions into safe, compiled functions
14
+ * Supports field references, operators, functions, and conditionals
15
+ * @private
16
+ */
17
+ export declare class ExpressionParser {
18
+ private supportedFunctions;
19
+ private availableFields;
20
+ /**
21
+ * Initialize parser with available fields for type validation
22
+ */
23
+ setAvailableFields(fields: AvailableField[]): void;
24
+ private validateFieldOperations;
25
+ /**
26
+ * Validate expression syntax
27
+ */
28
+ validate(expression: string): {
29
+ valid: boolean;
30
+ errors: string[];
31
+ };
32
+ /**
33
+ * Compile expression to executable function
34
+ */
35
+ compile(expression: string, options?: any): any;
36
+ private compileMatrixExpressions;
37
+ private compileBareFunctionCalls;
38
+ private compileFieldReferences;
39
+ private compileInputReferences;
40
+ }