@optionfactory/ful 0.37.0 → 0.38.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
 
@@ -895,19 +897,27 @@ var ful = (function (exports) {
895
897
 
896
898
  class Input 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
+ get value(){
916
+ return this.input.value;
917
+ }
918
+ set value(value){
919
+ this.input.value = value;
920
+ }
911
921
  static configure() {
912
922
  customElements.define('ful-input', Input);
913
923
  }
@@ -944,18 +954,17 @@ var ful = (function (exports) {
944
954
  const type = this.getAttribute("type") || 'local';
945
955
  const remote = type != 'local';
946
956
  const loadOnce = this.getAttribute('load') != 'always';
947
-
957
+ const name = this.getAttribute('name');
948
958
  const input = slotted.input = slotted.input || (() => {
949
959
  return document.createElement("select");
950
960
  })();
961
+ input.setAttribute('ful-validation-target', '');
962
+
951
963
  const id = input.getAttribute('id') || this.getAttribute('input-id') || Attributes.uid('ful-select');
952
964
  const tsId = `${id}-ts-control`;
953
965
  Attributes.forward('input-', this, input);
954
966
  Attributes.defaultValue(input, "id", id);
955
967
  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
968
 
960
969
  //tomselect needs the input to have a parent.
961
970
  //se we move the input to a fragment
@@ -996,19 +1005,19 @@ var ful = (function (exports) {
996
1005
  load: this._unwrappedRemoteLoad,
997
1006
  shouldLoad: (query) => this.shouldLoad ? this.shouldLoad(query) : true
998
1007
  } : {}, tsDefaultConfig, this.tsConfig));
999
- console.log("ts created");
1000
1008
  //we remove the input to move it
1001
1009
  input.remove();
1002
-
1003
1010
  return template.render({ id, tsId, name, input, slotted });
1004
1011
  }
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);
1012
+ set value(v) {
1013
+ (async () => {
1014
+ if(this._remote){
1015
+ await this._unwrappedRemoteLoad({byId: v}, this.ts.loadCallback.bind(this.ts));
1016
+ }
1017
+ this.ts.setValue(v);
1018
+ })();
1010
1019
  }
1011
- getValue() {
1020
+ get value() {
1012
1021
  const v = this.ts.getValue();
1013
1022
  return v === '' ? null : v;
1014
1023
  }
@@ -1050,14 +1059,16 @@ var ful = (function (exports) {
1050
1059
 
1051
1060
  class RadioGroup extends Stateful(Templated(HTMLElement, ful_radiougroup_template_), ['disabled']) {
1052
1061
  render(slotted, template) {
1053
- const name = this.getAttribute('input-name') || Attributes.uid('ful-radiogroup');
1062
+ const name = this.getAttribute('name') || Attributes.uid('ful-radiogroup');
1054
1063
  const radioEls = Array.from(slotted.default.querySelectorAll('ful-radio'));
1055
1064
  const inputsAndLabels = radioEls.map(el => {
1056
1065
  const input = document.createElement('input');
1057
1066
  input.setAttribute('type', 'radio');
1058
1067
  Attributes.forward('input-', this, input);
1059
1068
  Attributes.forward('', el, input);
1060
- Attributes.defaultValue(input, 'name', name);
1069
+ input.setAttribute('name', `${name}-ignore`);
1070
+ input.setAttribute('ful-validation-target', '');
1071
+ input.dataset['fulBindInclude'] = 'never';
1061
1072
  const label = Fragments.fromChildNodes(el);
1062
1073
  return [input, label];
1063
1074
  });
@@ -1070,6 +1081,13 @@ var ful = (function (exports) {
1070
1081
  });
1071
1082
  return fragment;
1072
1083
  }
1084
+ get value() {
1085
+ const checked = this.querySelector('input[type=radio]:checked');
1086
+ return checked ? checked.value : null;
1087
+ }
1088
+ set value(value){
1089
+ this.querySelector(`input[type=radio][value=${CSS.escape(value)}]`).checked = true;
1090
+ }
1073
1091
  static configure() {
1074
1092
  customElements.define('ful-radio-group', RadioGroup);
1075
1093
  }