@optionfactory/ful 0.37.0 → 0.39.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 CHANGED
@@ -700,6 +700,20 @@ var ful = (function (exports) {
700
700
 
701
701
  /* global Infinity, CSS */
702
702
 
703
+ function flatten(obj, prefix) {
704
+ return Object.keys(obj).reduce((acc, k) => {
705
+ const pre = prefix.length ? prefix + '.' : '';
706
+ if (typeof obj[k] === 'object' && obj[k] !== null) {
707
+ Object.assign(acc, flatten(obj[k], pre + k));
708
+ } else {
709
+ acc[pre + k] = obj[k];
710
+ }
711
+ return acc;
712
+ }, {});
713
+ }
714
+
715
+
716
+
703
717
  class Form extends Templated(HTMLElement) {
704
718
  static MUTATORS = {};
705
719
  static EXTRACTORS = {};
@@ -737,12 +751,9 @@ var ful = (function (exports) {
737
751
  });
738
752
  }
739
753
  setValues(values) {
740
- for (let k in values) {
741
- if (!values.hasOwnProperty(k)) {
742
- continue;
743
- }
744
- Array.from(this.querySelectorAll(`[name='${CSS.escape(k)}']`)).forEach((el) => {
745
- Form.mutate(Form.MUTATORS, el, values[k], k, values);
754
+ for (const [flattenedKey, value] of Object.entries(flatten(values, ''))) {
755
+ Array.from(this.querySelectorAll(`[name='${CSS.escape(flattenedKey)}']`)).forEach((el) => {
756
+ Form.mutate(Form.MUTATORS, el, value, flattenedKey);
746
757
  });
747
758
  }
748
759
  }
@@ -758,15 +769,13 @@ var ful = (function (exports) {
758
769
  return Form.providePath(result, el.getAttribute('name'), Form.extract(Form.EXTRACTORS, el));
759
770
  }, {});
760
771
  }
761
- setErrors(errors, scroll) {
772
+ setErrors(errors) {
762
773
  this.clearErrors();
763
774
  errors
764
775
  .filter((e) => e.type === 'FIELD_ERROR' || e.type === 'INVALID_FORMAT')
765
776
  .forEach((e) => {
766
777
  const name = e.context.replace("[", ".").replace("].", ".");
767
- //TODO: match [name=] ful-validation-target and [name=]:not(:has(ful-validation-target))
768
- //
769
- this.querySelectorAll(`[name='${CSS.escape(name)}']`)
778
+ this.querySelectorAll(`[name='${CSS.escape(name)}'] [ful-validation-target],[name='${CSS.escape(name)}']:not(:has([ful-validation-target]))`)
770
779
  .forEach(input => input.classList.add('is-invalid'));
771
780
  this.querySelectorAll(`ful-field-error[field='${CSS.escape(name)}']`)
772
781
  .forEach(el => el.innerText = e.reason);
@@ -780,7 +789,7 @@ var ful = (function (exports) {
780
789
  }
781
790
  });
782
791
 
783
- if (!scroll) {
792
+ if (!this.hasAttribute('scroll-on-error')) {
784
793
  return;
785
794
  }
786
795
  const ys = Array.from(this.querySelectorAll('ful-field-error'))
@@ -816,15 +825,12 @@ var ful = (function (exports) {
816
825
  if (el.dataset['fulBindType'] === 'boolean') {
817
826
  return !el.value ? null : el.value === 'true';
818
827
  }
819
- if (el.getValue) {
820
- return el.getValue();
821
- }
822
828
  return el.value || null;
823
829
  }
824
- static mutate(mutators, el, raw, key, values) {
830
+ static mutate(mutators, el, raw, flattenedKey) {
825
831
  const maybeMutator = mutators[el.dataset['fulBindMutator']] || mutators[el.dataset['fulBindProvide']];
826
832
  if (maybeMutator) {
827
- maybeMutator(el, raw, key, values);
833
+ maybeMutator(el, raw, flattenedKey);
828
834
  return;
829
835
  }
830
836
  if (el.getAttribute('type') === 'radio') {
@@ -835,10 +841,6 @@ var ful = (function (exports) {
835
841
  el.checked = raw;
836
842
  return;
837
843
  }
838
- if (el.setValue) {
839
- el.setValue(raw);
840
- return;
841
- }
842
844
  el.value = raw;
843
845
  }
844
846
 
@@ -893,21 +895,45 @@ var ful = (function (exports) {
893
895
  <ful-field-error data-tpl-if="name" data-tpl-field="name"></ful-field-error>
894
896
  `, ful_input_ec);
895
897
 
896
- class Input extends Templated(HTMLElement, ful_input_template_) {
898
+ class StatelessInput extends Templated(HTMLElement, ful_input_template_) {
897
899
  render(slotted, template) {
898
- const input = slotted.input = slotted.input || (() => {
900
+ const input = this.input = slotted.input = slotted.input || (() => {
899
901
  const el = document.createElement("input");
900
902
  el.classList.add("form-control");
901
903
  return el;
902
904
  })();
905
+ input.setAttribute('ful-validation-target', '');
906
+
903
907
  const id = input.getAttribute('id') || this.getAttribute('input-id') || Attributes.uid('ful-input');
904
908
  Attributes.forward('input-', this, slotted.input);
905
909
  Attributes.defaultValue(slotted.input, "id", id);
906
910
  Attributes.defaultValue(slotted.input, "type", "text");
907
911
  Attributes.defaultValue(slotted.input, "placeholder", " ");
908
- const name = input.getAttribute('name');
912
+ const name = this.getAttribute('name');
909
913
  return template.render({ id, name, slotted });
910
914
  }
915
+
916
+ }
917
+
918
+ class Input extends Stateful(StatelessInput, [], ['value']) {
919
+ render(slotted, template) {
920
+ const fragment = super.render(slotted, template);
921
+ this.input.value = this.getAttribute('value');
922
+ return fragment;
923
+ }
924
+ get value() {
925
+ if (this.input) {
926
+ return this.getAttribute('value');
927
+ }
928
+ return this.input.value;
929
+ }
930
+ set value(value) {
931
+ if (!this.input) {
932
+ //handled during rendering
933
+ return;
934
+ }
935
+ this.input.value = value;
936
+ }
911
937
  static configure() {
912
938
  customElements.define('ful-input', Input);
913
939
  }
@@ -944,18 +970,17 @@ var ful = (function (exports) {
944
970
  const type = this.getAttribute("type") || 'local';
945
971
  const remote = type != 'local';
946
972
  const loadOnce = this.getAttribute('load') != 'always';
947
-
973
+ const name = this.getAttribute('name');
948
974
  const input = slotted.input = slotted.input || (() => {
949
975
  return document.createElement("select");
950
976
  })();
977
+ input.setAttribute('ful-validation-target', '');
978
+
951
979
  const id = input.getAttribute('id') || this.getAttribute('input-id') || Attributes.uid('ful-select');
952
980
  const tsId = `${id}-ts-control`;
953
981
  Attributes.forward('input-', this, input);
954
982
  Attributes.defaultValue(input, "id", id);
955
983
  Attributes.defaultValue(input, "placeholder", " ");
956
- const name = input.getAttribute('name');
957
- input.setValue = this.setValue.bind(this);
958
- input.getValue = this.getValue.bind(this);
959
984
 
960
985
  //tomselect needs the input to have a parent.
961
986
  //se we move the input to a fragment
@@ -996,19 +1021,19 @@ var ful = (function (exports) {
996
1021
  load: this._unwrappedRemoteLoad,
997
1022
  shouldLoad: (query) => this.shouldLoad ? this.shouldLoad(query) : true
998
1023
  } : {}, tsDefaultConfig, this.tsConfig));
999
- console.log("ts created");
1000
1024
  //we remove the input to move it
1001
1025
  input.remove();
1002
-
1003
1026
  return template.render({ id, tsId, name, input, slotted });
1004
1027
  }
1005
- async setValue(v) {
1006
- if(this._remote){
1007
- await this._unwrappedRemoteLoad({byId: v}, this.ts.loadCallback.bind(this.ts));
1008
- }
1009
- this.ts.setValue(v);
1028
+ set value(v) {
1029
+ (async () => {
1030
+ if(this._remote){
1031
+ await this._unwrappedRemoteLoad({byId: v}, this.ts.loadCallback.bind(this.ts));
1032
+ }
1033
+ this.ts.setValue(v);
1034
+ })();
1010
1035
  }
1011
- getValue() {
1036
+ get value() {
1012
1037
  const v = this.ts.getValue();
1013
1038
  return v === '' ? null : v;
1014
1039
  }
@@ -1050,14 +1075,16 @@ var ful = (function (exports) {
1050
1075
 
1051
1076
  class RadioGroup extends Stateful(Templated(HTMLElement, ful_radiougroup_template_), ['disabled']) {
1052
1077
  render(slotted, template) {
1053
- const name = this.getAttribute('input-name') || Attributes.uid('ful-radiogroup');
1078
+ const name = this.getAttribute('name') || Attributes.uid('ful-radiogroup');
1054
1079
  const radioEls = Array.from(slotted.default.querySelectorAll('ful-radio'));
1055
1080
  const inputsAndLabels = radioEls.map(el => {
1056
1081
  const input = document.createElement('input');
1057
1082
  input.setAttribute('type', 'radio');
1058
1083
  Attributes.forward('input-', this, input);
1059
1084
  Attributes.forward('', el, input);
1060
- Attributes.defaultValue(input, 'name', name);
1085
+ input.setAttribute('name', `${name}-ignore`);
1086
+ input.setAttribute('ful-validation-target', '');
1087
+ input.dataset['fulBindInclude'] = 'never';
1061
1088
  const label = Fragments.fromChildNodes(el);
1062
1089
  return [input, label];
1063
1090
  });
@@ -1070,6 +1097,13 @@ var ful = (function (exports) {
1070
1097
  });
1071
1098
  return fragment;
1072
1099
  }
1100
+ get value() {
1101
+ const checked = this.querySelector('input[type=radio]:checked');
1102
+ return checked ? checked.value : null;
1103
+ }
1104
+ set value(value){
1105
+ this.querySelector(`input[type=radio][value=${CSS.escape(value)}]`).checked = true;
1106
+ }
1073
1107
  static configure() {
1074
1108
  customElements.define('ful-radio-group', RadioGroup);
1075
1109
  }
@@ -1193,6 +1227,7 @@ var ful = (function (exports) {
1193
1227
  exports.Slots = Slots;
1194
1228
  exports.Spinner = Spinner;
1195
1229
  exports.Stateful = Stateful;
1230
+ exports.StatelessInput = StatelessInput;
1196
1231
  exports.Templated = Templated;
1197
1232
  exports.VersionedStorage = VersionedStorage;
1198
1233
  exports.Wizard = Wizard;