formeo 2.2.0 → 2.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/formeo.es.js CHANGED
@@ -1,7 +1,7 @@
1
1
 
2
2
  /**
3
3
  formeo - https://formeo.io
4
- Version: 2.1.7
4
+ Version: 2.2.1
5
5
  Author: Draggable https://draggable.io
6
6
  */
7
7
 
@@ -231,7 +231,7 @@ class I18N {
231
231
  }
232
232
  const mi18n = new I18N();
233
233
  const name$1 = "formeo";
234
- const version$2 = "2.1.7";
234
+ const version$2 = "2.2.1";
235
235
  const type = "module";
236
236
  const main = "dist/formeo.cjs.js";
237
237
  const module = "dist/formeo.es.js";
@@ -302,15 +302,16 @@ const scripts = {
302
302
  "build:demo:watch": "vite build --mode demo --watch",
303
303
  "build:icons": "node ./tools/generate-sprite",
304
304
  lint: "eslint ./src --ext .js || true",
305
- test: "node --experimental-test-snapshots --require ./tools/test-setup.cjs --test --no-warnings src/**/*.test.js",
306
- "test:updateSnapshots": "node --experimental-test-snapshots --test-update-snapshots --require ./tools/test-setup.cjs --test --no-warnings src/**/*.test.js",
307
- "test:ci": "yarn test --coverage",
305
+ test: "node --experimental-test-snapshots --require ./tools/test-setup.cjs --test --no-warnings src/**/*.test.{js,mjs}",
306
+ "test:updateSnapshots": "node --experimental-test-snapshots --test-update-snapshots --require ./tools/test-setup.cjs --test --no-warnings src/**/*.test.{js,mjs}",
307
+ "test:ci": "npm test --coverage",
308
308
  start: "npm-run-all build:icons dev",
309
309
  "semantic-release": "semantic-release --ci --debug",
310
310
  "copy:lang": "node ./tools/copy-directory.mjs ./node_modules/formeo-i18n/dist/lang ./src/demo/assets/lang",
311
311
  "travis-deploy-once": "travis-deploy-once --pro",
312
- prepush: "yarn test",
313
- defaults: "webpack-defaults"
312
+ prepush: "npm test",
313
+ prepare: "lefthook install",
314
+ postmerge: "lefthook install"
314
315
  };
