@formio/js 5.0.0-rc.45 → 5.0.0-rc.47

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 (60) hide show
  1. package/dist/formio.embed.js +1 -1
  2. package/dist/formio.embed.min.js +1 -1
  3. package/dist/formio.embed.min.js.LICENSE.txt +1 -1
  4. package/dist/formio.form.js +6 -476
  5. package/dist/formio.form.min.js +1 -1
  6. package/dist/formio.form.min.js.LICENSE.txt +1 -1
  7. package/dist/formio.full.js +6 -186
  8. package/dist/formio.full.min.js +1 -1
  9. package/dist/formio.full.min.js.LICENSE.txt +1 -1
  10. package/dist/formio.js +2 -2
  11. package/dist/formio.min.js +1 -1
  12. package/dist/formio.min.js.LICENSE.txt +1 -1
  13. package/dist/formio.utils.js +1897 -429
  14. package/dist/formio.utils.min.js +1 -1
  15. package/dist/formio.utils.min.js.LICENSE.txt +9 -1
  16. package/lib/cjs/Webform.d.ts +2 -2
  17. package/lib/cjs/addons/PasswordStrength/PasswordStrengthAddon.d.ts +2 -2
  18. package/lib/cjs/addons/PasswordStrength/PasswordStrengthAddon.form.d.ts +2 -2
  19. package/lib/cjs/addons/index.d.ts +2 -2
  20. package/lib/cjs/components/Components.d.ts +3 -3
  21. package/lib/cjs/components/_classes/component/editForm/Component.edit.addons.d.ts +2 -2
  22. package/lib/cjs/components/_classes/component/editForm/Component.edit.conditional.d.ts +1 -1
  23. package/lib/cjs/components/_classes/component/editForm/Component.edit.data.d.ts +1 -1
  24. package/lib/cjs/components/_classes/component/editForm/Component.edit.validation.d.ts +1 -1
  25. package/lib/cjs/components/_classes/component/editForm/utils.d.ts +1 -1
  26. package/lib/cjs/components/datetime/editForm/DateTime.edit.date.d.ts +1 -1
  27. package/lib/cjs/components/editgrid/editForm/EditGrid.edit.templates.d.ts +1 -1
  28. package/lib/cjs/components/form/editForm/Form.edit.data.d.ts +1 -1
  29. package/lib/cjs/components/panel/editForm/Panel.edit.conditional.d.ts +1 -1
  30. package/lib/cjs/formio.form.d.ts +1 -0
  31. package/lib/cjs/formio.form.js +3 -1
  32. package/lib/cjs/utils/Evaluator.d.ts +7 -3
  33. package/lib/cjs/utils/Evaluator.js +12 -18
  34. package/lib/cjs/utils/formUtils.d.ts +38 -165
  35. package/lib/cjs/utils/formUtils.js +36 -566
  36. package/lib/cjs/utils/utils.d.ts +2 -2
  37. package/lib/cjs/utils/utils.js +9 -9
  38. package/lib/mjs/Webform.d.ts +2 -2
  39. package/lib/mjs/addons/PasswordStrength/PasswordStrengthAddon.d.ts +2 -2
  40. package/lib/mjs/addons/PasswordStrength/PasswordStrengthAddon.form.d.ts +2 -2
  41. package/lib/mjs/addons/index.d.ts +2 -2
  42. package/lib/mjs/components/Components.d.ts +3 -3
  43. package/lib/mjs/components/_classes/component/editForm/Component.edit.addons.d.ts +2 -2
  44. package/lib/mjs/components/_classes/component/editForm/Component.edit.conditional.d.ts +1 -1
  45. package/lib/mjs/components/_classes/component/editForm/Component.edit.data.d.ts +1 -1
  46. package/lib/mjs/components/_classes/component/editForm/Component.edit.validation.d.ts +1 -1
  47. package/lib/mjs/components/_classes/component/editForm/utils.d.ts +1 -1
  48. package/lib/mjs/components/datetime/editForm/DateTime.edit.date.d.ts +1 -1
  49. package/lib/mjs/components/editgrid/editForm/EditGrid.edit.templates.d.ts +1 -1
  50. package/lib/mjs/components/form/editForm/Form.edit.data.d.ts +1 -1
  51. package/lib/mjs/components/panel/editForm/Panel.edit.conditional.d.ts +1 -1
  52. package/lib/mjs/formio.form.d.ts +1 -0
  53. package/lib/mjs/formio.form.js +1 -0
  54. package/lib/mjs/utils/Evaluator.d.ts +7 -3
  55. package/lib/mjs/utils/Evaluator.js +10 -18
  56. package/lib/mjs/utils/formUtils.d.ts +38 -165
  57. package/lib/mjs/utils/formUtils.js +3 -550
  58. package/lib/mjs/utils/utils.d.ts +2 -2
  59. package/lib/mjs/utils/utils.js +1 -1
  60. package/package.json +1 -1
