@formio/js 5.0.0-dev.5708.6c19568 → 5.0.0-dev.5711.e2e3657

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 (40) hide show
  1. package/Changelog.md +1 -0
  2. package/dist/formio.embed.js +1 -1
  3. package/dist/formio.embed.min.js +1 -1
  4. package/dist/formio.form.js +6 -102
  5. package/dist/formio.form.min.js +1 -1
  6. package/dist/formio.full.js +6 -6
  7. package/dist/formio.full.min.js +1 -1
  8. package/dist/formio.js +1 -1
  9. package/dist/formio.min.js +1 -1
  10. package/lib/cjs/CDN.d.ts +1 -0
  11. package/lib/cjs/CDN.js +1 -0
  12. package/lib/cjs/Webform.js +1 -3
  13. package/lib/cjs/components/_classes/component/Component.d.ts +1 -0
  14. package/lib/cjs/components/_classes/component/Component.js +18 -0
  15. package/lib/cjs/components/currency/Currency.d.ts +1 -0
  16. package/lib/cjs/components/datagrid/DataGrid.d.ts +2 -0
  17. package/lib/cjs/components/datagrid/DataGrid.js +38 -26
  18. package/lib/cjs/components/datamap/DataMap.js +2 -2
  19. package/lib/cjs/components/number/Number.d.ts +10 -1
  20. package/lib/cjs/components/number/Number.js +15 -6
  21. package/lib/cjs/components/number/fixtures/comp9.d.ts +18 -0
  22. package/lib/cjs/components/number/fixtures/comp9.js +21 -0
  23. package/lib/cjs/components/number/fixtures/index.d.ts +2 -1
  24. package/lib/cjs/components/number/fixtures/index.js +3 -1
  25. package/lib/mjs/CDN.d.ts +1 -0
  26. package/lib/mjs/CDN.js +1 -0
  27. package/lib/mjs/Webform.js +1 -3
  28. package/lib/mjs/components/_classes/component/Component.d.ts +1 -0
  29. package/lib/mjs/components/_classes/component/Component.js +7 -0
  30. package/lib/mjs/components/currency/Currency.d.ts +1 -0
  31. package/lib/mjs/components/datagrid/DataGrid.d.ts +2 -0
  32. package/lib/mjs/components/datagrid/DataGrid.js +37 -25
  33. package/lib/mjs/components/datamap/DataMap.js +1 -1
  34. package/lib/mjs/components/number/Number.d.ts +10 -1
  35. package/lib/mjs/components/number/Number.js +14 -5
  36. package/lib/mjs/components/number/fixtures/comp9.d.ts +18 -0
  37. package/lib/mjs/components/number/fixtures/comp9.js +19 -0
  38. package/lib/mjs/components/number/fixtures/index.d.ts +2 -1
  39. package/lib/mjs/components/number/fixtures/index.js +2 -1
  40. package/package.json +1 -1