315
316
  const devDependencies = {
316
317
  "@biomejs/biome": "^1.9.3",
@@ -1570,17 +1571,23 @@ const sessionStorage = Object.create(null, {
1570
1571
  const isAddress = (str) => COMPONENT_INDEX_TYPES.some((indexType) => new RegExp(`^${indexType}.`).test(str));
1571
1572
  const isExternalAddress = (str) => str.startsWith("external");
1572
1573
  const isBoolKey = (key) => /^is|^has/.test(key);
1573
- function throttle$1(callback, limit) {
1574
- let wait = false;
1575
- return function() {
1576
- if (!wait) {
1577
- callback(...arguments);
1578
- wait = true;
1579
- const timeout = setTimeout(() => {
1580
- wait = false;
1581
- clearTimeout(timeout);
1582
- }, limit);
1574
+ function throttle$1(callback, limit = ANIMATION_SPEED_SLOW) {
1575
+ let lastCall = 0;
1576
+ return function(...args) {
1577
+ const now = Date.now();
1578
+ if (now - lastCall >= limit) {
1579
+ lastCall = now;
1580
+ callback.apply(this, args);
1581
+ }
1582
+ };
1583
+ }
1584
+ function debounce(fn, delay = ANIMATION_SPEED_SLOW) {
1585
+ let timeoutID;
1586
+ return function(...args) {
1587
+ if (timeoutID) {
1588
+ clearTimeout(timeoutID);
1583
1589
  }
1590
+ timeoutID = setTimeout(() => fn.apply(this, args), delay);
1584
1591
  };
1585
1592
  }
1586
1593
  function identity(value) {
@@ -1803,7 +1810,7 @@ const safeAttrName = (name2) => {
1803
1810
  return sanitizedAttributeNames[name2];
1804
1811
  }
1805
1812
  const attributeName = attributeMap[name2] || name2;
1806
- const sanitizedAttributeName = attributeName.replace(/^\d/, "").replace(/[^a-zA-Z0-9-:]/g, "");
1813
+ const sanitizedAttributeName = attributeName.replace(/^\d+/, "").replace(/[^a-zA-Z0-9-:]/g, "");
1807
1814
  sanitizedAttributeNames[name2] = sanitizedAttributeName;
1808
1815
  return sanitizedAttributeName;
1809
1816
  };
@@ -5018,7 +5025,10 @@ const BASE_NAME = "f-autocomplete";
5018
5025
  const HIGHLIGHT_CLASS_NAME = "highlight-component";
5019
5026
  let lastCache = Date.now();
5020
5027
  let optionsCache;
5021
- const labelCount = (arr, label) => arr.reduce((n, x) => n + (x === label), 0);
5028
+ const labelCount = (arr, label) => {
5029
+ const count = arr.reduce((n, x) => n + (x === label), 0);
5030
+ return count > 1 ? `(${count})` : "";
5031
+ };
5022
5032
  const getComponentLabel = ({ name: name2, id, ...component }) => {
5023
5033
  const labelPaths = ["config.label", "attrs.id", "meta.id"];
5024
5034
  const label = labelPaths.reduce((acc, cur) => {
@@ -5030,13 +5040,24 @@ const getComponentLabel = ({ name: name2, id, ...component }) => {
5030
5040
  const externalLabel = (...externalAddress) => mi18n.get(externalAddress.join(".")) || toTitleCase(externalAddress.join(" "));
5031
5041
  return label || name2 === "external" && externalLabel(name2, id);
5032
5042
  };
5033
- const componentOptions = (selected) => {
5043
+ const makeOption = ({ id, textLabel, htmlLabel, selectedId }) => {
5044
+ const option2 = {
5045
+ value: id,
5046
+ textLabel,
5047
+ htmlLabel
5048
+ };
5049
+ if (id === selectedId) {
5050
+ option2.selected = true;
5051
+ }
5052
+ return option2;
5053
+ };
5054
+ const componentOptions = (selectedId) => {
5034
5055
  const labels = [];
5035
5056
  const flatList = components.flatList();
5036
5057
  const options = Object.entries(flatList).map(([id, component]) => {
5037
5058
  const label = getComponentLabel(component);
5038
5059
  if (label) {
5039
- const type2 = {
5060
+ const typeConfig = {
5040
5061
  tag: "span",
5041
5062
  content: ` ${toTitleCase(component.name)}`,
5042
5063
  className: "component-type"
@@ -5046,10 +5067,12 @@ const componentOptions = (selected) => {
5046
5067
  const count = labelCount(labels, labelKey);
5047
5068
  const countConfig = {
5048
5069
  tag: "span",
5049
- content: count > 1 && `(${count})`,
5070
+ content: count,
5050
5071
  className: "component-label-count"
5051
5072
  };
5052
- return dom.makeOption([id, [`${label} `, countConfig, type2]], selected);
5073
+ const htmlLabel = [`${label} `, countConfig, typeConfig];
5074
+ const textLabel = [label, count].join(" ").trim();
5075
+ return makeOption({ id, textLabel, htmlLabel, selectedId });
5053
5076
  }
5054
5077
  });
5055
5078
  return options.filter(Boolean);
@@ -5147,9 +5170,9 @@ class Autocomplete {
5147
5170
  const activeOption = this.getActiveOption() || filteredOptions[0];
5148
5171
  this.showList(activeOption);
5149
5172
  }
5150
- this.hiddenField.value = evt.target.value;
5151
- this.value = evt.target.value;
5152
- this.runEvent("onChange", { target: this.hiddenField });
5173
+ const value = evt.target.value.trim();
5174
+ this.hiddenField.value = value;
5175
+ this.value = value;
5153
5176
  }
5154
5177
  };
5155
5178
  this.displayField = dom.create({
@@ -5195,7 +5218,9 @@ class Autocomplete {
5195
5218
  lastCache = now;
5196
5219
  }
5197
5220
  const options = optionsCache || this.generateOptions();
5198
- options.forEach((option2) => this.list.appendChild(option2));
5221
+ for (const option2 of options) {
5222
+ this.list.appendChild(option2);
5223
+ }
5199
5224
  }
5200
5225
  generateOptions() {
5201
5226
  const options = componentOptions();
@@ -5207,15 +5232,13 @@ class Autocomplete {
5207
5232
  return target;
5208
5233
  };
5209
5234
  optionsCache = options.map((optionData) => {
5210
- const value = optionData.value;
5211
- let [label] = optionData.label;
5212
- label = label.trim();
5235
+ const { value, textLabel, htmlLabel } = optionData;
5213
5236
  const optionConfig = {
5214
5237
  tag: "li",
5215
- children: optionData.label,
5238
+ children: htmlLabel,
5216
5239
  dataset: {
5217
5240
  value,
5218
- label
5241
+ label: textLabel
5219
5242
  },
5220
5243
  className: `${BASE_NAME}-list-item`,
5221
5244
  action: {
@@ -5296,15 +5319,16 @@ class Autocomplete {
5296
5319
  * @param {Object} selectedOption - option - 'li' element - to be selected in autocomplete list
5297
5320
  */
5298
5321
  selectOption(selectedOption, list = this.list) {
5322
+ var _a;
5299
5323
  const options = list.querySelectorAll("li");
5300
- for (let i = 0; i < options.length; i++) {
5324
+ for (const option2 of options) {
5301
5325
  const {
5302
5326
  dataset: { value }
5303
- } = options[i];
5304
- options[i].classList.remove("active-option");
5327
+ } = option2;
5328
+ option2.classList.remove("active-option");
5305
5329
  if (value) {
5306
5330
  const component = components.getAddress(value);
5307
- component.dom && component.dom.classList.remove(HIGHLIGHT_CLASS_NAME);
5331
+ (_a = component.dom) == null ? void 0 : _a.classList.remove(HIGHLIGHT_CLASS_NAME);
5308
5332
  }
5309
5333
  }
5310
5334
  if (selectedOption) {
@@ -5317,20 +5341,21 @@ class Autocomplete {
5317
5341
  */
5318
5342
  removeHighlight() {
5319
5343
  const highlightedComponents = document.getElementsByClassName(HIGHLIGHT_CLASS_NAME);
5320
- for (let i = 0; i < highlightedComponents.length; i++) {
5321
- highlightedComponents[i].classList.remove(HIGHLIGHT_CLASS_NAME);
5344
+ for (const component of highlightedComponents) {
5345
+ component.classList.remove(HIGHLIGHT_CLASS_NAME);
5322
5346
  }
5323
5347
  }
5324
5348
  /**
5325
5349
  * Highlight a component that maps to the option
5326
5350
  */
5327
5351
  highlightComponent(option2) {
5352
+ var _a;
5328
5353
  const {
5329
5354
  dataset: { value }
5330
5355
  } = option2;
5331
5356
  if (value) {
5332
5357
  const component = components.getAddress(value);
5333
- component.dom && component.dom.classList.add(HIGHLIGHT_CLASS_NAME);
5358
+ (_a = component.dom) == null ? void 0 : _a.classList.add(HIGHLIGHT_CLASS_NAME);
5334
5359
  }
5335
5360
  }
5336
5361
  /**
@@ -5359,11 +5384,11 @@ class Autocomplete {
5359
5384
  this.events.push([key, event]);
5360
5385
  }
5361
5386
  runEvent(eventName, evt) {
5362
- this.events.forEach(([key, event]) => {
5387
+ for (const [key, event] of this.events) {
5363
5388
  if (key === eventName) {
5364
5389
  event(evt);
5365
5390
  }
5366
- });
5391
+ }
5367
5392
  }
5368
5393
  }
5369
5394
  const getOptionData = (key) => {
@@ -5400,7 +5425,9 @@ const createOptions = (fieldVal, selected) => {
5400
5425
  };
5401
5426
  const addOptions = (select, options) => {
5402
5427
  dom.empty(select);
5403
- options.forEach((option2) => select.add(option2));
5428
+ for (const option2 of options) {
5429
+ select.add(option2);
5430
+ }
5404
5431
  };
5405
5432
  const inputConfigBase = ({ key, value, type: type2 = "text", checked }) => {
5406
5433
  const config2 = {
@@ -5446,7 +5473,6 @@ const ITEM_INPUT_TYPE_MAP = {
5446
5473
  },
5447
5474
  object: (val) => {
5448
5475
  return Object.entries(val).map(([key, val2]) => {
5449
- console.log(dom.childType(val2));
5450
5476
  return ITEM_INPUT_TYPE_MAP[dom.childType(val2)](key, val2);
5451
5477
  });
5452
5478
  }
@@ -5463,7 +5489,6 @@ const INPUT_TYPE_ACTION = {
5463
5489
  );
5464
5490
  }
5465
5491
  field.set(dataKey, checked);
5466
- field.updatePreview();
5467
5492
  }
5468
5493
  }),
5469
5494
  string: (dataKey, field) => ({
@@ -5474,13 +5499,11 @@ const INPUT_TYPE_ACTION = {
5474
5499
  number: (dataKey, field) => ({
5475
5500
  input: ({ target: { value } }) => {
5476
5501
  field.set(dataKey, Number(value));
5477
- field.updatePreview();
5478
5502
  }
5479
5503
  }),
5480
5504
  array: (dataKey, field) => ({
5481
5505
  change: ({ target: { value } }) => {
5482
5506
  field.set(dataKey, value);
5483
- field.updatePreview();
5484
5507
  }
5485
5508
  }),
5486
5509
  object: () => ({})
@@ -5590,12 +5613,12 @@ class EditPanelItem {
5590
5613
  }
5591
5614
  ]
5592
5615
  ]);
5593
- fields2.forEach((field) => {
5616
+ for (const field of fields2) {
5594
5617
  const action = actions2.get(field.className);
5595
5618
  if (action) {
5596
5619
  action(field);
5597
5620
  }
5598
- });
5621
+ }
5599
5622
  });
5600
5623
  __publicField(this, "conditionInput", (key, val, conditionType, i) => {
5601
5624
  const field = this.field;
@@ -5604,7 +5627,7 @@ class EditPanelItem {
5604
5627
  const dataPath = `${field.name}s.${conditionAddress}.${key}`;
5605
5628
  const createConditionSelect = (key2, propertyValue, i18nKey) => {
5606
5629
  const options = createOptions(i18nKey || key2, propertyValue);
5607
- const propertyFieldConfig = ITEM_INPUT_TYPE_MAP["array"](`condition.${key2}`);
5630
+ const propertyFieldConfig = ITEM_INPUT_TYPE_MAP.array(`condition.${key2}`);
5608
5631
  propertyFieldConfig.action = {
5609
5632
  change: conditionChangeAction,
5610
5633
  onRender: (elem) => conditionChangeAction({ target: elem })
@@ -5633,7 +5656,7 @@ class EditPanelItem {
5633
5656
  comparison: (value) => createConditionSelect("comparison", value),
5634
5657
  logical: (value) => createConditionSelect("logical", value),
5635
5658
  source: (value, type2 = "source") => {
5636
- const componentInput = ITEM_INPUT_TYPE_MAP["autocomplete"](`condition.${type2}`, value, conditionType);
5659
+ const componentInput = ITEM_INPUT_TYPE_MAP.autocomplete(`condition.${type2}`, value, conditionType);
5637
5660
  components.setConditionMap(value, field);
5638
5661
  componentInput.addEvent("onChange", (evt) => {
5639
5662
  components.removeConditionMap(components.getAddress(dataPath));
@@ -5646,7 +5669,7 @@ class EditPanelItem {
5646
5669
  targetProperty: (value) => createConditionSelect("targetProperty", value, "field.property"),
5647
5670
  target: (value) => segmentTypes.source(value, "target"),
5648
5671
  value: (value) => {
5649
- const valueField = ITEM_INPUT_TYPE_MAP["string"]("condition.value", value);
5672
+ const valueField = ITEM_INPUT_TYPE_MAP.string("condition.value", value);
5650
5673
  valueField.action = {
5651
5674
  input: conditionChangeAction
5652
5675
  };
@@ -5727,14 +5750,14 @@ class EditPanelItem {
5727
5750
  const valType = dom.childType(val) || "string";
5728
5751
  const inputTypeConfig = { ...{ config: {}, attrs: {} }, ...ITEM_INPUT_TYPE_MAP[valType](key, val) };
5729
5752
  const dataKey = this.itemKey.replace(/.\d+$/, (index2) => `${index2}.${key}`);
5730
- const labelKey = dataKey.split(".").filter(Number.isNaN).join(".");
5753
+ const labelKey = dataKey.split(".").filter(Number.isNaN).join(".") || key;
5731
5754
  const [id, name2] = [[...this.itemKey.split("."), key], [key]].map(
5732
5755
  (attrVars) => [this.field.id, ...attrVars].filter(Boolean).join("-")
5733
5756
  );
5734
5757
  inputTypeConfig.config = {
5735
5758
  ...inputTypeConfig.config,
5736
5759
  ...{
5737
- label: this.panelName !== "options" && labelHelper(labelKey),
5760
+ label: this.panelName !== "options" && (labelHelper(labelKey) || toTitleCase(labelKey)),
5738
5761
  labelAfter: false
5739
5762
  }
5740
5763
  };
@@ -6473,23 +6496,20 @@ class Field extends Component {
6473
6496
  /**
6474
6497
  * Updates the conditions panel when linked field data changes
6475
6498
  */
6476
- __publicField(this, "updateConditionsPanel", () => {
6477
- const updateConditionsTimeout = setTimeout(() => {
6478
- const newConditionsPanel = this.editPanels.find(({ name: name2 }) => name2 === "conditions");
6479
- if (!newConditionsPanel) {
6480
- return null;
6481
- }
6482
- const newProps = newConditionsPanel.createProps();
6483
- const currentConditionsProps = this.dom.querySelector(".field-edit-conditions");
6484
- currentConditionsProps.parentElement.replaceChild(newProps, currentConditionsProps);
6485
- clearTimeout(updateConditionsTimeout);
6486
- }, ANIMATION_SPEED_BASE);
6487
- });
6499
+ __publicField(this, "updateConditionsPanel", throttle$1(() => {
6500
+ const newConditionsPanel = this.editPanels.find(({ name: name2 }) => name2 === "conditions");
6501
+ if (!newConditionsPanel) {
6502
+ return null;
6503
+ }
6504
+ const newProps = newConditionsPanel.createProps();
6505
+ const currentConditionsProps = this.dom.querySelector(".field-edit-conditions");
6506
+ currentConditionsProps.parentElement.replaceChild(newProps, currentConditionsProps);
6507
+ }, ANIMATION_SPEED_BASE));
6488
6508
  /**
6489
6509
  * Updates a field's preview
6490
6510
  * @return {Object} fresh preview
6491
6511
  */
6492
- __publicField(this, "updatePreview", throttle$1(() => {
6512
+ __publicField(this, "updatePreview", () => {
6493
6513
  if (!this.preview.parentElement) {
6494
6514
  return null;
6495
6515
  }
@@ -6497,7 +6517,44 @@ class Field extends Component {
6497
6517
  const newPreview = dom.create(this.fieldPreview(), true);
6498
6518
  this.preview.parentElement.replaceChild(newPreview, this.preview);
6499
6519
  this.preview = newPreview;
6500
- }, ANIMATION_SPEED_BASE));
6520
+ });
6521
+ __publicField(this, "updateEditPanels", () => {
6522
+ this.editPanels = [];
6523
+ const editable = ["object", "array"];
6524
+ const panelOrder = unique([...this.config.panels.order, ...Object.keys(this.data)]);
6525
+ const noPanels = ["config", "meta", "action", "events", ...this.config.panels.disabled];
6526
+ const allowedPanels = panelOrder.filter((panelName) => !noPanels.includes(panelName));
6527
+ for (const panelName of allowedPanels) {
6528
+ const panelData = this.get(panelName);
6529
+ const propType = dom.childType(panelData);
6530
+ if (editable.includes(propType)) {
6531
+ const editPanel = new EditPanel(panelData, panelName, this);
6532
+ this.editPanels.push(editPanel);
6533
+ }
6534
+ }
6535
+ const panelsData = {
6536
+ panels: this.editPanels.map(({ panelConfig }) => panelConfig),
6537
+ id: this.id,
6538
+ displayType: "auto"
6539
+ };
6540
+ this.panels = new Panels(panelsData);
6541
+ if (this.dom) {
6542
+ this.dom.querySelector(".panel-nav").replaceWith(this.panels.panelNav);
6543
+ this.dom.querySelector(".panels").replaceWith(this.panels.panelsWrap);
6544
+ }
6545
+ });
6546
+ __publicField(this, "toggleCheckedOptions", (optionIndex, type2) => {
6547
+ const updatedOptionData = this.get("options").map((option2, index2) => {
6548
+ const isCurrentIndex = index2 === optionIndex;
6549
+ if (type2 === "radio") {
6550
+ option2.selected = isCurrentIndex;
6551
+ } else {
6552
+ option2.checked = isCurrentIndex ? !option2.checked : option2.checked;
6553
+ }
6554
+ return option2;
6555
+ });
6556
+ this.set("options", updatedOptionData);
6557
+ });
6501
6558
  /**
6502
6559
  * Checks if attribute is allowed to be edited
6503
6560
  * @param {String} propName
@@ -6524,6 +6581,7 @@ class Field extends Component {
6524
6581
  const lockedAttrs = propKind.locked.concat(this.get(`config.locked${toTitleCase(kind)}`));
6525
6582
  return lockedAttrs.includes(propName);
6526
6583
  });
6584
+ this.debouncedUpdateEditPanels = debounce(this.updateEditPanels);
6527
6585
  this.label = dom.create(this.labelConfig);
6528
6586
  this.preview = dom.create({});
6529
6587
  this.editPanels = [];
@@ -6642,65 +6700,42 @@ class Field extends Component {
6642
6700
  * @return {Object} fieldEdit element config
6643
6701
  */
6644
6702
  get fieldEdit() {
6645
- this.editPanels = [];
6646
- const editable = ["object", "array"];
6647
- const noPanels = ["config", "meta", "action", "events", ...this.config.panels.disabled];
6648
- const panelOrder = unique([...this.config.panels.order, ...Object.keys(this.data)]);
6649
- const allowedPanels = panelOrder.filter((panelName) => !noPanels.includes(panelName));
6650
6703
  const fieldEdit = {
6651
6704
  className: ["field-edit", "slide-toggle", "formeo-panels-wrap"]
6652
6705
  };
6653
- for (const panelName of allowedPanels) {
6654
- const panelData = this.get(panelName);
6655
- const propType = dom.childType(panelData);
6656
- if (editable.includes(propType)) {
6657
- const editPanel = new EditPanel(panelData, panelName, this);
6658
- this.editPanels.push(editPanel);
6659
- }
6660
- }
6661
- const panelsData = {
6662
- panels: this.editPanels.map(({ panelConfig }) => panelConfig),
6663
- id: this.id,
6664
- displayType: "auto"
6665
- };
6706
+ this.updateEditPanels();
6666
6707
  const editPanelLength = this.editPanels.length;
6667
6708
  if (editPanelLength) {
6668
- this.panels = new Panels(panelsData);
6669
6709
  fieldEdit.className.push(`panel-count-${editPanelLength}`);
6670
6710
  fieldEdit.content = [this.panels.panelNav, this.panels.panelsWrap];
6671
6711
  this.panelNav = this.panels.nav;
6672
6712
  this.resizePanelWrap = this.panels.nav.refresh;
6673
- fieldEdit.action = {
6674
- onRender: () => {
6713
+ }
6714
+ fieldEdit.action = {
6715
+ onRender: () => {
6716
+ if (editPanelLength === 0) {
6717
+ const field = this.dom;
6718
+ const editToggle = field.querySelector(".item-edit-toggle");
6719
+ const fieldActions = field.querySelector(".field-actions");
6720
+ const actionButtons = fieldActions.getElementsByTagName("button");
6721
+ fieldActions.style.maxWidth = `${actionButtons.length * actionButtons[0].clientWidth}px`;
6722
+ dom.remove(editToggle);
6723
+ } else {
6675
6724
  this.resizePanelWrap();
6676
- if (!editPanelLength) {
6677
- const field = this.dom;
6678
- const editToggle = field.querySelector(".item-edit-toggle");
6679
- const fieldActions = field.querySelector(".field-actions");
6680
- const actionButtons = fieldActions.getElementsByTagName("button");
6681
- fieldActions.style.maxWidth = `${actionButtons.length * actionButtons[0].clientWidth}px`;
6682
- dom.remove(editToggle);
6683
- }
6684
6725
  }
6685
- };
6686
- }
6687
- return fieldEdit;
6726
+ }
6727
+ };
6728
+ return dom.create(fieldEdit);
6688
6729
  }
6689
6730
  get defaultPreviewActions() {
6690
6731
  return {
6691
6732
  change: (evt) => {
6692
6733
  const { target } = evt;
6693
- const { checked, type: type2 } = target;
6734
+ const { type: type2 } = target;
6694
6735
  if (["checkbox", "radio"].includes(type2)) {
6695
6736
  const optionIndex = +target.id.split("-").pop();
6696
- if (type2 === "radio") {
6697
- this.set(
6698
- "options",
6699
- this.get("options").map((option2) => ({ ...option2, selected: false }))
6700
- );
6701
- }
6702
- const checkType = type2 === "checkbox" ? "checked" : "selected";
6703
- this.set(`options.${optionIndex}.${checkType}`, checked);
6737
+ this.toggleCheckedOptions(optionIndex, type2);
6738
+ this.debouncedUpdateEditPanels();
6704
6739
  }
6705
6740
  },
6706
6741
  click: (evt) => {
@@ -6711,6 +6746,7 @@ class Field extends Component {
6711
6746
  input: (evt) => {
6712
6747
  if (["input", "meter", "progress", "button"].includes(this.data.tag)) {
6713
6748
  super.set("attrs.value", evt.target.value);
6749
+ this.debouncedUpdateEditPanels();
6714
6750
  }
6715
6751
  if (evt.target.contentEditable) {
6716
6752
  super.set("content", evt.target.innerHTML);
@@ -6775,7 +6811,7 @@ const insertScript = (src) => {
6775
6811
  attrs: {
6776
6812
  type: "text/javascript",
6777
6813
  async: true,
6778
- src: `//${src.replace(/^https?:\/\//, "")}`
6814
+ src
6779
6815
  },
6780
6816
  action: {
6781
6817
  load: () => onLoadJavascript(script, resolve),
@@ -7348,7 +7384,7 @@ class TinyMCEControl extends Control {
7348
7384
  attrs: {
7349
7385
  required: false
7350
7386
  },
7351
- dependencies: { js: "cdnjs.cloudflare.com/ajax/libs/tinymce/4.9.11/tinymce.min.js" },
7387
+ dependencies: { js: "https://cdnjs.cloudflare.com/ajax/libs/tinymce/4.9.11/tinymce.min.js" },
7352
7388
  // this action is passed to the rendered control/element
7353
7389
  // useful for actions and events on the control preview
7354
7390
  action: {
@@ -8563,12 +8599,13 @@ const iconFontTemplates = {
8563
8599
  },
8564
8600
  fontello: (icon) => `<i class="${iconPrefix}${icon}">${icon}</i>`
8565
8601
  };
8602
+ const inputTags = /* @__PURE__ */ new Set(["input", "textarea", "select"]);
8566
8603
  class DOM {
8567
8604
  /**
8568
8605
  * Set defaults, store references to key elements
8569
8606
  * like stages, rows, columns etc
8570
8607
  */
8571
- constructor() {
8608
+ constructor(options = /* @__PURE__ */ Object.create(null)) {
8572
8609
  /**
8573
8610
  * Wraps dom.create to modify data
8574
8611
  * Used when rendering components in form- not editor
@@ -8584,11 +8621,10 @@ class DOM {
8584
8621
  * @return {Object} DOM Object
8585
8622
  */
8586
8623
  __publicField(this, "create", (elemArg, isPreview = false) => {
8587
- let elem = elemArg;
8588
- if (!elem) {
8624
+ if (!elemArg) {
8589
8625
  return;
8590
8626
  }
8591
- elem = this.processTagName(elem);
8627
+ const { className, options, ...elem } = this.processTagName(elemArg);
8592
8628
  const _this = this;
8593
8629
  let childType;
8594
8630
  const { tag } = elem;
@@ -8629,35 +8665,26 @@ class DOM {
8629
8665
  boolean: () => null
8630
8666
  };
8631
8667
  processed.push("tag");
8632
- if (elem.className) {
8633
- const { className } = elem;
8634
- elem.attrs = Object.assign({}, elem.attrs, { className });
8635
- delete elem.className;
8636
- }
8637
- if (elem.options) {
8638
- let { options } = elem;
8639
- options = this.processOptions(options, elem, isPreview);
8668
+ if (className) {
8669
+ elem.attrs = { ...elem.attrs, className };
8670
+ }
8671
+ if (options) {
8672
+ const processedOptions = this.processOptions(options, elem, isPreview);
8640
8673
  if (this.holdsContent(element) && tag !== "button") {
8641
- appendChildren.array.call(this, options);
8642
- delete elem.content;
8674
+ appendChildren.array.call(this, processedOptions);
8675
+ elem.content = void 0;
8643
8676
  } else {
8644
- helpers.forEach(options, (option2) => {
8677
+ helpers.forEach(processedOptions, (option2) => {
8645
8678
  wrap.children.push(_this.create(option2, isPreview));
8646
8679
  });
8647
8680
  if (elem.attrs.className) {
8648
8681
  wrap.className = elem.attrs.className;
8649
8682
  }
8650
- wrap.config = Object.assign({}, elem.config);
8683
+ wrap.config = { ...elem.config };
8651
8684
  return this.create(wrap, isPreview);
8652
8685
  }
8653
8686
  processed.push("options");
8654
8687
  }
8655
- if (element.tagName === "OPTION") {
8656
- const timeout = setTimeout(() => {
8657
- element.selected = false;
8658
- clearTimeout(timeout);
8659
- }, 0);
8660
- }
8661
8688
  if (elem.attrs) {
8662
8689
  _this.processAttrs(elem, element, isPreview);
8663
8690
  processed.push("attrs");
@@ -8754,16 +8781,6 @@ class DOM {
8754
8781
  }
8755
8782
  };
8756
8783
  });
8757
- __publicField(this, "makeOption", ([value, label], selected, i18nKey) => {
8758
- const option2 = {
8759
- value,
8760
- label: mi18n.get(`${i18nKey}.${label}`) || label
8761
- };
8762
- if (value === selected) {
8763
- option2.selected = true;
8764
- }
8765
- return option2;
8766
- });
8767
8784
  __publicField(this, "requiredMark", () => ({
8768
8785
  tag: "span",
8769
8786
  className: "text-error",
@@ -8782,9 +8799,8 @@ class DOM {
8782
8799
  if (!children.length) {
8783
8800
  if (!this.isStage(parent)) {
8784
8801
  return this.removeEmpty(parent);
8785
- } else {
8786
- this.emptyClass(parent);
8787
8802
  }
8803
+ return this.emptyClass(parent);
8788
8804
  }
8789
8805
  });
8790
8806
  __publicField(this, "btnTemplate", ({ title = "", ...rest }) => ({
@@ -8801,29 +8817,23 @@ class DOM {
8801
8817
  __publicField(this, "isColumn", (node) => componentType(node) === COLUMN_CLASSNAME);
8802
8818
  __publicField(this, "isField", (node) => componentType(node) === FIELD_CLASSNAME);
8803
8819
  __publicField(this, "asComponent", (elem) => components[`${componentType(elem)}s`].get(elem.id));
8804
- this.options = /* @__PURE__ */ Object.create(null);
8805
- this.styleSheet = (() => {
8806
- const style = document.createElement("style");
8807
- style.setAttribute("media", "screen");
8808
- style.setAttribute("type", "text/css");
8809
- style.appendChild(document.createTextNode(""));
8810
- document.head.appendChild(style);
8811
- return style.sheet;
8812
- })();
8820
+ this.options = options;
8813
8821
  }
8814
8822
  set setOptions(options) {
8815
- this.options = merge(Object.assign({}, this.options, options));
8823
+ this.options = merge(this.options, options);
8816
8824
  }
8817
8825
  /**
8818
8826
  * Ensure elements have proper tagName
8819
8827
  * @param {Object|String} elem
8820
8828
  * @return {Object} valid element object
8821
8829
  */
8822
- processTagName(elem) {
8830
+ processTagName(elemArg) {
8831
+ let elem = elemArg;
8823
8832
  let tagName;
8824
8833
  if (typeof elem === "string") {
8825
8834
  tagName = elem;
8826
8835
  elem = { tag: tagName };
8836
+ return elem;
8827
8837
  }
8828
8838
  if (elem.attrs) {
8829
8839
  const { tag, ...restAttrs } = elem.attrs;
@@ -8932,14 +8942,7 @@ class DOM {
8932
8942
  }
8933
8943
  }
8934
8944
  if (value) {
8935
- if (element.tagName === "OPTION" && name2 === "selected") {
8936
- const timeout = setTimeout(() => {
8937
- element.setAttribute(name2, value);
8938
- clearTimeout(timeout);
8939
- }, 0);
8940
- } else {
8941
- element.setAttribute(name2, value);
8942
- }
8945
+ element.setAttribute(name2, value === true ? "" : value);
8943
8946
  }
8944
8947
  }
8945
8948
  }
@@ -9049,11 +9052,12 @@ class DOM {
9049
9052
  * @param {String|Object} tag tagName or DOM element
9050
9053
  * @return {Boolean} isInput
9051
9054
  */
9052
- isInput(tag) {
9055
+ isInput(tagArg) {
9056
+ let tag = tagArg;
9053
9057
  if (typeof tag !== "string") {
9054
9058
  tag = tag.tagName;
9055
9059
  }
9056
- return ["input", "textarea", "select"].indexOf(tag) !== -1;
9060
+ return inputTags.has(tag);
9057
9061
  }
9058
9062
  /**
9059
9063
  * Converts escaped HTML into usable HTML
@@ -9101,7 +9105,7 @@ class DOM {
9101
9105
  action: {}
9102
9106
  };
9103
9107
  if (fMap) {
9104
- delete fieldLabel.attrs.for;
9108
+ fieldLabel.attrs.for = void 0;
9105
9109
  fieldLabel.attrs.contenteditable = true;
9106
9110
  fieldLabel.fMap = fMap;
9107
9111
  }
@@ -9257,7 +9261,8 @@ class DOM {
9257
9261
  * @param {Object} elem DOM element
9258
9262
  * @param {Boolean} state
9259
9263
  */
9260
- toggleSortable(elem, state) {
9264
+ toggleSortable(elem, stateArg) {
9265
+ let state = stateArg;
9261
9266
  const fType = componentType(elem);
9262
9267
  if (!fType) {
9263
9268
  return;