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/demo/assets/css/demo.min.css +2 -2
- package/dist/demo/assets/css/demo.min.css.gz +0 -0
- package/dist/demo/assets/css/formeo.min.css +2 -2
- package/dist/demo/assets/css/formeo.min.css.gz +0 -0
- package/dist/demo/assets/js/demo.min.js +2 -2
- package/dist/demo/assets/js/demo.min.js.gz +0 -0
- package/dist/demo/assets/js/formeo.min.js +3 -3
- package/dist/demo/assets/js/formeo.min.js.gz +0 -0
- package/dist/demo/index.html +1 -1
- package/dist/formeo.cjs.js +3 -3
- package/dist/formeo.es.js +172 -167
- package/dist/formeo.min.css +2 -2
- package/dist/formeo.min.js +3 -3
- package/dist/formeo.umd.js +3 -3
- package/package.json +7 -6
package/dist/formeo.es.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
|
|
2
2
|
/**
|
|
3
3
|
formeo - https://formeo.io
|
|
4
|
-
Version: 2.1
|
|
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
|
|
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": "
|
|
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: "
|
|
313
|
-
|
|
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
|
|
1575
|
-
return function() {
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
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
|
|
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) =>
|
|
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
|
|
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
|
|
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
|
|
5070
|
+
content: count,
|
|
5050
5071
|
className: "component-label-count"
|
|
5051
5072
|
};
|
|
5052
|
-
|
|
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
|
-
|
|
5151
|
-
this.value =
|
|
5152
|
-
this.
|
|
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
|
-
|
|
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
|
|
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:
|
|
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 (
|
|
5324
|
+
for (const option2 of options) {
|
|
5301
5325
|
const {
|
|
5302
5326
|
dataset: { value }
|
|
5303
|
-
} =
|
|
5304
|
-
|
|
5327
|
+
} = option2;
|
|
5328
|
+
option2.classList.remove("active-option");
|
|
5305
5329
|
if (value) {
|
|
5306
5330
|
const component = components.getAddress(value);
|
|
5307
|
-
component.dom
|
|
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 (
|
|
5321
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
6478
|
-
|
|
6479
|
-
|
|
6480
|
-
|
|
6481
|
-
|
|
6482
|
-
|
|
6483
|
-
|
|
6484
|
-
|
|
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",
|
|
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
|
-
}
|
|
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
|
-
|
|
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
|
-
|
|
6674
|
-
|
|
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 {
|
|
6734
|
+
const { type: type2 } = target;
|
|
6694
6735
|
if (["checkbox", "radio"].includes(type2)) {
|
|
6695
6736
|
const optionIndex = +target.id.split("-").pop();
|
|
6696
|
-
|
|
6697
|
-
|
|
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
|
|
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
|
-
|
|
8588
|
-
if (!elem) {
|
|
8624
|
+
if (!elemArg) {
|
|
8589
8625
|
return;
|
|
8590
8626
|
}
|
|
8591
|
-
elem = this.processTagName(
|
|
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 (
|
|
8633
|
-
|
|
8634
|
-
|
|
8635
|
-
|
|
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,
|
|
8642
|
-
|
|
8674
|
+
appendChildren.array.call(this, processedOptions);
|
|
8675
|
+
elem.content = void 0;
|
|
8643
8676
|
} else {
|
|
8644
|
-
helpers.forEach(
|
|
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 =
|
|
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 =
|
|
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(
|
|
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(
|
|
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
|
-
|
|
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(
|
|
9055
|
+
isInput(tagArg) {
|
|
9056
|
+
let tag = tagArg;
|
|
9053
9057
|
if (typeof tag !== "string") {
|
|
9054
9058
|
tag = tag.tagName;
|
|
9055
9059
|
}
|
|
9056
|
-
return
|
|
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
|
-
|
|
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,
|
|
9264
|
+
toggleSortable(elem, stateArg) {
|
|
9265
|
+
let state = stateArg;
|
|
9261
9266
|
const fType = componentType(elem);
|
|
9262
9267
|
if (!fType) {
|
|
9263
9268
|
return;
|