@optionfactory/ful 0.36.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 = {};
@@ -713,7 +727,7 @@ var ful = (function (exports) {
713
727
  e.preventDefault();
714
728
  this.spinner(true);
715
729
  try {
716
- if(this.submitter) {
730
+ if (this.submitter) {
717
731
  await this.submitter(this.getValues(), this);
718
732
  }
719
733
  } catch (e) {
@@ -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'))
@@ -818,10 +827,10 @@ var ful = (function (exports) {
818
827
  }
819
828
  return el.value || null;
820
829
  }
821
- static mutate(mutators, el, raw, key, values) {
830
+ static mutate(mutators, el, raw, flattenedKey) {
822
831
  const maybeMutator = mutators[el.dataset['fulBindMutator']] || mutators[el.dataset['fulBindProvide']];
823
832
  if (maybeMutator) {
824
- maybeMutator(el, raw, key, values);
833
+ maybeMutator(el, raw, flattenedKey);
825
834
  return;
826
835
  }
827
836
  if (el.getAttribute('type') === 'radio') {
@@ -888,19 +897,27 @@ var ful = (function (exports) {
888
897
 
889
898
  class Input extends Templated(HTMLElement, ful_input_template_) {
890
899
  render(slotted, template) {
891
- const input = slotted.input = slotted.input || (() => {
900
+ const input = this.input = slotted.input = slotted.input || (() => {
892
901
  const el = document.createElement("input");
893
902
  el.classList.add("form-control");
894
903
  return el;
895
904
  })();
905
+ input.setAttribute('ful-validation-target', '');
906
+
896
907
  const id = input.getAttribute('id') || this.getAttribute('input-id') || Attributes.uid('ful-input');
897
908
  Attributes.forward('input-', this, slotted.input);
898
909
  Attributes.defaultValue(slotted.input, "id", id);
899
910
  Attributes.defaultValue(slotted.input, "type", "text");
900
911
  Attributes.defaultValue(slotted.input, "placeholder", " ");
901
- const name = input.getAttribute('name');
912
+ const name = this.getAttribute('name');
902
913
  return template.render({ id, name, slotted });
903
914
  }
915
+ get value(){
916
+ return this.input.value;
917
+ }
918
+ set value(value){
919
+ this.input.value = value;
920
+ }
904
921
  static configure() {
905
922
  customElements.define('ful-input', Input);
906
923
  }
@@ -937,18 +954,17 @@ var ful = (function (exports) {
937
954
  const type = this.getAttribute("type") || 'local';
938
955
  const remote = type != 'local';
939
956
  const loadOnce = this.getAttribute('load') != 'always';
940
-
957
+ const name = this.getAttribute('name');
941
958
  const input = slotted.input = slotted.input || (() => {
942
959
  return document.createElement("select");
943
960
  })();
961
+ input.setAttribute('ful-validation-target', '');
962
+
944
963
  const id = input.getAttribute('id') || this.getAttribute('input-id') || Attributes.uid('ful-select');
945
964
  const tsId = `${id}-ts-control`;
946
965
  Attributes.forward('input-', this, input);
947
966
  Attributes.defaultValue(input, "id", id);
948
967
  Attributes.defaultValue(input, "placeholder", " ");
949
- const name = input.getAttribute('name');
950
- input.setValue = this.setValue.bind(this);
951
- input.getValue = this.getValue.bind(this);
952
968
 
953
969
  //tomselect needs the input to have a parent.
954
970
  //se we move the input to a fragment
@@ -989,19 +1005,19 @@ var ful = (function (exports) {
989
1005
  load: this._unwrappedRemoteLoad,
990
1006
  shouldLoad: (query) => this.shouldLoad ? this.shouldLoad(query) : true
991
1007
  } : {}, tsDefaultConfig, this.tsConfig));
992
- console.log("ts created");
993
1008
  //we remove the input to move it
994
1009
  input.remove();
995
-
996
1010
  return template.render({ id, tsId, name, input, slotted });
997
1011
  }
998
- async setValue(v) {
999
- if(this._remote){
1000
- await this._unwrappedRemoteLoad({byId: v}, this.ts.loadCallback.bind(this.ts));
1001
- }
1002
- 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
+ })();
1003
1019
  }
1004
- getValue() {
1020
+ get value() {
1005
1021
  const v = this.ts.getValue();
1006
1022
  return v === '' ? null : v;
1007
1023
  }
@@ -1043,14 +1059,16 @@ var ful = (function (exports) {
1043
1059
 
1044
1060
  class RadioGroup extends Stateful(Templated(HTMLElement, ful_radiougroup_template_), ['disabled']) {
1045
1061
  render(slotted, template) {
1046
- const name = this.getAttribute('input-name') || Attributes.uid('ful-radiogroup');
1062
+ const name = this.getAttribute('name') || Attributes.uid('ful-radiogroup');
1047
1063
  const radioEls = Array.from(slotted.default.querySelectorAll('ful-radio'));
1048
1064
  const inputsAndLabels = radioEls.map(el => {
1049
1065
  const input = document.createElement('input');
1050
1066
  input.setAttribute('type', 'radio');
1051
1067
  Attributes.forward('input-', this, input);
1052
1068
  Attributes.forward('', el, input);
1053
- Attributes.defaultValue(input, 'name', name);
1069
+ input.setAttribute('name', `${name}-ignore`);
1070
+ input.setAttribute('ful-validation-target', '');
1071
+ input.dataset['fulBindInclude'] = 'never';
1054
1072
  const label = Fragments.fromChildNodes(el);
1055
1073
  return [input, label];
1056
1074
  });
@@ -1063,6 +1081,13 @@ var ful = (function (exports) {
1063
1081
  });
1064
1082
  return fragment;
1065
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
+ }
1066
1091
  static configure() {
1067
1092
  customElements.define('ful-radio-group', RadioGroup);
1068
1093
  }