package/lib/cjs/CDN.d.ts CHANGED
@@ -13,6 +13,7 @@ declare class CDN {
13
13
  bootswatch: string;
14
14
  'bootstrap-icons': string;
15
15
  ckeditor: string;
16
+ dragula: string;
16
17
  flatpickr: string;
17
18
  'flatpickr-formio': string;
18
19
  'font-awesome': string;
package/lib/cjs/CDN.js CHANGED
@@ -17,6 +17,7 @@ class CDN {
17
17
  'bootswatch': '5.3.3',
18
18
  'bootstrap-icons': '1.11.1',
19
19
  'ckeditor': '19.0.0',
20
+ 'dragula': '3.7.3',
20
21
  'flatpickr': '4.6.8',
21
22
  'flatpickr-formio': '4.6.13-formio.3',
22
23
  'font-awesome': '4.7.0',
@@ -17,7 +17,6 @@ const formUtils_1 = require("./utils/formUtils");
17
17
  if (typeof window !== 'undefined' && typeof window.global === 'undefined') {
18
18
  window.global = window;
19
19
  }
20
- const dragula_1 = __importDefault(require("dragula"));
21
20
  // Initialize the available forms.
22
21
  Formio_1.Formio.forms = {};
23
22
  // Allow people to register components.
@@ -314,7 +313,6 @@ class Webform extends NestedDataComponent_1.default {
314
313
  // Ensure the root is set to this component.
315
314
  this.root = this;
316
315
  this.localRoot = this;
317
- this.root.dragulaLib = dragula_1.default;
318
316
  }
319
317
  /* eslint-enable max-statements */
320
318
  get language() {
@@ -1132,7 +1130,7 @@ class Webform extends NestedDataComponent_1.default {
1132
1130
  });
1133
1131
  const displayedErrors = [];
1134
1132
  if (errors.length) {
1135
- errors = lodash_1.default.uniqBy(errors, (error) => error.message);
1133
+ errors = lodash_1.default.uniqBy(errors, (error) => { var _a, _b; return [error.message, (_a = error.component) === null || _a === void 0 ? void 0 : _a.id, (_b = error.context) === null || _b === void 0 ? void 0 : _b.path].join(); });
1136
1134
  const createListItem = (message, index) => {
1137
1135
  var _a, _b, _c;
1138
1136
  const err = errors[index];
@@ -830,6 +830,7 @@ declare class Component extends Element {
830
830
  quill: any;
831
831
  get shouldSanitizeValue(): boolean;
832
832
  addAce(element: any, settings: any, onChange: any): any;
833
+ getDragula(): Promise<any>;
833
834
  get tree(): any;
834
835
  /**
835
836
  * The empty value for this component.
@@ -22,6 +22,15 @@ var __importStar = (this && this.__importStar) || function (mod) {
22
22
  __setModuleDefault(result, mod);
23
23
  return result;
24
24
  };
25
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
26
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
27
+ return new (P || (P = Promise))(function (resolve, reject) {
28
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
29
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
30
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
31
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
32
+ });
33
+ };
25
34
  var __importDefault = (this && this.__importDefault) || function (mod) {
26
35
  return (mod && mod.__esModule) ? mod : { "default": mod };
27
36
  };
@@ -2374,6 +2383,15 @@ class Component extends Element_1.default {
2374
2383
  return editor;
2375
2384
  });
2376
2385
  }
2386
+ getDragula() {
2387
+ return __awaiter(this, void 0, void 0, function* () {
2388
+ return new Promise((resolve) => {
2389
+ return Formio_1.Formio.requireLibrary('dragula', 'dragula', `${Formio_1.Formio.cdn.dragula}/dragula.js`, true, (ready) => {
2390
+ return ready.then(resolve);
2391
+ });
2392
+ });
2393
+ });
2394
+ }
2377
2395
  get tree() {
2378
2396
  return this.component.tree || false;
2379
2397
  }
@@ -2,6 +2,7 @@ export default class CurrencyComponent extends NumberComponent {
2
2
  constructor(component: any, options: any, data: any);
3
3
  currencyPrefix: any;
4
4
  currencySuffix: any;
5
+ parseValue(value: any): string | null;
5
6
  addZerosAndFormatValue(value: any): any;
6
7
  stripPrefixSuffix(value: any): any;
7
8
  }
@@ -12,6 +12,7 @@ export default class DataGridComponent extends NestedArrayComponent {
12
12
  tabIndex: number;
13
13
  rows: any[] | undefined;
14
14
  columns: any[] | undefined;
15
+ dragulaReady: Promise<any> | undefined;
15
16
  visibleColumns: {} | undefined;
16
17
  set dataValue(value: any[]);
17
18
  get dataValue(): any[];
@@ -71,6 +72,7 @@ export default class DataGridComponent extends NestedArrayComponent {
71
72
  */
72
73
  reorderValues(valuesArr: any, oldPosition: number, newPosition: number, movedBelow: boolean | any): void;
73
74
  onReorder(element: any, _target: any, _source: any, sibling: any): void;
75
+ onCloned(el: any, original: any): void;
74
76
  focusOnNewRowElement(row: any): void;
75
77
  addRow(): void;
76
78
  updateComponentsRowIndex(components: any, rowIndex: any): void;
@@ -6,8 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  const lodash_1 = __importDefault(require("lodash"));
7
7
  const NestedArrayComponent_1 = __importDefault(require("../_classes/nestedarray/NestedArrayComponent"));
8
8
  const utils_1 = require("../../utils/utils");
9
- const Components_1 = require("../Components");
10
- const dragula_1 = __importDefault(require("dragula"));
9
+ const Components_1 = __importDefault(require("../Components"));
11
10
  class DataGridComponent extends NestedArrayComponent_1.default {
12
11
  static schema(...extend) {
13
12
  return NestedArrayComponent_1.default.schema({
@@ -44,6 +43,9 @@ class DataGridComponent extends NestedArrayComponent_1.default {
44
43
  if (this.initRows || !lodash_1.default.isEqual(this.dataValue, this.emptyValue)) {
45
44
  this.createRows(true);
46
45
  }
46
+ if (this.allowReorder) {
47
+ this.dragulaReady = this.getDragula();
48
+ }
47
49
  this.visibleColumns = {};
48
50
  this.prevHasAddButton = this.hasAddButton();
49
51
  this.checkColumns();
@@ -282,31 +284,25 @@ class DataGridComponent extends NestedArrayComponent_1.default {
282
284
  this.refs[`${this.datagridKey}-row`].forEach((row, index) => {
283
285
  row.dragInfo = { index };
284
286
  });
285
- this.dragula = (0, dragula_1.default)([this.refs[`${this.datagridKey}-tbody`]], {
286
- moves: (_draggedElement, _oldParent, clickedElement) => {
287
- const clickedElementKey = clickedElement.getAttribute('data-key');
288
- const oldParentKey = _oldParent.getAttribute('data-key');
289
- //Check if the clicked button belongs to that container, if false, it belongs to the nested container
290
- if (oldParentKey === clickedElementKey) {
291
- return clickedElement.classList.contains('formio-drag-button');
292
- }
287
+ this.dragulaReady.then((dragula) => {
288
+ // The drop event may call redraw twice which calls attach twice and because this block of code is asynchronous
289
+ // BOTH redraws may be called before this block of code runs (which causes this block of code to run twice sequentially).
290
+ // This causes two dragula() calls on the same container which breaks dragula. To fix this the return value must
291
+ // be saved in this.dragula and have its container contents reset if it exists
292
+ if (this.dragula && this.dragula.containers) {
293
+ this.dragula.containers = [];
293
294
  }
294
- }).on('drop', this.onReorder.bind(this));
295
- this.dragula.on('cloned', (el, original) => {
296
- if (el && el.children && original && original.children) {
297
- lodash_1.default.each(original.children, (child, index) => {
298
- const styles = getComputedStyle(child, null);
299
- if (styles.cssText !== '') {
300
- el.children[index].style.cssText = styles.cssText;
295
+ this.dragula = dragula([this.refs[`${this.datagridKey}-tbody`]], {
296
+ moves: (_draggedElement, _oldParent, clickedElement) => {
297
+ const clickedElementKey = clickedElement.getAttribute('data-key');
298
+ const oldParentKey = _oldParent.getAttribute('data-key');
299
+ //Check if the clicked button belongs to that container, if false, it belongs to the nested container
300
+ if (oldParentKey === clickedElementKey) {
301
+ return clickedElement.classList.contains('formio-drag-button');
301
302
  }
302
- else {
303
- const cssText = Object.values(styles).reduce((css, propertyName) => {
304
- return `${css}${propertyName}:${styles.getPropertyValue(propertyName)};`;
305
- }, '');
306
- el.children[index].style.cssText = cssText;
307
- }
308
- });
309
- }
303
+ }
304
+ }).on('drop', this.onReorder.bind(this))
305
+ .on('cloned', this.onCloned.bind(this));
310
306
  });
311
307
  }
312
308
  this.refs[`${this.datagridKey}-addRow`].forEach((addButton) => {
@@ -373,6 +369,22 @@ class DataGridComponent extends NestedArrayComponent_1.default {
373
369
  this.setValue(dataValue, { isReordered: true });
374
370
  this.rebuild();
375
371
  }
372
+ onCloned(el, original) {
373
+ if (el && el.children && original && original.children) {
374
+ lodash_1.default.each(original.children, (child, index) => {
375
+ const styles = getComputedStyle(child, null);
376
+ if (styles.cssText !== '') {
377
+ el.children[index].style.cssText = styles.cssText;
378
+ }
379
+ else {
380
+ const cssText = Object.values(styles).reduce((css, propertyName) => {
381
+ return `${css}${propertyName}:${styles.getPropertyValue(propertyName)};`;
382
+ }, '');
383
+ el.children[index].style.cssText = cssText;
384
+ }
385
+ });
386
+ }
387
+ }
376
388
  focusOnNewRowElement(row) {
377
389
  Object.keys(row).find((key) => {
378
390
  const element = row[key].element;
@@ -422,7 +434,7 @@ class DataGridComponent extends NestedArrayComponent_1.default {
422
434
  }
423
435
  component.rowIndex = rowIndex;
424
436
  component.row = `${rowIndex}-${colIndex}`;
425
- component.path = Components_1.Components.getComponentPath(component);
437
+ component.path = Components_1.default.getComponentPath(component);
426
438
  });
427
439
  }
428
440
  updateRowsComponents(rowIndex) {
@@ -8,7 +8,7 @@ const DataGrid_1 = __importDefault(require("../datagrid/DataGrid"));
8
8
  const lodash_1 = __importDefault(require("lodash"));
9
9
  const eventemitter3_1 = __importDefault(require("eventemitter3"));
10
10
  const utils_1 = require("../../utils/utils");
11
- const Components_1 = require("../Components");
11
+ const Components_1 = __importDefault(require("../Components"));
12
12
  class DataMapComponent extends DataGrid_1.default {
13
13
  static schema(...extend) {
14
14
  return Component_1.default.schema({
@@ -241,7 +241,7 @@ class DataMapComponent extends DataGrid_1.default {
241
241
  delete dataValue[key];
242
242
  const comp = components[this.valueKey];
243
243
  comp.component.key = newKey;
244
- comp.path = Components_1.Components.calculateComponentPath(comp);
244
+ comp.path = Components_1.default.calculateComponentPath(comp);
245
245
  key = newKey;
246
246
  });
247
247
  const valueComponent = lodash_1.default.clone(this.component.valueComponent);
@@ -31,7 +31,16 @@ export default class NumberComponent extends Input {
31
31
  setInputMask(input: any): void;
32
32
  getValueAt(index: any): number | null;
33
33
  setValueAt(index: any, value: any, flags?: {}): void;
34
- parseValue(input: any): number;
34
+ /**
35
+ * Converts a string to a floating point number, formats the number based on the parsed float function
36
+ * (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/parseFloat) and then returns the
37
+ * formatted number back as a string
38
+ * Example Input: "123.456,22"
39
+ * Example Output: "123456,22"
40
+ * @param {string | number} input the numeric string to parse
41
+ * @returns {string | null} a parsed string
42
+ */
43
+ parseValue(input: string | number): string | null;
35
44
  focus(): void;
36
45
  getMaskedValue(value: any): any;
37
46
  getValueAsString(value: any, options: any): any;
@@ -45,19 +45,19 @@ class NumberComponent extends Input_1.default {
45
45
  return (0, utils_1.getComponentSavedTypes)(schema) || [utils_1.componentValueTypes.number];
46
46
  }
47
47
  constructor(...args) {
48
- var _a, _b;
48
+ var _a, _b, _c;
49
49
  super(...args);
50
50
  const separators = (0, utils_1.getNumberSeparators)(this.options.language || navigator.language);
51
51
  this.decimalSeparator = this.options.decimalSeparator = this.component.decimalSymbol || this.options.decimalSeparator
52
52
  || ((_a = this.options.properties) === null || _a === void 0 ? void 0 : _a.decimalSeparator)
53
53
  || separators.decimalSeparator;
54
54
  if (this.component.delimiter) {
55
- if (this.options.hasOwnProperty('thousandsSeparator')) {
56
- console.warn("Property 'thousandsSeparator' is deprecated. Please use i18n to specify delimiter.");
57
- }
58
- this.delimiter = ((_b = this.options.properties) === null || _b === void 0 ? void 0 : _b.thousandsSeparator) || this.options.thousandsSeparator || separators.delimiter;
55
+ this.delimiter = this.component.thousandsSeparator || ((_b = this.options.properties) === null || _b === void 0 ? void 0 : _b.thousandsSeparator) || this.options.thousandsSeparator || separators.delimiter;
59
56
  }
60
57
  else {
58
+ if (this.component.thousandsSeparator || ((_c = this.options.properties) === null || _c === void 0 ? void 0 : _c.thousandsSeparator) || this.options.thousandsSeparator) {
59
+ console.warn('In order for thousands separator to work properly, you must set the delimiter to true in the component json');
60
+ }
61
61
  this.delimiter = '';
62
62
  }
63
63
  const requireDecimal = lodash_1.default.get(this.component, 'requireDecimal', false);
@@ -79,7 +79,7 @@ class NumberComponent extends Input_1.default {
79
79
  prefix: '',
80
80
  suffix: '',
81
81
  requireDecimal: lodash_1.default.get(this.component, 'requireDecimal', false),
82
- thousandsSeparatorSymbol: lodash_1.default.get(this.component, 'thousandsSeparator', this.delimiter),
82
+ thousandsSeparatorSymbol: this.delimiter || '',
83
83
  decimalSymbol: lodash_1.default.get(this.component, 'decimalSymbol', this.decimalSeparator),
84
84
  decimalLimit: lodash_1.default.get(this.component, 'decimalLimit', this.decimalLimit),
85
85
  allowNegative: lodash_1.default.get(this.component, 'allowNegative', true),
@@ -146,6 +146,15 @@ class NumberComponent extends Input_1.default {
146
146
  setValueAt(index, value, flags = {}) {
147
147
  return super.setValueAt(index, this.formatValue(this.parseValue(value)), flags);
148
148
  }
149
+ /**
150
+ * Converts a string to a floating point number, formats the number based on the parsed float function
151
+ * (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/parseFloat) and then returns the
152
+ * formatted number back as a string
153
+ * Example Input: "123.456,22"
154
+ * Example Output: "123456,22"
155
+ * @param {string | number} input the numeric string to parse
156
+ * @returns {string | null} a parsed string
157
+ */
149
158
  parseValue(input) {
150
159
  if (typeof input === 'string') {
151
160
  input = input.split(this.delimiter).join('').replace(this.decimalSeparator, '.');
@@ -0,0 +1,18 @@
1
+ declare namespace _default {
2
+ let components: {
3
+ label: string;
4
+ applyMaskOn: string;
5
+ mask: boolean;
6
+ tableView: boolean;
7
+ delimiter: boolean;
8
+ requireDecimal: boolean;
9
+ inputFormat: string;
10
+ truncateMultipleSpaces: boolean;
11
+ key: string;
12
+ type: string;
13
+ input: boolean;
14
+ decimalSymbol: string;
15
+ thousandsSeparator: string;
16
+ }[];
17
+ }
18
+ export default _default;
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.default = {
4
+ components: [
5
+ {
6
+ "label": "Number",
7
+ "applyMaskOn": "change",
8
+ "mask": false,
9
+ "tableView": false,
10
+ "delimiter": true,
11
+ "requireDecimal": false,
12
+ "inputFormat": "plain",
13
+ "truncateMultipleSpaces": false,
14
+ "key": "number",
15
+ "type": "number",
16
+ "input": true,
17
+ "decimalSymbol": ",",
18
+ "thousandsSeparator": "."
19
+ }
20
+ ]
21
+ };
@@ -6,4 +6,5 @@ import comp5 from './comp5';
6
6
  import comp6 from './comp6';
7
7
  import comp7 from './comp7';
8
8
  import comp8 from './comp8';
9
- export { comp1, comp2, comp3, comp4, comp5, comp6, comp7, comp8 };
9
+ import comp9 from './comp9';
10
+ export { comp1, comp2, comp3, comp4, comp5, comp6, comp7, comp8, comp9 };
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.comp8 = exports.comp7 = exports.comp6 = exports.comp5 = exports.comp4 = exports.comp3 = exports.comp2 = exports.comp1 = void 0;
6
+ exports.comp9 = exports.comp8 = exports.comp7 = exports.comp6 = exports.comp5 = exports.comp4 = exports.comp3 = exports.comp2 = exports.comp1 = void 0;
7
7
  const comp1_1 = __importDefault(require("./comp1"));
8
8
  exports.comp1 = comp1_1.default;
9
9
  const comp2_1 = __importDefault(require("./comp2"));
@@ -20,3 +20,5 @@ const comp7_1 = __importDefault(require("./comp7"));
20
20
  exports.comp7 = comp7_1.default;
21
21
  const comp8_1 = __importDefault(require("./comp8"));
22
22
  exports.comp8 = comp8_1.default;
23
+ const comp9_1 = __importDefault(require("./comp9"));
24
+ exports.comp9 = comp9_1.default;
package/lib/mjs/CDN.d.ts CHANGED
@@ -13,6 +13,7 @@ declare class CDN {
13
13
  bootswatch: string;
14
14
  'bootstrap-icons': string;
15
15
  ckeditor: string;
16
+ dragula: string;
16
17
  flatpickr: string;
17
18
  'flatpickr-formio': string;
18
19
  'font-awesome': string;
package/lib/mjs/CDN.js CHANGED
@@ -16,6 +16,7 @@ class CDN {
16
16
  'bootswatch': '5.3.3',
17
17
  'bootstrap-icons': '1.11.1',
18
18
  'ckeditor': '19.0.0',
19
+ 'dragula': '3.7.3',
19
20
  'flatpickr': '4.6.8',
20
21
  'flatpickr-formio': '4.6.13-formio.3',
21
22
  'font-awesome': '4.7.0',
@@ -12,7 +12,6 @@ import { eachComponent } from "./utils/formUtils";
12
12
  if (typeof window !== 'undefined' && typeof window.global === 'undefined') {
13
13
  window.global = window;
14
14
  }
15
- import dragula from "dragula";
16
15
  // Initialize the available forms.
17
16
  Formio.forms = {};
18
17
  // Allow people to register components.
@@ -286,7 +285,6 @@ export default class Webform extends NestedDataComponent {
286
285
  // Ensure the root is set to this component.
287
286
  this.root = this;
288
287
  this.localRoot = this;
289
- this.root.dragulaLib = dragula;
290
288
  }
291
289
  /* eslint-enable max-statements */
292
290
  get language() {
@@ -1136,7 +1134,7 @@ export default class Webform extends NestedDataComponent {
1136
1134
  });
1137
1135
  const displayedErrors = [];
1138
1136
  if (errors.length) {
1139
- errors = _.uniqBy(errors, (error) => error.message);
1137
+ errors = _.uniqBy(errors, (error) => [error.message, error.component?.id, error.context?.path].join());
1140
1138
  const createListItem = (message, index) => {
1141
1139
  const err = errors[index];
1142
1140
  const messageFromIndex = !_.isUndefined(index) && errors && errors[index];
@@ -830,6 +830,7 @@ declare class Component extends Element {
830
830
  quill: any;
831
831
  get shouldSanitizeValue(): boolean;
832
832
  addAce(element: any, settings: any, onChange: any): any;
833
+ getDragula(): Promise<any>;
833
834
  get tree(): any;
834
835
  /**
835
836
  * The empty value for this component.
@@ -2351,6 +2351,13 @@ export default class Component extends Element {
2351
2351
  return editor;
2352
2352
  });
2353
2353
  }
2354
+ async getDragula() {
2355
+ return new Promise((resolve) => {
2356
+ return Formio.requireLibrary('dragula', 'dragula', `${Formio.cdn.dragula}/dragula.js`, true, (ready) => {
2357
+ return ready.then(resolve);
2358
+ });
2359
+ });
2360
+ }
2354
2361
  get tree() {
2355
2362
  return this.component.tree || false;
2356
2363
  }
@@ -2,6 +2,7 @@ export default class CurrencyComponent extends NumberComponent {
2
2
  constructor(component: any, options: any, data: any);
3
3
  currencyPrefix: any;
4
4
  currencySuffix: any;
5
+ parseValue(value: any): string | null;
5
6
  addZerosAndFormatValue(value: any): any;
6
7
  stripPrefixSuffix(value: any): any;
7
8
  }
@@ -12,6 +12,7 @@ export default class DataGridComponent extends NestedArrayComponent {
12
12
  tabIndex: number;
13
13
  rows: any[] | undefined;
14
14
  columns: any[] | undefined;
15
+ dragulaReady: Promise<any> | undefined;
15
16
  visibleColumns: {} | undefined;
16
17
  set dataValue(value: any[]);
17
18
  get dataValue(): any[];
@@ -71,6 +72,7 @@ export default class DataGridComponent extends NestedArrayComponent {
71
72
  */
72
73
  reorderValues(valuesArr: any, oldPosition: number, newPosition: number, movedBelow: boolean | any): void;
73
74
  onReorder(element: any, _target: any, _source: any, sibling: any): void;
75
+ onCloned(el: any, original: any): void;
74
76
  focusOnNewRowElement(row: any): void;
75
77
  addRow(): void;
76
78
  updateComponentsRowIndex(components: any, rowIndex: any): void;
@@ -1,8 +1,7 @@
1
1
  import _ from 'lodash';
2
2
  import NestedArrayComponent from '../_classes/nestedarray/NestedArrayComponent';
3
3
  import { fastCloneDeep, getFocusableElements } from '../../utils/utils';
4
- import { Components } from '../Components';
5
- import dragula from 'dragula';
4
+ import Components from '../Components';
6
5
  export default class DataGridComponent extends NestedArrayComponent {
7
6
  static schema(...extend) {
8
7
  return NestedArrayComponent.schema({
@@ -39,6 +38,9 @@ export default class DataGridComponent extends NestedArrayComponent {
39
38
  if (this.initRows || !_.isEqual(this.dataValue, this.emptyValue)) {
40
39
  this.createRows(true);
41
40
  }
41
+ if (this.allowReorder) {
42
+ this.dragulaReady = this.getDragula();
43
+ }
42
44
  this.visibleColumns = {};
43
45
  this.prevHasAddButton = this.hasAddButton();
44
46
  this.checkColumns();
@@ -279,31 +281,25 @@ export default class DataGridComponent extends NestedArrayComponent {
279
281
  this.refs[`${this.datagridKey}-row`].forEach((row, index) => {
280
282
  row.dragInfo = { index };
281
283
  });
282
- this.dragula = dragula([this.refs[`${this.datagridKey}-tbody`]], {
283
- moves: (_draggedElement, _oldParent, clickedElement) => {
284
- const clickedElementKey = clickedElement.getAttribute('data-key');
285
- const oldParentKey = _oldParent.getAttribute('data-key');
286
- //Check if the clicked button belongs to that container, if false, it belongs to the nested container
287
- if (oldParentKey === clickedElementKey) {
288
- return clickedElement.classList.contains('formio-drag-button');
289
- }
284
+ this.dragulaReady.then((dragula) => {
285
+ // The drop event may call redraw twice which calls attach twice and because this block of code is asynchronous
286
+ // BOTH redraws may be called before this block of code runs (which causes this block of code to run twice sequentially).
287
+ // This causes two dragula() calls on the same container which breaks dragula. To fix this the return value must
288
+ // be saved in this.dragula and have its container contents reset if it exists
289
+ if (this.dragula && this.dragula.containers) {
290
+ this.dragula.containers = [];
290
291
  }
291
- }).on('drop', this.onReorder.bind(this));
292
- this.dragula.on('cloned', (el, original) => {
293
- if (el && el.children && original && original.children) {
294
- _.each(original.children, (child, index) => {
295
- const styles = getComputedStyle(child, null);
296
- if (styles.cssText !== '') {
297
- el.children[index].style.cssText = styles.cssText;
292
+ this.dragula = dragula([this.refs[`${this.datagridKey}-tbody`]], {
293
+ moves: (_draggedElement, _oldParent, clickedElement) => {
294
+ const clickedElementKey = clickedElement.getAttribute('data-key');
295
+ const oldParentKey = _oldParent.getAttribute('data-key');
296
+ //Check if the clicked button belongs to that container, if false, it belongs to the nested container
297
+ if (oldParentKey === clickedElementKey) {
298
+ return clickedElement.classList.contains('formio-drag-button');
298
299
  }
299
- else {
300
- const cssText = Object.values(styles).reduce((css, propertyName) => {
301
- return `${css}${propertyName}:${styles.getPropertyValue(propertyName)};`;
302
- }, '');
303
- el.children[index].style.cssText = cssText;
304
- }
305
- });
306
- }
300
+ }
301
+ }).on('drop', this.onReorder.bind(this))
302
+ .on('cloned', this.onCloned.bind(this));
307
303
  });
308
304
  }
309
305
  this.refs[`${this.datagridKey}-addRow`].forEach((addButton) => {
@@ -370,6 +366,22 @@ export default class DataGridComponent extends NestedArrayComponent {
370
366
  this.setValue(dataValue, { isReordered: true });
371
367
  this.rebuild();
372
368
  }
369
+ onCloned(el, original) {
370
+ if (el && el.children && original && original.children) {
371
+ _.each(original.children, (child, index) => {
372
+ const styles = getComputedStyle(child, null);
373
+ if (styles.cssText !== '') {
374
+ el.children[index].style.cssText = styles.cssText;
375
+ }
376
+ else {
377
+ const cssText = Object.values(styles).reduce((css, propertyName) => {
378
+ return `${css}${propertyName}:${styles.getPropertyValue(propertyName)};`;
379
+ }, '');
380
+ el.children[index].style.cssText = cssText;
381
+ }
382
+ });
383
+ }
384
+ }
373
385
  focusOnNewRowElement(row) {
374
386
  Object.keys(row).find((key) => {
375
387
  const element = row[key].element;
@@ -3,7 +3,7 @@ import DataGridComponent from '../datagrid/DataGrid';
3
3
  import _ from 'lodash';
4
4
  import EventEmitter from 'eventemitter3';
5
5
  import { componentValueTypes, getComponentSavedTypes, uniqueKey } from '../../utils/utils';
6
- import { Components } from '../Components';
6
+ import Components from '../Components';
7
7
  export default class DataMapComponent extends DataGridComponent {
8
8
  static schema(...extend) {
9
9
  return Component.schema({
@@ -31,7 +31,16 @@ export default class NumberComponent extends Input {
31
31
  setInputMask(input: any): void;
32
32
  getValueAt(index: any): number | null;
33
33
  setValueAt(index: any, value: any, flags?: {}): void;
34
- parseValue(input: any): number;
34
+ /**
35
+ * Converts a string to a floating point number, formats the number based on the parsed float function
36
+ * (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/parseFloat) and then returns the
37
+ * formatted number back as a string
38
+ * Example Input: "123.456,22"
39
+ * Example Output: "123456,22"
40
+ * @param {string | number} input the numeric string to parse
41
+ * @returns {string | null} a parsed string
42
+ */
43
+ parseValue(input: string | number): string | null;
35
44
  focus(): void;
36
45
  getMaskedValue(value: any): any;
37
46
  getValueAsString(value: any, options: any): any;
@@ -50,12 +50,12 @@ export default class NumberComponent extends Input {
50
50
  || this.options.properties?.decimalSeparator
51
51
  || separators.decimalSeparator;
52
52
  if (this.component.delimiter) {
53
- if (this.options.hasOwnProperty('thousandsSeparator')) {
54
- console.warn("Property 'thousandsSeparator' is deprecated. Please use i18n to specify delimiter.");
55
- }
56
- this.delimiter = this.options.properties?.thousandsSeparator || this.options.thousandsSeparator || separators.delimiter;
53
+ this.delimiter = this.component.thousandsSeparator || this.options.properties?.thousandsSeparator || this.options.thousandsSeparator || separators.delimiter;
57
54
  }
58
55
  else {
56
+ if (this.component.thousandsSeparator || this.options.properties?.thousandsSeparator || this.options.thousandsSeparator) {
57
+ console.warn('In order for thousands separator to work properly, you must set the delimiter to true in the component json');
58
+ }
59
59
  this.delimiter = '';
60
60
  }
61
61
  const requireDecimal = _.get(this.component, 'requireDecimal', false);
@@ -77,7 +77,7 @@ export default class NumberComponent extends Input {
77
77
  prefix: '',
78
78
  suffix: '',
79
79
  requireDecimal: _.get(this.component, 'requireDecimal', false),
80
- thousandsSeparatorSymbol: _.get(this.component, 'thousandsSeparator', this.delimiter),
80
+ thousandsSeparatorSymbol: this.delimiter || '',
81
81
  decimalSymbol: _.get(this.component, 'decimalSymbol', this.decimalSeparator),
82
82
  decimalLimit: _.get(this.component, 'decimalLimit', this.decimalLimit),
83
83
  allowNegative: _.get(this.component, 'allowNegative', true),
@@ -144,6 +144,15 @@ export default class NumberComponent extends Input {
144
144
  setValueAt(index, value, flags = {}) {
145
145
  return super.setValueAt(index, this.formatValue(this.parseValue(value)), flags);
146
146
  }
147
+ /**
148
+ * Converts a string to a floating point number, formats the number based on the parsed float function
149
+ * (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/parseFloat) and then returns the
150
+ * formatted number back as a string
151
+ * Example Input: "123.456,22"
152
+ * Example Output: "123456,22"
153
+ * @param {string | number} input the numeric string to parse
154
+ * @returns {string | null} a parsed string
155
+ */
147
156
  parseValue(input) {
148
157
  if (typeof input === 'string') {
149
158
  input = input.split(this.delimiter).join('').replace(this.decimalSeparator, '.');