formeo 5.3.1 → 5.3.3
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 +1 -1
- package/dist/demo/assets/css/demo.min.css.gz +0 -0
- package/dist/demo/assets/css/formeo.min.css +1 -1
- package/dist/demo/assets/js/demo.min.js +48 -48
- package/dist/demo/assets/js/demo.min.js.gz +0 -0
- package/dist/demo/assets/js/form.min.js +2 -2
- package/dist/demo/assets/js/formeo.cjs.js +47 -13
- package/dist/demo/assets/js/formeo.es.js +47 -13
- package/dist/demo/assets/js/formeo.min.cjs.js +2 -2
- package/dist/demo/assets/js/formeo.min.es.js +2 -2
- package/dist/demo/assets/js/formeo.min.js +47 -13
- package/dist/demo/assets/js/formeo.min.umd.js +2 -2
- package/dist/demo/assets/js/formeo.umd.js +47 -13
- package/dist/demo/assets/js/html.min.js +1 -1
- package/dist/demo/assets/js/layout.min.js +1 -1
- package/dist/demo/assets/js/mode-json.min.js +1 -1
- package/dist/demo/assets/js/mode-json.min.js.gz +0 -0
- package/dist/demo/assets/js/theme-github_light_default.min.js +1 -1
- package/dist/demo/index.html +1 -1
- package/dist/formeo.cjs.js +47 -13
- package/dist/formeo.css +1 -1
- package/dist/formeo.es.js +47 -13
- package/dist/formeo.min.cjs.js +2 -2
- package/dist/formeo.min.css +1 -1
- package/dist/formeo.min.es.js +2 -2
- package/dist/formeo.min.js +47 -13
- package/dist/formeo.min.umd.js +2 -2
- package/dist/formeo.umd.js +47 -13
- package/package.json +1 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
|
|
2
2
|
/**
|
|
3
3
|
formeo - https://formeo.io
|
|
4
|
-
Version: 5.3.
|
|
4
|
+
Version: 5.3.2
|
|
5
5
|
Author: Draggable https://draggable.io
|
|
6
6
|
*/
|
|
7
7
|
|
|
@@ -8068,7 +8068,7 @@ Author: Draggable https://draggable.io
|
|
|
8068
8068
|
})), name$1, version$2, type, main, module$1, unpkg, exports$1, files, homepage, repository, author, contributors, bugs, description, keywords, ignore, config, scripts, devDependencies, dependencies, release, commitlint, package_default;
|
|
8069
8069
|
var init_package = __esmMin((() => {
|
|
8070
8070
|
name$1 = "formeo";
|
|
8071
|
-
version$2 = "5.3.
|
|
8071
|
+
version$2 = "5.3.2";
|
|
8072
8072
|
type = "module";
|
|
8073
8073
|
main = "dist/formeo.cjs.js";
|
|
8074
8074
|
module$1 = "dist/formeo.es.js";
|
|
@@ -8681,7 +8681,7 @@ Author: Draggable https://draggable.io
|
|
|
8681
8681
|
function trimKeyPrefix(key) {
|
|
8682
8682
|
return key.replaceAll(keyPrefixRegex, "");
|
|
8683
8683
|
}
|
|
8684
|
-
var toTitleCaseLowers, toTitleCaseRegex, regexSpace, slugify, splitAddress, slugifyAddress, extractTextFromHtml, truncateByWord, keyPrefixRegex;
|
|
8684
|
+
var toTitleCaseLowers, toTitleCaseRegex, regexSpace, slugify, splitAddress, slugifyAddress, extractTextFromHtml, truncateByWord, keyPrefixRegex, groupInputName;
|
|
8685
8685
|
var init_string = __esmMin((() => {
|
|
8686
8686
|
toTitleCaseLowers = "a an and as at but by for for from in into near nor of on onto or the to with".split(" ").map((lower) => String.raw`\s${lower}\s`);
|
|
8687
8687
|
toTitleCaseRegex = new RegExp(String.raw`(?!${toTitleCaseLowers.join("|")})\w\S*`, "g");
|
|
@@ -8718,6 +8718,7 @@ Author: Draggable https://draggable.io
|
|
|
8718
8718
|
return truncatedWord;
|
|
8719
8719
|
};
|
|
8720
8720
|
keyPrefixRegex = /^attrs\.|^meta\.|^options\.|^config\./g;
|
|
8721
|
+
groupInputName = (name, fieldType, optionCount) => fieldType === "checkbox" && optionCount > 1 && name && !name.endsWith("[]") ? `${name}[]` : name;
|
|
8721
8722
|
}));
|
|
8722
8723
|
//#endregion
|
|
8723
8724
|
//#region src/lib/js/common/events.js
|
|
@@ -14525,6 +14526,23 @@ Author: Draggable https://draggable.io
|
|
|
14525
14526
|
});
|
|
14526
14527
|
}));
|
|
14527
14528
|
//#endregion
|
|
14529
|
+
//#region src/lib/js/components/fields/control-attr-config.mjs
|
|
14530
|
+
var getControlConfig, controlAttrPanelConfig;
|
|
14531
|
+
var init_control_attr_config = __esmMin((() => {
|
|
14532
|
+
init_utils();
|
|
14533
|
+
getControlConfig = (control) => control?.controlData?.config ?? control?.config;
|
|
14534
|
+
controlAttrPanelConfig = (...sources) => {
|
|
14535
|
+
const collect = (key) => unique(sources.flatMap((source) => Array.isArray(source?.[key]) ? source[key] : []));
|
|
14536
|
+
const disabled = collect("disabledAttrs");
|
|
14537
|
+
const locked = collect("lockedAttrs");
|
|
14538
|
+
if (!disabled.length && !locked.length) return null;
|
|
14539
|
+
return { panels: { attrs: {
|
|
14540
|
+
disabled,
|
|
14541
|
+
locked
|
|
14542
|
+
} } };
|
|
14543
|
+
};
|
|
14544
|
+
}));
|
|
14545
|
+
//#endregion
|
|
14528
14546
|
//#region src/lib/js/components/fields/field.js
|
|
14529
14547
|
var field_exports = /* @__PURE__ */ __exportAll({ default: () => Field });
|
|
14530
14548
|
var checkableTypes, isSelectableType, Field;
|
|
@@ -14535,6 +14553,8 @@ Author: Draggable https://draggable.io
|
|
|
14535
14553
|
init_utils();
|
|
14536
14554
|
init_constants();
|
|
14537
14555
|
init_component();
|
|
14556
|
+
init_components();
|
|
14557
|
+
init_control_attr_config();
|
|
14538
14558
|
checkableTypes = new Set(["checkbox", "radio"]);
|
|
14539
14559
|
isSelectableType = new Set([
|
|
14540
14560
|
"radio",
|
|
@@ -14550,11 +14570,12 @@ Author: Draggable https://draggable.io
|
|
|
14550
14570
|
*/
|
|
14551
14571
|
constructor(fieldData = Object.create(null)) {
|
|
14552
14572
|
super("field", fieldData);
|
|
14573
|
+
this.controlId = this.get("config.controlId") || this.get("meta.id");
|
|
14574
|
+
this.applyControlAttrConfig();
|
|
14553
14575
|
this.debouncedUpdateEditPanels = debounce(this.updateEditPanels);
|
|
14554
14576
|
this.debouncedUpdatePreview = debounce(this.updatePreview);
|
|
14555
14577
|
this.label = dom.create(this.labelConfig);
|
|
14556
14578
|
this.preview = this.fieldPreview();
|
|
14557
|
-
this.controlId = this.get("config.controlId") || this.get("meta.id");
|
|
14558
14579
|
const actionButtons = this.getActionButtons();
|
|
14559
14580
|
const hasEditButton = this.actionButtons.some((child) => child.meta?.id === "edit");
|
|
14560
14581
|
this.updateEditPanels();
|
|
@@ -14575,6 +14596,15 @@ Author: Draggable https://draggable.io
|
|
|
14575
14596
|
this.dom = field;
|
|
14576
14597
|
this.isEditing = false;
|
|
14577
14598
|
}
|
|
14599
|
+
/**
|
|
14600
|
+
* Honour control-level `disabledAttrs` / `lockedAttrs` by merging them into this field's
|
|
14601
|
+
* panels.attrs config. Reads both the registered control definition and the field's own
|
|
14602
|
+
* saved config so forms saved before a control changed still pick up its rules.
|
|
14603
|
+
*/
|
|
14604
|
+
applyControlAttrConfig() {
|
|
14605
|
+
const attrConfig = controlAttrPanelConfig(getControlConfig(components.controls?.get(this.controlId)), this.get("config"));
|
|
14606
|
+
if (attrConfig) this.config = { [this.id]: attrConfig };
|
|
14607
|
+
}
|
|
14578
14608
|
get labelConfig() {
|
|
14579
14609
|
if (!!this.get("config.hideLabel")) return null;
|
|
14580
14610
|
const { label, editorLabel, disableHtmlLabel, helpText, tooltip } = this.get("config");
|
|
@@ -15018,7 +15048,7 @@ Author: Draggable https://draggable.io
|
|
|
15018
15048
|
},
|
|
15019
15049
|
config: {
|
|
15020
15050
|
label: s.get("controls.form.radio-group"),
|
|
15021
|
-
|
|
15051
|
+
disabledAttrs: ["type"]
|
|
15022
15052
|
},
|
|
15023
15053
|
meta: {
|
|
15024
15054
|
group: "common",
|
|
@@ -17191,7 +17221,7 @@ Author: Draggable https://draggable.io
|
|
|
17191
17221
|
const { action, attrs = {} } = elem;
|
|
17192
17222
|
const fieldType = attrs.type || elem.tag;
|
|
17193
17223
|
const id = attrs.id || elem.id;
|
|
17194
|
-
const name =
|
|
17224
|
+
const name = isPreview ? id : groupInputName(attrs.name || id, fieldType, options.length);
|
|
17195
17225
|
const sharedInputAttrs = Object.fromEntries(OPTION_INPUT_ATTRS.filter((key) => key in attrs).map((key) => [key, attrs[key]]));
|
|
17196
17226
|
if (attrs.required) sharedInputAttrs.required = fieldType !== "checkbox" || !options.some(({ selected, checked }) => selected || checked);
|
|
17197
17227
|
const optionMap = (option, i) => {
|
|
@@ -18457,12 +18487,12 @@ Author: Draggable https://draggable.io
|
|
|
18457
18487
|
* @return {Object|undefined}
|
|
18458
18488
|
*/
|
|
18459
18489
|
componentByName(name) {
|
|
18460
|
-
return this.components[baseId(name)] || Object.values(this.components).find((component) => component.attrs?.name === name);
|
|
18490
|
+
return this.components[baseId(name)] || Object.values(this.components).find((component) => component.attrs?.name === name || component.attrs?.name === `${name}[]`);
|
|
18461
18491
|
}
|
|
18462
18492
|
set userData(data = {}) {
|
|
18463
18493
|
const form = this.container.querySelector("form");
|
|
18464
18494
|
for (const key of Object.keys(data)) {
|
|
18465
|
-
const fields = form.elements[key];
|
|
18495
|
+
const fields = form.elements[key] ?? form.elements[`${key}[]`];
|
|
18466
18496
|
const checkables = checkableInputs(fields);
|
|
18467
18497
|
if (checkables?.[0].type === "checkbox") {
|
|
18468
18498
|
const values = Array.isArray(data[key]) ? data[key] : [data[key]];
|
|
@@ -18748,11 +18778,12 @@ Author: Draggable https://draggable.io
|
|
|
18748
18778
|
};
|
|
18749
18779
|
getComponents = (address) => {
|
|
18750
18780
|
const components = [];
|
|
18751
|
-
const
|
|
18752
|
-
components.push(...this.renderedForm.querySelectorAll(`[name=
|
|
18781
|
+
const name = `f-${address.slice(address.indexOf(".") + 1)}`;
|
|
18782
|
+
components.push(...this.renderedForm.querySelectorAll(`[name="${name}"], [name="${name}[]"]`));
|
|
18753
18783
|
return components;
|
|
18754
18784
|
};
|
|
18755
18785
|
};
|
|
18786
|
+
var fieldKey = (key) => key.endsWith("[]") ? key.slice(0, -2) : key;
|
|
18756
18787
|
/**
|
|
18757
18788
|
* Converts a rendered form's fields to a plain object, the same shape the `userData`
|
|
18758
18789
|
* getter exposes. Handles multiple values for the same key by converting them to arrays.
|
|
@@ -18763,9 +18794,12 @@ Author: Draggable https://draggable.io
|
|
|
18763
18794
|
if (!form) return {};
|
|
18764
18795
|
const formEntries = new FormData(form);
|
|
18765
18796
|
const formDataObj = {};
|
|
18766
|
-
for (const [
|
|
18767
|
-
|
|
18768
|
-
|
|
18797
|
+
for (const [rawKey, value] of formEntries.entries()) {
|
|
18798
|
+
const key = fieldKey(rawKey);
|
|
18799
|
+
if (Object.hasOwn(formDataObj, key)) if (Array.isArray(formDataObj[key])) formDataObj[key].push(value);
|
|
18800
|
+
else formDataObj[key] = [formDataObj[key], value];
|
|
18801
|
+
else formDataObj[key] = value;
|
|
18802
|
+
}
|
|
18769
18803
|
return formDataObj;
|
|
18770
18804
|
};
|
|
18771
18805
|
var isCheckable = (elem) => ["checkbox", "radio"].includes(elem?.type);
|
|
Binary file
|
package/dist/demo/index.html
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
<!doctype html><html lang="en" xml:lang="en"><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="chrome=1"><meta name="viewport" content="user-scalable=no,width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1"><meta name="description" content="Vanilla Javascript form building module"><meta name="theme-color" content="#232323"><title>Formeo | Drag & Drop Form Creation</title><script type="module" crossorigin src="/formeo/assets/js/demo.min.js"></script><link rel="stylesheet" crossorigin href="/formeo/assets/css/demo.min.css"></head><body><div class="site-wrap"><header id="demo-header"><div class="header-inner"><img id="formeo-logo" src="/formeo/assets/img/formeo-logo.svg" alt="Formeo Logo" width="100"><nav aria-label="Framework navigation"><ul><li><label for="framework-select">Framework:</label> <select name="framework-select" id="framework-select" class="form-control"><option value="vanilla">Vanilla JavaScript</option><option value="angular">Angular</option><option value="react">React</option></select></li><li><label for="locale">Language</label> <select name="locale" id="locale" class="form-control"><option value="af-ZA" dir="ltr">Afrikaans (Suid-Afrika)</option><option value="ar-TN" dir="rtl">العربية (تونس)</option><option value="cs-CZ" dir="ltr">čeština (Česko)</option><option value="de-DE" dir="ltr">Deutsch (Deutschland)</option><option value="en-US" dir="ltr">English</option><option value="es-ES" dir="ltr">español de España</option><option value="fa-IR" dir="rtl">فارسی (ایران)</option><option value="fi-FI" dir="ltr">suomi (Suomi)</option><option value="fr-FR" dir="ltr">français (France)</option><option value="he-IL" dir="rtl">עברית (ישראל)</option><option value="hi-IN" dir="ltr">हिन्दी (भारत)</option><option value="hu-HU" dir="ltr">magyar (Magyarország)</option><option value="it-IT" dir="ltr">italiano (Italia)</option><option value="ja-JP" dir="ltr">日本語 (日本)</option><option value="nb-NO" dir="ltr">norsk bokmål (Norge)</option><option value="pl-PL" dir="ltr">polski (Polska)</option><option value="pt-BR" dir="ltr">português (Brasil)</option><option value="pt-PT" dir="ltr">português europeu</option><option value="ro-RO" dir="ltr">română (România)</option><option value="ru-RU" dir="ltr">русский (Россия)</option><option value="th-TH" dir="ltr">ไทย (ไทย)</option><option value="tr-TR" dir="ltr">Türkçe (Türkiye)</option><option value="zh-CN" dir="ltr">中文(中国)</option><option value="zh-HK" dir="ltr">中文(中國香港特別行政區)</option></select></li><li><label for="control-filter">Control Filter:</label> <input id="control-filter" placeholder="ex. text" class="form-control"></li><li style="float:right">v5.3.
|
|
1
|
+
<!doctype html><html lang="en" xml:lang="en"><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="chrome=1"><meta name="viewport" content="user-scalable=no,width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1"><meta name="description" content="Vanilla Javascript form building module"><meta name="theme-color" content="#232323"><title>Formeo | Drag & Drop Form Creation</title><script type="module" crossorigin src="/formeo/assets/js/demo.min.js"></script><link rel="stylesheet" crossorigin href="/formeo/assets/css/demo.min.css"></head><body><div class="site-wrap"><header id="demo-header"><div class="header-inner"><img id="formeo-logo" src="/formeo/assets/img/formeo-logo.svg" alt="Formeo Logo" width="100"><nav aria-label="Framework navigation"><ul><li><label for="framework-select">Framework:</label> <select name="framework-select" id="framework-select" class="form-control"><option value="vanilla">Vanilla JavaScript</option><option value="angular">Angular</option><option value="react">React</option></select></li><li><label for="locale">Language</label> <select name="locale" id="locale" class="form-control"><option value="af-ZA" dir="ltr">Afrikaans (Suid-Afrika)</option><option value="ar-TN" dir="rtl">العربية (تونس)</option><option value="cs-CZ" dir="ltr">čeština (Česko)</option><option value="de-DE" dir="ltr">Deutsch (Deutschland)</option><option value="en-US" dir="ltr">English</option><option value="es-ES" dir="ltr">español de España</option><option value="fa-IR" dir="rtl">فارسی (ایران)</option><option value="fi-FI" dir="ltr">suomi (Suomi)</option><option value="fr-FR" dir="ltr">français (France)</option><option value="he-IL" dir="rtl">עברית (ישראל)</option><option value="hi-IN" dir="ltr">हिन्दी (भारत)</option><option value="hu-HU" dir="ltr">magyar (Magyarország)</option><option value="it-IT" dir="ltr">italiano (Italia)</option><option value="ja-JP" dir="ltr">日本語 (日本)</option><option value="nb-NO" dir="ltr">norsk bokmål (Norge)</option><option value="pl-PL" dir="ltr">polski (Polska)</option><option value="pt-BR" dir="ltr">português (Brasil)</option><option value="pt-PT" dir="ltr">português europeu</option><option value="ro-RO" dir="ltr">română (România)</option><option value="ru-RU" dir="ltr">русский (Россия)</option><option value="th-TH" dir="ltr">ไทย (ไทย)</option><option value="tr-TR" dir="ltr">Türkçe (Türkiye)</option><option value="zh-CN" dir="ltr">中文(中国)</option><option value="zh-HK" dir="ltr">中文(中國香港特別行政區)</option></select></li><li><label for="control-filter">Control Filter:</label> <input id="control-filter" placeholder="ex. text" class="form-control"></li><li style="float:right">v5.3.2</li></ul></nav></div></header><section id="main_content" class="inner"><div id="framework-container"></div></section><div class="container render-btn-wrap" id="editor-action-buttons"></div><div id="formData-popover" popover><div class="popover-header"><h3>Test formData</h3><div><button type="button" id="format-json">Format</button> <button type="button" id="collapse-json">Collapse</button> <button type="button" id="copy-json">Copy to Clipboard</button></div></div><pre id="formData-editor"></pre><div class="formData-actions"><button popovertarget="formData-popover" popovertargetaction="hide" type="button">Cancel</button> <button id="submit-formData" type="button">Submit</button></div></div><footer id="demo-footer"><nav aria-label="Footer navigation"><ul><li><a href="https://github.com/Draggable/formeo" target="_blank" title="View project on GitHub"><img src="/formeo/assets/img/github.png" width="77" alt="GitHub"></a></li></ul></nav></footer></div></body></html>
|
package/dist/formeo.cjs.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
|
|
2
2
|
/**
|
|
3
3
|
formeo - https://formeo.io
|
|
4
|
-
Version: 5.3.
|
|
4
|
+
Version: 5.3.2
|
|
5
5
|
Author: Draggable https://draggable.io
|
|
6
6
|
*/
|
|
7
7
|
|
|
@@ -8065,7 +8065,7 @@ var require_mergeWith = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
8065
8065
|
})), name$1, version$2, type, main, module$1, unpkg, exports$1, files, homepage, repository, author, contributors, bugs, description, keywords, ignore, config, scripts, devDependencies, dependencies, release, commitlint, package_default;
|
|
8066
8066
|
var init_package = __esmMin((() => {
|
|
8067
8067
|
name$1 = "formeo";
|
|
8068
|
-
version$2 = "5.3.
|
|
8068
|
+
version$2 = "5.3.2";
|
|
8069
8069
|
type = "module";
|
|
8070
8070
|
main = "dist/formeo.cjs.js";
|
|
8071
8071
|
module$1 = "dist/formeo.es.js";
|
|
@@ -8678,7 +8678,7 @@ function toTitleCase(str) {
|
|
|
8678
8678
|
function trimKeyPrefix(key) {
|
|
8679
8679
|
return key.replaceAll(keyPrefixRegex, "");
|
|
8680
8680
|
}
|
|
8681
|
-
var toTitleCaseLowers, toTitleCaseRegex, regexSpace, slugify, splitAddress, slugifyAddress, extractTextFromHtml, truncateByWord, keyPrefixRegex;
|
|
8681
|
+
var toTitleCaseLowers, toTitleCaseRegex, regexSpace, slugify, splitAddress, slugifyAddress, extractTextFromHtml, truncateByWord, keyPrefixRegex, groupInputName;
|
|
8682
8682
|
var init_string = __esmMin((() => {
|
|
8683
8683
|
toTitleCaseLowers = "a an and as at but by for for from in into near nor of on onto or the to with".split(" ").map((lower) => String.raw`\s${lower}\s`);
|
|
8684
8684
|
toTitleCaseRegex = new RegExp(String.raw`(?!${toTitleCaseLowers.join("|")})\w\S*`, "g");
|
|
@@ -8715,6 +8715,7 @@ var init_string = __esmMin((() => {
|
|
|
8715
8715
|
return truncatedWord;
|
|
8716
8716
|
};
|
|
8717
8717
|
keyPrefixRegex = /^attrs\.|^meta\.|^options\.|^config\./g;
|
|
8718
|
+
groupInputName = (name, fieldType, optionCount) => fieldType === "checkbox" && optionCount > 1 && name && !name.endsWith("[]") ? `${name}[]` : name;
|
|
8718
8719
|
}));
|
|
8719
8720
|
//#endregion
|
|
8720
8721
|
//#region src/lib/js/common/events.js
|
|
@@ -14522,6 +14523,23 @@ var init_options = __esmMin((() => {
|
|
|
14522
14523
|
});
|
|
14523
14524
|
}));
|
|
14524
14525
|
//#endregion
|
|
14526
|
+
//#region src/lib/js/components/fields/control-attr-config.mjs
|
|
14527
|
+
var getControlConfig, controlAttrPanelConfig;
|
|
14528
|
+
var init_control_attr_config = __esmMin((() => {
|
|
14529
|
+
init_utils();
|
|
14530
|
+
getControlConfig = (control) => control?.controlData?.config ?? control?.config;
|
|
14531
|
+
controlAttrPanelConfig = (...sources) => {
|
|
14532
|
+
const collect = (key) => unique(sources.flatMap((source) => Array.isArray(source?.[key]) ? source[key] : []));
|
|
14533
|
+
const disabled = collect("disabledAttrs");
|
|
14534
|
+
const locked = collect("lockedAttrs");
|
|
14535
|
+
if (!disabled.length && !locked.length) return null;
|
|
14536
|
+
return { panels: { attrs: {
|
|
14537
|
+
disabled,
|
|
14538
|
+
locked
|
|
14539
|
+
} } };
|
|
14540
|
+
};
|
|
14541
|
+
}));
|
|
14542
|
+
//#endregion
|
|
14525
14543
|
//#region src/lib/js/components/fields/field.js
|
|
14526
14544
|
var field_exports = /* @__PURE__ */ __exportAll({ default: () => Field });
|
|
14527
14545
|
var checkableTypes, isSelectableType, Field;
|
|
@@ -14532,6 +14550,8 @@ var init_field = __esmMin((() => {
|
|
|
14532
14550
|
init_utils();
|
|
14533
14551
|
init_constants();
|
|
14534
14552
|
init_component();
|
|
14553
|
+
init_components();
|
|
14554
|
+
init_control_attr_config();
|
|
14535
14555
|
checkableTypes = new Set(["checkbox", "radio"]);
|
|
14536
14556
|
isSelectableType = new Set([
|
|
14537
14557
|
"radio",
|
|
@@ -14547,11 +14567,12 @@ var init_field = __esmMin((() => {
|
|
|
14547
14567
|
*/
|
|
14548
14568
|
constructor(fieldData = Object.create(null)) {
|
|
14549
14569
|
super("field", fieldData);
|
|
14570
|
+
this.controlId = this.get("config.controlId") || this.get("meta.id");
|
|
14571
|
+
this.applyControlAttrConfig();
|
|
14550
14572
|
this.debouncedUpdateEditPanels = debounce(this.updateEditPanels);
|
|
14551
14573
|
this.debouncedUpdatePreview = debounce(this.updatePreview);
|
|
14552
14574
|
this.label = dom.create(this.labelConfig);
|
|
14553
14575
|
this.preview = this.fieldPreview();
|
|
14554
|
-
this.controlId = this.get("config.controlId") || this.get("meta.id");
|
|
14555
14576
|
const actionButtons = this.getActionButtons();
|
|
14556
14577
|
const hasEditButton = this.actionButtons.some((child) => child.meta?.id === "edit");
|
|
14557
14578
|
this.updateEditPanels();
|
|
@@ -14572,6 +14593,15 @@ var init_field = __esmMin((() => {
|
|
|
14572
14593
|
this.dom = field;
|
|
14573
14594
|
this.isEditing = false;
|
|
14574
14595
|
}
|
|
14596
|
+
/**
|
|
14597
|
+
* Honour control-level `disabledAttrs` / `lockedAttrs` by merging them into this field's
|
|
14598
|
+
* panels.attrs config. Reads both the registered control definition and the field's own
|
|
14599
|
+
* saved config so forms saved before a control changed still pick up its rules.
|
|
14600
|
+
*/
|
|
14601
|
+
applyControlAttrConfig() {
|
|
14602
|
+
const attrConfig = controlAttrPanelConfig(getControlConfig(components.controls?.get(this.controlId)), this.get("config"));
|
|
14603
|
+
if (attrConfig) this.config = { [this.id]: attrConfig };
|
|
14604
|
+
}
|
|
14575
14605
|
get labelConfig() {
|
|
14576
14606
|
if (!!this.get("config.hideLabel")) return null;
|
|
14577
14607
|
const { label, editorLabel, disableHtmlLabel, helpText, tooltip } = this.get("config");
|
|
@@ -15015,7 +15045,7 @@ var init_radio_group = __esmMin((() => {
|
|
|
15015
15045
|
},
|
|
15016
15046
|
config: {
|
|
15017
15047
|
label: s.get("controls.form.radio-group"),
|
|
15018
|
-
|
|
15048
|
+
disabledAttrs: ["type"]
|
|
15019
15049
|
},
|
|
15020
15050
|
meta: {
|
|
15021
15051
|
group: "common",
|
|
@@ -17188,7 +17218,7 @@ var init_dom = __esmMin((() => {
|
|
|
17188
17218
|
const { action, attrs = {} } = elem;
|
|
17189
17219
|
const fieldType = attrs.type || elem.tag;
|
|
17190
17220
|
const id = attrs.id || elem.id;
|
|
17191
|
-
const name =
|
|
17221
|
+
const name = isPreview ? id : groupInputName(attrs.name || id, fieldType, options.length);
|
|
17192
17222
|
const sharedInputAttrs = Object.fromEntries(OPTION_INPUT_ATTRS.filter((key) => key in attrs).map((key) => [key, attrs[key]]));
|
|
17193
17223
|
if (attrs.required) sharedInputAttrs.required = fieldType !== "checkbox" || !options.some(({ selected, checked }) => selected || checked);
|
|
17194
17224
|
const optionMap = (option, i) => {
|
|
@@ -18454,12 +18484,12 @@ var FormeoRenderer$1 = class {
|
|
|
18454
18484
|
* @return {Object|undefined}
|
|
18455
18485
|
*/
|
|
18456
18486
|
componentByName(name) {
|
|
18457
|
-
return this.components[baseId(name)] || Object.values(this.components).find((component) => component.attrs?.name === name);
|
|
18487
|
+
return this.components[baseId(name)] || Object.values(this.components).find((component) => component.attrs?.name === name || component.attrs?.name === `${name}[]`);
|
|
18458
18488
|
}
|
|
18459
18489
|
set userData(data = {}) {
|
|
18460
18490
|
const form = this.container.querySelector("form");
|
|
18461
18491
|
for (const key of Object.keys(data)) {
|
|
18462
|
-
const fields = form.elements[key];
|
|
18492
|
+
const fields = form.elements[key] ?? form.elements[`${key}[]`];
|
|
18463
18493
|
const checkables = checkableInputs(fields);
|
|
18464
18494
|
if (checkables?.[0].type === "checkbox") {
|
|
18465
18495
|
const values = Array.isArray(data[key]) ? data[key] : [data[key]];
|
|
@@ -18745,11 +18775,12 @@ var FormeoRenderer$1 = class {
|
|
|
18745
18775
|
};
|
|
18746
18776
|
getComponents = (address) => {
|
|
18747
18777
|
const components = [];
|
|
18748
|
-
const
|
|
18749
|
-
components.push(...this.renderedForm.querySelectorAll(`[name=
|
|
18778
|
+
const name = `f-${address.slice(address.indexOf(".") + 1)}`;
|
|
18779
|
+
components.push(...this.renderedForm.querySelectorAll(`[name="${name}"], [name="${name}[]"]`));
|
|
18750
18780
|
return components;
|
|
18751
18781
|
};
|
|
18752
18782
|
};
|
|
18783
|
+
var fieldKey = (key) => key.endsWith("[]") ? key.slice(0, -2) : key;
|
|
18753
18784
|
/**
|
|
18754
18785
|
* Converts a rendered form's fields to a plain object, the same shape the `userData`
|
|
18755
18786
|
* getter exposes. Handles multiple values for the same key by converting them to arrays.
|
|
@@ -18760,9 +18791,12 @@ var userDataOf = (form) => {
|
|
|
18760
18791
|
if (!form) return {};
|
|
18761
18792
|
const formEntries = new FormData(form);
|
|
18762
18793
|
const formDataObj = {};
|
|
18763
|
-
for (const [
|
|
18764
|
-
|
|
18765
|
-
|
|
18794
|
+
for (const [rawKey, value] of formEntries.entries()) {
|
|
18795
|
+
const key = fieldKey(rawKey);
|
|
18796
|
+
if (Object.hasOwn(formDataObj, key)) if (Array.isArray(formDataObj[key])) formDataObj[key].push(value);
|
|
18797
|
+
else formDataObj[key] = [formDataObj[key], value];
|
|
18798
|
+
else formDataObj[key] = value;
|
|
18799
|
+
}
|
|
18766
18800
|
return formDataObj;
|
|
18767
18801
|
};
|
|
18768
18802
|
var isCheckable = (elem) => ["checkbox", "radio"].includes(elem?.type);
|
package/dist/formeo.css
CHANGED
package/dist/formeo.es.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
|
|
2
2
|
/**
|
|
3
3
|
formeo - https://formeo.io
|
|
4
|
-
Version: 5.3.
|
|
4
|
+
Version: 5.3.2
|
|
5
5
|
Author: Draggable https://draggable.io
|
|
6
6
|
*/
|
|
7
7
|
|
|
@@ -8064,7 +8064,7 @@ var require_mergeWith = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
8064
8064
|
})), name$1, version$2, type, main, module$1, unpkg, exports$1, files, homepage, repository, author, contributors, bugs, description, keywords, ignore, config, scripts, devDependencies, dependencies, release, commitlint, package_default;
|
|
8065
8065
|
var init_package = __esmMin((() => {
|
|
8066
8066
|
name$1 = "formeo";
|
|
8067
|
-
version$2 = "5.3.
|
|
8067
|
+
version$2 = "5.3.2";
|
|
8068
8068
|
type = "module";
|
|
8069
8069
|
main = "dist/formeo.cjs.js";
|
|
8070
8070
|
module$1 = "dist/formeo.es.js";
|
|
@@ -8677,7 +8677,7 @@ function toTitleCase(str) {
|
|
|
8677
8677
|
function trimKeyPrefix(key) {
|
|
8678
8678
|
return key.replaceAll(keyPrefixRegex, "");
|
|
8679
8679
|
}
|
|
8680
|
-
var toTitleCaseLowers, toTitleCaseRegex, regexSpace, slugify, splitAddress, slugifyAddress, extractTextFromHtml, truncateByWord, keyPrefixRegex;
|
|
8680
|
+
var toTitleCaseLowers, toTitleCaseRegex, regexSpace, slugify, splitAddress, slugifyAddress, extractTextFromHtml, truncateByWord, keyPrefixRegex, groupInputName;
|
|
8681
8681
|
var init_string = __esmMin((() => {
|
|
8682
8682
|
toTitleCaseLowers = "a an and as at but by for for from in into near nor of on onto or the to with".split(" ").map((lower) => String.raw`\s${lower}\s`);
|
|
8683
8683
|
toTitleCaseRegex = new RegExp(String.raw`(?!${toTitleCaseLowers.join("|")})\w\S*`, "g");
|
|
@@ -8714,6 +8714,7 @@ var init_string = __esmMin((() => {
|
|
|
8714
8714
|
return truncatedWord;
|
|
8715
8715
|
};
|
|
8716
8716
|
keyPrefixRegex = /^attrs\.|^meta\.|^options\.|^config\./g;
|
|
8717
|
+
groupInputName = (name, fieldType, optionCount) => fieldType === "checkbox" && optionCount > 1 && name && !name.endsWith("[]") ? `${name}[]` : name;
|
|
8717
8718
|
}));
|
|
8718
8719
|
//#endregion
|
|
8719
8720
|
//#region src/lib/js/common/events.js
|
|
@@ -14521,6 +14522,23 @@ var init_options = __esmMin((() => {
|
|
|
14521
14522
|
});
|
|
14522
14523
|
}));
|
|
14523
14524
|
//#endregion
|
|
14525
|
+
//#region src/lib/js/components/fields/control-attr-config.mjs
|
|
14526
|
+
var getControlConfig, controlAttrPanelConfig;
|
|
14527
|
+
var init_control_attr_config = __esmMin((() => {
|
|
14528
|
+
init_utils();
|
|
14529
|
+
getControlConfig = (control) => control?.controlData?.config ?? control?.config;
|
|
14530
|
+
controlAttrPanelConfig = (...sources) => {
|
|
14531
|
+
const collect = (key) => unique(sources.flatMap((source) => Array.isArray(source?.[key]) ? source[key] : []));
|
|
14532
|
+
const disabled = collect("disabledAttrs");
|
|
14533
|
+
const locked = collect("lockedAttrs");
|
|
14534
|
+
if (!disabled.length && !locked.length) return null;
|
|
14535
|
+
return { panels: { attrs: {
|
|
14536
|
+
disabled,
|
|
14537
|
+
locked
|
|
14538
|
+
} } };
|
|
14539
|
+
};
|
|
14540
|
+
}));
|
|
14541
|
+
//#endregion
|
|
14524
14542
|
//#region src/lib/js/components/fields/field.js
|
|
14525
14543
|
var field_exports = /* @__PURE__ */ __exportAll({ default: () => Field });
|
|
14526
14544
|
var checkableTypes, isSelectableType, Field;
|
|
@@ -14531,6 +14549,8 @@ var init_field = __esmMin((() => {
|
|
|
14531
14549
|
init_utils();
|
|
14532
14550
|
init_constants();
|
|
14533
14551
|
init_component();
|
|
14552
|
+
init_components();
|
|
14553
|
+
init_control_attr_config();
|
|
14534
14554
|
checkableTypes = new Set(["checkbox", "radio"]);
|
|
14535
14555
|
isSelectableType = new Set([
|
|
14536
14556
|
"radio",
|
|
@@ -14546,11 +14566,12 @@ var init_field = __esmMin((() => {
|
|
|
14546
14566
|
*/
|
|
14547
14567
|
constructor(fieldData = Object.create(null)) {
|
|
14548
14568
|
super("field", fieldData);
|
|
14569
|
+
this.controlId = this.get("config.controlId") || this.get("meta.id");
|
|
14570
|
+
this.applyControlAttrConfig();
|
|
14549
14571
|
this.debouncedUpdateEditPanels = debounce(this.updateEditPanels);
|
|
14550
14572
|
this.debouncedUpdatePreview = debounce(this.updatePreview);
|
|
14551
14573
|
this.label = dom.create(this.labelConfig);
|
|
14552
14574
|
this.preview = this.fieldPreview();
|
|
14553
|
-
this.controlId = this.get("config.controlId") || this.get("meta.id");
|
|
14554
14575
|
const actionButtons = this.getActionButtons();
|
|
14555
14576
|
const hasEditButton = this.actionButtons.some((child) => child.meta?.id === "edit");
|
|
14556
14577
|
this.updateEditPanels();
|
|
@@ -14571,6 +14592,15 @@ var init_field = __esmMin((() => {
|
|
|
14571
14592
|
this.dom = field;
|
|
14572
14593
|
this.isEditing = false;
|
|
14573
14594
|
}
|
|
14595
|
+
/**
|
|
14596
|
+
* Honour control-level `disabledAttrs` / `lockedAttrs` by merging them into this field's
|
|
14597
|
+
* panels.attrs config. Reads both the registered control definition and the field's own
|
|
14598
|
+
* saved config so forms saved before a control changed still pick up its rules.
|
|
14599
|
+
*/
|
|
14600
|
+
applyControlAttrConfig() {
|
|
14601
|
+
const attrConfig = controlAttrPanelConfig(getControlConfig(components.controls?.get(this.controlId)), this.get("config"));
|
|
14602
|
+
if (attrConfig) this.config = { [this.id]: attrConfig };
|
|
14603
|
+
}
|
|
14574
14604
|
get labelConfig() {
|
|
14575
14605
|
if (!!this.get("config.hideLabel")) return null;
|
|
14576
14606
|
const { label, editorLabel, disableHtmlLabel, helpText, tooltip } = this.get("config");
|
|
@@ -15014,7 +15044,7 @@ var init_radio_group = __esmMin((() => {
|
|
|
15014
15044
|
},
|
|
15015
15045
|
config: {
|
|
15016
15046
|
label: s.get("controls.form.radio-group"),
|
|
15017
|
-
|
|
15047
|
+
disabledAttrs: ["type"]
|
|
15018
15048
|
},
|
|
15019
15049
|
meta: {
|
|
15020
15050
|
group: "common",
|
|
@@ -17187,7 +17217,7 @@ var init_dom = __esmMin((() => {
|
|
|
17187
17217
|
const { action, attrs = {} } = elem;
|
|
17188
17218
|
const fieldType = attrs.type || elem.tag;
|
|
17189
17219
|
const id = attrs.id || elem.id;
|
|
17190
|
-
const name =
|
|
17220
|
+
const name = isPreview ? id : groupInputName(attrs.name || id, fieldType, options.length);
|
|
17191
17221
|
const sharedInputAttrs = Object.fromEntries(OPTION_INPUT_ATTRS.filter((key) => key in attrs).map((key) => [key, attrs[key]]));
|
|
17192
17222
|
if (attrs.required) sharedInputAttrs.required = fieldType !== "checkbox" || !options.some(({ selected, checked }) => selected || checked);
|
|
17193
17223
|
const optionMap = (option, i) => {
|
|
@@ -18453,12 +18483,12 @@ var FormeoRenderer$1 = class {
|
|
|
18453
18483
|
* @return {Object|undefined}
|
|
18454
18484
|
*/
|
|
18455
18485
|
componentByName(name) {
|
|
18456
|
-
return this.components[baseId(name)] || Object.values(this.components).find((component) => component.attrs?.name === name);
|
|
18486
|
+
return this.components[baseId(name)] || Object.values(this.components).find((component) => component.attrs?.name === name || component.attrs?.name === `${name}[]`);
|
|
18457
18487
|
}
|
|
18458
18488
|
set userData(data = {}) {
|
|
18459
18489
|
const form = this.container.querySelector("form");
|
|
18460
18490
|
for (const key of Object.keys(data)) {
|
|
18461
|
-
const fields = form.elements[key];
|
|
18491
|
+
const fields = form.elements[key] ?? form.elements[`${key}[]`];
|
|
18462
18492
|
const checkables = checkableInputs(fields);
|
|
18463
18493
|
if (checkables?.[0].type === "checkbox") {
|
|
18464
18494
|
const values = Array.isArray(data[key]) ? data[key] : [data[key]];
|
|
@@ -18744,11 +18774,12 @@ var FormeoRenderer$1 = class {
|
|
|
18744
18774
|
};
|
|
18745
18775
|
getComponents = (address) => {
|
|
18746
18776
|
const components = [];
|
|
18747
|
-
const
|
|
18748
|
-
components.push(...this.renderedForm.querySelectorAll(`[name=
|
|
18777
|
+
const name = `f-${address.slice(address.indexOf(".") + 1)}`;
|
|
18778
|
+
components.push(...this.renderedForm.querySelectorAll(`[name="${name}"], [name="${name}[]"]`));
|
|
18749
18779
|
return components;
|
|
18750
18780
|
};
|
|
18751
18781
|
};
|
|
18782
|
+
var fieldKey = (key) => key.endsWith("[]") ? key.slice(0, -2) : key;
|
|
18752
18783
|
/**
|
|
18753
18784
|
* Converts a rendered form's fields to a plain object, the same shape the `userData`
|
|
18754
18785
|
* getter exposes. Handles multiple values for the same key by converting them to arrays.
|
|
@@ -18759,9 +18790,12 @@ var userDataOf = (form) => {
|
|
|
18759
18790
|
if (!form) return {};
|
|
18760
18791
|
const formEntries = new FormData(form);
|
|
18761
18792
|
const formDataObj = {};
|
|
18762
|
-
for (const [
|
|
18763
|
-
|
|
18764
|
-
|
|
18793
|
+
for (const [rawKey, value] of formEntries.entries()) {
|
|
18794
|
+
const key = fieldKey(rawKey);
|
|
18795
|
+
if (Object.hasOwn(formDataObj, key)) if (Array.isArray(formDataObj[key])) formDataObj[key].push(value);
|
|
18796
|
+
else formDataObj[key] = [formDataObj[key], value];
|
|
18797
|
+
else formDataObj[key] = value;
|
|
18798
|
+
}
|
|
18765
18799
|
return formDataObj;
|
|
18766
18800
|
};
|
|
18767
18801
|
var isCheckable = (elem) => ["checkbox", "radio"].includes(elem?.type);
|