@aemforms/af-core 0.22.68 → 0.22.69

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 (58) hide show
  1. package/esm/afb-events.js +161 -0
  2. package/esm/afb-runtime.js +4304 -0
  3. package/esm/types/src/BaseNode.d.ts +99 -0
  4. package/esm/types/src/Captcha.d.ts +5 -0
  5. package/esm/types/src/Checkbox.d.ts +84 -0
  6. package/esm/types/src/CheckboxGroup.d.ts +23 -0
  7. package/esm/types/src/Container.d.ts +75 -0
  8. package/esm/types/src/DateField.d.ts +9 -0
  9. package/esm/types/src/EmailInput.d.ts +16 -0
  10. package/esm/types/src/Field.d.ts +223 -0
  11. package/esm/types/src/Fieldset.d.ts +16 -0
  12. package/esm/types/src/FileObject.d.ts +16 -0
  13. package/esm/types/src/FileUpload.d.ts +27 -0
  14. package/esm/types/src/Form.d.ts +125 -0
  15. package/esm/types/src/FormInstance.d.ts +16 -0
  16. package/esm/types/src/FormMetaData.d.ts +7 -0
  17. package/esm/types/src/InstanceManager.d.ts +9 -0
  18. package/esm/types/src/Node.d.ts +7 -0
  19. package/esm/types/src/Scriptable.d.ts +17 -0
  20. package/esm/types/src/SubmitMetaData.d.ts +7 -0
  21. package/esm/types/src/controller/EventQueue.d.ts +18 -0
  22. package/esm/types/src/controller/Events.d.ts +91 -0
  23. package/esm/types/src/controller/Logger.d.ts +11 -0
  24. package/esm/types/src/data/DataGroup.d.ts +20 -0
  25. package/esm/types/src/data/DataValue.d.ts +16 -0
  26. package/esm/types/src/data/EmptyDataValue.d.ts +14 -0
  27. package/esm/types/src/index.d.ts +24 -0
  28. package/esm/types/src/rules/FunctionRuntime.d.ts +62 -0
  29. package/esm/types/src/rules/RuleEngine.d.ts +16 -0
  30. package/esm/types/src/types/Json.d.ts +180 -0
  31. package/esm/types/src/types/Model.d.ts +141 -0
  32. package/esm/types/src/types/index.d.ts +2 -0
  33. package/esm/types/src/utils/CoercionUtils.d.ts +1 -0
  34. package/esm/types/src/utils/DataRefParser.d.ts +33 -0
  35. package/esm/types/src/utils/Fetch.d.ts +8 -0
  36. package/esm/types/src/utils/FormCreationUtils.d.ts +10 -0
  37. package/esm/types/src/utils/FormUtils.d.ts +14 -0
  38. package/esm/types/src/utils/JsonUtils.d.ts +13 -0
  39. package/esm/types/src/utils/LogUtils.d.ts +4 -0
  40. package/esm/types/src/utils/SchemaUtils.d.ts +3 -0
  41. package/esm/types/src/utils/TranslationUtils.d.ts +11 -0
  42. package/esm/types/src/utils/ValidationUtils.d.ts +20 -0
  43. package/lib/BaseNode.d.ts +8 -5
  44. package/lib/BaseNode.js +19 -3
  45. package/lib/Container.d.ts +12 -5
  46. package/lib/Container.js +43 -19
  47. package/lib/Field.d.ts +8 -3
  48. package/lib/Field.js +12 -12
  49. package/lib/Fieldset.d.ts +2 -1
  50. package/lib/Form.d.ts +10 -6
  51. package/lib/Form.js +15 -11
  52. package/lib/FormInstance.d.ts +3 -0
  53. package/lib/FormInstance.js +16 -1
  54. package/lib/controller/EventQueue.d.ts +1 -0
  55. package/lib/controller/EventQueue.js +3 -0
  56. package/lib/types/Model.d.ts +2 -1
  57. package/lib/utils/FormCreationUtils.d.ts +2 -1
  58. package/package.json +5 -3