@@ -1,173 +1,5 @@
1
- import get from 'lodash/get';
2
- import set from 'lodash/set';
3
- import has from 'lodash/has';
4
- import clone from 'lodash/clone';
5
- import forOwn from 'lodash/forOwn';
6
- import isString from 'lodash/isString';
7
- import isNaN from 'lodash/isNaN';
8
- import isNil from 'lodash/isNil';
9
- import isPlainObject from 'lodash/isPlainObject';
10
- import round from 'lodash/round';
11
- import chunk from 'lodash/chunk';
12
- import pad from 'lodash/pad';
13
- import { compare, applyPatch } from 'fast-json-patch';
14
- import _ from 'lodash';
15
- import { fastCloneDeep } from './utils';
16
- /**
17
- * Determine if a component is a layout component or not.
18
- *
19
- * @param {Object} component
20
- * The component to check.
21
- *
22
- * @returns {Boolean}
23
- * Whether or not the component is a layout component.
24
- */
25
- export function isLayoutComponent(component) {
26
- return Boolean((component.columns && Array.isArray(component.columns)) ||
27
- (component.rows && Array.isArray(component.rows)) ||
28
- (component.components && Array.isArray(component.components)));
29
- }
30
- /**
31
- * Iterate through each component within a form.
32
- *
33
- * @param {Object} components
34
- * The components to iterate.
35
- * @param {Function} fn
36
- * The iteration function to invoke for each component.
37
- * @param {Boolean} includeAll
38
- * Whether or not to include layout components.
39
- * @param {String} path
40
- * The current data path of the element. Example: data.user.firstName
41
- * @param {Object} parent
42
- * The parent object.
43
- */
44
- export function eachComponent(components, fn, includeAll, path, parent, inRecursion) {
45
- if (!components)
46
- return;
47
- path = path || '';
48
- if (inRecursion) {
49
- if (components.noRecurse) {
50
- delete components.noRecurse;
51
- return;
52
- }
53
- components.noRecurse = true;
54
- }
55
- components.forEach((component) => {
56
- if (!component) {
57
- return;
58
- }
59
- const hasColumns = component.columns && Array.isArray(component.columns);
60
- const hasRows = component.rows && Array.isArray(component.rows);
61
- const hasComps = component.components && Array.isArray(component.components);
62
- let noRecurse = false;
63
- const newPath = component.key ? (path ? (`${path}.${component.key}`) : component.key) : '';
64
- // Keep track of parent references.
65
- if (parent) {
66
- // Ensure we don't create infinite JSON structures.
67
- component.parent = clone(parent);
68
- delete component.parent.components;
69
- delete component.parent.componentMap;
70
- delete component.parent.columns;
71
- delete component.parent.rows;
72
- }
73
- // there's no need to add other layout components here because we expect that those would either have columns, rows or components
74
- const layoutTypes = ['htmlelement', 'content'];
75
- const isLayoutComponent = hasColumns || hasRows || (hasComps && !component.input) || layoutTypes.indexOf(component.type) > -1;
76
- if (includeAll || component.tree || !isLayoutComponent) {
77
- noRecurse = fn(component, newPath, components);
78
- }
79
- const subPath = () => {
80
- if (component.key &&
81
- !['panel', 'table', 'well', 'columns', 'fieldset', 'tabs', 'form'].includes(component.type) &&
82
- (['datagrid', 'container', 'editgrid', 'address', 'dynamicWizard', 'datatable', 'tagpad'].includes(component.type) ||
83
- component.tree)) {
84
- return newPath;
85
- }
86
- else if (component.key &&
87
- component.type === 'form') {
88
- return `${newPath}.data`;
89
- }
90
- return path;
91
- };
92
- if (!noRecurse) {
93
- if (hasColumns) {
94
- component.columns.forEach((column) => eachComponent(column.components, fn, includeAll, subPath(), parent ? component : null), true);
95
- }
96
- else if (hasRows) {
97
- component.rows.forEach((row) => {
98
- if (Array.isArray(row)) {
99
- row.forEach((column) => eachComponent(column.components, fn, includeAll, subPath(), parent ? component : null), true);
100
- }
101
- });
102
- }
103
- else if (hasComps) {
104
- eachComponent(component.components, fn, includeAll, subPath(), parent ? component : null, true);
105
- }
106
- }
107
- });
108
- if (components.noRecurse) {
109
- delete components.noRecurse;
110
- }
111
- }
112
- /**
113
- * Matches if a component matches the query.
114
- *
115
- * @param component
116
- * @param query
117
- * @return {boolean}
118
- */
119
- export function matchComponent(component, query) {
120
- if (isString(query)) {
121
- return (component.key === query) || (component.path === query);
122
- }
123
- else {
124
- let matches = false;
125
- forOwn(query, (value, key) => {
126
- matches = (get(component, key) === value);
127
- if (!matches) {
128
- return false;
129
- }
130
- });
131
- return matches;
132
- }
133
- }
134
- /**
135
- * Get a component by its key
136
- *
137
- * @param {Object} components
138
- * The components to iterate.
139
- * @param {String|Object} key
140
- * The key of the component to get, or a query of the component to search.
141
- *
142
- * @returns {Object}
143
- * The component that matches the given key, or undefined if not found.
144
- */
145
- export function getComponent(components, key, includeAll) {
146
- let result;
147
- eachComponent(components, (component, path) => {
148
- if ((path === key) || (component.path === key)) {
149
- result = component;
150
- return true;
151
- }
152
- }, includeAll);
153
- return result;
154
- }
155
- /**
156
- * Finds a component provided a query of properties of that component.
157
- *
158
- * @param components
159
- * @param query
160
- * @return {*}
161
- */
162
- export function searchComponents(components, query) {
163
- const results = [];
164
- eachComponent(components, (component) => {
165
- if (matchComponent(component, query)) {
166
- results.push(component);
167
- }
168
- }, true);
169
- return results;
170
- }
1
+ import { Utils } from '@formio/core';
2
+ const { flattenComponents, guid, uniqueName, MODEL_TYPES, getModelType, getComponentAbsolutePath, getComponentPath, isComponentModelType, isComponentNestedDataType, componentPath, componentChildPath, eachComponentDataAsync, eachComponentData, getComponentKey, getContextualRowPath, getContextualRowData, componentInfo, eachComponent, eachComponentAsync, getComponentData, getComponentActualValue, isLayoutComponent, matchComponent, getComponent, searchComponents, removeComponent, hasCondition, parseFloatExt, formatAsCurrency, escapeRegExCharacters, getValue, getStrings, generateFormChange, applyFormChanges, findComponent, getEmptyValue, isComponentDataEmpty } = Utils;
171
3
  /**
172
4
  * Deprecated version of findComponents. Renamed to searchComponents.
173
5
  *
@@ -179,383 +11,4 @@ export function findComponents(components, query) {
179
11
  console.warn('formio.js/utils findComponents is deprecated. Use searchComponents instead.');
180
12
  return searchComponents(components, query);
181
13
  }
182
- /**
183
- * This function will find a component in a form and return the component AND THE PATH to the component in the form.
184
- * Path to the component is stored as an array of nested components and their indexes.The Path is being filled recursively
185
- * when you iterating through the nested structure.
186
- * If the component is not found the callback won't be called and function won't return anything.
187
- *
188
- * @param components
189
- * @param key
190
- * @param fn
191
- * @param path
192
- * @returns {*}
193
- */
194
- export function findComponent(components, key, path, fn) {
195
- if (!components)
196
- return;
197
- path = path || [];
198
- if (!key) {
199
- return fn(components);
200
- }
201
- components.forEach(function (component, index) {
202
- var newPath = path.slice();
203
- // Add an index of the component it iterates through in nested structure
204
- newPath.push(index);
205
- if (!component)
206
- return;
207
- if (component.hasOwnProperty('columns') && Array.isArray(component.columns)) {
208
- newPath.push('columns');
209
- component.columns.forEach(function (column, index) {
210
- var colPath = newPath.slice();
211
- colPath.push(index);
212
- colPath.push('components');
213
- findComponent(column.components, key, colPath, fn);
214
- });
215
- }
216
- if (component.hasOwnProperty('rows') && Array.isArray(component.rows)) {
217
- newPath.push('rows');
218
- component.rows.forEach(function (row, index) {
219
- var rowPath = newPath.slice();
220
- rowPath.push(index);
221
- row.forEach(function (column, index) {
222
- var colPath = rowPath.slice();
223
- colPath.push(index);
224
- colPath.push('components');
225
- findComponent(column.components, key, colPath, fn);
226
- });
227
- });
228
- }
229
- if (component.hasOwnProperty('components') && Array.isArray(component.components)) {
230
- newPath.push('components');
231
- findComponent(component.components, key, newPath, fn);
232
- }
233
- if (component.key === key) {
234
- //Final callback if the component is found
235
- fn(component, newPath, components);
236
- }
237
- });
238
- }
239
- /**
240
- * Remove a component by path.
241
- *
242
- * @param components
243
- * @param path
244
- */
245
- export function removeComponent(components, path) {
246
- // Using _.unset() leave a null value. Use Array splice instead.
247
- var index = path.pop();
248
- if (path.length !== 0) {
249
- components = get(components, path);
250
- }
251
- components.splice(index, 1);
252
- }
253
- export function generateFormChange(type, data) {
254
- let change;
255
- switch (type) {
256
- case 'add':
257
- change = {
258
- op: 'add',
259
- key: data.component.key,
260
- container: data.parent.key, // Parent component
261
- path: data.path, // Path to container within parent component.
262
- index: data.index, // Index of component in parent container.
263
- component: data.component
264
- };
265
- break;
266
- case 'edit':
267
- change = {
268
- op: 'edit',
269
- key: data.originalComponent.key,
270
- patches: compare(data.originalComponent, data.component)
271
- };
272
- // Don't save if nothing changed.
273
- if (!change.patches.length) {
274
- change = null;
275
- }
276
- break;
277
- case 'remove':
278
- change = {
279
- op: 'remove',
280
- key: data.component.key,
281
- };
282
- break;
283
- }
284
- return change;
285
- }
286
- export function applyFormChanges(form, changes) {
287
- const failed = [];
288
- changes.forEach(function (change) {
289
- var found = false;
290
- switch (change.op) {
291
- case 'add':
292
- var newComponent = change.component;
293
- // Find the container to set the component in.
294
- findComponent(form.components, change.container, null, function (parent) {
295
- if (!change.container) {
296
- parent = form;
297
- }
298
- // A move will first run an add so remove any existing components with matching key before inserting.
299
- findComponent(form.components, change.key, null, function (component, path) {
300
- // If found, use the existing component. (If someone else edited it, the changes would be here)
301
- newComponent = component;
302
- removeComponent(form.components, path);
303
- });
304
- found = true;
305
- var container = get(parent, change.path);
306
- container.splice(change.index, 0, newComponent);
307
- });
308
- break;
309
- case 'remove':
310
- findComponent(form.components, change.key, null, function (component, path) {
311
- found = true;
312
- const oldComponent = get(form.components, path);
313
- if (oldComponent.key !== component.key) {
314
- path.pop();
315
- }
316
- removeComponent(form.components, path);
317
- });
318
- break;
319
- case 'edit':
320
- findComponent(form.components, change.key, null, function (component, path) {
321
- found = true;
322
- try {
323
- const oldComponent = get(form.components, path);
324
- const newComponent = applyPatch(component, change.patches).newDocument;
325
- if (oldComponent.key !== newComponent.key) {
326
- path.pop();
327
- }
328
- set(form.components, path, newComponent);
329
- }
330
- catch (err) {
331
- failed.push(change);
332
- }
333
- });
334
- break;
335
- case 'move':
336
- break;
337
- }
338
- if (!found) {
339
- failed.push(change);
340
- }
341
- });
342
- return {
343
- form,
344
- failed
345
- };
346
- }
347
- /**
348
- * Flatten the form components for data manipulation.
349
- *
350
- * @param {Object} components
351
- * The components to iterate.
352
- * @param {Boolean} includeAll
353
- * Whether or not to include layout components.
354
- *
355
- * @returns {Object}
356
- * The flattened components map.
357
- */
358
- export function flattenComponents(components, includeAll = false) {
359
- const flattened = {};
360
- eachComponent(components, (component, path) => {
361
- flattened[path] = component;
362
- }, includeAll);
363
- return flattened;
364
- }
365
- /**
366
- * Returns if this component has a conditional statement.
367
- *
368
- * @param component - The component JSON schema.
369
- *
370
- * @returns {boolean} - TRUE - This component has a conditional, FALSE - No conditional provided.
371
- */
372
- export function hasCondition(component) {
373
- return Boolean((component.customConditional) ||
374
- (component.conditional && (component.conditional.when ||
375
- (_.some(component.conditional.conditions || [], (condition => condition.component && condition.operator))) ||
376
- component.conditional.json ||
377
- component.conditional.condition)));
378
- }
379
- /**
380
- * Extension of standard #parseFloat(value) function, that also clears input string.
381
- *
382
- * @param {any} value
383
- * The value to parse.
384
- *
385
- * @returns {Number}
386
- * Parsed value.
387
- */
388
- export function parseFloatExt(value) {
389
- return parseFloat(isString(value)
390
- ? value.replace(/[^\de.+-]/gi, '')
391
- : value);
392
- }
393
- /**
394
- * Formats provided value in way how Currency component uses it.
395
- *
396
- * @param {any} value
397
- * The value to format.
398
- *
399
- * @returns {String}
400
- * Value formatted for Currency component.
401
- */
402
- export function formatAsCurrency(value) {
403
- const parsedValue = parseFloatExt(value);
404
- if (isNaN(parsedValue)) {
405
- return '';
406
- }
407
- const parts = round(parsedValue, 2)
408
- .toString()
409
- .split('.');
410
- parts[0] = chunk(Array.from(parts[0]).reverse(), 3)
411
- .reverse()
412
- .map((part) => part
413
- .reverse()
414
- .join(''))
415
- .join(',');
416
- parts[1] = pad(parts[1], 2, '0');
417
- return parts.join('.');
418
- }
419
- /**
420
- * Escapes RegEx characters in provided String value.
421
- *
422
- * @param {String} value
423
- * String for escaping RegEx characters.
424
- * @returns {string}
425
- * String with escaped RegEx characters.
426
- */
427
- export function escapeRegExCharacters(value) {
428
- return value.replace(/[-[\]/{}()*+?.\\^$|]/g, '\\$&');
429
- }
430
- /**
431
- * Get the value for a component key, in the given submission.
432
- *
433
- * @param {Object} submission
434
- * A submission object to search.
435
- * @param {String} key
436
- * A for components API key to search for.
437
- */
438
- export function getValue(submission, key) {
439
- const search = (data) => {
440
- if (isPlainObject(data)) {
441
- if (has(data, key)) {
442
- return _.get(data, key);
443
- }
444
- let value = null;
445
- forOwn(data, (prop) => {
446
- const result = search(prop);
447
- if (!isNil(result)) {
448
- value = result;
449
- return false;
450
- }
451
- });
452
- return value;
453
- }
454
- else {
455
- return null;
456
- }
457
- };
458
- return search(submission.data);
459
- }
460
- /**
461
- * Iterate over all components in a form and get string values for translation.
462
- * @param form
463
- */
464
- export function getStrings(form) {
465
- const properties = ['label', 'title', 'legend', 'tooltip', 'description', 'placeholder', 'prefix', 'suffix', 'errorLabel', 'content', 'html'];
466
- const strings = [];
467
- eachComponent(form.components, component => {
468
- properties.forEach(property => {
469
- if (component.hasOwnProperty(property) && component[property]) {
470
- strings.push({
471
- key: component.key,
472
- type: component.type,
473
- property,
474
- string: component[property]
475
- });
476
- }
477
- });
478
- if ((!component.dataSrc || component.dataSrc === 'values') && component.hasOwnProperty('values') && Array.isArray(component.values) && component.values.length) {
479
- component.values.forEach((value, index) => {
480
- strings.push({
481
- key: component.key,
482
- property: `value[${index}].label`,
483
- string: component.values[index].label
484
- });
485
- });
486
- }
487
- // Hard coded values from Day component
488
- if (component.type === 'day') {
489
- [
490
- 'day',
491
- 'month',
492
- 'year',
493
- 'Day',
494
- 'Month',
495
- 'Year',
496
- 'january',
497
- 'february',
498
- 'march',
499
- 'april',
500
- 'may',
501
- 'june',
502
- 'july',
503
- 'august',
504
- 'september',
505
- 'october',
506
- 'november',
507
- 'december'
508
- ].forEach(string => {
509
- strings.push({
510
- key: component.key,
511
- property: 'day',
512
- string,
513
- });
514
- });
515
- if (component.fields.day.placeholder) {
516
- strings.push({
517
- key: component.key,
518
- property: 'fields.day.placeholder',
519
- string: component.fields.day.placeholder,
520
- });
521
- }
522
- if (component.fields.month.placeholder) {
523
- strings.push({
524
- key: component.key,
525
- property: 'fields.month.placeholder',
526
- string: component.fields.month.placeholder,
527
- });
528
- }
529
- if (component.fields.year.placeholder) {
530
- strings.push({
531
- key: component.key,
532
- property: 'fields.year.placeholder',
533
- string: component.fields.year.placeholder,
534
- });
535
- }
536
- }
537
- if (component.type === 'editgrid') {
538
- const string = component.addAnother || 'Add Another';
539
- if (component.addAnother) {
540
- strings.push({
541
- key: component.key,
542
- property: 'addAnother',
543
- string,
544
- });
545
- }
546
- }
547
- if (component.type === 'select') {
548
- [
549
- 'loading...',
550
- 'Type to search'
551
- ].forEach(string => {
552
- strings.push({
553
- key: component.key,
554
- property: 'select',
555
- string,
556
- });
557
- });
558
- }
559
- }, true);
560
- return strings;
561
- }
14
+ export { flattenComponents, guid, uniqueName, MODEL_TYPES, getModelType, getComponentAbsolutePath, getComponentPath, isComponentModelType, isComponentNestedDataType, componentPath, componentChildPath, eachComponentDataAsync, eachComponentData, getComponentKey, getContextualRowPath, getContextualRowData, componentInfo, eachComponent, eachComponentAsync, getComponentData, getComponentActualValue, isLayoutComponent, matchComponent, getComponent, searchComponents, removeComponent, hasCondition, parseFloatExt, formatAsCurrency, escapeRegExCharacters, getValue, getStrings, generateFormChange, applyFormChanges, findComponent, getEmptyValue, isComponentDataEmpty };
@@ -372,6 +372,6 @@ export namespace componentValueTypes {
372
372
  export function interpolateErrors(component: any, errors: FieldError[], interpolateFn: any): [];
373
373
  import jsonLogic from 'json-logic-js';
374
374
  import ConditionOperators from './conditionOperators';
375
- import Evaluator from './Evaluator';
376
- export const interpolate: (rawTemplate: any, data: any, _options: any) => any;
375
+ import { Evaluator } from './Evaluator';
376
+ export const interpolate: typeof Evaluator.interpolate;
377
377
  export { jsonLogic, ConditionOperators, Evaluator, _ };
@@ -7,7 +7,7 @@ import jtz from 'jstimezonedetect';
7
7
  import { lodashOperators } from './jsonlogic/operators';
8
8
  import dompurify from 'dompurify';
9
9
  import { getValue } from './formUtils';
10
- import Evaluator from './Evaluator';
10
+ import { Evaluator } from './Evaluator';
11
11
  import ConditionOperators from './conditionOperators';
12
12
  const interpolate = Evaluator.interpolate;
13
13
  const { fetch } = fetchPonyfill({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@formio/js",
3
- "version": "5.0.0-rc.45",
3
+ "version": "5.0.0-rc.47",
4
4
  "description": "JavaScript powered Forms with JSON Form Builder",
5
5
  "main": "lib/cjs/index.js",
6
6
  "exports": {