@optionfactory/ful 0.46.0 → 0.48.0
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/ful.iife.js +149 -131
- package/dist/ful.iife.js.map +1 -1
- package/dist/ful.iife.min.js +1 -1
- package/dist/ful.iife.min.js.map +1 -1
- package/dist/ful.min.mjs +1 -1
- package/dist/ful.min.mjs.map +1 -1
- package/dist/ful.mjs +147 -129
- package/dist/ful.mjs.map +1 -1
- package/package.json +1 -1
package/dist/ful.iife.js
CHANGED
|
@@ -668,6 +668,38 @@ var ful = (function (exports) {
|
|
|
668
668
|
}
|
|
669
669
|
}
|
|
670
670
|
|
|
671
|
+
class TemplateRegistry {
|
|
672
|
+
#idToFragment = {};
|
|
673
|
+
#idToTemplate = {};
|
|
674
|
+
#ec;
|
|
675
|
+
put(k, fragment) {
|
|
676
|
+
if (this.#ec) {
|
|
677
|
+
this.#idToTemplate[k] = ftl.Template.fromFragment(fragment, ec);
|
|
678
|
+
return;
|
|
679
|
+
}
|
|
680
|
+
this.#idToFragment[k] = fragment;
|
|
681
|
+
}
|
|
682
|
+
get(k) {
|
|
683
|
+
if (!this.#ec) {
|
|
684
|
+
throw new Error("evaluationContext is not configured");
|
|
685
|
+
}
|
|
686
|
+
const tpl = this.#idToTemplate[k];
|
|
687
|
+
if (!tpl) {
|
|
688
|
+
throw new Error(`missing template: '${k}'`);
|
|
689
|
+
}
|
|
690
|
+
return tpl;
|
|
691
|
+
}
|
|
692
|
+
configure(ec) {
|
|
693
|
+
this.#ec = ec;
|
|
694
|
+
for (const [k, fragment] of Object.entries(this.#idToFragment)) {
|
|
695
|
+
delete this.#idToFragment[k];
|
|
696
|
+
this.#idToTemplate[k] = ftl.Template.fromFragment(fragment, ec);
|
|
697
|
+
}
|
|
698
|
+
}
|
|
699
|
+
}
|
|
700
|
+
|
|
701
|
+
const templates = new TemplateRegistry();
|
|
702
|
+
|
|
671
703
|
class UpgradeQueue {
|
|
672
704
|
#q = [];
|
|
673
705
|
constructor() {
|
|
@@ -686,83 +718,85 @@ var ful = (function (exports) {
|
|
|
686
718
|
|
|
687
719
|
const upgradeQueue = new UpgradeQueue();
|
|
688
720
|
|
|
689
|
-
|
|
690
|
-
#parsed;
|
|
691
|
-
connectedCallback() {
|
|
692
|
-
if (this.#parsed) {
|
|
693
|
-
return;
|
|
694
|
-
}
|
|
695
|
-
if (this.ownerDocument.readyState === 'complete' || Nodes.isParsed(this)) {
|
|
696
|
-
upgradeQueue.enqueue(this);
|
|
697
|
-
return;
|
|
698
|
-
}
|
|
699
|
-
this.ownerDocument.addEventListener('DOMContentLoaded', () => {
|
|
700
|
-
observer.disconnect();
|
|
701
|
-
upgradeQueue.enqueue(this);
|
|
702
|
-
});
|
|
703
|
-
const observer = new MutationObserver(() => {
|
|
704
|
-
if (!Nodes.isParsed(this)) {
|
|
705
|
-
return;
|
|
706
|
-
}
|
|
707
|
-
observer.disconnect();
|
|
708
|
-
upgradeQueue.enqueue(this);
|
|
709
|
-
});
|
|
710
|
-
observer.observe(this.parentNode, { childList: true, subtree: true });
|
|
711
|
-
}
|
|
712
|
-
attributeChangedCallback(name, oldValue, newValue) {
|
|
713
|
-
if (!this.#parsed || oldValue === newValue) {
|
|
714
|
-
return;
|
|
715
|
-
}
|
|
716
|
-
this[name] = newValue;
|
|
717
|
-
}
|
|
718
|
-
upgrade() {
|
|
719
|
-
if (this.#parsed) {
|
|
720
|
-
return;
|
|
721
|
-
}
|
|
722
|
-
this.#parsed = true;
|
|
723
|
-
return this.ready();
|
|
724
|
-
}
|
|
725
|
-
}
|
|
726
|
-
|
|
721
|
+
const ParsedElement = (flags, others) => {
|
|
727
722
|
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
const slotted = Slots.from(this);
|
|
732
|
-
const fragment = await Promise.resolve(this.render(slotted, template));
|
|
733
|
-
this.replaceChildren(fragment);
|
|
734
|
-
}
|
|
735
|
-
};
|
|
736
|
-
};
|
|
737
|
-
|
|
738
|
-
const Stateful = (SuperClass, flags, others) => {
|
|
723
|
+
const observed_flags = flags || [];
|
|
724
|
+
const observed_others = others || [];
|
|
725
|
+
const observed = [].concat(observed_flags).concat(observed_others);
|
|
739
726
|
|
|
740
|
-
const
|
|
741
|
-
|
|
742
|
-
const k = class extends SuperClass {
|
|
727
|
+
const k = class extends HTMLElement {
|
|
743
728
|
static get observedAttributes() {
|
|
744
|
-
return
|
|
729
|
+
return observed;
|
|
745
730
|
}
|
|
731
|
+
#parsed;
|
|
732
|
+
#internals;
|
|
746
733
|
constructor(...args) {
|
|
747
734
|
super(...args);
|
|
748
|
-
this
|
|
735
|
+
this.#internals = this.attachInternals();
|
|
736
|
+
}
|
|
737
|
+
get internals() {
|
|
738
|
+
return this.#internals;
|
|
739
|
+
}
|
|
740
|
+
connectedCallback() {
|
|
741
|
+
if (this.#parsed) {
|
|
742
|
+
return;
|
|
743
|
+
}
|
|
744
|
+
if (this.ownerDocument.readyState === 'complete' || Nodes.isParsed(this)) {
|
|
745
|
+
upgradeQueue.enqueue(this);
|
|
746
|
+
return;
|
|
747
|
+
}
|
|
748
|
+
this.ownerDocument.addEventListener('DOMContentLoaded', () => {
|
|
749
|
+
observer.disconnect();
|
|
750
|
+
upgradeQueue.enqueue(this);
|
|
751
|
+
});
|
|
752
|
+
const observer = new MutationObserver(() => {
|
|
753
|
+
if (!Nodes.isParsed(this)) {
|
|
754
|
+
return;
|
|
755
|
+
}
|
|
756
|
+
observer.disconnect();
|
|
757
|
+
upgradeQueue.enqueue(this);
|
|
758
|
+
});
|
|
759
|
+
observer.observe(this.parentNode, { childList: true, subtree: true });
|
|
749
760
|
}
|
|
761
|
+
attributeChangedCallback(name, oldValue, newValue) {
|
|
762
|
+
if (!this.#parsed || oldValue === newValue) {
|
|
763
|
+
return;
|
|
764
|
+
}
|
|
765
|
+
this[name] = newValue;
|
|
766
|
+
}
|
|
767
|
+
async upgrade() {
|
|
768
|
+
if (this.#parsed) {
|
|
769
|
+
return;
|
|
770
|
+
}
|
|
771
|
+
this.#parsed = true;
|
|
772
|
+
await this.render();
|
|
773
|
+
for (const flag of observed_flags) {
|
|
774
|
+
if(this.hasAttribute(flag)){
|
|
775
|
+
this[flag] = true;
|
|
776
|
+
}
|
|
777
|
+
}
|
|
778
|
+
for (const other of observed_others) {
|
|
779
|
+
if(this.hasAttribute(other)){
|
|
780
|
+
this[other] = this.getAttribute(other);
|
|
781
|
+
}
|
|
782
|
+
}
|
|
783
|
+
}
|
|
750
784
|
};
|
|
751
785
|
|
|
752
|
-
for (const flag of
|
|
786
|
+
for (const flag of observed_flags) {
|
|
753
787
|
Object.defineProperty(k.prototype, flag, {
|
|
754
788
|
enumerable: true,
|
|
755
789
|
configurable: true,
|
|
756
790
|
get() {
|
|
757
|
-
return this.
|
|
791
|
+
return this.internals.states.has(`--${flag}`);
|
|
758
792
|
},
|
|
759
793
|
set(value) {
|
|
760
794
|
//see https://developer.mozilla.org/en-US/docs/Web/API/CustomStateSet#using_double_dash_prefixed_idents
|
|
761
795
|
if (Attributes.asBoolean(value)) {
|
|
762
|
-
this.
|
|
796
|
+
this.internals.states.add(`--${flag}`);
|
|
763
797
|
return;
|
|
764
798
|
}
|
|
765
|
-
this.
|
|
799
|
+
this.internals.states.delete(`--${flag}`);
|
|
766
800
|
}
|
|
767
801
|
});
|
|
768
802
|
}
|
|
@@ -839,12 +873,12 @@ var ful = (function (exports) {
|
|
|
839
873
|
el.value = raw;
|
|
840
874
|
}
|
|
841
875
|
|
|
842
|
-
class Form extends
|
|
876
|
+
class Form extends ParsedElement() {
|
|
843
877
|
static IGNORED_CHILDREN_SELECTOR = '.d-none, [hidden]';
|
|
844
878
|
static SCROLL_OFFSET = 50;
|
|
845
|
-
render(
|
|
879
|
+
render() {
|
|
846
880
|
const form = document.createElement('form');
|
|
847
|
-
form.
|
|
881
|
+
form.replaceChildren(...this.childNodes);
|
|
848
882
|
form.addEventListener('submit', async (e) => {
|
|
849
883
|
e.preventDefault();
|
|
850
884
|
this.spinner(true);
|
|
@@ -862,7 +896,7 @@ var ful = (function (exports) {
|
|
|
862
896
|
this.spinner(false);
|
|
863
897
|
}
|
|
864
898
|
});
|
|
865
|
-
|
|
899
|
+
this.replaceChildren(form);
|
|
866
900
|
}
|
|
867
901
|
spinner(spin) {
|
|
868
902
|
this.querySelectorAll('ful-spinner').forEach(el => el.hidden = !spin);
|
|
@@ -919,11 +953,7 @@ var ful = (function (exports) {
|
|
|
919
953
|
}
|
|
920
954
|
}
|
|
921
955
|
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
});
|
|
925
|
-
|
|
926
|
-
const ful_input_template_ = globalThis.ful_input_template || ftl.Template.fromHtml(`
|
|
956
|
+
templates.put('ful-input', Fragments.fromHtml(`
|
|
927
957
|
<label data-tpl-for="id" class="form-label">{{{{ slotted.default }}}}</label>
|
|
928
958
|
<div class="input-group">
|
|
929
959
|
<span data-tpl-if="slotted.ibefore" class="input-group-text">{{{{ slotted.ibefore }}}}</span>
|
|
@@ -933,33 +963,31 @@ var ful = (function (exports) {
|
|
|
933
963
|
<span data-tpl-if="slotted.iafter" class="input-group-text">{{{{ slotted.iafter }}}}</span>
|
|
934
964
|
</div>
|
|
935
965
|
<ful-field-error data-tpl-if="name" data-tpl-field="name"></ful-field-error>
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
}
|
|
966
|
+
`));
|
|
967
|
+
|
|
968
|
+
|
|
969
|
+
const makeInputFragment = (el, slotted) => {
|
|
970
|
+
const input = el.input = slotted.input = slotted.input || (() => {
|
|
971
|
+
const el = document.createElement("input");
|
|
972
|
+
el.classList.add("form-control");
|
|
973
|
+
return el;
|
|
974
|
+
})();
|
|
975
|
+
input.setAttribute('ful-validation-target', '');
|
|
976
|
+
|
|
977
|
+
const id = input.getAttribute('id') || el.getAttribute('input-id') || Attributes.uid('ful-input');
|
|
978
|
+
Attributes.forward('input-', el, slotted.input);
|
|
979
|
+
Attributes.defaultValue(slotted.input, "id", id);
|
|
980
|
+
Attributes.defaultValue(slotted.input, "type", "text");
|
|
981
|
+
Attributes.defaultValue(slotted.input, "placeholder", " ");
|
|
982
|
+
const name = el.getAttribute('name');
|
|
983
|
+
return templates.get('ful-input').render(el, { id, name, slotted });
|
|
984
|
+
};
|
|
957
985
|
|
|
958
|
-
class Input extends
|
|
959
|
-
render(
|
|
960
|
-
const
|
|
961
|
-
|
|
962
|
-
|
|
986
|
+
class Input extends ParsedElement([], ['value']) {
|
|
987
|
+
render() {
|
|
988
|
+
const slotted = Slots.from(el);
|
|
989
|
+
const fragment = makeInputFragment(this, slotted);
|
|
990
|
+
this.replaceChildren(fragment);
|
|
963
991
|
}
|
|
964
992
|
get value() {
|
|
965
993
|
return this.input.value;
|
|
@@ -973,11 +1001,8 @@ var ful = (function (exports) {
|
|
|
973
1001
|
* <script src="tom-select.complete.js"></script>
|
|
974
1002
|
* <link href="tom-select.bootstrap5.css" rel="stylesheet" />
|
|
975
1003
|
*/
|
|
976
|
-
const ful_select_ec = globalThis.ec || ftl.EvaluationContext.configure({
|
|
977
|
-
|
|
978
|
-
});
|
|
979
1004
|
|
|
980
|
-
|
|
1005
|
+
templates.put('ful-select', Fragments.fromHtml(`
|
|
981
1006
|
<label data-tpl-for="tsId" class="form-label">{{{{ slotted.default }}}}</label>
|
|
982
1007
|
{{{{ input }}}}
|
|
983
1008
|
<div class="input-group">
|
|
@@ -988,15 +1013,17 @@ var ful = (function (exports) {
|
|
|
988
1013
|
<span data-tpl-if="slotted.iafter" class="input-group-text">{{{{ slotted.iafter }}}}</span>
|
|
989
1014
|
</div>
|
|
990
1015
|
<ful-field-error data-tpl-if="name" data-tpl-field="name"></ful-field-error>
|
|
991
|
-
|
|
1016
|
+
`));
|
|
992
1017
|
|
|
993
1018
|
|
|
994
|
-
class Select extends
|
|
1019
|
+
class Select extends ParsedElement([], ["value"]) {
|
|
995
1020
|
constructor(tsConfig) {
|
|
996
1021
|
super();
|
|
997
1022
|
this.tsConfig = tsConfig;
|
|
998
1023
|
}
|
|
999
|
-
render(
|
|
1024
|
+
render() {
|
|
1025
|
+
const slotted = Slots.from(this);
|
|
1026
|
+
|
|
1000
1027
|
const type = this.getAttribute("type") || 'local';
|
|
1001
1028
|
const remote = type != 'local';
|
|
1002
1029
|
const loadOnce = this.getAttribute('load') != 'always';
|
|
@@ -1024,7 +1051,6 @@ var ful = (function (exports) {
|
|
|
1024
1051
|
}
|
|
1025
1052
|
};
|
|
1026
1053
|
|
|
1027
|
-
|
|
1028
1054
|
this._remote = remote;
|
|
1029
1055
|
// we need to await this load in setValue when remote is configured and the option
|
|
1030
1056
|
// is not loaded yet.
|
|
@@ -1039,7 +1065,7 @@ var ful = (function (exports) {
|
|
|
1039
1065
|
const type = query && query.hasOwnProperty('byId') ? 'id' : 'query';
|
|
1040
1066
|
const qvalue = type === 'id' ? query.byId : query;
|
|
1041
1067
|
const data = await (this.loader ? this.loader(qvalue, type) : []);
|
|
1042
|
-
if(type !== 'id'){
|
|
1068
|
+
if (type !== 'id') {
|
|
1043
1069
|
this.loaded = true;
|
|
1044
1070
|
}
|
|
1045
1071
|
callback(data);
|
|
@@ -1053,12 +1079,12 @@ var ful = (function (exports) {
|
|
|
1053
1079
|
} : {}, tsDefaultConfig, this.tsConfig));
|
|
1054
1080
|
//we remove the input to move it
|
|
1055
1081
|
input.remove();
|
|
1056
|
-
|
|
1082
|
+
templates.get('ful-select').renderTo(this, { id, tsId, name, input, slotted });
|
|
1057
1083
|
}
|
|
1058
1084
|
set value(v) {
|
|
1059
1085
|
(async () => {
|
|
1060
|
-
if(this._remote){
|
|
1061
|
-
await this._unwrappedRemoteLoad({byId: v}, this.ts.loadCallback.bind(this.ts));
|
|
1086
|
+
if (this._remote) {
|
|
1087
|
+
await this._unwrappedRemoteLoad({ byId: v }, this.ts.loadCallback.bind(this.ts));
|
|
1062
1088
|
}
|
|
1063
1089
|
this.ts.setValue(v);
|
|
1064
1090
|
})();
|
|
@@ -1069,11 +1095,7 @@ var ful = (function (exports) {
|
|
|
1069
1095
|
}
|
|
1070
1096
|
}
|
|
1071
1097
|
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
});
|
|
1075
|
-
|
|
1076
|
-
const ful_radiougroup_template_ = globalThis.ful_radiogroup_template || ftl.Template.fromHtml(`
|
|
1098
|
+
templates.put('ful-radio-group', Fragments.fromHtml(`
|
|
1077
1099
|
<fieldset>
|
|
1078
1100
|
<legend class="form-label">
|
|
1079
1101
|
{{{{ slotted.default }}}}
|
|
@@ -1092,11 +1114,12 @@ var ful = (function (exports) {
|
|
|
1092
1114
|
{{{{ slotted.footer }}}}
|
|
1093
1115
|
</footer>
|
|
1094
1116
|
</fieldset>
|
|
1095
|
-
|
|
1117
|
+
`));
|
|
1096
1118
|
|
|
1097
1119
|
|
|
1098
|
-
class RadioGroup extends
|
|
1099
|
-
render(
|
|
1120
|
+
class RadioGroup extends ParsedElement(['disabled'], ['value']) {
|
|
1121
|
+
render() {
|
|
1122
|
+
const slotted = Slots.from(this);
|
|
1100
1123
|
const name = this.getAttribute('name') || Attributes.uid('ful-radiogroup');
|
|
1101
1124
|
const radioEls = Array.from(slotted.default.querySelectorAll('ful-radio'));
|
|
1102
1125
|
const inputsAndLabels = radioEls.map(el => {
|
|
@@ -1111,38 +1134,32 @@ var ful = (function (exports) {
|
|
|
1111
1134
|
return [input, label];
|
|
1112
1135
|
});
|
|
1113
1136
|
radioEls.forEach(el => el.remove());
|
|
1114
|
-
|
|
1115
|
-
const fragment = template.render({
|
|
1137
|
+
templates.get('ful-radio-group').renderTo(this, {
|
|
1116
1138
|
name: name,
|
|
1117
1139
|
slotted: slotted,
|
|
1118
1140
|
inputsAndLabels: inputsAndLabels
|
|
1119
1141
|
});
|
|
1120
|
-
return fragment;
|
|
1121
1142
|
}
|
|
1122
1143
|
get value() {
|
|
1123
1144
|
const checked = this.querySelector('input[type=radio]:checked');
|
|
1124
1145
|
return checked ? checked.value : null;
|
|
1125
1146
|
}
|
|
1126
|
-
set value(value){
|
|
1147
|
+
set value(value) {
|
|
1127
1148
|
this.querySelector(`input[type=radio][value=${CSS.escape(value)}]`).checked = true;
|
|
1128
1149
|
}
|
|
1129
1150
|
}
|
|
1130
1151
|
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
});
|
|
1134
|
-
|
|
1135
|
-
const ful_spinner_template_ = globalThis.ful_spinner_template || ftl.Template.fromHtml(`
|
|
1152
|
+
templates.put('ful-spinner', Fragments.fromHtml(`
|
|
1136
1153
|
<div class="ful-spinner-wrapper">
|
|
1137
1154
|
<div class="ful-spinner-text">{{{{ slotted.default }}}}</div>
|
|
1138
1155
|
<div class="ful-spinner-icon"></div>
|
|
1139
1156
|
</div>
|
|
1140
|
-
|
|
1157
|
+
`));
|
|
1141
1158
|
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1159
|
+
class Spinner extends ParsedElement() {
|
|
1160
|
+
render() {
|
|
1161
|
+
const slotted = Slots.from(this);
|
|
1162
|
+
templates.get('ful-spinner').renderTo(this, { slotted });
|
|
1146
1163
|
}
|
|
1147
1164
|
}
|
|
1148
1165
|
|
|
@@ -1219,7 +1236,8 @@ var ful = (function (exports) {
|
|
|
1219
1236
|
}
|
|
1220
1237
|
|
|
1221
1238
|
class CustomElements {
|
|
1222
|
-
static configure() {
|
|
1239
|
+
static configure(ec) {
|
|
1240
|
+
templates.configure(ec);
|
|
1223
1241
|
customElements.define('ful-spinner', Spinner);
|
|
1224
1242
|
customElements.define('ful-input', Input);
|
|
1225
1243
|
customElements.define('ful-radio-group', RadioGroup);
|
|
@@ -1248,16 +1266,16 @@ var ful = (function (exports) {
|
|
|
1248
1266
|
exports.SessionStorage = SessionStorage;
|
|
1249
1267
|
exports.Slots = Slots;
|
|
1250
1268
|
exports.Spinner = Spinner;
|
|
1251
|
-
exports.Stateful = Stateful;
|
|
1252
|
-
exports.StatelessInput = StatelessInput;
|
|
1253
1269
|
exports.SyncEvent = SyncEvent;
|
|
1254
|
-
exports.
|
|
1270
|
+
exports.TemplateRegistry = TemplateRegistry;
|
|
1255
1271
|
exports.VersionedStorage = VersionedStorage;
|
|
1256
1272
|
exports.Wizard = Wizard;
|
|
1257
1273
|
exports.jsonPatch = jsonPatch;
|
|
1258
1274
|
exports.jsonPost = jsonPost;
|
|
1259
1275
|
exports.jsonPut = jsonPut;
|
|
1260
1276
|
exports.jsonRequest = jsonRequest;
|
|
1277
|
+
exports.makeInputFragment = makeInputFragment;
|
|
1278
|
+
exports.templates = templates;
|
|
1261
1279
|
exports.timing = timing;
|
|
1262
1280
|
|
|
1263
1281
|
Object.defineProperty(exports, '__esModule', { value: true });
|