@@ -0,0 +1,4304 @@
1
+ import { propertyChange, ExecuteRule, Initialize, RemoveItem, SubmitSuccess, CustomEvent, SubmitFailure, Submit, RemoveInstance, AddInstance, Reset, AddItem, Click, Change, FormLoad, FieldChanged, ValidationComplete, Valid, Invalid } from './afb-events.js';
2
+ import Formula from '@adobe/json-formula';
3
+ import { parseDefaultDate, datetimeToNumber, format, parseDateSkeleton, formatDate, numberToDatetime } from '@aemforms/af-formatters';
4
+
5
+ function __decorate(decorators, target, key, desc) {
6
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
7
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
8
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
9
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
10
+ }
11
+
12
+ const ConstraintType = Object.freeze({
13
+ PATTERN_MISMATCH: 'patternMismatch',
14
+ TOO_SHORT: 'tooShort',
15
+ TOO_LONG: 'tooLong',
16
+ RANGE_OVERFLOW: 'rangeOverflow',
17
+ RANGE_UNDERFLOW: 'rangeUnderflow',
18
+ TYPE_MISMATCH: 'typeMismatch',
19
+ VALUE_MISSING: 'valueMissing',
20
+ STEP_MISMATCH: 'stepMismatch',
21
+ FORMAT_MISMATCH: 'formatMismatch',
22
+ ACCEPT_MISMATCH: 'acceptMismatch',
23
+ FILE_SIZE_MISMATCH: 'fileSizeMismatch',
24
+ UNIQUE_ITEMS_MISMATCH: 'uniqueItemsMismatch',
25
+ MIN_ITEMS_MISMATCH: 'minItemsMismatch',
26
+ MAX_ITEMS_MISMATCH: 'maxItemsMismatch',
27
+ EXPRESSION_MISMATCH: 'expressionMismatch'
28
+ });
29
+ const constraintKeys = Object.freeze({
30
+ pattern: ConstraintType.PATTERN_MISMATCH,
31
+ minLength: ConstraintType.TOO_SHORT,
32
+ maxLength: ConstraintType.TOO_LONG,
33
+ maximum: ConstraintType.RANGE_OVERFLOW,
34
+ minimum: ConstraintType.RANGE_UNDERFLOW,
35
+ type: ConstraintType.TYPE_MISMATCH,
36
+ required: ConstraintType.VALUE_MISSING,
37
+ step: ConstraintType.STEP_MISMATCH,
38
+ format: ConstraintType.FORMAT_MISMATCH,
39
+ accept: ConstraintType.ACCEPT_MISMATCH,
40
+ maxFileSize: ConstraintType.FILE_SIZE_MISMATCH,
41
+ uniqueItems: ConstraintType.UNIQUE_ITEMS_MISMATCH,
42
+ minItems: ConstraintType.MIN_ITEMS_MISMATCH,
43
+ maxItems: ConstraintType.MAX_ITEMS_MISMATCH,
44
+ validationExpression: ConstraintType.EXPRESSION_MISMATCH
45
+ });
46
+ const defaultConstraintTypeMessages = Object.freeze({
47
+ [ConstraintType.PATTERN_MISMATCH]: 'Please match the format requested.',
48
+ [ConstraintType.TOO_SHORT]: 'Please lengthen this text to ${0} characters or more.',
49
+ [ConstraintType.TOO_LONG]: 'Please shorten this text to ${0} characters or less.',
50
+ [ConstraintType.RANGE_OVERFLOW]: 'Value must be less than or equal to ${0}.',
51
+ [ConstraintType.RANGE_UNDERFLOW]: 'Value must be greater than or equal to ${0}.',
52
+ [ConstraintType.TYPE_MISMATCH]: 'Please enter a valid value.',
53
+ [ConstraintType.VALUE_MISSING]: 'Please fill in this field.',
54
+ [ConstraintType.STEP_MISMATCH]: 'Please enter a valid value.',
55
+ [ConstraintType.FORMAT_MISMATCH]: 'Specify the value in allowed format : ${0}.',
56
+ [ConstraintType.ACCEPT_MISMATCH]: 'The specified file type not supported.',
57
+ [ConstraintType.FILE_SIZE_MISMATCH]: 'File too large. Reduce size and try again.',
58
+ [ConstraintType.UNIQUE_ITEMS_MISMATCH]: 'All the items must be unique.',
59
+ [ConstraintType.MIN_ITEMS_MISMATCH]: 'Specify a number of items equal to or greater than ${0}.',
60
+ [ConstraintType.MAX_ITEMS_MISMATCH]: 'Specify a number of items equal to or less than ${0}.',
61
+ [ConstraintType.EXPRESSION_MISMATCH]: 'Please enter a valid value.'
62
+ });
63
+ let customConstraintTypeMessages = {};
64
+ const getConstraintTypeMessages = () => {
65
+ return {
66
+ ...defaultConstraintTypeMessages,
67
+ ...customConstraintTypeMessages
68
+ };
69
+ };
70
+
71
+ class ValidationError {
72
+ fieldName;
73
+ errorMessages;
74
+ constructor(fieldName = '', errorMessages = []) {
75
+ this.errorMessages = errorMessages;
76
+ this.fieldName = fieldName;
77
+ }
78
+ }
79
+ var FocusOption;
80
+ (function (FocusOption) {
81
+ FocusOption["NEXT_ITEM"] = "nextItem";
82
+ FocusOption["PREVIOUS_ITEM"] = "previousItem";
83
+ })(FocusOption || (FocusOption = {}));
84
+
85
+ const objToMap = (o) => new Map(Object.entries(o));
86
+ const stringViewTypes = objToMap({ 'date': 'date-input', 'data-url': 'file-input', 'binary': 'file-input' });
87
+ const typeToViewTypes = objToMap({
88
+ 'number': 'number-input',
89
+ 'boolean': 'checkbox',
90
+ 'object': 'panel',
91
+ 'array': 'panel',
92
+ 'file': 'file-input',
93
+ 'file[]': 'file-input'
94
+ });
95
+ const arrayTypes = ['string[]', 'boolean[]', 'number[]', 'array'];
96
+ const defaultFieldTypes = (schema) => {
97
+ const type = schema.type || 'string';
98
+ if ('enum' in schema) {
99
+ const enums = schema.enum;
100
+ if (enums.length > 2 || arrayTypes.indexOf(type) > -1) {
101
+ return 'drop-down';
102
+ }
103
+ else {
104
+ return 'checkbox';
105
+ }
106
+ }
107
+ if (type === 'string' || type === 'string[]') {
108
+ return stringViewTypes.get(schema.format) || 'text-input';
109
+ }
110
+ return typeToViewTypes.get(type) || 'text-input';
111
+ };
112
+
113
+ const getProperty = (data, key, def) => {
114
+ if (key in data) {
115
+ return data[key];
116
+ }
117
+ else if (!key.startsWith(':')) {
118
+ const prefixedKey = `:${key}`;
119
+ if (prefixedKey in data) {
120
+ return data[prefixedKey];
121
+ }
122
+ }
123
+ return def;
124
+ };
125
+ const isFile = function (item) {
126
+ return (item?.type === 'file' || item?.type === 'file[]') ||
127
+ ((item?.type === 'string' || item?.type === 'string[]') &&
128
+ (item?.format === 'binary' || item?.format === 'data-url'));
129
+ };
130
+ const isCheckbox = function (item) {
131
+ const fieldType = item?.fieldType || defaultFieldTypes(item);
132
+ return fieldType === 'checkbox';
133
+ };
134
+ const isCheckboxGroup = function (item) {
135
+ const fieldType = item?.fieldType || defaultFieldTypes(item);
136
+ return fieldType === 'checkbox-group';
137
+ };
138
+ const isEmailInput = function (item) {
139
+ const fieldType = item?.fieldType || defaultFieldTypes(item);
140
+ return (fieldType === 'text-input' && item?.format === 'email') || fieldType === 'email';
141
+ };
142
+ const isDateField = function (item) {
143
+ const fieldType = item?.fieldType || defaultFieldTypes(item);
144
+ return (fieldType === 'text-input' && item?.format === 'date') || fieldType === 'date-input';
145
+ };
146
+ const isCaptcha = function (item) {
147
+ const fieldType = item?.fieldType || defaultFieldTypes(item);
148
+ return fieldType === 'captcha';
149
+ };
150
+ function deepClone(obj, idGenerator) {
151
+ let result;
152
+ if (obj instanceof Array) {
153
+ result = [];
154
+ result = obj.map(x => deepClone(x, idGenerator));
155
+ }
156
+ else if (typeof obj === 'object' && obj !== null) {
157
+ result = {};
158
+ Object.entries(obj).forEach(([key, value]) => {
159
+ result[key] = deepClone(value, idGenerator);
160
+ });
161
+ }
162
+ else {
163
+ result = obj;
164
+ }
165
+ if (idGenerator && result && result.id) {
166
+ result.id = idGenerator();
167
+ }
168
+ return result;
169
+ }
170
+ const jsonString = (obj) => {
171
+ return JSON.stringify(obj, null, 2);
172
+ };
173
+ const isRepeatable$1 = (obj) => {
174
+ return ((obj.repeatable &&
175
+ ((obj.minOccur === undefined && obj.maxOccur === undefined) ||
176
+ (obj.minOccur !== undefined && obj.maxOccur !== undefined && obj.maxOccur !== 0) ||
177
+ (obj.minOccur !== undefined && obj.maxOccur !== undefined && obj.minOccur !== 0 && obj.maxOccur !== 0) ||
178
+ (obj.minOccur !== undefined && obj.minOccur >= 0) ||
179
+ (obj.maxOccur !== undefined && obj.maxOccur !== 0))) || false);
180
+ };
181
+
182
+ class DataValue {
183
+ $_name;
184
+ $_value;
185
+ $_type;
186
+ $_fields = [];
187
+ constructor($_name, $_value, $_type = typeof $_value) {
188
+ this.$_name = $_name;
189
+ this.$_value = $_value;
190
+ this.$_type = $_type;
191
+ }
192
+ valueOf() {
193
+ return this.$_value;
194
+ }
195
+ get $name() {
196
+ return this.$_name;
197
+ }
198
+ get $value() {
199
+ const enabled = this.$_fields.find(x => x.enabled !== false);
200
+ if (!enabled && this.$_fields.length) {
201
+ return undefined;
202
+ }
203
+ return this.$_value;
204
+ }
205
+ setValue(typedValue, originalValue, fromField) {
206
+ this.$_value = typedValue;
207
+ this.$_fields.forEach(x => {
208
+ if (fromField !== x) {
209
+ x.value = originalValue;
210
+ }
211
+ });
212
+ }
213
+ get $type() {
214
+ return this.$_type;
215
+ }
216
+ $bindToField(field) {
217
+ if (this.$_fields.indexOf(field) === -1) {
218
+ this.$_fields.push(field);
219
+ }
220
+ }
221
+ $convertToDataValue() {
222
+ return this;
223
+ }
224
+ get $isDataGroup() {
225
+ return false;
226
+ }
227
+ }
228
+
229
+ const value = Symbol('NullValue');
230
+ class NullDataValueClass extends DataValue {
231
+ constructor() {
232
+ super('', value, 'null');
233
+ }
234
+ setValue() {
235
+ }
236
+ $bindToField() {
237
+ }
238
+ $length() {
239
+ return 0;
240
+ }
241
+ $convertToDataValue() {
242
+ return this;
243
+ }
244
+ $addDataNode() {
245
+ }
246
+ $removeDataNode() {
247
+ }
248
+ $getDataNode() {
249
+ return this;
250
+ }
251
+ $containsDataNode() {
252
+ return false;
253
+ }
254
+ }
255
+ const NullDataValue = new NullDataValueClass();
256
+
257
+ class DataGroup extends DataValue {
258
+ $_items;
259
+ createEntry(key, value) {
260
+ const t = value instanceof Array ? 'array' : typeof value;
261
+ if (typeof value === 'object' && value != null) {
262
+ return new DataGroup(key, value, t);
263
+ }
264
+ else {
265
+ return new DataValue(key, value, t);
266
+ }
267
+ }
268
+ constructor(_name, _value, _type = typeof _value) {
269
+ super(_name, _value, _type);
270
+ if (_value instanceof Array) {
271
+ this.$_items = _value.map((value, index) => {
272
+ return this.createEntry(index, value);
273
+ });
274
+ }
275
+ else {
276
+ this.$_items = Object.fromEntries(Object.entries(_value).map(([key, value]) => {
277
+ return [key, this.createEntry(key, value)];
278
+ }));
279
+ }
280
+ }
281
+ get $value() {
282
+ const enabled = this.$_fields.find(x => x.enabled !== false);
283
+ if (!enabled && this.$_fields.length) {
284
+ return this.$type === 'array' ? [] : {};
285
+ }
286
+ else if (this.$type === 'array') {
287
+ return Object.values(this.$_items).filter(x => typeof x !== 'undefined').map(x => x.$value);
288
+ }
289
+ else {
290
+ return Object.fromEntries(Object.values(this.$_items).filter(x => typeof x !== 'undefined').map(x => {
291
+ return [x.$name, x.$value];
292
+ }));
293
+ }
294
+ }
295
+ get $length() {
296
+ return Object.entries(this.$_items).length;
297
+ }
298
+ $convertToDataValue() {
299
+ return new DataValue(this.$name, this.$value, this.$type);
300
+ }
301
+ $addDataNode(name, value, override = false) {
302
+ if (value !== NullDataValue) {
303
+ if (this.$type === 'array') {
304
+ const index = name;
305
+ if (!override) {
306
+ this.$_items.splice(index, 0, value);
307
+ }
308
+ else {
309
+ this.$_items[name] = value;
310
+ }
311
+ }
312
+ else {
313
+ this.$_items[name] = value;
314
+ }
315
+ }
316
+ }
317
+ $removeDataNode(name) {
318
+ if (this.$type === 'array') {
319
+ this.$_items.splice(name, 1);
320
+ }
321
+ else {
322
+ this.$_items[name] = undefined;
323
+ }
324
+ }
325
+ $getDataNode(name) {
326
+ if (this.$_items.hasOwnProperty(name)) {
327
+ return this.$_items[name];
328
+ }
329
+ }
330
+ $containsDataNode(name) {
331
+ return this.$_items.hasOwnProperty(name) && typeof (this.$_items[name]) !== 'undefined';
332
+ }
333
+ get $isDataGroup() {
334
+ return true;
335
+ }
336
+ }
337
+
338
+ const TOK_DOT = 'DOT';
339
+ const TOK_IDENTIFIER = 'Identifier';
340
+ const TOK_GLOBAL = 'Global';
341
+ const TOK_REPEATABLE = 'Repeatable';
342
+ const TOK_BRACKET = 'bracket';
343
+ const TOK_NUMBER = 'Number';
344
+ const globalStartToken = '$';
345
+ const repeatableStartToken = '#';
346
+ const identifier = (value, start) => {
347
+ return {
348
+ type: TOK_IDENTIFIER,
349
+ value,
350
+ start
351
+ };
352
+ };
353
+ const bracket = (value, start) => {
354
+ return {
355
+ type: TOK_BRACKET,
356
+ value,
357
+ start
358
+ };
359
+ };
360
+ const global$ = () => {
361
+ return {
362
+ type: TOK_GLOBAL,
363
+ start: 0,
364
+ value: globalStartToken
365
+ };
366
+ };
367
+ const repeatable = () => {
368
+ return {
369
+ type: TOK_REPEATABLE,
370
+ start: 0,
371
+ value: repeatableStartToken
372
+ };
373
+ };
374
+ const isAlphaNum = function (ch) {
375
+ return (ch >= 'a' && ch <= 'z')
376
+ || (ch >= 'A' && ch <= 'Z')
377
+ || (ch >= '0' && ch <= '9')
378
+ || ch === '_';
379
+ };
380
+ const isGlobal = (prev, stream, pos) => {
381
+ return prev === null && stream[pos] === globalStartToken;
382
+ };
383
+ const isRepeatable = (prev, stream, pos) => {
384
+ return prev === null && stream[pos] === repeatableStartToken;
385
+ };
386
+ const isIdentifier = (stream, pos) => {
387
+ const ch = stream[pos];
388
+ if (ch === '$') {
389
+ return stream.length > pos && isAlphaNum(stream[pos + 1]);
390
+ }
391
+ return (ch >= 'a' && ch <= 'z')
392
+ || (ch >= 'A' && ch <= 'Z')
393
+ || ch === '_';
394
+ };
395
+ const isNum = (ch) => {
396
+ return (ch >= '0' && ch <= '9');
397
+ };
398
+ class Tokenizer {
399
+ stream;
400
+ _current;
401
+ _tokens = [];
402
+ _result_tokens = [];
403
+ constructor(stream) {
404
+ this.stream = stream;
405
+ this._current = 0;
406
+ }
407
+ _consumeGlobal() {
408
+ this._current += 1;
409
+ return global$();
410
+ }
411
+ _consumeRepeatable() {
412
+ this._current += 1;
413
+ return repeatable();
414
+ }
415
+ _consumeUnquotedIdentifier(stream) {
416
+ const start = this._current;
417
+ this._current += 1;
418
+ while (this._current < stream.length && isAlphaNum(stream[this._current])) {
419
+ this._current += 1;
420
+ }
421
+ return identifier(stream.slice(start, this._current), start);
422
+ }
423
+ _consumeQuotedIdentifier(stream) {
424
+ const start = this._current;
425
+ this._current += 1;
426
+ const maxLength = stream.length;
427
+ while (stream[this._current] !== '"' && this._current < maxLength) {
428
+ let current = this._current;
429
+ if (stream[current] === '\\' && (stream[current + 1] === '\\'
430
+ || stream[current + 1] === '"')) {
431
+ current += 2;
432
+ }
433
+ else {
434
+ current += 1;
435
+ }
436
+ this._current = current;
437
+ }
438
+ this._current += 1;
439
+ return identifier(JSON.parse(stream.slice(start, this._current)), start);
440
+ }
441
+ _consumeNumber(stream) {
442
+ const start = this._current;
443
+ this._current += 1;
444
+ const maxLength = stream.length;
445
+ while (isNum(stream[this._current]) && this._current < maxLength) {
446
+ this._current += 1;
447
+ }
448
+ const n = stream.slice(start, this._current);
449
+ const value = parseInt(n, 10);
450
+ return { type: TOK_NUMBER, value, start };
451
+ }
452
+ _consumeBracket(stream) {
453
+ const start = this._current;
454
+ this._current += 1;
455
+ let value;
456
+ if (isNum(stream[this._current])) {
457
+ value = this._consumeNumber(stream).value;
458
+ }
459
+ else {
460
+ throw new Error(`unexpected exception at position ${this._current}. Must be a character`);
461
+ }
462
+ if (this._current < this.stream.length && stream[this._current] !== ']') {
463
+ throw new Error(`unexpected exception at position ${this._current}. Must be a character`);
464
+ }
465
+ this._current++;
466
+ return bracket(value, start);
467
+ }
468
+ tokenize() {
469
+ const stream = this.stream;
470
+ while (this._current < stream.length) {
471
+ const prev = this._tokens.length ? this._tokens.slice(-1)[0] : null;
472
+ if (isGlobal(prev, stream, this._current)) {
473
+ const token = this._consumeGlobal();
474
+ this._tokens.push(token);
475
+ this._result_tokens.push(token);
476
+ }
477
+ else if (isRepeatable(prev, stream, this._current)) {
478
+ const token = this._consumeRepeatable();
479
+ this._tokens.push(token);
480
+ this._result_tokens.push(token);
481
+ }
482
+ else if (isIdentifier(stream, this._current)) {
483
+ const token = this._consumeUnquotedIdentifier(stream);
484
+ this._tokens.push(token);
485
+ this._result_tokens.push(token);
486
+ }
487
+ else if (stream[this._current] === '.' && prev != null && prev.type !== TOK_DOT) {
488
+ this._tokens.push({
489
+ type: TOK_DOT,
490
+ value: '.',
491
+ start: this._current
492
+ });
493
+ this._current += 1;
494
+ }
495
+ else if (stream[this._current] === '[') {
496
+ const token = this._consumeBracket(stream);
497
+ this._tokens.push(token);
498
+ this._result_tokens.push(token);
499
+ }
500
+ else if (stream[this._current] === '"') {
501
+ const token = this._consumeQuotedIdentifier(stream);
502
+ this._tokens.push(token);
503
+ this._result_tokens.push(token);
504
+ }
505
+ else {
506
+ const p = Math.max(0, this._current - 2);
507
+ const s = Math.min(this.stream.length, this._current + 2);
508
+ throw new Error(`Exception at parsing stream ${this.stream.slice(p, s)}`);
509
+ }
510
+ }
511
+ return this._result_tokens;
512
+ }
513
+ }
514
+ const tokenize = (stream) => {
515
+ return new Tokenizer(stream).tokenize();
516
+ };
517
+ const resolveData = (data, input, create) => {
518
+ let tokens;
519
+ if (typeof input === 'string') {
520
+ tokens = tokenize(input);
521
+ }
522
+ else {
523
+ tokens = input;
524
+ }
525
+ let result = data;
526
+ let i = 0;
527
+ const createIntermediateNode = (token, nextToken, create) => {
528
+ return nextToken === null ? create :
529
+ (nextToken.type === TOK_BRACKET) ? new DataGroup(token.value, [], 'array') :
530
+ new DataGroup(token.value, {});
531
+ };
532
+ while (i < tokens.length && result != null) {
533
+ const token = tokens[i];
534
+ if (token.type === TOK_GLOBAL) {
535
+ result = data;
536
+ }
537
+ else if (token.type === TOK_IDENTIFIER) {
538
+ if (result instanceof DataGroup && result.$type === 'object') {
539
+ if (result.$containsDataNode(token.value) && result.$getDataNode(token.value).$value !== null) {
540
+ result = result.$getDataNode(token.value);
541
+ }
542
+ else if (create) {
543
+ const nextToken = i < tokens.length - 1 ? tokens[i + 1] : null;
544
+ const toCreate = createIntermediateNode(token, nextToken, create);
545
+ result.$addDataNode(token.value, toCreate);
546
+ result = toCreate;
547
+ }
548
+ else {
549
+ result = undefined;
550
+ }
551
+ }
552
+ else {
553
+ throw new Error(`Looking for ${token.value} in ${result.$value}`);
554
+ }
555
+ }
556
+ else if (token.type === TOK_BRACKET) {
557
+ if (result instanceof DataGroup && result.$type === 'array') {
558
+ const index = token.value;
559
+ if (index < result.$length) {
560
+ result = result.$getDataNode(index);
561
+ }
562
+ else if (create) {
563
+ const nextToken = i < tokens.length - 1 ? tokens[i + 1] : null;
564
+ const toCreate = createIntermediateNode(token, nextToken, create);
565
+ result.$addDataNode(index, toCreate);
566
+ result = toCreate;
567
+ }
568
+ else {
569
+ result = undefined;
570
+ }
571
+ }
572
+ else {
573
+ throw new Error(`Looking for index ${token.value} in non array${result.$value}`);
574
+ }
575
+ }
576
+ i += 1;
577
+ }
578
+ return result;
579
+ };
580
+
581
+ const editableProperties = [
582
+ 'value',
583
+ 'label',
584
+ 'description',
585
+ 'visible',
586
+ 'enabled',
587
+ 'valid',
588
+ 'errorMessage',
589
+ 'readOnly',
590
+ 'enum',
591
+ 'enumNames',
592
+ 'required',
593
+ 'properties',
594
+ 'exclusiveMinimum',
595
+ 'exclusiveMaximum',
596
+ 'maximum',
597
+ 'maxItems',
598
+ 'minimum',
599
+ 'minItems'
600
+ ];
601
+ const dynamicProps = [
602
+ ...editableProperties,
603
+ 'index',
604
+ 'activeChild'
605
+ ];
606
+ const staticFields = ['plain-text', 'image'];
607
+ class ActionImplWithTarget {
608
+ _action;
609
+ _target;
610
+ constructor(_action, _target) {
611
+ this._action = _action;
612
+ this._target = _target;
613
+ }
614
+ get type() {
615
+ return this._action.type;
616
+ }
617
+ get payload() {
618
+ return this._action.payload;
619
+ }
620
+ get metadata() {
621
+ return this._action.metadata;
622
+ }
623
+ get target() {
624
+ return this._target;
625
+ }
626
+ get isCustomEvent() {
627
+ return this._action.isCustomEvent;
628
+ }
629
+ get originalAction() {
630
+ return this._action.originalAction;
631
+ }
632
+ toString() {
633
+ return this._action.toString();
634
+ }
635
+ }
636
+ const target = Symbol('target');
637
+ const qualifiedName = Symbol('qualifiedName');
638
+ function dependencyTracked() {
639
+ return function (target, propertyKey, descriptor) {
640
+ const get = descriptor.get;
641
+ if (get != undefined) {
642
+ descriptor.get = function () {
643
+ this.ruleEngine.trackDependency(this);
644
+ return get.call(this);
645
+ };
646
+ }
647
+ };
648
+ }
649
+ const addOnly = (includeOrExclude) => (...fieldTypes) => (target, propertyKey, descriptor) => {
650
+ const get = descriptor.get;
651
+ if (get != undefined) {
652
+ descriptor.get = function () {
653
+ if (fieldTypes.indexOf(this.fieldType) > -1 === includeOrExclude) {
654
+ return get.call(this);
655
+ }
656
+ return undefined;
657
+ };
658
+ }
659
+ const set = descriptor.set;
660
+ if (set != undefined) {
661
+ descriptor.set = function (value) {
662
+ if (fieldTypes.indexOf(this.fieldType) > -1 === includeOrExclude) {
663
+ set.call(this, value);
664
+ }
665
+ };
666
+ }
667
+ };
668
+ const include = addOnly(true);
669
+ const exclude = addOnly(false);
670
+ class BaseNode {
671
+ _options;
672
+ _ruleNode;
673
+ _lang = '';
674
+ _callbacks = {};
675
+ _dependents = [];
676
+ _jsonModel;
677
+ _tokens = [];
678
+ get isContainer() {
679
+ return false;
680
+ }
681
+ constructor(params, _options) {
682
+ this._options = _options;
683
+ this[qualifiedName] = null;
684
+ this._jsonModel = {
685
+ ...params,
686
+ id: 'id' in params ? params.id : this.form.getUniqueId()
687
+ };
688
+ }
689
+ setupRuleNode() {
690
+ const self = this;
691
+ this._ruleNode = new Proxy(this.ruleNodeReference(), {
692
+ get: (ruleNodeReference, prop) => {
693
+ return self.getFromRule(ruleNodeReference, prop);
694
+ }
695
+ });
696
+ }
697
+ ruleNodeReference() {
698
+ return this;
699
+ }
700
+ getRuleNode() {
701
+ return this._ruleNode;
702
+ }
703
+ getFromRule(ruleNodeReference, prop) {
704
+ if (prop === Symbol.toPrimitive || (prop === 'valueOf' && !ruleNodeReference.hasOwnProperty('valueOf'))) {
705
+ return this.valueOf;
706
+ }
707
+ else if (prop === target) {
708
+ return this;
709
+ }
710
+ else if (typeof (prop) === 'string') {
711
+ if (prop.startsWith('$')) {
712
+ prop = prop.substr(1);
713
+ if (typeof this[prop] !== 'function') {
714
+ const retValue = this[prop];
715
+ if (retValue instanceof BaseNode) {
716
+ return retValue.getRuleNode();
717
+ }
718
+ else if (retValue instanceof Array) {
719
+ return retValue.map(r => r instanceof BaseNode ? r.getRuleNode() : r);
720
+ }
721
+ else {
722
+ return retValue;
723
+ }
724
+ }
725
+ }
726
+ else {
727
+ if (ruleNodeReference.hasOwnProperty(prop)) {
728
+ return ruleNodeReference[prop];
729
+ }
730
+ else if (typeof ruleNodeReference[prop] === 'function') {
731
+ return ruleNodeReference[prop];
732
+ }
733
+ }
734
+ }
735
+ }
736
+ get id() {
737
+ return this._jsonModel.id;
738
+ }
739
+ get index() {
740
+ if (this.parent) {
741
+ return this.parent.indexOf(this);
742
+ }
743
+ return 0;
744
+ }
745
+ get parent() {
746
+ return this._options.parent;
747
+ }
748
+ get type() {
749
+ return this._jsonModel.type;
750
+ }
751
+ get repeatable() {
752
+ return this.parent?.hasDynamicItems();
753
+ }
754
+ get fieldType() {
755
+ return this._jsonModel.fieldType || 'text-input';
756
+ }
757
+ get ':type'() {
758
+ return this._jsonModel[':type'] || this.fieldType;
759
+ }
760
+ get name() {
761
+ return this._jsonModel.name;
762
+ }
763
+ get description() {
764
+ return this._jsonModel.description;
765
+ }
766
+ set description(d) {
767
+ this._setProperty('description', d);
768
+ }
769
+ get dataRef() {
770
+ return this._jsonModel.dataRef;
771
+ }
772
+ get visible() {
773
+ if (this.parent?.visible !== undefined) {
774
+ return this.parent?.visible ? this._jsonModel.visible : false;
775
+ }
776
+ else {
777
+ return this._jsonModel.visible;
778
+ }
779
+ }
780
+ set visible(v) {
781
+ if (v !== this._jsonModel.visible) {
782
+ const changeAction = propertyChange('visible', v, this._jsonModel.visible);
783
+ this._jsonModel.visible = v;
784
+ this.notifyDependents(changeAction);
785
+ }
786
+ }
787
+ get form() {
788
+ return this._options.form;
789
+ }
790
+ get ruleEngine() {
791
+ return this.form.ruleEngine;
792
+ }
793
+ get label() {
794
+ return this._jsonModel.label;
795
+ }
796
+ set label(l) {
797
+ if (l !== this._jsonModel.label) {
798
+ const changeAction = propertyChange('label', l, this._jsonModel.label);
799
+ this._jsonModel = {
800
+ ...this._jsonModel,
801
+ label: l
802
+ };
803
+ this.notifyDependents(changeAction);
804
+ }
805
+ }
806
+ get uniqueItems() {
807
+ return this._jsonModel.uniqueItems;
808
+ }
809
+ isTransparent() {
810
+ const isNonTransparent = this.parent?._jsonModel.type === 'array';
811
+ return !this._jsonModel.name && !isNonTransparent;
812
+ }
813
+ getState(forRestore = false) {
814
+ return {
815
+ ...this._jsonModel,
816
+ properties: this.properties,
817
+ index: this.index,
818
+ parent: undefined,
819
+ qualifiedName: this.qualifiedName,
820
+ repeatable: this.repeatable === true ? true : undefined,
821
+ ':type': this[':type'],
822
+ ...(forRestore ? {
823
+ _dependents: this._dependents.length ? this._dependents.map(x => x.node.id) : undefined,
824
+ allowedComponents: undefined,
825
+ columnClassNames: undefined,
826
+ columnCount: undefined,
827
+ gridClassNames: undefined
828
+ } : {})
829
+ };
830
+ }
831
+ subscribe(callback, eventName = 'change') {
832
+ this._callbacks[eventName] = this._callbacks[eventName] || [];
833
+ this._callbacks[eventName].push(callback);
834
+ return {
835
+ unsubscribe: () => {
836
+ this._callbacks[eventName] = this._callbacks[eventName].filter(x => x !== callback);
837
+ }
838
+ };
839
+ }
840
+ _addDependent(dependent) {
841
+ if (this._dependents.find(({ node }) => node === dependent) === undefined) {
842
+ const subscription = this.subscribe((change) => {
843
+ const changes = change.payload.changes;
844
+ const propsToLook = [...dynamicProps, 'items'];
845
+ const isPropChanged = changes.findIndex(x => {
846
+ return propsToLook.indexOf(x.propertyName) > -1;
847
+ }) > -1;
848
+ if (isPropChanged) {
849
+ dependent.dispatch(new ExecuteRule());
850
+ }
851
+ });
852
+ this._dependents.push({ node: dependent, subscription });
853
+ }
854
+ }
855
+ removeDependent(dependent) {
856
+ const index = this._dependents.findIndex(({ node }) => node === dependent);
857
+ if (index > -1) {
858
+ this._dependents[index].subscription.unsubscribe();
859
+ this._dependents.splice(index, 1);
860
+ }
861
+ }
862
+ queueEvent(action) {
863
+ const actionWithTarget = new ActionImplWithTarget(action, this);
864
+ this.form.getEventQueue().queue(this, actionWithTarget, ['valid', 'invalid'].indexOf(actionWithTarget.type) > -1);
865
+ }
866
+ dispatch(action) {
867
+ this.queueEvent(action);
868
+ this.form.getEventQueue().runPendingQueue();
869
+ }
870
+ notifyDependents(action) {
871
+ const depsToRestore = this._jsonModel._dependents;
872
+ if (depsToRestore) {
873
+ depsToRestore.forEach((x) => {
874
+ const node = this.form.getElement(x);
875
+ if (node) {
876
+ this._addDependent(node);
877
+ }
878
+ });
879
+ this._jsonModel._dependents = undefined;
880
+ }
881
+ const handlers = this._callbacks[action.type] || [];
882
+ handlers.forEach(x => {
883
+ x(new ActionImplWithTarget(action, this));
884
+ });
885
+ }
886
+ isEmpty(value = this._jsonModel.value) {
887
+ return value === undefined || value === null || value === '';
888
+ }
889
+ _setProperty(prop, newValue, notify = true, notifyChildren = (action) => { }) {
890
+ const oldValue = this._jsonModel[prop];
891
+ let isValueSame = false;
892
+ if (newValue !== null && oldValue !== null &&
893
+ typeof newValue === 'object' && typeof oldValue === 'object') {
894
+ isValueSame = JSON.stringify(newValue) === JSON.stringify(oldValue);
895
+ }
896
+ else {
897
+ isValueSame = oldValue === newValue;
898
+ }
899
+ if (!isValueSame) {
900
+ this._jsonModel[prop] = newValue;
901
+ const changeAction = propertyChange(prop, newValue, oldValue);
902
+ if (notify) {
903
+ this.notifyDependents(changeAction);
904
+ }
905
+ notifyChildren.call(this, changeAction);
906
+ return changeAction.payload.changes;
907
+ }
908
+ return [];
909
+ }
910
+ _bindToDataModel(contextualDataModel) {
911
+ if (this.id === '$form') {
912
+ this._data = contextualDataModel;
913
+ return;
914
+ }
915
+ const dataRef = this._jsonModel.dataRef;
916
+ let _data, _parent = contextualDataModel, _key = '';
917
+ if (dataRef === null) {
918
+ _data = NullDataValue;
919
+ }
920
+ else if (dataRef !== undefined && !this.repeatable) {
921
+ if (this._tokens.length === 0) {
922
+ this._tokens = tokenize(dataRef);
923
+ }
924
+ let searchData = contextualDataModel;
925
+ if (this._tokens[0].type === TOK_GLOBAL) {
926
+ searchData = this.form.getDataNode();
927
+ }
928
+ else if (this._tokens[0].type === TOK_REPEATABLE) {
929
+ let repeatRoot = this.parent;
930
+ while (!repeatRoot.repeatable && repeatRoot !== this.form) {
931
+ repeatRoot = repeatRoot.parent;
932
+ }
933
+ searchData = repeatRoot.getDataNode();
934
+ }
935
+ if (typeof searchData !== 'undefined') {
936
+ const name = this._tokens[this._tokens.length - 1].value;
937
+ const create = this.defaultDataModel(name);
938
+ _data = resolveData(searchData, this._tokens, create);
939
+ _parent = resolveData(searchData, this._tokens.slice(0, -1));
940
+ _key = name;
941
+ }
942
+ }
943
+ else {
944
+ if (contextualDataModel !== NullDataValue && staticFields.indexOf(this.fieldType) === -1) {
945
+ _parent = contextualDataModel;
946
+ const name = this._jsonModel.name || '';
947
+ const key = contextualDataModel.$type === 'array' ? this.index : name;
948
+ _key = key;
949
+ if (key !== '') {
950
+ const create = this.defaultDataModel(key);
951
+ if (create !== undefined) {
952
+ _data = contextualDataModel.$getDataNode(key);
953
+ if (_data === undefined) {
954
+ _data = create;
955
+ contextualDataModel.$addDataNode(key, _data);
956
+ }
957
+ }
958
+ }
959
+ else {
960
+ _data = undefined;
961
+ }
962
+ }
963
+ }
964
+ if (_data) {
965
+ if (!this.isContainer && _parent !== NullDataValue && _data !== NullDataValue) {
966
+ _data = _data?.$convertToDataValue();
967
+ _parent.$addDataNode(_key, _data, true);
968
+ }
969
+ _data?.$bindToField(this);
970
+ this._data = _data;
971
+ }
972
+ }
973
+ _data;
974
+ getDataNode() {
975
+ return this._data;
976
+ }
977
+ get lang() {
978
+ if (this._jsonModel.lang) {
979
+ this._lang = this._jsonModel.lang;
980
+ }
981
+ if (!this._lang) {
982
+ if (this.parent) {
983
+ this._lang = this.parent.lang;
984
+ }
985
+ else {
986
+ this._lang = Intl.DateTimeFormat().resolvedOptions().locale;
987
+ }
988
+ }
989
+ return this._lang;
990
+ }
991
+ get properties() {
992
+ return this._jsonModel.properties || {};
993
+ }
994
+ set properties(p) {
995
+ this._setProperty('properties', { ...p });
996
+ }
997
+ getNonTransparentParent() {
998
+ let nonTransparentParent = this.parent;
999
+ while (nonTransparentParent != null && nonTransparentParent.isTransparent()) {
1000
+ nonTransparentParent = nonTransparentParent.parent;
1001
+ }
1002
+ return nonTransparentParent;
1003
+ }
1004
+ _initialize(mode) {
1005
+ if (typeof this._data === 'undefined') {
1006
+ let dataNode, parent = this.parent;
1007
+ do {
1008
+ dataNode = parent.getDataNode();
1009
+ parent = parent.parent;
1010
+ } while (dataNode === undefined);
1011
+ this._bindToDataModel(dataNode);
1012
+ }
1013
+ }
1014
+ _applyUpdates(propNames, updates) {
1015
+ return propNames.reduce((acc, propertyName) => {
1016
+ const currentValue = updates[propertyName];
1017
+ const changes = this._setProperty(propertyName, currentValue, false);
1018
+ if (changes.length > 0) {
1019
+ acc[propertyName] = changes[0];
1020
+ }
1021
+ return acc;
1022
+ }, {});
1023
+ }
1024
+ get qualifiedName() {
1025
+ if (this.isTransparent()) {
1026
+ return null;
1027
+ }
1028
+ if (this[qualifiedName] !== null) {
1029
+ return this[qualifiedName];
1030
+ }
1031
+ const parent = this.getNonTransparentParent();
1032
+ if (parent && parent.type === 'array') {
1033
+ this[qualifiedName] = `${parent.qualifiedName}[${this.index}]`;
1034
+ }
1035
+ else {
1036
+ this[qualifiedName] = `${parent.qualifiedName}.${this.name}`;
1037
+ }
1038
+ return this[qualifiedName];
1039
+ }
1040
+ focus() {
1041
+ if (this.parent) {
1042
+ this.parent.activeChild = this;
1043
+ }
1044
+ }
1045
+ _getDefaults() {
1046
+ return {};
1047
+ }
1048
+ _applyDefaultsInModel() {
1049
+ Object.entries(this._getDefaults()).map(([key, value]) => {
1050
+ if (this._jsonModel[key] === undefined && value !== undefined) {
1051
+ this._jsonModel[key] = value;
1052
+ }
1053
+ else if (typeof value === 'object' && value !== null && !Array.isArray(value)) {
1054
+ Object.keys(value).forEach((keyOfValue) => {
1055
+ if (this._jsonModel[key][keyOfValue] === undefined) {
1056
+ this._jsonModel[key][keyOfValue] = value[keyOfValue];
1057
+ }
1058
+ });
1059
+ }
1060
+ });
1061
+ }
1062
+ }
1063
+ __decorate([
1064
+ dependencyTracked()
1065
+ ], BaseNode.prototype, "index", null);
1066
+ __decorate([
1067
+ dependencyTracked()
1068
+ ], BaseNode.prototype, "description", null);
1069
+ __decorate([
1070
+ dependencyTracked()
1071
+ ], BaseNode.prototype, "visible", null);
1072
+ __decorate([
1073
+ dependencyTracked()
1074
+ ], BaseNode.prototype, "label", null);
1075
+ __decorate([
1076
+ dependencyTracked()
1077
+ ], BaseNode.prototype, "properties", null);
1078
+
1079
+ class Scriptable extends BaseNode {
1080
+ _events = {};
1081
+ _rules = {};
1082
+ getRules() {
1083
+ return typeof this._jsonModel.rules !== 'object' ? {} : this._jsonModel.rules;
1084
+ }
1085
+ getCompiledRule(eName, rule) {
1086
+ if (!(eName in this._rules)) {
1087
+ const eString = rule || this.getRules()[eName];
1088
+ if (typeof eString === 'string' && eString.length > 0) {
1089
+ try {
1090
+ this._rules[eName] = this.ruleEngine.compileRule(eString, this.lang);
1091
+ }
1092
+ catch (e) {
1093
+ this.form.logger.error(`Unable to compile rule \`"${eName}" : "${eString}"\` Exception : ${e}`);
1094
+ }
1095
+ }
1096
+ else {
1097
+ throw new Error(`only expression strings are supported. ${typeof (eString)} types are not supported`);
1098
+ }
1099
+ }
1100
+ return this._rules[eName];
1101
+ }
1102
+ getCompiledEvent(eName) {
1103
+ if (!(eName in this._events)) {
1104
+ let eString = this._jsonModel.events?.[eName];
1105
+ if (typeof eString === 'string' && eString.length > 0) {
1106
+ eString = [eString];
1107
+ }
1108
+ if (typeof eString !== 'undefined' && eString.length > 0) {
1109
+ this._events[eName] = eString.map(x => {
1110
+ try {
1111
+ return this.ruleEngine.compileRule(x, this.lang);
1112
+ }
1113
+ catch (e) {
1114
+ this.form.logger.error(`Unable to compile expression \`"${eName}" : "${eString}"\` Exception : ${e}`);
1115
+ }
1116
+ return null;
1117
+ }).filter(x => x !== null);
1118
+ }
1119
+ }
1120
+ return this._events[eName] || [];
1121
+ }
1122
+ applyUpdates(updates) {
1123
+ Object.entries(updates).forEach(([key, value]) => {
1124
+ if (key in editableProperties || (key in this && typeof this[key] !== 'function')) {
1125
+ try {
1126
+ this[key] = value;
1127
+ }
1128
+ catch (e) {
1129
+ console.error(e);
1130
+ }
1131
+ }
1132
+ });
1133
+ }
1134
+ executeAllRules(context) {
1135
+ const entries = Object.entries(this.getRules());
1136
+ if (entries.length > 0) {
1137
+ const scope = this.getExpressionScope();
1138
+ entries.forEach(([prop, rule]) => {
1139
+ const node = this.getCompiledRule(prop, rule);
1140
+ if (node) {
1141
+ const newVal = this.ruleEngine.execute(node, scope, context, true);
1142
+ if (editableProperties.indexOf(prop) > -1) {
1143
+ const oldAndNewValueAreEmpty = this.isEmpty() && this.isEmpty(newVal) && prop === 'value';
1144
+ if (!oldAndNewValueAreEmpty) {
1145
+ this[prop] = newVal;
1146
+ }
1147
+ }
1148
+ else {
1149
+ this.form.logger.warn(`${prop} is not a valid editable property.`);
1150
+ }
1151
+ }
1152
+ });
1153
+ }
1154
+ }
1155
+ getExpressionScope() {
1156
+ const parent = this.getNonTransparentParent();
1157
+ const target = {
1158
+ self: this.getRuleNode(),
1159
+ siblings: parent?.ruleNodeReference() || {}
1160
+ };
1161
+ const scope = new Proxy(target, {
1162
+ get: (target, prop) => {
1163
+ if (prop === Symbol.toStringTag) {
1164
+ return 'Object';
1165
+ }
1166
+ prop = prop;
1167
+ if (prop.startsWith('$')) {
1168
+ const retValue = target.self[prop];
1169
+ if (retValue instanceof BaseNode) {
1170
+ return retValue.getRuleNode();
1171
+ }
1172
+ else if (retValue instanceof Array) {
1173
+ return retValue.map(r => r instanceof BaseNode ? r.getRuleNode() : r);
1174
+ }
1175
+ else {
1176
+ return retValue;
1177
+ }
1178
+ }
1179
+ else {
1180
+ if (prop in target.siblings) {
1181
+ return target.siblings[prop];
1182
+ }
1183
+ else {
1184
+ return target.self[prop];
1185
+ }
1186
+ }
1187
+ },
1188
+ has: (target, prop) => {
1189
+ prop = prop;
1190
+ const selfPropertyOrChild = target.self[prop];
1191
+ const sibling = target.siblings[prop];
1192
+ return typeof selfPropertyOrChild != 'undefined' || typeof sibling != 'undefined';
1193
+ }
1194
+ });
1195
+ return scope;
1196
+ }
1197
+ executeEvent(context, node) {
1198
+ let updates;
1199
+ if (node) {
1200
+ updates = this.ruleEngine.execute(node, this.getExpressionScope(), context);
1201
+ }
1202
+ if (typeof updates !== 'undefined' && updates != null) {
1203
+ this.applyUpdates(updates);
1204
+ }
1205
+ }
1206
+ executeRule(event, context) {
1207
+ if (typeof event.payload.ruleName === 'undefined') {
1208
+ this.executeAllRules(context);
1209
+ }
1210
+ }
1211
+ executeExpression(expr) {
1212
+ const ruleContext = {
1213
+ 'form': this.form,
1214
+ '$form': this.form.getRuleNode(),
1215
+ '$field': this.getRuleNode(),
1216
+ 'field': this
1217
+ };
1218
+ const node = this.ruleEngine.compileRule(expr, this.lang);
1219
+ return this.ruleEngine.execute(node, this.getExpressionScope(), ruleContext);
1220
+ }
1221
+ executeAction(action) {
1222
+ const context = {
1223
+ 'form': this.form,
1224
+ '$form': this.form.getRuleNode(),
1225
+ '$field': this.getRuleNode(),
1226
+ 'field': this,
1227
+ '$event': {
1228
+ type: action.type,
1229
+ payload: action.payload,
1230
+ target: this.getRuleNode()
1231
+ }
1232
+ };
1233
+ const eventName = action.isCustomEvent ? `custom:${action.type}` : action.type;
1234
+ const funcName = action.isCustomEvent ? `custom_${action.type}` : action.type;
1235
+ const node = this.getCompiledEvent(eventName);
1236
+ if (funcName in this && typeof this[funcName] === 'function') {
1237
+ this[funcName](action, context);
1238
+ }
1239
+ node.forEach((n) => this.executeEvent(context, n));
1240
+ this.notifyDependents(action);
1241
+ }
1242
+ }
1243
+
1244
+ const notifyChildrenAttributes = [
1245
+ 'readOnly', 'enabled'
1246
+ ];
1247
+ class Container extends Scriptable {
1248
+ _children = [];
1249
+ _childrenReference;
1250
+ _itemTemplate = null;
1251
+ fieldFactory;
1252
+ constructor(json, _options) {
1253
+ super(json, { form: _options.form, parent: _options.parent });
1254
+ this.fieldFactory = _options.fieldFactory;
1255
+ }
1256
+ _getDefaults() {
1257
+ return {
1258
+ ...super._getDefaults(),
1259
+ enabled: true,
1260
+ readOnly: false
1261
+ };
1262
+ }
1263
+ ruleNodeReference() {
1264
+ return this._childrenReference;
1265
+ }
1266
+ get items() {
1267
+ return this._children;
1268
+ }
1269
+ get maxItems() {
1270
+ return this._jsonModel.maxItems;
1271
+ }
1272
+ set maxItems(m) {
1273
+ this._jsonModel.maxItems = m;
1274
+ const minItems = this._jsonModel.minItems || 1;
1275
+ const itemsLength = this._children.length;
1276
+ const items2Remove = Math.min(itemsLength - m, itemsLength - minItems);
1277
+ if (items2Remove > 0) {
1278
+ for (let i = 0; i < items2Remove; i++) {
1279
+ this.getDataNode().$removeDataNode(m + i);
1280
+ this._childrenReference.pop();
1281
+ }
1282
+ const elems = this._children.splice(m, items2Remove);
1283
+ this.notifyDependents(propertyChange('items', elems, null));
1284
+ }
1285
+ }
1286
+ get minItems() {
1287
+ return this._jsonModel.minItems;
1288
+ }
1289
+ set minItems(m) {
1290
+ this._jsonModel.minItems = m;
1291
+ const itemsLength = this._children.length;
1292
+ const difference = itemsLength - m;
1293
+ const items2Add = Math.abs(difference);
1294
+ if (difference < 0) {
1295
+ const elems = [];
1296
+ for (let i = 0; i < items2Add; i++) {
1297
+ elems.push(this._addChild(this._itemTemplate, null, true));
1298
+ }
1299
+ this.notifyDependents(propertyChange('items', elems, null));
1300
+ }
1301
+ }
1302
+ hasDynamicItems() {
1303
+ return this._itemTemplate != null;
1304
+ }
1305
+ get isContainer() {
1306
+ return true;
1307
+ }
1308
+ _activeChild = null;
1309
+ isSiteContainer(item) {
1310
+ return (':items' in item || 'cqItems' in item) && !('fieldType' in item);
1311
+ }
1312
+ isAFormField(item) {
1313
+ return ('fieldType' in item || 'id' in item || 'name' in item || 'dataRef' in item || 'type' in item);
1314
+ }
1315
+ _getFormAndSitesState(isRepeatableChild = false, forRestore = false) {
1316
+ return this._jsonModel.items ? this._jsonModel.items.map((x) => {
1317
+ if (this.isSiteContainer(x)) {
1318
+ const newObjWithId = {
1319
+ ...(x?.id ? { id: this.form.getUniqueId() } : {})
1320
+ };
1321
+ return {
1322
+ ...x,
1323
+ ...newObjWithId,
1324
+ ':items': this.walkSiteContainerItems(x)
1325
+ };
1326
+ }
1327
+ else if (this.isAFormField(x)) {
1328
+ return { ...this.form.getElement(x?.id).getState(isRepeatableChild, forRestore) };
1329
+ }
1330
+ else {
1331
+ return x;
1332
+ }
1333
+ }) : [];
1334
+ }
1335
+ getItemsState(isRepeatableChild = false, forRestore = false) {
1336
+ if (this._jsonModel.type === 'array' || isRepeatable$1(this._jsonModel) || isRepeatableChild) {
1337
+ if (isRepeatableChild) {
1338
+ return this._getFormAndSitesState(isRepeatableChild, forRestore);
1339
+ }
1340
+ else {
1341
+ return this._children.map(x => {
1342
+ return { ...x.getState(true, forRestore) };
1343
+ });
1344
+ }
1345
+ }
1346
+ else {
1347
+ return this._getFormAndSitesState(isRepeatableChild, forRestore);
1348
+ }
1349
+ }
1350
+ getState(isRepeatableChild = false, forRestore = false) {
1351
+ return {
1352
+ ...super.getState(forRestore),
1353
+ ...(forRestore ? {
1354
+ ':items': undefined,
1355
+ ':itemsOrder': undefined
1356
+ } : {}),
1357
+ items: this.getItemsState(isRepeatableChild, forRestore),
1358
+ enabled: this.enabled,
1359
+ readOnly: this.readOnly
1360
+ };
1361
+ }
1362
+ _createChild(child, options) {
1363
+ const { parent = this } = options;
1364
+ return this.fieldFactory.createField(child, {
1365
+ form: options.form,
1366
+ parent
1367
+ });
1368
+ }
1369
+ walkSiteContainerItems(x) {
1370
+ return Object.fromEntries(Object.entries(x[':items']).map(([key, value]) => {
1371
+ if (this.isAFormField(value)) {
1372
+ return [key, this.form.getElement(value?.id).getState()];
1373
+ }
1374
+ else if (this.isSiteContainer(value)) {
1375
+ return this.walkSiteContainerItems(value);
1376
+ }
1377
+ else {
1378
+ if (typeof value === 'object') {
1379
+ const newObjWithId = {
1380
+ ...(value?.id ? { id: this.form.getUniqueId() } : {})
1381
+ };
1382
+ return [key, {
1383
+ ...value,
1384
+ ...newObjWithId
1385
+ }
1386
+ ];
1387
+ }
1388
+ else {
1389
+ return [key, value];
1390
+ }
1391
+ }
1392
+ }));
1393
+ }
1394
+ _addChildToRuleNode(child, options) {
1395
+ const self = this;
1396
+ const { parent = this } = options;
1397
+ const name = parent.type == 'array' ? parent._children.length + '' : child.name || '';
1398
+ if (name.length > 0) {
1399
+ Object.defineProperty(parent._childrenReference, name, {
1400
+ get: () => {
1401
+ if (child.isContainer && child.hasDynamicItems()) {
1402
+ self.ruleEngine.trackDependency(child);
1403
+ }
1404
+ if (self.hasDynamicItems()) {
1405
+ self.ruleEngine.trackDependency(self);
1406
+ if (this._children[name] !== undefined) {
1407
+ return this._children[name].getRuleNode();
1408
+ }
1409
+ }
1410
+ else {
1411
+ return child.getRuleNode();
1412
+ }
1413
+ },
1414
+ configurable: true,
1415
+ enumerable: true
1416
+ });
1417
+ }
1418
+ }
1419
+ _addChild(itemJson, index, cloneIds = false) {
1420
+ let nonTransparentParent = this;
1421
+ while (nonTransparentParent != null && nonTransparentParent.isTransparent()) {
1422
+ nonTransparentParent = nonTransparentParent.parent;
1423
+ }
1424
+ if (typeof index !== 'number' || index > nonTransparentParent._children.length) {
1425
+ index = this._children.length;
1426
+ }
1427
+ const form = this.form;
1428
+ const itemTemplate = {
1429
+ index,
1430
+ ...deepClone(itemJson, cloneIds ? () => { return form.getUniqueId(); } : undefined)
1431
+ };
1432
+ const retVal = this._createChild(itemTemplate, { parent: this, form: this.form });
1433
+ itemJson.id = retVal.id;
1434
+ this.form.fieldAdded(retVal);
1435
+ this._addChildToRuleNode(retVal, { parent: nonTransparentParent });
1436
+ if (index === this._children.length) {
1437
+ this._children.push(retVal);
1438
+ }
1439
+ else {
1440
+ this._children.splice(index, 0, retVal);
1441
+ }
1442
+ return retVal;
1443
+ }
1444
+ indexOf(f) {
1445
+ return this._children.indexOf(f);
1446
+ }
1447
+ defaultDataModel(name) {
1448
+ const type = this._jsonModel.type || undefined;
1449
+ if (type === undefined) {
1450
+ return undefined;
1451
+ }
1452
+ else {
1453
+ const instance = type === 'array' ? [] : {};
1454
+ return new DataGroup(name, instance, type);
1455
+ }
1456
+ }
1457
+ _canHaveRepeatingChildren(mode = 'create') {
1458
+ const items = this._jsonModel.items;
1459
+ return this._jsonModel.type == 'array' && this.getDataNode() != null &&
1460
+ (items.length === 1 || (items[0].repeatable == true && mode === 'restore'));
1461
+ }
1462
+ _initialize(mode) {
1463
+ super._initialize(mode);
1464
+ const items = this._jsonModel.items || [];
1465
+ this._childrenReference = this._jsonModel.type == 'array' ? [] : {};
1466
+ if (this._canHaveRepeatingChildren(mode)) {
1467
+ this._itemTemplate = deepClone(items[0]);
1468
+ if (mode === 'restore') {
1469
+ this._itemTemplate.repeatable = undefined;
1470
+ }
1471
+ if (typeof (this._jsonModel.minItems) !== 'number') {
1472
+ this._jsonModel.minItems = 0;
1473
+ }
1474
+ if (typeof (this._jsonModel.maxItems) !== 'number') {
1475
+ this._jsonModel.maxItems = -1;
1476
+ }
1477
+ if (typeof (this._jsonModel.initialItems) !== 'number') {
1478
+ this._jsonModel.initialItems = Math.max(1, this._jsonModel.minItems);
1479
+ }
1480
+ for (let i = 0; i < this._jsonModel.initialItems; i++) {
1481
+ let child;
1482
+ if (mode === 'restore') {
1483
+ let itemTemplate = this._itemTemplate;
1484
+ if (i < this._jsonModel.items.length) {
1485
+ itemTemplate = deepClone(items[i]);
1486
+ itemTemplate.repeatable = undefined;
1487
+ }
1488
+ child = this._addChild(itemTemplate, undefined, i > this._jsonModel.items.length - 1);
1489
+ }
1490
+ else {
1491
+ child = this._addChild(this._itemTemplate, undefined, i > this._jsonModel.items.length - 1);
1492
+ }
1493
+ if (mode === 'create') {
1494
+ items[0].id = child.id;
1495
+ }
1496
+ child._initialize(mode);
1497
+ }
1498
+ }
1499
+ else if (items.length > 0) {
1500
+ items.forEach((item) => {
1501
+ if (this.isSiteContainer(item)) {
1502
+ this._initializeSiteContainer(item);
1503
+ }
1504
+ else if (this.isAFormField(item)) {
1505
+ const child = this._addChild(item);
1506
+ child._initialize(mode);
1507
+ }
1508
+ else {
1509
+ this.form.logger.warn(`A container item was not initialized. ${item}`);
1510
+ }
1511
+ });
1512
+ this._jsonModel.minItems = this._children.length;
1513
+ this._jsonModel.maxItems = this._children.length;
1514
+ this._jsonModel.initialItems = this._children.length;
1515
+ }
1516
+ else {
1517
+ this.form.logger.warn('A container exists with no items.');
1518
+ }
1519
+ this.setupRuleNode();
1520
+ }
1521
+ _initializeSiteContainer(item) {
1522
+ Object.entries(item[':items']).forEach(([key, value]) => {
1523
+ if (this.isAFormField(value)) {
1524
+ const child = this._addChild(value);
1525
+ child._initialize();
1526
+ }
1527
+ else if (this.isSiteContainer(value)) {
1528
+ return this._initializeSiteContainer(value);
1529
+ }
1530
+ });
1531
+ }
1532
+ addItem(action) {
1533
+ if ((action.type === 'addItem' || action.type == 'addInstance') && this._itemTemplate != null) {
1534
+ if ((this._jsonModel.maxItems === -1) || (this._children.length < this._jsonModel.maxItems)) {
1535
+ const dataNode = this.getDataNode();
1536
+ let instanceIndex = action.payload;
1537
+ const retVal = this._addChild(this._itemTemplate, action.payload, true);
1538
+ if (typeof instanceIndex !== 'number' || instanceIndex > this._children.length) {
1539
+ instanceIndex = this._children.length;
1540
+ }
1541
+ const _data = retVal.defaultDataModel(instanceIndex);
1542
+ if (_data) {
1543
+ dataNode.$addDataNode(instanceIndex, _data);
1544
+ }
1545
+ retVal._initialize('create');
1546
+ this.notifyDependents(propertyChange('items', retVal.getState(), null));
1547
+ retVal.dispatch(new Initialize());
1548
+ retVal.dispatch(new ExecuteRule());
1549
+ for (let i = instanceIndex + 1; i < this._children.length; i++) {
1550
+ this._children[i].dispatch(new ExecuteRule());
1551
+ }
1552
+ }
1553
+ }
1554
+ }
1555
+ removeItem(action) {
1556
+ if ((action.type === 'removeItem' || action.type == 'removeInstance') && this._itemTemplate != null) {
1557
+ if (this._children.length == 0) {
1558
+ return;
1559
+ }
1560
+ let instanceIndex = action.payload;
1561
+ if (typeof instanceIndex !== 'number') {
1562
+ instanceIndex = this._children.length - 1;
1563
+ }
1564
+ const state = this._children[instanceIndex].getState();
1565
+ if (this._children.length > this._jsonModel.minItems) {
1566
+ this._childrenReference.pop();
1567
+ this._children.splice(instanceIndex, 1);
1568
+ this.getDataNode().$removeDataNode(instanceIndex);
1569
+ for (let i = instanceIndex; i < this._children.length; i++) {
1570
+ this._children[i].dispatch(new ExecuteRule());
1571
+ }
1572
+ this.notifyDependents(propertyChange('items', null, state));
1573
+ }
1574
+ }
1575
+ }
1576
+ queueEvent(action) {
1577
+ super.queueEvent(action);
1578
+ if (action.metadata?.dispatch) {
1579
+ this.items.forEach(x => {
1580
+ x.queueEvent(action);
1581
+ });
1582
+ }
1583
+ }
1584
+ reset() {
1585
+ if (this.type === 'array' || isRepeatable$1(this._jsonModel)) {
1586
+ if (this.items.length > this._jsonModel.initialItems) {
1587
+ const itemsToBeRemoved = this.items.length - this._jsonModel.initialItems;
1588
+ for (let i = 0; i < itemsToBeRemoved; i++) {
1589
+ this.dispatch(new RemoveItem());
1590
+ }
1591
+ }
1592
+ }
1593
+ this.items.forEach(x => {
1594
+ x.reset();
1595
+ });
1596
+ }
1597
+ validate() {
1598
+ return this.items.flatMap(x => {
1599
+ return x.validate();
1600
+ }).filter(x => x.fieldName !== '');
1601
+ }
1602
+ dispatch(action) {
1603
+ super.dispatch(action);
1604
+ }
1605
+ importData(contextualDataModel) {
1606
+ this._bindToDataModel(contextualDataModel);
1607
+ const dataNode = this.getDataNode() || contextualDataModel;
1608
+ this.syncDataAndFormModel(dataNode);
1609
+ }
1610
+ syncDataAndFormModel(contextualDataModel) {
1611
+ if (contextualDataModel?.$type === 'array' && this._itemTemplate != null) {
1612
+ const dataLength = contextualDataModel?.$value.length;
1613
+ const itemsLength = this._children.length;
1614
+ const maxItems = this._jsonModel.maxItems === -1 ? dataLength : this._jsonModel.maxItems;
1615
+ const minItems = this._jsonModel.minItems;
1616
+ let items2Add = Math.min(dataLength - itemsLength, maxItems - itemsLength);
1617
+ const items2Remove = Math.min(itemsLength - dataLength, itemsLength - minItems);
1618
+ while (items2Add > 0) {
1619
+ items2Add--;
1620
+ const child = this._addChild(this._itemTemplate);
1621
+ child._initialize('create');
1622
+ }
1623
+ if (items2Remove > 0) {
1624
+ this._children.splice(dataLength, items2Remove);
1625
+ for (let i = 0; i < items2Remove; i++) {
1626
+ this._childrenReference.pop();
1627
+ }
1628
+ }
1629
+ }
1630
+ this._children.forEach(x => {
1631
+ x.importData(contextualDataModel);
1632
+ });
1633
+ }
1634
+ get activeChild() {
1635
+ return this._activeChild;
1636
+ }
1637
+ set activeChild(c) {
1638
+ if (c !== this._activeChild) {
1639
+ let activeChild = this._activeChild;
1640
+ while (activeChild instanceof Container) {
1641
+ const temp = activeChild.activeChild;
1642
+ activeChild.activeChild = null;
1643
+ activeChild = temp;
1644
+ }
1645
+ const change = propertyChange('activeChild', c, this._activeChild);
1646
+ this._activeChild = c;
1647
+ if (this.parent && c !== null) {
1648
+ this.parent.activeChild = this;
1649
+ }
1650
+ this._jsonModel.activeChild = c?.id;
1651
+ this.notifyDependents(change);
1652
+ }
1653
+ }
1654
+ get enabled() {
1655
+ if (this.parent?.enabled !== undefined) {
1656
+ return !this.parent?.enabled ? false : this._jsonModel.enabled;
1657
+ }
1658
+ else {
1659
+ return this._jsonModel.enabled;
1660
+ }
1661
+ }
1662
+ set enabled(e) {
1663
+ this._setProperty('enabled', e, true, this.notifyChildren);
1664
+ }
1665
+ get readOnly() {
1666
+ if (this.parent?.readOnly !== undefined) {
1667
+ return this.parent.readOnly ? true : this._jsonModel.readOnly;
1668
+ }
1669
+ else {
1670
+ return this._jsonModel.readOnly;
1671
+ }
1672
+ }
1673
+ set readOnly(e) {
1674
+ this._setProperty('readOnly', e, true, this.notifyChildren);
1675
+ }
1676
+ notifyChildren(action) {
1677
+ if (action.payload !== undefined && action.payload.changes !== undefined) {
1678
+ for (const change of action.payload.changes) {
1679
+ if (change.propertyName !== undefined && notifyChildrenAttributes.includes(change.propertyName)) {
1680
+ this.items.forEach((child) => {
1681
+ this.notifyDependents.call(child, propertyChange(change.propertyName, child.getState()[change.propertyName], null));
1682
+ if (child.fieldType === 'panel') {
1683
+ this.notifyChildren.call(child, action);
1684
+ }
1685
+ });
1686
+ }
1687
+ }
1688
+ }
1689
+ }
1690
+ }
1691
+ __decorate([
1692
+ dependencyTracked()
1693
+ ], Container.prototype, "maxItems", null);
1694
+ __decorate([
1695
+ dependencyTracked()
1696
+ ], Container.prototype, "minItems", null);
1697
+ __decorate([
1698
+ dependencyTracked()
1699
+ ], Container.prototype, "activeChild", null);
1700
+
1701
+ class Node {
1702
+ _jsonModel;
1703
+ constructor(inputModel) {
1704
+ this._jsonModel = {
1705
+ ...inputModel
1706
+ };
1707
+ }
1708
+ getP(key, def) {
1709
+ return getProperty(this._jsonModel, key, def);
1710
+ }
1711
+ get isContainer() {
1712
+ return false;
1713
+ }
1714
+ }
1715
+
1716
+ class FormMetaData extends Node {
1717
+ get version() {
1718
+ return this.getP('version', '');
1719
+ }
1720
+ get grammar() {
1721
+ return this.getP('grammar', '');
1722
+ }
1723
+ }
1724
+
1725
+ class SubmitMetaData {
1726
+ lang;
1727
+ captchaInfo;
1728
+ constructor(lang = '', captchaInfo) {
1729
+ this.lang = lang;
1730
+ this.captchaInfo = captchaInfo;
1731
+ }
1732
+ }
1733
+
1734
+ const levels = {
1735
+ off: 0,
1736
+ debug: 1,
1737
+ info: 2,
1738
+ warn: 3,
1739
+ error: 4
1740
+ };
1741
+ class Logger {
1742
+ debug(msg) {
1743
+ this.log(msg, 'debug');
1744
+ }
1745
+ info(msg) {
1746
+ this.log(msg, 'info');
1747
+ }
1748
+ warn(msg) {
1749
+ this.log(msg, 'warn');
1750
+ }
1751
+ error(msg) {
1752
+ this.log(msg, 'error');
1753
+ }
1754
+ log(msg, level) {
1755
+ if (this.logLevel !== 0 && this.logLevel <= levels[level]) {
1756
+ console[level](msg);
1757
+ }
1758
+ }
1759
+ logLevel;
1760
+ constructor(logLevel = 'off') {
1761
+ this.logLevel = levels[logLevel];
1762
+ }
1763
+ }
1764
+
1765
+ class EventNode {
1766
+ _node;
1767
+ _event;
1768
+ constructor(_node, _event) {
1769
+ this._node = _node;
1770
+ this._event = _event;
1771
+ }
1772
+ get node() {
1773
+ return this._node;
1774
+ }
1775
+ get event() {
1776
+ return this._event;
1777
+ }
1778
+ isEqual(that) {
1779
+ return that !== null && that !== undefined && this._node == that._node && this._event.type == that._event.type;
1780
+ }
1781
+ toString() {
1782
+ return this._node.id + '__' + this.event.type;
1783
+ }
1784
+ valueOf() {
1785
+ return this.toString();
1786
+ }
1787
+ }
1788
+ class EventQueue {
1789
+ logger;
1790
+ static MAX_EVENT_CYCLE_COUNT = 10;
1791
+ _runningEventCount;
1792
+ _isProcessing = false;
1793
+ _pendingEvents = [];
1794
+ constructor(logger = new Logger('off')) {
1795
+ this.logger = logger;
1796
+ this._runningEventCount = {};
1797
+ }
1798
+ get length() {
1799
+ return this._pendingEvents.length;
1800
+ }
1801
+ get isProcessing() {
1802
+ return this._isProcessing;
1803
+ }
1804
+ isQueued(node, event) {
1805
+ const evntNode = new EventNode(node, event);
1806
+ return this._pendingEvents.find(x => evntNode.isEqual(x)) !== undefined;
1807
+ }
1808
+ queue(node, events, priority = false) {
1809
+ if (!node || !events) {
1810
+ return;
1811
+ }
1812
+ if (!(events instanceof Array)) {
1813
+ events = [events];
1814
+ }
1815
+ events.forEach(e => {
1816
+ const evntNode = new EventNode(node, e);
1817
+ const counter = this._runningEventCount[evntNode.valueOf()] || 0;
1818
+ if (counter < EventQueue.MAX_EVENT_CYCLE_COUNT) {
1819
+ this.logger.info(`Queued event : ${e.type} node: ${node.id} - ${node.name}`);
1820
+ if (priority) {
1821
+ const index = this._isProcessing ? 1 : 0;
1822
+ this._pendingEvents.splice(index, 0, evntNode);
1823
+ }
1824
+ else {
1825
+ this._pendingEvents.push(evntNode);
1826
+ }
1827
+ this._runningEventCount[evntNode.valueOf()] = counter + 1;
1828
+ }
1829
+ else {
1830
+ this.logger.info(`Skipped queueing event : ${e.type} node: ${node.id} - ${node.name} with count=${counter}`);
1831
+ }
1832
+ });
1833
+ }
1834
+ empty() {
1835
+ this._pendingEvents = [];
1836
+ }
1837
+ runPendingQueue() {
1838
+ if (this._isProcessing) {
1839
+ return;
1840
+ }
1841
+ this._isProcessing = true;
1842
+ while (this._pendingEvents.length > 0) {
1843
+ const e = this._pendingEvents[0];
1844
+ this.logger.info(`Dequeued event : ${e.event.type} node: ${e.node.id} - ${e.node.name}`);
1845
+ e.node.executeAction(e.event);
1846
+ this._pendingEvents.shift();
1847
+ }
1848
+ this._runningEventCount = {};
1849
+ this._isProcessing = false;
1850
+ }
1851
+ }
1852
+
1853
+ class FileObject {
1854
+ data;
1855
+ mediaType = 'application/octet-stream';
1856
+ name = 'unknown';
1857
+ size = 0;
1858
+ constructor(init) {
1859
+ Object.assign(this, init);
1860
+ }
1861
+ get type() {
1862
+ return this.mediaType;
1863
+ }
1864
+ toJSON() {
1865
+ return {
1866
+ 'name': this.name,
1867
+ 'size': this.size,
1868
+ 'mediaType': this.mediaType,
1869
+ 'data': this.data.toString()
1870
+ };
1871
+ }
1872
+ equals(obj) {
1873
+ return (this.data === obj.data &&
1874
+ this.mediaType === obj.mediaType &&
1875
+ this.name === obj.name &&
1876
+ this.size === obj.size);
1877
+ }
1878
+ }
1879
+
1880
+ const chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_'.split('');
1881
+ const fileSizeRegex = /^(\d*\.?\d+)(\\?(?=[KMGT])([KMGT])(?:i?B)?|B?)$/i;
1882
+ const randomWord = (l) => {
1883
+ const ret = [];
1884
+ for (let i = 0; i <= l; i++) {
1885
+ let randIndex;
1886
+ if (i === 0) {
1887
+ randIndex = Math.floor(Math.random() * (chars.length - 11));
1888
+ }
1889
+ else {
1890
+ randIndex = Math.floor(Math.random() * (chars.length));
1891
+ }
1892
+ ret.push(chars[randIndex]);
1893
+ }
1894
+ return ret.join('');
1895
+ };
1896
+ const getAttachments = (input, excludeUnbound = false) => {
1897
+ const items = input.items || [];
1898
+ return items?.reduce((acc, item) => {
1899
+ if (excludeUnbound && item.dataRef === null) {
1900
+ return acc;
1901
+ }
1902
+ let ret = null;
1903
+ if (item.isContainer) {
1904
+ ret = getAttachments(item, excludeUnbound);
1905
+ }
1906
+ else {
1907
+ if (isFile(item.getState())) {
1908
+ ret = {};
1909
+ const name = item.name || '';
1910
+ const dataRef = (item.dataRef != null)
1911
+ ? item.dataRef
1912
+ : (name.length > 0 ? item.name : undefined);
1913
+ if (item.value instanceof Array) {
1914
+ ret[item.id] = item.value.map((x) => {
1915
+ return { ...x, 'dataRef': dataRef };
1916
+ });
1917
+ }
1918
+ else if (item.value != null) {
1919
+ ret[item.id] = { ...item.value, 'dataRef': dataRef };
1920
+ }
1921
+ }
1922
+ }
1923
+ return Object.assign(acc, ret);
1924
+ }, {});
1925
+ };
1926
+ const getFileSizeInBytes = (str) => {
1927
+ let retVal = 0;
1928
+ if (typeof str === 'string') {
1929
+ const matches = fileSizeRegex.exec(str.trim());
1930
+ if (matches != null) {
1931
+ retVal = sizeToBytes(parseFloat(matches[1]), (matches[2] || 'kb').toUpperCase());
1932
+ }
1933
+ }
1934
+ return retVal;
1935
+ };
1936
+ const sizeToBytes = (size, symbol) => {
1937
+ const sizes = { 'KB': 1, 'MB': 2, 'GB': 3, 'TB': 4 };
1938
+ const i = Math.pow(1024, sizes[symbol]);
1939
+ return Math.round(size * i);
1940
+ };
1941
+ const IdGenerator = function* (initial = 50) {
1942
+ const initialize = function () {
1943
+ const arr = [];
1944
+ for (let i = 0; i < initial; i++) {
1945
+ arr.push(randomWord(10));
1946
+ }
1947
+ return arr;
1948
+ };
1949
+ const passedIds = {};
1950
+ let ids = initialize();
1951
+ do {
1952
+ let x = ids.pop();
1953
+ while (x in passedIds) {
1954
+ if (ids.length === 0) {
1955
+ ids = initialize();
1956
+ }
1957
+ x = ids.pop();
1958
+ }
1959
+ passedIds[x] = true;
1960
+ yield ids.pop();
1961
+ if (ids.length === 0) {
1962
+ ids = initialize();
1963
+ }
1964
+ } while (ids.length > 0);
1965
+ };
1966
+ const isDataUrl = (str) => {
1967
+ const dataUrlRegex = /^data:([a-z]+\/[a-z0-9-+.]+)?;(?:name=(.*);)?base64,(.*)$/;
1968
+ return dataUrlRegex.exec(str.trim()) != null;
1969
+ };
1970
+ const extractFileInfo = (file) => {
1971
+ if (file !== null) {
1972
+ let retVal = null;
1973
+ if (file instanceof FileObject) {
1974
+ retVal = file;
1975
+ }
1976
+ else if (typeof File !== 'undefined' && file instanceof File) {
1977
+ retVal = {
1978
+ name: file.name,
1979
+ mediaType: file.type,
1980
+ size: file.size,
1981
+ data: file
1982
+ };
1983
+ }
1984
+ else if (typeof file === 'string' && isDataUrl(file)) {
1985
+ const result = dataURItoBlob(file);
1986
+ if (result !== null) {
1987
+ const { blob, name } = result;
1988
+ retVal = {
1989
+ name: name,
1990
+ mediaType: blob.type,
1991
+ size: blob.size,
1992
+ data: blob
1993
+ };
1994
+ }
1995
+ }
1996
+ else {
1997
+ let jFile = file;
1998
+ try {
1999
+ jFile = JSON.parse(file);
2000
+ retVal = jFile;
2001
+ if (!retVal.mediaType) {
2002
+ retVal.mediaType = retVal.type;
2003
+ }
2004
+ }
2005
+ catch (ex) {
2006
+ }
2007
+ if (typeof jFile?.data === 'string' && isDataUrl(jFile?.data)) {
2008
+ const result = dataURItoBlob(jFile?.data);
2009
+ if (result !== null) {
2010
+ const blob = result.blob;
2011
+ retVal = {
2012
+ name: jFile?.name,
2013
+ mediaType: jFile?.type || jFile?.mediaType,
2014
+ size: blob.size,
2015
+ data: blob
2016
+ };
2017
+ }
2018
+ }
2019
+ else if (typeof jFile === 'string') {
2020
+ const fileName = jFile.split('/').pop();
2021
+ retVal = {
2022
+ name: fileName,
2023
+ mediaType: 'application/octet-stream',
2024
+ size: 0,
2025
+ data: jFile
2026
+ };
2027
+ }
2028
+ else if (typeof jFile === 'object') {
2029
+ retVal = {
2030
+ name: jFile?.name,
2031
+ mediaType: jFile?.type || jFile?.mediaType,
2032
+ size: jFile?.size,
2033
+ data: jFile?.data
2034
+ };
2035
+ }
2036
+ }
2037
+ if (retVal !== null && retVal.data != null) {
2038
+ return new FileObject(retVal);
2039
+ }
2040
+ return null;
2041
+ }
2042
+ else {
2043
+ return null;
2044
+ }
2045
+ };
2046
+ const dataURItoBlob = (dataURI) => {
2047
+ const regex = /^data:([a-z]+\/[a-z0-9-+.]+)?(?:;name=([^;]+))?(;base64)?,(.+)$/;
2048
+ const groups = regex.exec(dataURI);
2049
+ if (groups !== null) {
2050
+ const type = groups[1] || '';
2051
+ const name = groups[2] || 'unknown';
2052
+ const isBase64 = typeof groups[3] === 'string';
2053
+ if (isBase64) {
2054
+ const binary = atob(groups[4]);
2055
+ const array = [];
2056
+ for (let i = 0; i < binary.length; i++) {
2057
+ array.push(binary.charCodeAt(i));
2058
+ }
2059
+ const blob = new window.Blob([new Uint8Array(array)], { type });
2060
+ return { name, blob };
2061
+ }
2062
+ else {
2063
+ const blob = new window.Blob([groups[4]], { type });
2064
+ return { name, blob };
2065
+ }
2066
+ }
2067
+ else {
2068
+ return null;
2069
+ }
2070
+ };
2071
+ const isFormOrSiteContainer = (model) => {
2072
+ return (':items' in model || 'cqItems' in model) && (':itemsOrder' in model || 'cqItemsOrder' in model);
2073
+ };
2074
+ const sitesModelToFormModel = (sitesModel) => {
2075
+ if (!sitesModel || !Object.keys(sitesModel).length) {
2076
+ return sitesModel;
2077
+ }
2078
+ if (isFormOrSiteContainer(sitesModel)) {
2079
+ const itemsArr = [];
2080
+ const itemsOrder = sitesModel[':itemsOrder'] || sitesModel.cqItemsOrder;
2081
+ const items = sitesModel[':items'] || sitesModel.cqItems;
2082
+ itemsOrder.forEach((elemName) => {
2083
+ itemsArr.push(sitesModelToFormModel(items[elemName]));
2084
+ });
2085
+ sitesModel.items = itemsArr;
2086
+ }
2087
+ return sitesModel;
2088
+ };
2089
+ const replaceTemplatePlaceholders = (str, values = []) => {
2090
+ return str?.replace(/\${(\d+)}/g, (match, index) => {
2091
+ const replacement = values[index];
2092
+ return typeof replacement !== 'undefined' ? replacement : match;
2093
+ });
2094
+ };
2095
+
2096
+ const request$1 = (url, data = null, options = {}) => {
2097
+ const opts = { ...defaultRequestOptions, ...options };
2098
+ const updatedUrl = opts.method === 'GET' && data ? convertQueryString(url, data) : url;
2099
+ if (opts.method !== 'GET') {
2100
+ opts.body = data;
2101
+ }
2102
+ return fetch(updatedUrl, {
2103
+ ...opts
2104
+ }).then(async (response) => {
2105
+ let body;
2106
+ if (!response.ok) {
2107
+ console.error(`Error while fetching response from ${url} : ${response.statusText}`);
2108
+ }
2109
+ if (response?.headers?.get('Content-Type')?.includes('application/json')) {
2110
+ body = await response.json();
2111
+ }
2112
+ else {
2113
+ body = await response.text();
2114
+ }
2115
+ const headers = {};
2116
+ response?.headers?.forEach((value, key) => {
2117
+ headers[key] = value;
2118
+ });
2119
+ return {
2120
+ status: response.status,
2121
+ body,
2122
+ headers
2123
+ };
2124
+ });
2125
+ };
2126
+ const defaultRequestOptions = {
2127
+ method: 'GET'
2128
+ };
2129
+ const convertQueryString = (endpoint, payload) => {
2130
+ if (!payload) {
2131
+ return endpoint;
2132
+ }
2133
+ let updatedPayload = {};
2134
+ try {
2135
+ updatedPayload = JSON.parse(payload);
2136
+ }
2137
+ catch (err) {
2138
+ console.log('Query params invalid');
2139
+ }
2140
+ const params = [];
2141
+ Object.keys(updatedPayload).forEach((key) => {
2142
+ if (Array.isArray(updatedPayload[key])) {
2143
+ params.push(`${encodeURIComponent(key)}=${encodeURIComponent(JSON.stringify(updatedPayload[key]))}`);
2144
+ }
2145
+ else {
2146
+ params.push(`${encodeURIComponent(key)}=${encodeURIComponent(updatedPayload[key])}`);
2147
+ }
2148
+ });
2149
+ if (!params.length) {
2150
+ return endpoint;
2151
+ }
2152
+ return endpoint.includes('?') ? `${endpoint}&${params.join('&')}` : `${endpoint}?${params.join('&')}`;
2153
+ };
2154
+
2155
+ const getCustomEventName = (name) => {
2156
+ const eName = name;
2157
+ if (eName.length > 0 && eName.startsWith('custom:')) {
2158
+ return eName.substring('custom:'.length);
2159
+ }
2160
+ return eName;
2161
+ };
2162
+ const request = async (context, uri, httpVerb, payload, success, error, headers) => {
2163
+ const endpoint = uri;
2164
+ const requestOptions = {
2165
+ method: httpVerb
2166
+ };
2167
+ let inputPayload;
2168
+ if (payload && payload instanceof FileObject && payload.data instanceof File) {
2169
+ const formData = new FormData();
2170
+ formData.append(payload.name, payload.data);
2171
+ inputPayload = formData;
2172
+ }
2173
+ else if (payload instanceof FormData) {
2174
+ inputPayload = payload;
2175
+ }
2176
+ else if (payload && typeof payload === 'object' && Object.keys(payload).length > 0) {
2177
+ const headerNames = Object.keys(headers);
2178
+ if (headerNames.length > 0) {
2179
+ requestOptions.headers = {
2180
+ ...headers,
2181
+ ...(headerNames.indexOf('Content-Type') === -1 ? { 'Content-Type': 'application/json' } : {})
2182
+ };
2183
+ }
2184
+ else {
2185
+ requestOptions.headers = { 'Content-Type': 'application/json' };
2186
+ }
2187
+ const contentType = requestOptions?.headers?.['Content-Type'] || 'application/json';
2188
+ if (contentType === 'application/json') {
2189
+ inputPayload = JSON.stringify(payload);
2190
+ }
2191
+ else if (contentType.indexOf('multipart/form-data') > -1) {
2192
+ inputPayload = multipartFormData(payload);
2193
+ }
2194
+ else if (contentType.indexOf('application/x-www-form-urlencoded') > -1) {
2195
+ inputPayload = urlEncoded(payload);
2196
+ }
2197
+ }
2198
+ const result = await request$1(endpoint, inputPayload, requestOptions);
2199
+ if (result?.status >= 200 && result?.status <= 299) {
2200
+ const eName = getCustomEventName(success);
2201
+ if (success === 'submitSuccess') {
2202
+ context.form.dispatch(new SubmitSuccess(result, true));
2203
+ }
2204
+ else {
2205
+ context.form.dispatch(new CustomEvent(eName, result, true));
2206
+ }
2207
+ }
2208
+ else {
2209
+ context.form.logger.error('Error invoking a rest API');
2210
+ const eName = getCustomEventName(error);
2211
+ if (error === 'submitFailure') {
2212
+ context.form.dispatch(new SubmitFailure(result, true));
2213
+ }
2214
+ else {
2215
+ context.form.dispatch(new CustomEvent(eName, result, true));
2216
+ }
2217
+ }
2218
+ };
2219
+ const urlEncoded = (data) => {
2220
+ const formData = new URLSearchParams();
2221
+ Object.entries(data).forEach(([key, value]) => {
2222
+ if (value != null && typeof value === 'object') {
2223
+ formData.append(key, jsonString(value));
2224
+ }
2225
+ else {
2226
+ formData.append(key, value);
2227
+ }
2228
+ });
2229
+ return formData;
2230
+ };
2231
+ const multipartFormData = (data, attachments) => {
2232
+ const formData = new FormData();
2233
+ Object.entries(data).forEach(([key, value]) => {
2234
+ if (value != null && typeof value === 'object') {
2235
+ formData.append(key, jsonString(value));
2236
+ }
2237
+ else {
2238
+ formData.append(key, value);
2239
+ }
2240
+ });
2241
+ const addAttachmentToFormData = (objValue, formData) => {
2242
+ if (objValue?.data instanceof File) {
2243
+ let attIdentifier = `${objValue?.dataRef}/${objValue?.name}`;
2244
+ if (!attIdentifier.startsWith('/')) {
2245
+ attIdentifier = `/${attIdentifier}`;
2246
+ }
2247
+ formData.append(attIdentifier, objValue.data);
2248
+ }
2249
+ };
2250
+ if (attachments) {
2251
+ Object.keys(attachments).reduce((acc, curr) => {
2252
+ const objValue = attachments[curr];
2253
+ if (objValue && objValue instanceof Array) {
2254
+ return [...acc, ...objValue.map((x) => addAttachmentToFormData(x, formData))];
2255
+ }
2256
+ else {
2257
+ return [...acc, addAttachmentToFormData(objValue, formData)];
2258
+ }
2259
+ }, []);
2260
+ }
2261
+ return formData;
2262
+ };
2263
+ const submit = async (context, success, error, submitAs = 'multipart/form-data', input_data = null) => {
2264
+ const endpoint = context.form.action;
2265
+ let data = input_data;
2266
+ if (typeof data != 'object' || data == null) {
2267
+ data = context.form.exportData();
2268
+ }
2269
+ const attachments = getAttachments(context.form, true);
2270
+ let submitContentType = submitAs;
2271
+ const submitDataAndMetaData = { 'data': data, 'submitMetadata': context.form.exportSubmitMetaData() };
2272
+ let formData = submitDataAndMetaData;
2273
+ if (Object.keys(attachments).length > 0 || submitAs === 'multipart/form-data') {
2274
+ formData = multipartFormData(submitDataAndMetaData, attachments);
2275
+ submitContentType = 'multipart/form-data';
2276
+ }
2277
+ await request(context, endpoint, 'POST', formData, success, error, {
2278
+ 'Content-Type': submitContentType
2279
+ });
2280
+ };
2281
+ const createAction = (name, payload = {}) => {
2282
+ switch (name) {
2283
+ case 'change':
2284
+ return new Change(payload);
2285
+ case 'submit':
2286
+ return new Submit(payload);
2287
+ case 'click':
2288
+ return new Click(payload);
2289
+ case 'addItem':
2290
+ return new AddItem(payload);
2291
+ case 'removeItem':
2292
+ return new RemoveItem(payload);
2293
+ case 'reset':
2294
+ return new Reset(payload);
2295
+ case 'addInstance':
2296
+ return new AddInstance(payload);
2297
+ case 'removeInstance':
2298
+ return new RemoveInstance(payload);
2299
+ default:
2300
+ console.error('invalid action');
2301
+ }
2302
+ };
2303
+ class FunctionRuntimeImpl {
2304
+ static instance = null;
2305
+ customFunctions = {};
2306
+ constructor() {
2307
+ }
2308
+ static getInstance() {
2309
+ if (!FunctionRuntimeImpl.instance) {
2310
+ FunctionRuntimeImpl.instance = new FunctionRuntimeImpl();
2311
+ }
2312
+ return FunctionRuntimeImpl.instance;
2313
+ }
2314
+ registerFunctions(functions) {
2315
+ Object.entries(functions).forEach(([name, funcDef]) => {
2316
+ let finalFunction = funcDef;
2317
+ if (typeof funcDef === 'function') {
2318
+ finalFunction = {
2319
+ _func: (args, data, interpreter) => {
2320
+ const globals = {
2321
+ form: interpreter.globals.form,
2322
+ invoke: (funcName, ...args) => {
2323
+ return FunctionRuntimeImpl.getInstance().customFunctions[funcName]._func.call(undefined, args, data, interpreter);
2324
+ }
2325
+ };
2326
+ return funcDef(...args, globals);
2327
+ },
2328
+ _signature: []
2329
+ };
2330
+ }
2331
+ if (!finalFunction.hasOwnProperty('_func')) {
2332
+ console.warn(`Unable to register function with name ${name}.`);
2333
+ return;
2334
+ }
2335
+ FunctionRuntimeImpl.getInstance().customFunctions[name] = finalFunction;
2336
+ });
2337
+ }
2338
+ unregisterFunctions(...names) {
2339
+ names.forEach(name => {
2340
+ if (name in FunctionRuntimeImpl.getInstance().customFunctions) {
2341
+ delete FunctionRuntimeImpl?.getInstance().customFunctions[name];
2342
+ }
2343
+ });
2344
+ }
2345
+ getFunctions() {
2346
+ function isArray(obj) {
2347
+ if (obj !== null) {
2348
+ return Object.prototype.toString.call(obj) === '[object Array]';
2349
+ }
2350
+ return false;
2351
+ }
2352
+ function valueOf(a) {
2353
+ if (a === null || a === undefined) {
2354
+ return a;
2355
+ }
2356
+ if (isArray(a)) {
2357
+ return a.map(i => valueOf(i));
2358
+ }
2359
+ return a.valueOf();
2360
+ }
2361
+ function toString(a) {
2362
+ if (a === null || a === undefined) {
2363
+ return '';
2364
+ }
2365
+ return a.toString();
2366
+ }
2367
+ const defaultFunctions = {
2368
+ validate: {
2369
+ _func: (args, data, interpreter) => {
2370
+ const element = args[0];
2371
+ let validation;
2372
+ if (typeof element === 'string' || typeof element === 'undefined') {
2373
+ validation = interpreter.globals.form.validate();
2374
+ }
2375
+ else {
2376
+ validation = interpreter.globals.form.getElement(element.$id).validate();
2377
+ }
2378
+ if (Array.isArray(validation) && validation.length) {
2379
+ interpreter.globals.form.logger.error('Form Validation Error');
2380
+ }
2381
+ return validation;
2382
+ },
2383
+ _signature: []
2384
+ },
2385
+ setFocus: {
2386
+ _func: (args, data, interpreter) => {
2387
+ const element = args[0];
2388
+ const flag = args[1];
2389
+ try {
2390
+ const field = interpreter.globals.form.getElement(element?.$id) || interpreter.globals.field;
2391
+ interpreter.globals.form.setFocus(field, flag);
2392
+ }
2393
+ catch (e) {
2394
+ interpreter.globals.form.logger.error('An error has occurred within the setFocus API.');
2395
+ }
2396
+ },
2397
+ _signature: []
2398
+ },
2399
+ getData: {
2400
+ _func: (args, data, interpreter) => {
2401
+ interpreter.globals.form.logger.warn('The `getData` function is depricated. Use `exportData` instead.');
2402
+ return interpreter.globals.form.exportData();
2403
+ },
2404
+ _signature: []
2405
+ },
2406
+ exportData: {
2407
+ _func: (args, data, interpreter) => {
2408
+ return interpreter.globals.form.exportData();
2409
+ },
2410
+ _signature: []
2411
+ },
2412
+ importData: {
2413
+ _func: (args, data, interpreter) => {
2414
+ const inputData = args[0];
2415
+ if (typeof inputData === 'object' && inputData !== null) {
2416
+ interpreter.globals.form.importData(inputData);
2417
+ }
2418
+ return {};
2419
+ },
2420
+ _signature: []
2421
+ },
2422
+ submitForm: {
2423
+ _func: (args, data, interpreter) => {
2424
+ const success = toString(args[0]);
2425
+ const error = toString(args[1]);
2426
+ const submit_as = args.length > 2 ? toString(args[2]) : 'multipart/form-data';
2427
+ const submit_data = args.length > 3 ? valueOf(args[3]) : null;
2428
+ interpreter.globals.form.dispatch(new Submit({
2429
+ success,
2430
+ error,
2431
+ submit_as,
2432
+ data: submit_data
2433
+ }));
2434
+ return {};
2435
+ },
2436
+ _signature: []
2437
+ },
2438
+ request: {
2439
+ _func: (args, data, interpreter) => {
2440
+ const uri = toString(args[0]);
2441
+ const httpVerb = toString(args[1]);
2442
+ const payload = valueOf(args[2]);
2443
+ let success, error, headers = {};
2444
+ if (typeof (args[3]) === 'string') {
2445
+ interpreter.globals.form.logger.warn('This usage of request is deprecated. Please see the documentation and update');
2446
+ success = valueOf(args[3]);
2447
+ error = valueOf(args[4]);
2448
+ }
2449
+ else {
2450
+ headers = valueOf(args[3]);
2451
+ success = valueOf(args[4]);
2452
+ error = valueOf(args[5]);
2453
+ }
2454
+ request(interpreter.globals, uri, httpVerb, payload, success, error, headers);
2455
+ return {};
2456
+ },
2457
+ _signature: []
2458
+ },
2459
+ addInstance: {
2460
+ _func: (args, data, interpreter) => {
2461
+ const element = args[0];
2462
+ const payload = args.length > 2 ? valueOf(args[2]) : undefined;
2463
+ try {
2464
+ const formElement = interpreter.globals.form.getElement(element.$id);
2465
+ const action = createAction('addInstance', payload);
2466
+ formElement.addItem(action);
2467
+ }
2468
+ catch (e) {
2469
+ interpreter.globals.form.logger.error('Invalid argument passed in addInstance. An element is expected');
2470
+ }
2471
+ },
2472
+ _signature: []
2473
+ },
2474
+ removeInstance: {
2475
+ _func: (args, data, interpreter) => {
2476
+ const element = args[0];
2477
+ const payload = args.length > 2 ? valueOf(args[2]) : undefined;
2478
+ try {
2479
+ const formElement = interpreter.globals.form.getElement(element.$id);
2480
+ const action = createAction('removeInstance', payload);
2481
+ formElement.removeItem(action);
2482
+ }
2483
+ catch (e) {
2484
+ interpreter.globals.form.logger.error('Invalid argument passed in removeInstance. An element is expected');
2485
+ }
2486
+ },
2487
+ _signature: []
2488
+ },
2489
+ dispatchEvent: {
2490
+ _func: (args, data, interpreter) => {
2491
+ const element = args[0];
2492
+ let eventName = valueOf(args[1]);
2493
+ let payload = args.length > 2 ? valueOf(args[2]) : undefined;
2494
+ let dispatch = false;
2495
+ if (typeof element === 'string') {
2496
+ payload = eventName;
2497
+ eventName = element;
2498
+ dispatch = true;
2499
+ }
2500
+ let event;
2501
+ if (eventName.startsWith('custom:')) {
2502
+ event = new CustomEvent(eventName.substring('custom:'.length), payload, dispatch);
2503
+ }
2504
+ else {
2505
+ event = createAction(eventName, payload);
2506
+ }
2507
+ if (event != null) {
2508
+ if (typeof element === 'string') {
2509
+ interpreter.globals.form.dispatch(event);
2510
+ }
2511
+ else {
2512
+ interpreter.globals.form.getElement(element.$id).dispatch(event);
2513
+ }
2514
+ }
2515
+ return {};
2516
+ },
2517
+ _signature: []
2518
+ }
2519
+ };
2520
+ return { ...defaultFunctions, ...FunctionRuntimeImpl.getInstance().customFunctions };
2521
+ }
2522
+ }
2523
+ const FunctionRuntime = FunctionRuntimeImpl.getInstance();
2524
+
2525
+ class Form extends Container {
2526
+ _ruleEngine;
2527
+ _eventQueue;
2528
+ _fields = {};
2529
+ _ids;
2530
+ _invalidFields = [];
2531
+ constructor(n, fieldFactory, _ruleEngine, _eventQueue = new EventQueue(), logLevel = 'off', mode = 'create') {
2532
+ super(n, { fieldFactory: fieldFactory, mode });
2533
+ this._ruleEngine = _ruleEngine;
2534
+ this._eventQueue = _eventQueue;
2535
+ this._logger = new Logger(logLevel);
2536
+ if (mode === 'create') {
2537
+ this.queueEvent(new Initialize());
2538
+ this.queueEvent(new ExecuteRule());
2539
+ }
2540
+ this._ids = IdGenerator();
2541
+ this._bindToDataModel(new DataGroup('$form', {}));
2542
+ this._initialize(mode);
2543
+ if (mode === 'create') {
2544
+ this.queueEvent(new FormLoad());
2545
+ }
2546
+ }
2547
+ _logger;
2548
+ get logger() {
2549
+ return this._logger;
2550
+ }
2551
+ dataRefRegex = /("[^"]+?"|[^.]+?)(?:\.|$)/g;
2552
+ get metaData() {
2553
+ const metaData = this._jsonModel.metadata || {};
2554
+ return new FormMetaData(metaData);
2555
+ }
2556
+ get action() {
2557
+ return this._jsonModel.action;
2558
+ }
2559
+ importData(dataModel) {
2560
+ this._bindToDataModel(new DataGroup('$form', dataModel));
2561
+ this.syncDataAndFormModel(this.getDataNode());
2562
+ this._eventQueue.runPendingQueue();
2563
+ }
2564
+ exportData() {
2565
+ return this.getDataNode()?.$value;
2566
+ }
2567
+ resolveQualifiedName(qualifiedName) {
2568
+ let foundFormElement = null;
2569
+ this.visit(formElement => {
2570
+ if (formElement.qualifiedName === qualifiedName) {
2571
+ foundFormElement = formElement;
2572
+ }
2573
+ });
2574
+ return foundFormElement;
2575
+ }
2576
+ exportSubmitMetaData() {
2577
+ let submitMetaInstance = null;
2578
+ const captchaInfoObj = {};
2579
+ function addCaptchaField(fieldName, fieldValue) {
2580
+ if (captchaInfoObj[fieldName]) {
2581
+ return;
2582
+ }
2583
+ captchaInfoObj[fieldName] = fieldValue;
2584
+ }
2585
+ this.visit(field => {
2586
+ if (field.fieldType === 'captcha') {
2587
+ addCaptchaField(field.qualifiedName, field.value);
2588
+ }
2589
+ });
2590
+ submitMetaInstance = new SubmitMetaData(this.form.lang, captchaInfoObj);
2591
+ return submitMetaInstance;
2592
+ }
2593
+ #getNavigableChildren(children) {
2594
+ return children.filter(child => child.visible === true);
2595
+ }
2596
+ #getFirstNavigableChild(container) {
2597
+ const navigableChidren = this.#getNavigableChildren(container.items);
2598
+ if (navigableChidren) {
2599
+ return navigableChidren[0];
2600
+ }
2601
+ return null;
2602
+ }
2603
+ #setActiveFirstDeepChild(currentField) {
2604
+ if (!currentField.isContainer) {
2605
+ const parent = currentField.parent;
2606
+ parent.activeChild = currentField;
2607
+ return;
2608
+ }
2609
+ this.#clearCurrentFocus(currentField);
2610
+ let currentActiveChild = currentField.activeChild;
2611
+ currentActiveChild = (currentActiveChild === null) ? this.#getFirstNavigableChild(currentField) : currentField.activeChild;
2612
+ this.#setActiveFirstDeepChild(currentActiveChild);
2613
+ }
2614
+ #getNextItem(currIndex, navigableChidren) {
2615
+ if (currIndex < (navigableChidren.length - 1)) {
2616
+ return navigableChidren[currIndex + 1];
2617
+ }
2618
+ return null;
2619
+ }
2620
+ #getPreviousItem(currIndex, navigableChidren) {
2621
+ if (currIndex > 0) {
2622
+ return navigableChidren[currIndex - 1];
2623
+ }
2624
+ return null;
2625
+ }
2626
+ #clearCurrentFocus(field) {
2627
+ const parent = field.parent;
2628
+ if (parent != null && parent.activeChild != null) {
2629
+ parent.activeChild = null;
2630
+ }
2631
+ }
2632
+ setFocus(field, focusOption) {
2633
+ if (!focusOption) {
2634
+ this.#clearCurrentFocus(field);
2635
+ this.#setActiveFirstDeepChild(field);
2636
+ return;
2637
+ }
2638
+ const parent = (field?.isContainer ? field : field.parent);
2639
+ const navigableChidren = this.#getNavigableChildren(parent.items);
2640
+ let activeChild = parent.activeChild;
2641
+ let currActiveChildIndex = activeChild !== null ? navigableChidren.indexOf(activeChild) : -1;
2642
+ if (parent.activeChild === null) {
2643
+ this.#setActiveFirstDeepChild(navigableChidren[0]);
2644
+ currActiveChildIndex = 0;
2645
+ return;
2646
+ }
2647
+ if (focusOption === FocusOption.NEXT_ITEM) {
2648
+ activeChild = this.#getNextItem(currActiveChildIndex, navigableChidren);
2649
+ }
2650
+ else if (focusOption === FocusOption.PREVIOUS_ITEM) {
2651
+ activeChild = this.#getPreviousItem(currActiveChildIndex, navigableChidren);
2652
+ }
2653
+ if (activeChild !== null) {
2654
+ this.#setActiveFirstDeepChild(activeChild);
2655
+ }
2656
+ }
2657
+ getState(forRestore = false) {
2658
+ const self = this;
2659
+ const res = super.getState(false, forRestore);
2660
+ res.id = '$form';
2661
+ Object.defineProperty(res, 'data', {
2662
+ get: function () {
2663
+ return self.exportData();
2664
+ }
2665
+ });
2666
+ Object.defineProperty(res, 'attachments', {
2667
+ get: function () {
2668
+ return getAttachments(self);
2669
+ }
2670
+ });
2671
+ return res;
2672
+ }
2673
+ get type() {
2674
+ return 'object';
2675
+ }
2676
+ isTransparent() {
2677
+ return false;
2678
+ }
2679
+ get form() {
2680
+ return this;
2681
+ }
2682
+ get ruleEngine() {
2683
+ return this._ruleEngine;
2684
+ }
2685
+ getUniqueId() {
2686
+ if (this._ids == null) {
2687
+ return '';
2688
+ }
2689
+ return this._ids.next().value;
2690
+ }
2691
+ fieldAdded(field) {
2692
+ this._fields[field.id] = field;
2693
+ field.subscribe((action) => {
2694
+ if (this._invalidFields.indexOf(action.target.id) === -1) {
2695
+ this._invalidFields.push(action.target.id);
2696
+ }
2697
+ }, 'invalid');
2698
+ field.subscribe((action) => {
2699
+ const index = this._invalidFields.indexOf(action.target.id);
2700
+ if (index > -1) {
2701
+ this._invalidFields.splice(index, 1);
2702
+ }
2703
+ }, 'valid');
2704
+ field.subscribe((action) => {
2705
+ const field = action.target.getState();
2706
+ if (field) {
2707
+ const shallowClone = (obj) => {
2708
+ if (obj && typeof obj === 'object') {
2709
+ if (Array.isArray(obj)) {
2710
+ return obj.map(shallowClone);
2711
+ }
2712
+ else {
2713
+ return { ...obj };
2714
+ }
2715
+ }
2716
+ return obj;
2717
+ };
2718
+ const changes = action.payload.changes.map(({ propertyName, currentValue, prevValue }) => {
2719
+ return {
2720
+ propertyName,
2721
+ currentValue: shallowClone(currentValue),
2722
+ prevValue: shallowClone(prevValue)
2723
+ };
2724
+ });
2725
+ const fieldChangedAction = new FieldChanged(changes, field);
2726
+ this.dispatch(fieldChangedAction);
2727
+ }
2728
+ });
2729
+ }
2730
+ visit(callBack) {
2731
+ this.traverseChild(this, callBack);
2732
+ }
2733
+ traverseChild(container, callBack) {
2734
+ container.items.forEach((field) => {
2735
+ if (field.isContainer) {
2736
+ this.traverseChild(field, callBack);
2737
+ }
2738
+ callBack(field);
2739
+ });
2740
+ }
2741
+ validate() {
2742
+ const validationErrors = super.validate();
2743
+ this.dispatch(new ValidationComplete(validationErrors));
2744
+ return validationErrors;
2745
+ }
2746
+ isValid() {
2747
+ return this._invalidFields.length === 0;
2748
+ }
2749
+ dispatch(action) {
2750
+ if (action.type === 'submit') {
2751
+ super.queueEvent(action);
2752
+ this._eventQueue.runPendingQueue();
2753
+ }
2754
+ else {
2755
+ super.dispatch(action);
2756
+ }
2757
+ }
2758
+ submit(action, context) {
2759
+ if (this.validate().length === 0) {
2760
+ const payload = action?.payload || {};
2761
+ const successEventName = payload?.success ? payload?.success : 'submitSuccess';
2762
+ const failureEventName = payload?.error ? payload?.error : 'submitFailure';
2763
+ submit(context, successEventName, failureEventName, payload?.submit_as, payload?.data);
2764
+ }
2765
+ }
2766
+ reset() {
2767
+ super.reset();
2768
+ this._invalidFields = [];
2769
+ }
2770
+ getElement(id) {
2771
+ if (id == this.id) {
2772
+ return this;
2773
+ }
2774
+ return this._fields[id];
2775
+ }
2776
+ get qualifiedName() {
2777
+ return '$form';
2778
+ }
2779
+ getEventQueue() {
2780
+ return this._eventQueue;
2781
+ }
2782
+ get name() {
2783
+ return '$form';
2784
+ }
2785
+ get value() {
2786
+ return null;
2787
+ }
2788
+ get id() {
2789
+ return '$form';
2790
+ }
2791
+ get title() {
2792
+ return this._jsonModel.title || '';
2793
+ }
2794
+ }
2795
+
2796
+ function stringToNumber(str, language) {
2797
+ if (str === null) {
2798
+ return 0;
2799
+ }
2800
+ const n = +str;
2801
+ if (!isNaN(n)) {
2802
+ return n;
2803
+ }
2804
+ if (language) {
2805
+ const date = parseDefaultDate(str, language, true);
2806
+ if (date !== str) {
2807
+ return datetimeToNumber(date);
2808
+ }
2809
+ }
2810
+ return 0;
2811
+ }
2812
+
2813
+ function getStringToNumberFn(locale) {
2814
+ if (locale == null) {
2815
+ const localeOptions = new Intl.DateTimeFormat().resolvedOptions();
2816
+ locale = localeOptions.locale;
2817
+ }
2818
+ return (str) => stringToNumber(str, locale);
2819
+ }
2820
+ class RuleEngine {
2821
+ _context;
2822
+ _globalNames = [
2823
+ '$form',
2824
+ '$field',
2825
+ '$event'
2826
+ ];
2827
+ customFunctions;
2828
+ debugInfo = [];
2829
+ constructor() {
2830
+ this.customFunctions = FunctionRuntime.getFunctions();
2831
+ }
2832
+ compileRule(rule, locale) {
2833
+ const formula = new Formula(this.customFunctions, getStringToNumberFn(locale), this.debugInfo);
2834
+ return { formula, ast: formula.compile(rule, this._globalNames) };
2835
+ }
2836
+ execute(node, data, globals, useValueOf = false) {
2837
+ const { formula, ast } = node;
2838
+ const oldContext = this._context;
2839
+ this._context = globals;
2840
+ let res = undefined;
2841
+ try {
2842
+ res = formula.run(ast, data, 'en-US', globals);
2843
+ }
2844
+ catch (err) {
2845
+ this._context?.form?.logger?.error(err);
2846
+ }
2847
+ while (this.debugInfo.length > 0) {
2848
+ this._context?.form?.logger?.debug(this.debugInfo.pop());
2849
+ }
2850
+ let finalRes = res;
2851
+ if (useValueOf) {
2852
+ if (typeof res === 'object' && res !== null) {
2853
+ finalRes = Object.getPrototypeOf(res).valueOf.call(res);
2854
+ }
2855
+ }
2856
+ this._context = oldContext;
2857
+ return finalRes;
2858
+ }
2859
+ trackDependency(subscriber) {
2860
+ if (this._context && this._context.field !== undefined && this._context.field !== subscriber) {
2861
+ subscriber._addDependent(this._context.field);
2862
+ }
2863
+ }
2864
+ }
2865
+
2866
+ class Fieldset extends Container {
2867
+ constructor(params, _options) {
2868
+ super(params, _options);
2869
+ this._applyDefaults();
2870
+ this.queueEvent(new Initialize());
2871
+ this.queueEvent(new ExecuteRule());
2872
+ }
2873
+ _getDefaults() {
2874
+ return {
2875
+ ...super._getDefaults(),
2876
+ visible: true,
2877
+ required: false,
2878
+ label: {
2879
+ visible: true,
2880
+ richText: false
2881
+ }
2882
+ };
2883
+ }
2884
+ _applyDefaults() {
2885
+ super._applyDefaultsInModel();
2886
+ if (this._jsonModel.dataRef && this._jsonModel.type === undefined) {
2887
+ this._jsonModel.type = 'object';
2888
+ }
2889
+ }
2890
+ get type() {
2891
+ const ret = super.type;
2892
+ if (ret === 'array' || ret === 'object') {
2893
+ return ret;
2894
+ }
2895
+ return undefined;
2896
+ }
2897
+ get items() {
2898
+ return super.items;
2899
+ }
2900
+ get value() {
2901
+ return null;
2902
+ }
2903
+ get fieldType() {
2904
+ return 'panel';
2905
+ }
2906
+ }
2907
+
2908
+ class InstanceManager extends Fieldset {
2909
+ get maxOccur() {
2910
+ return this._jsonModel.maxItems;
2911
+ }
2912
+ set maxOccur(m) {
2913
+ this.maxItems = m;
2914
+ }
2915
+ get minOccur() {
2916
+ return this.minItems;
2917
+ }
2918
+ addInstance(action) {
2919
+ return this.addItem(action);
2920
+ }
2921
+ removeInstance(action) {
2922
+ return this.removeItem(action);
2923
+ }
2924
+ }
2925
+ __decorate([
2926
+ dependencyTracked()
2927
+ ], InstanceManager.prototype, "maxOccur", null);
2928
+ __decorate([
2929
+ dependencyTracked()
2930
+ ], InstanceManager.prototype, "minOccur", null);
2931
+
2932
+ const dateRegex = /^(\d{4})-(\d{1,2})-(\d{1,2})$/;
2933
+ const emailRegex = /^[a-zA-Z0-9.!#$%&’*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/;
2934
+ const days = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
2935
+ const daysInMonth = (leapYear, month) => {
2936
+ if (leapYear && month == 2) {
2937
+ return 29;
2938
+ }
2939
+ return days[month - 1];
2940
+ };
2941
+ const isLeapYear = (year) => {
2942
+ return year % 400 === 0 || year % 4 === 0 && year % 100 !== 0;
2943
+ };
2944
+ const coerceType = (param, type) => {
2945
+ let num;
2946
+ switch (type) {
2947
+ case 'string':
2948
+ return param + '';
2949
+ case 'number':
2950
+ num = +param;
2951
+ if (!isNaN(num)) {
2952
+ return num;
2953
+ }
2954
+ break;
2955
+ case 'boolean':
2956
+ if (typeof param === 'string') {
2957
+ return param === 'true';
2958
+ }
2959
+ else if (typeof param === 'number') {
2960
+ return param !== 0;
2961
+ }
2962
+ }
2963
+ throw `${param} has invalid type. Expected : ${type}, Actual ${typeof param}`;
2964
+ };
2965
+ const checkNumber = (inputVal) => {
2966
+ if (inputVal === '' || inputVal == null) {
2967
+ return {
2968
+ value: '', valid: true
2969
+ };
2970
+ }
2971
+ let value = parseFloat(inputVal);
2972
+ const valid = !isNaN(value);
2973
+ if (!valid) {
2974
+ value = inputVal;
2975
+ }
2976
+ return {
2977
+ value, valid
2978
+ };
2979
+ };
2980
+ const checkInteger = (inputVal) => {
2981
+ if (inputVal == '' || inputVal == null) {
2982
+ return {
2983
+ value: '', valid: true
2984
+ };
2985
+ }
2986
+ let value = parseFloat(inputVal);
2987
+ const valid = !isNaN(value) && Math.round(value) === value;
2988
+ if (!valid) {
2989
+ value = inputVal;
2990
+ }
2991
+ return {
2992
+ value, valid
2993
+ };
2994
+ };
2995
+ const toArray = (inputVal) => {
2996
+ if (inputVal != null && !(inputVal instanceof Array)) {
2997
+ return [inputVal];
2998
+ }
2999
+ return inputVal;
3000
+ };
3001
+ const checkBool = (inputVal) => {
3002
+ const valid = typeof inputVal === 'boolean' || inputVal === 'true' || inputVal === 'false';
3003
+ const value = typeof inputVal === 'boolean' ? inputVal : (valid ? inputVal === 'true' : inputVal);
3004
+ return { valid, value };
3005
+ };
3006
+ const checkFile = (inputVal) => {
3007
+ const value = extractFileInfo(inputVal);
3008
+ const valid = value !== null;
3009
+ return {
3010
+ value: valid ? value : inputVal,
3011
+ valid
3012
+ };
3013
+ };
3014
+ const matchMediaType = (mediaType, accepts) => {
3015
+ return !mediaType || accepts.some((accept) => {
3016
+ const trimmedAccept = accept.trim();
3017
+ const prefixAccept = trimmedAccept.split('/')[0];
3018
+ const suffixAccept = trimmedAccept.split('.')[1];
3019
+ return ((trimmedAccept.includes('*') && mediaType.startsWith(prefixAccept)) ||
3020
+ (trimmedAccept.includes('.') && mediaType.endsWith(suffixAccept)) ||
3021
+ (trimmedAccept === mediaType));
3022
+ });
3023
+ };
3024
+ const partitionArray = (inputVal, validatorFn) => {
3025
+ const value = toArray(inputVal);
3026
+ if (value == null) {
3027
+ return [[], [value]];
3028
+ }
3029
+ return value.reduce((acc, x) => {
3030
+ if (acc[1].length == 0) {
3031
+ const r = validatorFn(x);
3032
+ const index = r.valid ? 0 : 1;
3033
+ acc[index].push(r.value);
3034
+ }
3035
+ return acc;
3036
+ }, [[], []]);
3037
+ };
3038
+ const ValidConstraints = {
3039
+ date: ['minimum', 'maximum', 'exclusiveMinimum', 'exclusiveMaximum', 'format'],
3040
+ string: ['minLength', 'maxLength', 'pattern'],
3041
+ number: ['minimum', 'maximum', 'exclusiveMinimum', 'exclusiveMaximum'],
3042
+ array: ['minItems', 'maxItems', 'uniqueItems'],
3043
+ file: ['accept', 'maxFileSize'],
3044
+ email: ['minLength', 'maxLength', 'format', 'pattern']
3045
+ };
3046
+ const Constraints = {
3047
+ type: (constraint, inputVal) => {
3048
+ let value = inputVal;
3049
+ if (inputVal == undefined) {
3050
+ return {
3051
+ valid: true,
3052
+ value: inputVal
3053
+ };
3054
+ }
3055
+ let valid = true, res;
3056
+ switch (constraint) {
3057
+ case 'string':
3058
+ valid = true;
3059
+ value = inputVal.toString();
3060
+ break;
3061
+ case 'string[]':
3062
+ value = toArray(inputVal);
3063
+ break;
3064
+ case 'number':
3065
+ res = checkNumber(inputVal);
3066
+ value = res.value;
3067
+ valid = res.valid;
3068
+ break;
3069
+ case 'boolean':
3070
+ res = checkBool(inputVal);
3071
+ valid = res.valid;
3072
+ value = res.value;
3073
+ break;
3074
+ case 'integer':
3075
+ res = checkInteger(inputVal);
3076
+ valid = res.valid;
3077
+ value = res.value;
3078
+ break;
3079
+ case 'integer[]':
3080
+ res = partitionArray(inputVal, checkInteger);
3081
+ valid = res[1].length === 0;
3082
+ value = valid ? res[0] : inputVal;
3083
+ break;
3084
+ case 'file':
3085
+ res = checkFile(inputVal instanceof Array ? inputVal[0] : inputVal);
3086
+ valid = res.valid;
3087
+ value = res.value;
3088
+ break;
3089
+ case 'file[]':
3090
+ res = partitionArray(inputVal, checkFile);
3091
+ valid = res[1].length === 0;
3092
+ value = valid ? res[0] : inputVal;
3093
+ break;
3094
+ case 'number[]':
3095
+ res = partitionArray(inputVal, checkNumber);
3096
+ valid = res[1].length === 0;
3097
+ value = valid ? res[0] : inputVal;
3098
+ break;
3099
+ case 'boolean[]':
3100
+ res = partitionArray(inputVal, checkBool);
3101
+ valid = res[1].length === 0;
3102
+ value = valid ? res[0] : inputVal;
3103
+ break;
3104
+ }
3105
+ return {
3106
+ valid,
3107
+ value
3108
+ };
3109
+ },
3110
+ format: (constraint, input) => {
3111
+ let valid = true;
3112
+ const value = input;
3113
+ if (input === null) {
3114
+ return { value, valid };
3115
+ }
3116
+ let res;
3117
+ switch (constraint) {
3118
+ case 'date':
3119
+ res = dateRegex.exec((input || '').trim());
3120
+ if (res != null) {
3121
+ const [match, year, month, date] = res;
3122
+ const [nMonth, nDate] = [+month, +date];
3123
+ const leapYear = isLeapYear(+year);
3124
+ valid = (nMonth >= 1 && nMonth <= 12) &&
3125
+ (nDate >= 1 && nDate <= daysInMonth(leapYear, nMonth));
3126
+ }
3127
+ else {
3128
+ valid = false;
3129
+ }
3130
+ break;
3131
+ case 'email':
3132
+ valid = new RegExp(emailRegex).test((input || '').trim());
3133
+ break;
3134
+ case 'data-url':
3135
+ valid = true;
3136
+ break;
3137
+ }
3138
+ return { valid, value };
3139
+ },
3140
+ minimum: (constraint, value) => {
3141
+ return { valid: value >= constraint, value };
3142
+ },
3143
+ maximum: (constraint, value) => {
3144
+ return { valid: value <= constraint, value };
3145
+ },
3146
+ exclusiveMinimum: (constraint, value) => {
3147
+ return { valid: value > constraint, value };
3148
+ },
3149
+ exclusiveMaximum: (constraint, value) => {
3150
+ return { valid: value < constraint, value };
3151
+ },
3152
+ minItems: (constraint, value) => {
3153
+ return { valid: (value instanceof Array) && value.length >= constraint, value };
3154
+ },
3155
+ maxItems: (constraint, value) => {
3156
+ return { valid: (value instanceof Array) && value.length <= constraint, value };
3157
+ },
3158
+ uniqueItems: (constraint, value) => {
3159
+ return { valid: !constraint || ((value instanceof Array) && value.length === new Set(value).size), value };
3160
+ },
3161
+ minLength: (constraint, value) => {
3162
+ return { ...Constraints.minimum(constraint, typeof value === 'string' ? value.length : 0), value };
3163
+ },
3164
+ maxLength: (constraint, value) => {
3165
+ return { ...Constraints.maximum(constraint, typeof value === 'string' ? value.length : 0), value };
3166
+ },
3167
+ pattern: (constraint, value) => {
3168
+ let regex;
3169
+ if (typeof constraint === 'string') {
3170
+ regex = new RegExp(constraint);
3171
+ }
3172
+ else {
3173
+ regex = constraint;
3174
+ }
3175
+ return { valid: regex.test(value), value };
3176
+ },
3177
+ required: (constraint, value) => {
3178
+ const valid = constraint ? value != null && value !== '' : true;
3179
+ return { valid, value };
3180
+ },
3181
+ enum: (constraint, value) => {
3182
+ return {
3183
+ valid: constraint.indexOf(value) > -1,
3184
+ value
3185
+ };
3186
+ },
3187
+ accept: (constraint, value) => {
3188
+ if (!constraint || constraint.length === 0 || value === null || value === undefined) {
3189
+ return {
3190
+ valid: true,
3191
+ value
3192
+ };
3193
+ }
3194
+ const tempValue = value instanceof Array ? value : [value];
3195
+ const invalidFile = tempValue.some((file) => !matchMediaType(file.type, constraint));
3196
+ return {
3197
+ valid: !invalidFile,
3198
+ value
3199
+ };
3200
+ },
3201
+ maxFileSize: (constraint, value) => {
3202
+ const sizeLimit = typeof constraint === 'string' ? getFileSizeInBytes(constraint) : constraint;
3203
+ return {
3204
+ valid: !(value instanceof FileObject) || value.size <= sizeLimit,
3205
+ value
3206
+ };
3207
+ }
3208
+ };
3209
+
3210
+ const validTypes = ['string', 'number', 'integer', 'boolean', 'file', 'string[]', 'number[]', 'integer[]', 'boolean[]', 'file[]', 'array', 'object'];
3211
+ class Field extends Scriptable {
3212
+ constructor(params, _options) {
3213
+ super(params, _options);
3214
+ this._applyDefaults();
3215
+ this.queueEvent(new Initialize());
3216
+ this.queueEvent(new ExecuteRule());
3217
+ }
3218
+ _ruleNodeReference = [];
3219
+ _initialize() {
3220
+ super._initialize();
3221
+ this.setupRuleNode();
3222
+ }
3223
+ ruleNodeReference() {
3224
+ if (this.type?.endsWith('[]')) {
3225
+ this._ruleNodeReference = [];
3226
+ }
3227
+ else {
3228
+ this._ruleNodeReference = this;
3229
+ }
3230
+ return this._ruleNodeReference;
3231
+ }
3232
+ _getDefaults() {
3233
+ return {
3234
+ readOnly: false,
3235
+ enabled: true,
3236
+ visible: true,
3237
+ label: {
3238
+ visible: true,
3239
+ richText: false
3240
+ },
3241
+ required: false,
3242
+ type: this._getFallbackType()
3243
+ };
3244
+ }
3245
+ _getFallbackType() {
3246
+ const type = this._jsonModel.type;
3247
+ let finalType = type;
3248
+ if (typeof type !== 'string' || validTypes.indexOf(type) === -1) {
3249
+ const _enum = this.enum;
3250
+ finalType = typeof (_enum?.[0]);
3251
+ if (finalType === 'undefined' && typeof this._jsonModel.default !== 'undefined') {
3252
+ if (this._jsonModel.default instanceof Array && this._jsonModel.default.length > 0) {
3253
+ finalType = `${typeof (this._jsonModel.default[0])}[]`;
3254
+ }
3255
+ else {
3256
+ finalType = typeof (this._jsonModel.default);
3257
+ }
3258
+ }
3259
+ if (finalType.indexOf('undefined') === 0) {
3260
+ const typeMappings = {
3261
+ 'text-input': 'string',
3262
+ 'multiline-input': 'string',
3263
+ 'number-input': 'number',
3264
+ 'date-input': 'string',
3265
+ 'email': 'string',
3266
+ 'plain-text': 'string',
3267
+ 'image': 'string',
3268
+ 'checkbox': 'boolean'
3269
+ };
3270
+ finalType = typeMappings[this.fieldType];
3271
+ }
3272
+ }
3273
+ return finalType;
3274
+ }
3275
+ _applyDefaults() {
3276
+ super._applyDefaultsInModel();
3277
+ this.coerceParam('required', 'boolean');
3278
+ this.coerceParam('readOnly', 'boolean');
3279
+ this.coerceParam('enabled', 'boolean');
3280
+ const type = this._jsonModel.type;
3281
+ if (typeof type !== 'string' || validTypes.indexOf(type) === -1) {
3282
+ this._jsonModel.type = this._getFallbackType();
3283
+ }
3284
+ if (['plain-text', 'image'].indexOf(this.fieldType) === -1) {
3285
+ this._jsonModel.value = undefined;
3286
+ }
3287
+ const value = this._jsonModel.value;
3288
+ if (value === undefined) {
3289
+ const typedRes = Constraints.type(this.getInternalType() || 'string', this._jsonModel.default);
3290
+ this._jsonModel.value = typedRes.value;
3291
+ }
3292
+ if (this._jsonModel.type !== 'string') {
3293
+ this.unset('emptyValue');
3294
+ }
3295
+ if (this._jsonModel.fieldType === undefined) {
3296
+ this.form.logger.debug('fieldType property is mandatory. Please ensure all the fields have a fieldType');
3297
+ if (this._jsonModel.viewType) {
3298
+ if (this._jsonModel.viewType.startsWith('custom:')) {
3299
+ this.form.logger.error('viewType property has been removed. For custom types, use :type property');
3300
+ }
3301
+ else {
3302
+ this.form.logger.error('viewType property has been removed. Use fieldType property');
3303
+ }
3304
+ this._jsonModel.fieldType = this._jsonModel.viewType;
3305
+ }
3306
+ else {
3307
+ this._jsonModel.fieldType = defaultFieldTypes(this._jsonModel);
3308
+ }
3309
+ }
3310
+ if (this._jsonModel.enum === undefined) {
3311
+ const type = this._jsonModel.type;
3312
+ if (type === 'boolean') {
3313
+ this._jsonModel.enum = [true, false];
3314
+ }
3315
+ }
3316
+ else {
3317
+ if (typeof this._jsonModel.enumNames === 'undefined') {
3318
+ this._jsonModel.enumNames = this._jsonModel.enum.map(_ => _.toString());
3319
+ }
3320
+ while (this._jsonModel.enumNames.length < this._jsonModel.enum.length) {
3321
+ this._jsonModel.enumNames.push(this._jsonModel.enum[this._jsonModel.enumNames.length].toString());
3322
+ }
3323
+ }
3324
+ const props = ['minimum', 'maximum', 'exclusiveMinimum', 'exclusiveMaximum'];
3325
+ if (this._jsonModel.type !== 'string') {
3326
+ this.unset('format', 'pattern', 'minLength', 'maxLength');
3327
+ }
3328
+ else if (this._jsonModel.fieldType === 'date-input') {
3329
+ this._jsonModel.format = 'date';
3330
+ }
3331
+ this.coerceParam('minLength', 'number');
3332
+ this.coerceParam('maxLength', 'number');
3333
+ if (this._jsonModel.type !== 'number' && this._jsonModel.format !== 'date' && this._jsonModel.type !== 'integer') {
3334
+ this.unset('step', ...props);
3335
+ }
3336
+ props.forEach(c => {
3337
+ this.coerceParam(c, this._jsonModel.type === 'integer' ? 'number' : this._jsonModel.type);
3338
+ });
3339
+ if (typeof this._jsonModel.step !== 'number') {
3340
+ this.coerceParam('step', 'number');
3341
+ }
3342
+ }
3343
+ unset(...props) {
3344
+ props.forEach(p => this._jsonModel[p] = undefined);
3345
+ }
3346
+ coerceParam(param, type) {
3347
+ const val = this._jsonModel[param];
3348
+ if (typeof val !== 'undefined' && typeof val !== type) {
3349
+ this.form.logger.info(`${param} is not of type ${type}. Trying to coerce.`);
3350
+ try {
3351
+ this._jsonModel[param] = coerceType(val, type);
3352
+ }
3353
+ catch (e) {
3354
+ this.form.logger.warn(e);
3355
+ this.unset(param);
3356
+ }
3357
+ }
3358
+ }
3359
+ get editFormat() {
3360
+ return this.withCategory(this._jsonModel.editFormat);
3361
+ }
3362
+ get displayFormat() {
3363
+ return this.withCategory(this._jsonModel.displayFormat);
3364
+ }
3365
+ get placeholder() {
3366
+ return this._jsonModel.placeholder;
3367
+ }
3368
+ get readOnly() {
3369
+ if (this.parent.readOnly !== undefined) {
3370
+ return this.parent.readOnly === true ? true : this._jsonModel.readOnly;
3371
+ }
3372
+ else {
3373
+ return this._jsonModel.readOnly;
3374
+ }
3375
+ }
3376
+ set readOnly(e) {
3377
+ this._setProperty('readOnly', e);
3378
+ }
3379
+ get enabled() {
3380
+ if (this.parent.enabled !== undefined) {
3381
+ return this.parent.enabled === false ? false : this._jsonModel.enabled;
3382
+ }
3383
+ else {
3384
+ return this._jsonModel.enabled;
3385
+ }
3386
+ }
3387
+ set enabled(e) {
3388
+ this._setProperty('enabled', e);
3389
+ }
3390
+ get valid() {
3391
+ return this._jsonModel?.validity?.valid;
3392
+ }
3393
+ set valid(e) {
3394
+ const validity = {
3395
+ valid: e
3396
+ };
3397
+ this._setProperty('valid', e);
3398
+ this._setProperty('validity', validity);
3399
+ }
3400
+ get validity() {
3401
+ return this._jsonModel.validity;
3402
+ }
3403
+ get emptyValue() {
3404
+ if (this._jsonModel.emptyValue === 'null') {
3405
+ return null;
3406
+ }
3407
+ else if (this._jsonModel.emptyValue === '' && this.type === 'string') {
3408
+ return '';
3409
+ }
3410
+ else {
3411
+ return undefined;
3412
+ }
3413
+ }
3414
+ get enum() {
3415
+ return this._jsonModel.enum;
3416
+ }
3417
+ set enum(e) {
3418
+ this._setProperty('enum', e);
3419
+ }
3420
+ get enumNames() {
3421
+ return this._jsonModel.enumNames;
3422
+ }
3423
+ set enumNames(e) {
3424
+ this._setProperty('enumNames', e);
3425
+ }
3426
+ get required() {
3427
+ return this._jsonModel.required || false;
3428
+ }
3429
+ set required(r) {
3430
+ this._setProperty('required', r);
3431
+ }
3432
+ get maximum() {
3433
+ if (this.type === 'number' || this.format === 'date' || this.type === 'integer') {
3434
+ return this._jsonModel.maximum;
3435
+ }
3436
+ }
3437
+ set maximum(m) {
3438
+ if (this.type === 'number' || this.format === 'date' || this.type === 'integer') {
3439
+ this._setProperty('maximum', m);
3440
+ }
3441
+ }
3442
+ get minimum() {
3443
+ if (this.type === 'number' || this.format === 'date' || this.type === 'integer') {
3444
+ return this._jsonModel.minimum;
3445
+ }
3446
+ }
3447
+ set minimum(m) {
3448
+ if (this.type === 'number' || this.format === 'date' || this.type === 'integer') {
3449
+ this._setProperty('minimum', m);
3450
+ }
3451
+ }
3452
+ withCategory(df) {
3453
+ if (df) {
3454
+ const hasCategory = df?.match(/^(?:date|num)\|/);
3455
+ if (hasCategory === null) {
3456
+ if (this.format === 'date') {
3457
+ df = `date|${df}`;
3458
+ }
3459
+ else if (this.type === 'number' || this.type === 'integer') {
3460
+ df = `num|${df}`;
3461
+ }
3462
+ return df;
3463
+ }
3464
+ }
3465
+ return df;
3466
+ }
3467
+ get editValue() {
3468
+ const df = this.editFormat;
3469
+ if (df && this.isNotEmpty(this.value) && this.valid !== false) {
3470
+ try {
3471
+ return format(this.value, this.lang, df);
3472
+ }
3473
+ catch (e) {
3474
+ return this.value;
3475
+ }
3476
+ }
3477
+ else {
3478
+ return this.value;
3479
+ }
3480
+ }
3481
+ get displayValue() {
3482
+ const df = this.displayFormat;
3483
+ if (df && this.isNotEmpty(this.value) && this.valid !== false) {
3484
+ try {
3485
+ return format(this.value, this.lang, df);
3486
+ }
3487
+ catch (e) {
3488
+ return this.value;
3489
+ }
3490
+ }
3491
+ else {
3492
+ return this.value;
3493
+ }
3494
+ }
3495
+ getDataNodeValue(typedValue) {
3496
+ return this.isEmpty() ? this.emptyValue : typedValue;
3497
+ }
3498
+ updateDataNodeAndTypedValue(val) {
3499
+ const dataNode = this.getDataNode();
3500
+ if (staticFields.indexOf(this.fieldType) > -1 && typeof dataNode !== 'undefined') {
3501
+ return;
3502
+ }
3503
+ const Constraints = this._getConstraintObject();
3504
+ const typeRes = Constraints.type(this.getInternalType() || 'string', val);
3505
+ const changes = this._setProperty('value', typeRes.value, false);
3506
+ if (changes.length > 0) {
3507
+ this._updateRuleNodeReference(typeRes.value);
3508
+ if (typeof dataNode !== 'undefined') {
3509
+ dataNode.setValue(this.getDataNodeValue(this._jsonModel.value), this._jsonModel.value, this);
3510
+ }
3511
+ }
3512
+ return changes;
3513
+ }
3514
+ get value() {
3515
+ if (this._jsonModel.value === undefined) {
3516
+ return null;
3517
+ }
3518
+ else {
3519
+ return this._jsonModel.value;
3520
+ }
3521
+ }
3522
+ set value(v) {
3523
+ const changes = this.updateDataNodeAndTypedValue(v);
3524
+ let uniqueRes = { valid: true };
3525
+ let constraint = 'type';
3526
+ if (changes?.length > 0) {
3527
+ let updates = {};
3528
+ const typeRes = Constraints.type(this.getInternalType() || 'string', v);
3529
+ if (this.parent.uniqueItems && this.parent.type === 'array') {
3530
+ uniqueRes = Constraints.uniqueItems(this.parent.uniqueItems, this.parent.getDataNode().$value);
3531
+ constraint = 'uniqueItems';
3532
+ }
3533
+ if (typeRes.valid && uniqueRes.valid) {
3534
+ updates = this.evaluateConstraints();
3535
+ }
3536
+ else {
3537
+ const valid = typeRes.valid && uniqueRes.valid;
3538
+ const changes = {
3539
+ valid,
3540
+ 'errorMessage': typeRes.valid && uniqueRes.valid ? '' : this.getErrorMessage('type'),
3541
+ ...(valid ? {} : {
3542
+ 'validationMessage': valid ? '' : this.getErrorMessage(constraint),
3543
+ 'validity': {
3544
+ valid,
3545
+ [constraintKeys[constraint]]: true
3546
+ }
3547
+ })
3548
+ };
3549
+ updates = this._applyUpdates(['valid', 'errorMessage', 'validationMessage', 'validity'], changes);
3550
+ }
3551
+ if (updates.valid) {
3552
+ this.triggerValidationEvent(updates);
3553
+ }
3554
+ const changeAction = new Change({ changes: changes.concat(Object.values(updates)) });
3555
+ this.dispatch(changeAction);
3556
+ }
3557
+ }
3558
+ reset() {
3559
+ const changes = this.updateDataNodeAndTypedValue(this.default);
3560
+ const validationStateChanges = {
3561
+ 'valid': undefined,
3562
+ 'errorMessage': '',
3563
+ 'validationMessage': '',
3564
+ 'validity': {
3565
+ valid: undefined
3566
+ }
3567
+ };
3568
+ const updates = this._applyUpdates(['valid', 'errorMessage', 'validationMessage', 'validity'], validationStateChanges);
3569
+ const changeAction = new Change({ changes: changes.concat(Object.values(updates)) });
3570
+ this.dispatch(changeAction);
3571
+ }
3572
+ _updateRuleNodeReference(value) {
3573
+ if (this.type?.endsWith('[]')) {
3574
+ if (value != null) {
3575
+ value.forEach((val, index) => {
3576
+ this._ruleNodeReference[index] = val;
3577
+ });
3578
+ while (value.length !== this._ruleNodeReference.length) {
3579
+ this._ruleNodeReference.pop();
3580
+ }
3581
+ }
3582
+ else {
3583
+ while (this._ruleNodeReference.length !== 0) {
3584
+ this._ruleNodeReference.pop();
3585
+ }
3586
+ }
3587
+ }
3588
+ }
3589
+ getInternalType() {
3590
+ return this.type;
3591
+ }
3592
+ valueOf() {
3593
+ const obj = this[target];
3594
+ const actualField = obj === undefined ? this : obj;
3595
+ actualField.ruleEngine.trackDependency(actualField);
3596
+ return actualField._jsonModel.value || null;
3597
+ }
3598
+ toString() {
3599
+ const obj = this[target];
3600
+ const actualField = obj === undefined ? this : obj;
3601
+ return actualField._jsonModel.value?.toString() || '';
3602
+ }
3603
+ getErrorMessage(constraint) {
3604
+ const afConstraintKey = constraint;
3605
+ const html5ConstraintType = constraintKeys[afConstraintKey];
3606
+ const constraintTypeMessages = getConstraintTypeMessages();
3607
+ return this._jsonModel.constraintMessages?.[afConstraintKey]
3608
+ || replaceTemplatePlaceholders(constraintTypeMessages[html5ConstraintType], [this._jsonModel[afConstraintKey]]);
3609
+ }
3610
+ get errorMessage() {
3611
+ return this._jsonModel.errorMessage;
3612
+ }
3613
+ set errorMessage(e) {
3614
+ this._setProperty('errorMessage', e);
3615
+ this._setProperty('validationMessage', e);
3616
+ }
3617
+ get screenReaderText() {
3618
+ return this._jsonModel.screenReaderText;
3619
+ }
3620
+ _getConstraintObject() {
3621
+ return Constraints;
3622
+ }
3623
+ isArrayType() {
3624
+ return this.type ? this.type.indexOf('[]') > -1 : false;
3625
+ }
3626
+ checkEnum(value, constraints) {
3627
+ if (this._jsonModel.enforceEnum === true && value != null) {
3628
+ const fn = constraints.enum;
3629
+ if (value instanceof Array && this.isArrayType()) {
3630
+ return value.every(x => fn(this.enum || [], x).valid);
3631
+ }
3632
+ else {
3633
+ return fn(this.enum || [], value).valid;
3634
+ }
3635
+ }
3636
+ return true;
3637
+ }
3638
+ checkStep() {
3639
+ const value = this._jsonModel.value;
3640
+ const step = this._jsonModel.step;
3641
+ if (typeof step === 'number') {
3642
+ const prec = step.toString().split('.')?.[1]?.length || 0;
3643
+ const factor = Math.pow(10, prec);
3644
+ const fStep = step * factor;
3645
+ const fVal = value * factor;
3646
+ const iv = this._jsonModel.minimum || this._jsonModel.default || 0;
3647
+ const fIVal = iv * factor;
3648
+ const qt = (fVal - fIVal) / fStep;
3649
+ const valid = Math.abs(fVal - fIVal) % fStep < .001;
3650
+ let next, prev;
3651
+ if (!valid) {
3652
+ next = (Math.ceil(qt) * fStep + fIVal) / factor;
3653
+ prev = (next - fStep) / factor;
3654
+ }
3655
+ return {
3656
+ valid,
3657
+ next,
3658
+ prev
3659
+ };
3660
+ }
3661
+ return {
3662
+ valid: true
3663
+ };
3664
+ }
3665
+ checkValidationExpression() {
3666
+ const validationExp = this._jsonModel.validationExpression;
3667
+ if (typeof validationExp === 'string' && validationExp.length !== 0) {
3668
+ return this.executeExpression(validationExp);
3669
+ }
3670
+ return true;
3671
+ }
3672
+ getConstraints() {
3673
+ switch (this.type) {
3674
+ case 'string':
3675
+ switch (this.format) {
3676
+ case 'date':
3677
+ return ValidConstraints.date;
3678
+ case 'email':
3679
+ return ValidConstraints.email;
3680
+ case 'binary':
3681
+ return ValidConstraints.file;
3682
+ case 'data-url':
3683
+ return ValidConstraints.file;
3684
+ default:
3685
+ return ValidConstraints.string;
3686
+ }
3687
+ case 'file':
3688
+ return ValidConstraints.file;
3689
+ case 'number':
3690
+ case 'integer':
3691
+ return ValidConstraints.number;
3692
+ }
3693
+ if (this.isArrayType()) {
3694
+ return ValidConstraints.array;
3695
+ }
3696
+ return [];
3697
+ }
3698
+ get format() {
3699
+ if (typeof this._jsonModel.format === 'undefined') {
3700
+ if (this.type === 'string') {
3701
+ switch (this.fieldType) {
3702
+ case 'date-input':
3703
+ this._jsonModel.format = 'date';
3704
+ break;
3705
+ case 'file-input':
3706
+ this._jsonModel.format = 'data-url';
3707
+ break;
3708
+ }
3709
+ }
3710
+ }
3711
+ return this._jsonModel.format;
3712
+ }
3713
+ get enforceEnum() {
3714
+ return this._jsonModel.enforceEnum;
3715
+ }
3716
+ get tooltip() {
3717
+ return this._jsonModel.tooltip;
3718
+ }
3719
+ get maxLength() {
3720
+ return this._jsonModel.maxLength;
3721
+ }
3722
+ get minLength() {
3723
+ return this._jsonModel.minLength;
3724
+ }
3725
+ get pattern() {
3726
+ return this._jsonModel.pattern;
3727
+ }
3728
+ get step() {
3729
+ if (this.type === 'number' || this.format === 'date') {
3730
+ return this._jsonModel.step;
3731
+ }
3732
+ }
3733
+ get exclusiveMinimum() {
3734
+ if (this.type === 'number' || this.format === 'date' || this.type === 'integer') {
3735
+ return this._jsonModel.exclusiveMinimum;
3736
+ }
3737
+ }
3738
+ set exclusiveMinimum(eM) {
3739
+ if (this.type === 'number' || this.format === 'date' || this.type === 'integer') {
3740
+ this._jsonModel.exclusiveMinimum = eM;
3741
+ }
3742
+ }
3743
+ get exclusiveMaximum() {
3744
+ if (this.type === 'number' || this.format === 'date' || this.type === 'integer') {
3745
+ return this._jsonModel.exclusiveMaximum;
3746
+ }
3747
+ }
3748
+ set exclusiveMaximum(eM) {
3749
+ if (this.type === 'number' || this.format === 'date' || this.type === 'integer') {
3750
+ this._jsonModel.exclusiveMaximum = eM;
3751
+ }
3752
+ }
3753
+ get default() {
3754
+ return this._jsonModel.default;
3755
+ }
3756
+ isNotEmpty(value) {
3757
+ return value != null && value !== '';
3758
+ }
3759
+ evaluateConstraints() {
3760
+ let constraint = 'type';
3761
+ const elem = this._jsonModel;
3762
+ const value = this._jsonModel.value;
3763
+ const Constraints = this._getConstraintObject();
3764
+ const supportedConstraints = this.getConstraints();
3765
+ let valid = true;
3766
+ if (valid) {
3767
+ valid = Constraints.required(this.required, value).valid &&
3768
+ (this.isArrayType() && this.required ? value.length > 0 : true);
3769
+ constraint = 'required';
3770
+ }
3771
+ if (valid && this.isNotEmpty(value)) {
3772
+ const invalidConstraint = supportedConstraints.find(key => {
3773
+ if (key in elem && elem[key] !== undefined) {
3774
+ const restriction = elem[key];
3775
+ const fn = Constraints[key];
3776
+ if (value instanceof Array && this.isArrayType()) {
3777
+ if (ValidConstraints.array.indexOf(key) !== -1) {
3778
+ return !fn(restriction, value).valid;
3779
+ }
3780
+ else {
3781
+ return value.some(x => !(fn(restriction, x).valid));
3782
+ }
3783
+ }
3784
+ else if (typeof fn === 'function') {
3785
+ return !fn(restriction, value).valid;
3786
+ }
3787
+ else {
3788
+ return false;
3789
+ }
3790
+ }
3791
+ else {
3792
+ return false;
3793
+ }
3794
+ });
3795
+ if (invalidConstraint != null) {
3796
+ valid = false;
3797
+ constraint = invalidConstraint;
3798
+ }
3799
+ else {
3800
+ valid = this.checkEnum(value, Constraints);
3801
+ constraint = 'enum';
3802
+ if (valid && this.type === 'number') {
3803
+ valid = this.checkStep().valid;
3804
+ constraint = 'step';
3805
+ }
3806
+ if (valid) {
3807
+ valid = this.checkValidationExpression();
3808
+ constraint = 'validationExpression';
3809
+ }
3810
+ }
3811
+ }
3812
+ if (!valid) {
3813
+ this.form.logger.info(`${constraint} constraint evaluation failed ${this._jsonModel[constraint]}. Received ${this._jsonModel.value}`);
3814
+ }
3815
+ const changes = {
3816
+ 'valid': valid,
3817
+ 'errorMessage': valid ? '' : this.getErrorMessage(constraint),
3818
+ ...({
3819
+ 'validationMessage': valid ? '' : this.getErrorMessage(constraint),
3820
+ 'validity': {
3821
+ valid,
3822
+ ...(valid ? {} : { [constraintKeys[constraint]]: true })
3823
+ }
3824
+ })
3825
+ };
3826
+ return this._applyUpdates(['valid', 'errorMessage', 'validationMessage', 'validity'], changes);
3827
+ }
3828
+ triggerValidationEvent(changes) {
3829
+ if (changes.validity) {
3830
+ if (this.validity.valid) {
3831
+ this.dispatch(new Valid());
3832
+ }
3833
+ else {
3834
+ this.dispatch(new Invalid());
3835
+ }
3836
+ }
3837
+ }
3838
+ validate() {
3839
+ if (this.visible === false) {
3840
+ return [];
3841
+ }
3842
+ const changes = this.evaluateConstraints();
3843
+ if (changes.validity) {
3844
+ this.triggerValidationEvent(changes);
3845
+ this.notifyDependents(new Change({ changes: Object.values(changes) }));
3846
+ }
3847
+ return this.valid ? [] : [new ValidationError(this.id, [this._jsonModel.errorMessage])];
3848
+ }
3849
+ importData(contextualDataModel) {
3850
+ this._bindToDataModel(contextualDataModel);
3851
+ const dataNode = this.getDataNode();
3852
+ if (dataNode !== undefined && dataNode !== NullDataValue && dataNode.$value !== this._jsonModel.value) {
3853
+ const changeAction = propertyChange('value', dataNode.$value, this._jsonModel.value);
3854
+ this._jsonModel.value = dataNode.$value;
3855
+ this.queueEvent(changeAction);
3856
+ }
3857
+ }
3858
+ defaultDataModel(name) {
3859
+ const value = staticFields.indexOf(this.fieldType) > -1 ? undefined : this.getDataNodeValue(this._jsonModel.value);
3860
+ return new DataValue(name, value, this.type || 'string');
3861
+ }
3862
+ getState(isRepeatableChild = false, forRestore = false) {
3863
+ return {
3864
+ ...super.getState(forRestore),
3865
+ editFormat: this.editFormat,
3866
+ displayFormat: this.displayFormat,
3867
+ editValue: this.editValue,
3868
+ displayValue: this.displayValue,
3869
+ enabled: this.enabled,
3870
+ readOnly: this.readOnly
3871
+ };
3872
+ }
3873
+ markAsInvalid(message, constraint = null) {
3874
+ const changes = {
3875
+ 'valid': false,
3876
+ 'errorMessage': message,
3877
+ 'validationMessage': message,
3878
+ 'validity': {
3879
+ valid: false,
3880
+ ...(constraint != null ? { [constraintKeys[constraint]]: true } : {})
3881
+ }
3882
+ };
3883
+ const updates = this._applyUpdates(['valid', 'errorMessage', 'validationMessage', 'validity'], changes);
3884
+ const changeAction = new Change({ changes: [].concat(Object.values(updates)) });
3885
+ if (changeAction.payload.changes.length !== 0) {
3886
+ this.triggerValidationEvent(updates);
3887
+ this.dispatch(changeAction);
3888
+ }
3889
+ }
3890
+ }
3891
+ __decorate([
3892
+ dependencyTracked(),
3893
+ exclude('button', 'image', 'plain-text')
3894
+ ], Field.prototype, "readOnly", null);
3895
+ __decorate([
3896
+ dependencyTracked(),
3897
+ exclude('image', 'plain-text')
3898
+ ], Field.prototype, "enabled", null);
3899
+ __decorate([
3900
+ dependencyTracked()
3901
+ ], Field.prototype, "valid", null);
3902
+ __decorate([
3903
+ dependencyTracked()
3904
+ ], Field.prototype, "validity", null);
3905
+ __decorate([
3906
+ dependencyTracked()
3907
+ ], Field.prototype, "enum", null);
3908
+ __decorate([
3909
+ dependencyTracked()
3910
+ ], Field.prototype, "enumNames", null);
3911
+ __decorate([
3912
+ dependencyTracked()
3913
+ ], Field.prototype, "required", null);
3914
+ __decorate([
3915
+ include('date-input', 'number-input')
3916
+ ], Field.prototype, "editValue", null);
3917
+ __decorate([
3918
+ dependencyTracked()
3919
+ ], Field.prototype, "value", null);
3920
+ __decorate([
3921
+ dependencyTracked()
3922
+ ], Field.prototype, "errorMessage", null);
3923
+ __decorate([
3924
+ include('text-input', 'date-input', 'file-input', 'email')
3925
+ ], Field.prototype, "format", null);
3926
+ __decorate([
3927
+ include('text-input')
3928
+ ], Field.prototype, "maxLength", null);
3929
+ __decorate([
3930
+ include('text-input')
3931
+ ], Field.prototype, "minLength", null);
3932
+ __decorate([
3933
+ include('text-input')
3934
+ ], Field.prototype, "pattern", null);
3935
+ __decorate([
3936
+ dependencyTracked()
3937
+ ], Field.prototype, "exclusiveMinimum", null);
3938
+ __decorate([
3939
+ dependencyTracked()
3940
+ ], Field.prototype, "exclusiveMaximum", null);
3941
+
3942
+ function addNameToDataURL(dataURL, name) {
3943
+ return dataURL.replace(';base64', `;name=${encodeURIComponent(name)};base64`);
3944
+ }
3945
+ function processFiles(files) {
3946
+ return Promise.all([].map.call(files, processFile));
3947
+ }
3948
+ async function processFile(file) {
3949
+ const { name, size, type } = file;
3950
+ const fileObj = await new Promise((resolve, reject) => {
3951
+ const reader = new FileReader();
3952
+ reader.onload = event => {
3953
+ resolve(new FileObject({
3954
+ data: addNameToDataURL(event.target.result, name),
3955
+ type,
3956
+ name,
3957
+ size
3958
+ }));
3959
+ };
3960
+ reader.readAsDataURL(file.data);
3961
+ });
3962
+ return fileObj;
3963
+ }
3964
+ class FileUpload extends Field {
3965
+ _getDefaults() {
3966
+ return {
3967
+ ...super._getDefaults(),
3968
+ accept: ['audio/*', 'video/*', 'image/*', 'text/*', 'application/pdf'],
3969
+ maxFileSize: '2MB'
3970
+ };
3971
+ }
3972
+ _getFallbackType() {
3973
+ return 'file';
3974
+ }
3975
+ get maxFileSize() {
3976
+ return getFileSizeInBytes(this._jsonModel.maxFileSize);
3977
+ }
3978
+ get accept() {
3979
+ return this._jsonModel.accept;
3980
+ }
3981
+ _applyUpdates(propNames, updates) {
3982
+ return propNames.reduce((acc, propertyName) => {
3983
+ const prevValue = this._jsonModel[propertyName];
3984
+ const currentValue = updates[propertyName];
3985
+ if (currentValue !== prevValue) {
3986
+ acc[propertyName] = {
3987
+ propertyName,
3988
+ currentValue,
3989
+ prevValue
3990
+ };
3991
+ if (prevValue instanceof FileObject && typeof currentValue === 'object' && propertyName === 'value') {
3992
+ this._jsonModel[propertyName] = new FileObject({ ...prevValue, ...{ 'data': currentValue.data } });
3993
+ }
3994
+ else {
3995
+ this._jsonModel[propertyName] = currentValue;
3996
+ }
3997
+ }
3998
+ return acc;
3999
+ }, {});
4000
+ }
4001
+ getInternalType() {
4002
+ return this.type?.endsWith('[]') ? 'file[]' : 'file';
4003
+ }
4004
+ getDataNodeValue(typedValue) {
4005
+ let dataNodeValue = typedValue;
4006
+ if (dataNodeValue != null) {
4007
+ if (this.type === 'string') {
4008
+ dataNodeValue = dataNodeValue.data?.toString();
4009
+ }
4010
+ else if (this.type === 'string[]') {
4011
+ dataNodeValue = dataNodeValue instanceof Array ? dataNodeValue : [dataNodeValue];
4012
+ dataNodeValue = dataNodeValue.map((_) => _?.data?.toString());
4013
+ }
4014
+ }
4015
+ return dataNodeValue;
4016
+ }
4017
+ async _serialize() {
4018
+ const val = this._jsonModel.value;
4019
+ if (val === undefined) {
4020
+ return null;
4021
+ }
4022
+ const filesInfo = await processFiles(val instanceof Array ? val : [val]);
4023
+ return filesInfo;
4024
+ }
4025
+ importData(dataModel) {
4026
+ this._bindToDataModel(dataModel);
4027
+ const dataNode = this.getDataNode();
4028
+ if (dataNode !== undefined && dataNode !== NullDataValue) {
4029
+ const value = dataNode?.$value;
4030
+ if (value != null) {
4031
+ const res = Constraints.type(this.getInternalType(), value);
4032
+ if (!res.valid) {
4033
+ this.form.logger.debug(`unable to bind ${this.name} to data`);
4034
+ }
4035
+ this.form.getEventQueue().queue(this, propertyChange('value', res.value, this._jsonModel.value));
4036
+ this._jsonModel.value = res.value;
4037
+ }
4038
+ else {
4039
+ this._jsonModel.value = null;
4040
+ }
4041
+ }
4042
+ }
4043
+ }
4044
+
4045
+ const requiredConstraint = (offValue) => (constraint, value) => {
4046
+ const valid = Constraints.required(constraint, value).valid && (!constraint || value != offValue);
4047
+ return { valid, value };
4048
+ };
4049
+ class Checkbox extends Field {
4050
+ offValue() {
4051
+ const opts = this.enum;
4052
+ return opts.length > 1 ? opts[1] : null;
4053
+ }
4054
+ _getConstraintObject() {
4055
+ const baseConstraints = { ...super._getConstraintObject() };
4056
+ baseConstraints.required = requiredConstraint(this.offValue());
4057
+ return baseConstraints;
4058
+ }
4059
+ _getDefaults() {
4060
+ return {
4061
+ ...super._getDefaults(),
4062
+ enforceEnum: true
4063
+ };
4064
+ }
4065
+ get enum() {
4066
+ return this._jsonModel.enum || [];
4067
+ }
4068
+ }
4069
+
4070
+ class CheckboxGroup extends Field {
4071
+ constructor(params, _options) {
4072
+ super(params, _options);
4073
+ }
4074
+ _getFallbackType() {
4075
+ const fallbackType = super._getFallbackType();
4076
+ if (typeof fallbackType === 'string') {
4077
+ return `${fallbackType}[]`;
4078
+ }
4079
+ else {
4080
+ return 'string[]';
4081
+ }
4082
+ }
4083
+ _getDefaults() {
4084
+ return {
4085
+ ...super._getDefaults(),
4086
+ enforceEnum: true,
4087
+ enum: []
4088
+ };
4089
+ }
4090
+ }
4091
+
4092
+ class DateField extends Field {
4093
+ locale;
4094
+ _dataFormat = 'yyyy-MM-dd';
4095
+ _applyDefaults() {
4096
+ super._applyDefaults();
4097
+ this.locale = new Intl.DateTimeFormat().resolvedOptions().locale;
4098
+ if (!this._jsonModel.editFormat) {
4099
+ this._jsonModel.editFormat = 'short';
4100
+ }
4101
+ if (!this._jsonModel.displayFormat) {
4102
+ this._jsonModel.displayFormat = this._jsonModel.editFormat;
4103
+ }
4104
+ if (!this._jsonModel.placeholder) {
4105
+ this._jsonModel.placeholder = parseDateSkeleton(this._jsonModel.editFormat, this.locale);
4106
+ }
4107
+ if (!this._jsonModel.description) {
4108
+ this._jsonModel.description = `To enter today's date use ${formatDate(new Date(), this.locale, this._jsonModel.editFormat)}`;
4109
+ }
4110
+ }
4111
+ get value() {
4112
+ return super.value;
4113
+ }
4114
+ set value(value) {
4115
+ if (typeof value === 'number') {
4116
+ const coercedValue = numberToDatetime(value);
4117
+ if (!isNaN(coercedValue)) {
4118
+ super.value = formatDate(coercedValue, this.locale, this._dataFormat);
4119
+ }
4120
+ }
4121
+ else {
4122
+ super.value = value;
4123
+ }
4124
+ }
4125
+ }
4126
+
4127
+ class EmailInput extends Field {
4128
+ _getDefaults() {
4129
+ return {
4130
+ ...super._getDefaults(),
4131
+ format: 'email'
4132
+ };
4133
+ }
4134
+ }
4135
+
4136
+ class Captcha extends Field {
4137
+ getDataNode() {
4138
+ return undefined;
4139
+ }
4140
+ }
4141
+
4142
+ const alternateFieldTypeMapping = {
4143
+ 'text': 'text-input',
4144
+ 'number': 'number-input',
4145
+ 'email': 'email',
4146
+ 'file': 'file-input',
4147
+ 'range': 'range',
4148
+ 'textarea': 'multiline-input'
4149
+ };
4150
+ class FormFieldFactoryImpl {
4151
+ createField(child, _options) {
4152
+ let retVal;
4153
+ const options = {
4154
+ ..._options,
4155
+ fieldFactory: this
4156
+ };
4157
+ child.fieldType = child.fieldType ? (child.fieldType in alternateFieldTypeMapping ?
4158
+ alternateFieldTypeMapping[child.fieldType] : child.fieldType)
4159
+ : 'text-input';
4160
+ if (isRepeatable$1(child)) {
4161
+ const newChild = {
4162
+ ...child,
4163
+ ...('items' in child && { 'type': 'object' }),
4164
+ minOccur: undefined,
4165
+ maxOccur: undefined,
4166
+ repeatable: undefined,
4167
+ name: undefined
4168
+ };
4169
+ const newJson = {
4170
+ ...{
4171
+ minItems: child.minOccur || 0,
4172
+ maxItems: child.maxOccur || -1,
4173
+ fieldType: child.fieldType,
4174
+ type: 'array',
4175
+ name: child.name,
4176
+ dataRef: child.dataRef
4177
+ },
4178
+ ...{
4179
+ 'items': [newChild]
4180
+ }
4181
+ };
4182
+ retVal = new InstanceManager(newJson, options);
4183
+ }
4184
+ else if ('items' in child) {
4185
+ retVal = new Fieldset(child, options);
4186
+ }
4187
+ else {
4188
+ if (isFile(child) || child.fieldType === 'file-input') {
4189
+ retVal = new FileUpload(child, options);
4190
+ }
4191
+ else if (isCheckbox(child)) {
4192
+ retVal = new Checkbox(child, options);
4193
+ }
4194
+ else if (isCheckboxGroup(child)) {
4195
+ retVal = new CheckboxGroup(child, options);
4196
+ }
4197
+ else if (isEmailInput(child)) {
4198
+ retVal = new EmailInput(child, options);
4199
+ }
4200
+ else if (isDateField(child)) {
4201
+ retVal = new DateField(child, options);
4202
+ }
4203
+ else if (isCaptcha(child)) {
4204
+ retVal = new Captcha(child, options);
4205
+ }
4206
+ else {
4207
+ retVal = new Field(child, options);
4208
+ }
4209
+ }
4210
+ return retVal;
4211
+ }
4212
+ }
4213
+ const FormFieldFactory = new FormFieldFactoryImpl();
4214
+
4215
+ const createFormInstance = (formModel, callback, logLevel = 'error', fModel = undefined) => {
4216
+ try {
4217
+ let f = fModel;
4218
+ if (f == null) {
4219
+ formModel = sitesModelToFormModel(formModel);
4220
+ f = new Form({ ...formModel }, FormFieldFactory, new RuleEngine(), new EventQueue(new Logger(logLevel)), logLevel);
4221
+ }
4222
+ const formData = formModel?.data;
4223
+ if (formData) {
4224
+ f.importData(formData);
4225
+ }
4226
+ if (typeof callback === 'function') {
4227
+ callback(f);
4228
+ }
4229
+ f.getEventQueue().runPendingQueue();
4230
+ return f;
4231
+ }
4232
+ catch (e) {
4233
+ console.error(`Unable to create an instance of the Form ${e}`);
4234
+ throw new Error(e);
4235
+ }
4236
+ };
4237
+ const defaultOptions = {
4238
+ logLevel: 'error'
4239
+ };
4240
+ const restoreFormInstance = (formModel, { logLevel } = defaultOptions) => {
4241
+ try {
4242
+ const form = new Form({ ...formModel }, FormFieldFactory, new RuleEngine(), new EventQueue(new Logger(logLevel)), logLevel, 'restore');
4243
+ form.getEventQueue().empty();
4244
+ return form;
4245
+ }
4246
+ catch (e) {
4247
+ console.error(`Unable to restore an instance of the Form ${e}`);
4248
+ throw new Error(e);
4249
+ }
4250
+ };
4251
+ const validateFormInstance = (formModel, data) => {
4252
+ try {
4253
+ const f = new Form({ ...formModel }, FormFieldFactory, new RuleEngine());
4254
+ if (data) {
4255
+ f.importData(data);
4256
+ }
4257
+ return f.validate().length === 0;
4258
+ }
4259
+ catch (e) {
4260
+ throw new Error(e);
4261
+ }
4262
+ };
4263
+ const validateFormData = (formModel, data) => {
4264
+ try {
4265
+ const f = new Form({ ...formModel }, FormFieldFactory, new RuleEngine());
4266
+ if (data) {
4267
+ f.importData(data);
4268
+ }
4269
+ const res = f.validate();
4270
+ return {
4271
+ messages: res,
4272
+ valid: res.length === 0
4273
+ };
4274
+ }
4275
+ catch (e) {
4276
+ throw new Error(e);
4277
+ }
4278
+ };
4279
+ const fetchForm = (url, headers = {}) => {
4280
+ const headerObj = new Headers();
4281
+ Object.entries(headers).forEach(([key, value]) => {
4282
+ headerObj.append(key, value);
4283
+ });
4284
+ return new Promise((resolve, reject) => {
4285
+ request$1(`${url}.model.json`, null, { headers }).then((response) => {
4286
+ if (response.status !== 200) {
4287
+ reject('Not Found');
4288
+ }
4289
+ else {
4290
+ let formObj = response.body;
4291
+ if ('model' in formObj) {
4292
+ const { model } = formObj;
4293
+ formObj = model;
4294
+ }
4295
+ resolve(jsonString(formObj));
4296
+ }
4297
+ });
4298
+ });
4299
+ };
4300
+ const registerFunctions = (functions) => {
4301
+ FunctionRuntime.registerFunctions(functions);
4302
+ };
4303
+
4304
+ export { createFormInstance, fetchForm, registerFunctions, restoreFormInstance, validateFormData, validateFormInstance };