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

Sign up to get free protection for your applications and to get access to all the features.
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 +8 -2
  33. package/lib/cjs/utils/Evaluator.js +11 -13
  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 +8 -2
  55. package/lib/mjs/utils/Evaluator.js +9 -13
  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.46",
4
4
  "description": "JavaScript powered Forms with JSON Form Builder",
5
5
  "main": "lib/cjs/index.js",
6
6
  "exports": {