inviton-powerduck 0.0.101 → 0.0.104

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.
@@ -13,6 +13,7 @@ import { PortalUtils } from "../../common/utils/utils";
13
13
  import { isNullOrEmpty } from "../../common/utils/is-null-or-empty";
14
14
  import { capitalize } from "../../common/utils/capitalize-string";
15
15
  import PowerduckState from "../../app/powerduck-state";
16
+ import { arrayRemove } from "../../common/utils/array-remove";
16
17
 
17
18
  type RowToString = (row) => string;
18
19
  export enum MultiselectMode {
@@ -164,8 +165,7 @@ class DropdownListComponent extends TsxComponent<DropdownListArgs> implements Dr
164
165
  @Prop() containerCssClass?: string
165
166
  @Prop() customIdProperty?: string;
166
167
 
167
- currentSelected: string | any | Array<string> | Array<any> = this.selected;
168
- pendingChangeTimeout: any = null;
168
+ pendingChange: { timeout: any, data: any } = null;
169
169
  preventDefaultTimeout: any = null;
170
170
  preventDefaultTrigger: boolean = null;
171
171
  currentExclusivity: MultiSelectExclusivity = null;
@@ -180,7 +180,6 @@ class DropdownListComponent extends TsxComponent<DropdownListArgs> implements Dr
180
180
  selVal = selVal[0];
181
181
  }
182
182
 
183
- this.currentSelected = selVal;
184
183
  if (this.changed != null) {
185
184
  this.changed(selVal, this.currentExclusivity);
186
185
  }
@@ -286,12 +285,12 @@ class DropdownListComponent extends TsxComponent<DropdownListArgs> implements Dr
286
285
 
287
286
  getSelectedItems(): DropdownDisplayArgs[] {
288
287
  var opts = this.getOptions();
289
- if (this.currentSelected == null || opts.length == 0) {
288
+ if (this.selected == null || opts.length == 0) {
290
289
  return [];
291
290
  }
292
291
 
293
292
  var retArr: DropdownDisplayArgs[] = [];
294
- var selItemArr: Array<string> = PortalUtils.isArray(this.currentSelected) ? this.currentSelected : [this.currentSelected];
293
+ var selItemArr: Array<string> = PortalUtils.isArray(this.selected) ? this.selected : [this.selected];
295
294
 
296
295
  selItemArr.forEach((arrItem) => {
297
296
  var selItem: string;
@@ -342,8 +341,8 @@ class DropdownListComponent extends TsxComponent<DropdownListArgs> implements Dr
342
341
  render(h) {
343
342
  //Dummy stuff to ensure reactivity
344
343
  let dummyCss: string = "";
345
- if (this.currentSelected != null) {
346
- dummyCss += "ddl-dummy-selected" + this.currentSelected.toString().substring(0, 1);
344
+ if (this.selected != null) {
345
+ dummyCss += "ddl-dummy-selected" + this.selected.toString().substring(0, 1);
347
346
  }
348
347
  if (this.options != null) {
349
348
  dummyCss += "opts";
@@ -384,7 +383,7 @@ class DropdownListComponent extends TsxComponent<DropdownListArgs> implements Dr
384
383
 
385
384
  renderSelectComponent(h) {
386
385
  return (
387
- <div class={this.getRootBaseCssClass() + (this.useMultiCheckbxoes() ? " s2-multi-chb" : "")}>
386
+ <div class={this.getRootBaseCssClass() + (this.useMultiCheckboxes() ? " s2-multi-chb" : "")}>
388
387
  <LoadingIndicator visible={this.blocked} />
389
388
  <select name={this.name} autocomplete={this.autocomplete} class={PowerduckState.getFormControlCssClass() + " make-select2"}></select>
390
389
  </div>
@@ -560,18 +559,27 @@ class DropdownListComponent extends TsxComponent<DropdownListArgs> implements Dr
560
559
  return !this.useMobile();
561
560
  }
562
561
 
563
- useMultiCheckbxoes() {
562
+ useMultiCheckboxes() {
564
563
  return this.multiselect == true && this.multiselectMode == MultiselectMode.Checkboxes;
565
564
  }
566
565
 
567
- getCurrentSelect2Data(): DropdownCurrentData {
566
+ handleChange(data: any) {
567
+ if (this.skipChange) {
568
+ this.skipChange = false;
569
+ return;
570
+ }
571
+
572
+ if (this.pendingChange?.timeout != null) {
573
+ clearTimeout(this.pendingChange.timeout);
574
+ this.pendingChange = null;
575
+ }
576
+
568
577
  var selArr: DropdownDisplayArgs[] = [];
569
578
  var addArr: string[] = [];
570
579
  var cOpts = this.getOptions();
571
- var currData = $(this.$el).find(".make-select2")["select2"]("data");
572
580
  this.currentExclusivity = ($(this.$el).find(".make-select2").data("select2") as any).exclusivity;
573
581
 
574
- currData.forEach((item) => {
582
+ (data || []).forEach((item) => {
575
583
  var optItem = cOpts.filter((p) => p.id == item.id)[0];
576
584
  if (optItem != null) {
577
585
  selArr.push(optItem);
@@ -580,10 +588,51 @@ class DropdownListComponent extends TsxComponent<DropdownListArgs> implements Dr
580
588
  }
581
589
  });
582
590
 
583
- return {
584
- data: selArr,
591
+ let currentData = {
585
592
  added: addArr,
593
+ data: selArr
586
594
  };
595
+
596
+ let forceClose = false;
597
+ if (this.tags == true) {
598
+ if (!isNullOrEmpty(currentData.added) && this.tagsAdded != null) {
599
+ let eventArgs: DropdownListTagAddedArgs = {
600
+ closeSelection: false,
601
+ tagArr: currentData.added,
602
+ };
603
+
604
+ this.tagsAdded(eventArgs);
605
+ forceClose = eventArgs.closeSelection;
606
+ }
607
+ }
608
+
609
+ try {
610
+ let searchElem = DropdownSelect2Helper.getSelect2Instance(this.getSelect2RootElement()).selection.$search[0];
611
+ if (searchElem != null) {
612
+ this.searchWasActive = searchElem == document.activeElement;
613
+ } else {
614
+ this.searchWasActive = false;
615
+ }
616
+ } catch (e) {
617
+ this.searchWasActive = false;
618
+ }
619
+
620
+ if (forceClose) {
621
+ this.searchWasActive = false;
622
+ }
623
+
624
+ if (this.changedEventDelay == null || this.changedEventDelay == 0) {
625
+ this.raiseChangedEvent(currentData.data, false);
626
+ } else {
627
+ this.pendingChange = {
628
+ data: currentData.data,
629
+ timeout: setTimeout(() => {
630
+ const data = this.pendingChange?.data;
631
+ this.pendingChange = null;
632
+ this.raiseChangedEvent(data, false);
633
+ }, this.changedEventDelay)
634
+ }
635
+ }
587
636
  }
588
637
 
589
638
  getSelect2AddResource(): string {
@@ -617,7 +666,7 @@ class DropdownListComponent extends TsxComponent<DropdownListArgs> implements Dr
617
666
  if (this.useSelect2()) {
618
667
  var self = this;
619
668
  var opts = this.getOptions();
620
- var s2Constructor: "select2MultiCheckboxes" | "select2" = this.useMultiCheckbxoes() ? "select2MultiCheckboxes" : "select2";
669
+ var s2Constructor: "select2MultiCheckboxes" | "select2" = this.useMultiCheckboxes() ? "select2MultiCheckboxes" : "select2";
621
670
  var selected = this.getSelectedItems();
622
671
  var s2Elem = this.getSelect2RootElement();
623
672
  var alreadyBound = true;
@@ -632,59 +681,11 @@ class DropdownListComponent extends TsxComponent<DropdownListArgs> implements Dr
632
681
  alreadyBound = false;
633
682
  s2Elem
634
683
  .attr("data-vebound", "true")
635
- .change(function (e) {
636
- if (self.skipChange) {
637
- self.skipChange = false;
638
- return;
639
- }
640
-
641
- if (self.pendingChangeTimeout != null) {
642
- clearTimeout(self.pendingChangeTimeout);
643
- }
644
-
645
- let forceClose = false;
646
- if (self.tags == true) {
647
- let currentData = self.getCurrentSelect2Data();
648
- if (!isNullOrEmpty(currentData.added) && self.tagsAdded != null) {
649
- let eventArgs: DropdownListTagAddedArgs = {
650
- closeSelection: false,
651
- tagArr: currentData.added,
652
- };
653
-
654
- self.tagsAdded(eventArgs);
655
- forceClose = eventArgs.closeSelection;
656
- }
657
- }
658
-
659
- try {
660
- let searchElem = DropdownSelect2Helper.getSelect2Instance(s2Elem).selection.$search[0];
661
- if (searchElem != null) {
662
- self.searchWasActive = searchElem == document.activeElement;
663
- } else {
664
- self.searchWasActive = false;
665
- }
666
- } catch (e) {
667
- self.searchWasActive = false;
668
- }
669
-
670
- if (forceClose) {
671
- self.searchWasActive = false;
672
- }
673
-
674
- if (self.changedEventDelay == null || self.changedEventDelay == 0) {
675
- self.raiseChangedEvent(self.getCurrentSelect2Data().data, false);
676
- } else {
677
- self.pendingChangeTimeout = setTimeout(function () {
678
- self.pendingChangeTimeout = null;
679
- self.raiseChangedEvent(self.getCurrentSelect2Data().data, false);
680
- }, self.changedEventDelay);
681
- }
682
- })
683
684
  .on("select2:close", function () {
684
- if (self.pendingChangeTimeout != null) {
685
- clearTimeout(self.pendingChangeTimeout);
686
- self.pendingChangeTimeout = null;
687
- self.raiseChangedEvent(self.getCurrentSelect2Data().data, false);
685
+ if (self.pendingChange != null) {
686
+ const data = self.pendingChange?.data;
687
+ self.pendingChange = null;
688
+ self.raiseChangedEvent(data, false);
688
689
  }
689
690
  })
690
691
  .on("select2:opening", function (e) {
@@ -724,6 +725,12 @@ class DropdownListComponent extends TsxComponent<DropdownListArgs> implements Dr
724
725
  }
725
726
  }
726
727
  });
728
+
729
+ if (this.useMultiCheckboxes()) {
730
+ s2Elem.on('change', (e) => {
731
+ this.handleChange($(this.$el).find(".make-select2")["select2"]("data"));
732
+ });
733
+ }
727
734
  }
728
735
 
729
736
  let dataChanged = false;
@@ -800,10 +807,10 @@ class DropdownListComponent extends TsxComponent<DropdownListArgs> implements Dr
800
807
  $(l).remove();
801
808
  });
802
809
 
803
- var s2Args = {
810
+ var s2Args: any = {
804
811
  allowExclusiveSearch: this.allowExclusiveSearch == true,
805
812
  minimumResultsForSearch: this.disableSearch == true ? -1 : 0,
806
- closeOnSelect: this.closeOnSelect != false && !this.useMultiCheckbxoes(),
813
+ closeOnSelect: this.closeOnSelect != false && !this.useMultiCheckboxes(),
807
814
  placeholder: this.placeholder,
808
815
  allowClear: this.placeholder != null && this.placeholder.length > 0,
809
816
  multiple: this.multiselect == true,
@@ -821,6 +828,23 @@ class DropdownListComponent extends TsxComponent<DropdownListArgs> implements Dr
821
828
  },
822
829
  };
823
830
 
831
+ if (!this.useMultiCheckboxes()) {
832
+ s2Args.data = null
833
+ s2Args.ajax = {
834
+ transport: function (params, success, failure) {
835
+ let resData: any;
836
+ const instance = DropdownSelect2Helper.getSelect2Instance(self.getSelect2RootElement());
837
+ if (instance?.dataAccessor != null) {
838
+ resData = instance.dataAccessor.getData();
839
+ } else {
840
+ resData = opts;
841
+ }
842
+
843
+ success({ results: resData });
844
+ }
845
+ };
846
+ }
847
+
824
848
  var formatResult = this.getFormatResult();
825
849
  if (formatResult != null) {
826
850
  s2Args["templateResult"] = formatResult;
@@ -893,87 +917,207 @@ class DropdownListComponent extends TsxComponent<DropdownListArgs> implements Dr
893
917
  }
894
918
  }
895
919
 
896
- s2Elem[s2Constructor](s2Args);
920
+ let instance = DropdownSelect2Helper.getSelect2Instance(s2Elem);
921
+ if (instance == null || this.useMultiCheckboxes()) {
922
+ s2Elem[s2Constructor](s2Args);
897
923
 
898
- if (this.containerCssClass?.length > 0) {
899
- DropdownSelect2Helper.getSelect2Instance(s2Elem).$dropdown.addClass(this.containerCssClass);
900
- }
924
+ instance = DropdownSelect2Helper.getSelect2Instance(s2Elem)
925
+ instance.dataAccessor = {};
926
+
927
+ if (!this.useMultiCheckboxes()) {
928
+ const currentMethod = instance.dataAdapter.current;
929
+ const getCurrentData = () => {
930
+ return instance.dataAccessor?.getData();
931
+ }
932
+
933
+ const getSelected = () => {
934
+ let retArr = [];
935
+ const data = getCurrentData();
936
+
937
+ if (data != null) {
938
+ const recCheck = (arr: any[]) => {
939
+ for (const item of arr) {
940
+ if (item.selected == true) {
941
+ retArr.push(item);
942
+ }
943
+
944
+ if (item.children?.length > 0) {
945
+ recCheck(item.children);
946
+ }
947
+ }
948
+ }
949
+ recCheck(data);
950
+ }
951
+
952
+ return retArr;
953
+ }
954
+
955
+ const unselectOthers = (data, validIds: any[]) => {
956
+ let retArr = [];
957
+ validIds = validIds || [];
958
+ if (data != null) {
959
+ const recCheck = (arr: any[]) => {
960
+ for (const item of arr) {
961
+ if (item.selected == true && validIds.indexOf(item.id) == -1) {
962
+ item.selected = false;
963
+ }
964
+
965
+ if (item.children?.length > 0) {
966
+ recCheck(item.children);
967
+ }
968
+ }
969
+ }
970
+ recCheck(data);
971
+ }
972
+
973
+ return retArr;
974
+ }
901
975
 
902
- if (s2Args.tags) {
903
- if (!isNullOrEmpty(tagsTemplate)) {
904
- DropdownSelect2Helper.getSelect2Instance(s2Elem).selection.selectionContainer = function () {
905
- let retVal = $(tagsTemplate);
906
- if (self.tagsShouldPrependContent != false) {
907
- let oldAppend = retVal.append;
908
- retVal.append = function (elem) {
909
- retVal.prepend(elem);
910
- retVal.append = oldAppend;
911
- } as any;
976
+ instance.dataAdapter.current = (cb) => {
977
+ const instance = DropdownSelect2Helper.getSelect2Instance(this.getSelect2RootElement());
978
+ const currData = getCurrentData();
979
+
980
+ if (currData != null) {
981
+ cb.call(instance.dataAdapter, getSelected());
982
+ } else {
983
+ currentMethod.call(instance.dataAdapter, cb);
912
984
  }
985
+ }
913
986
 
914
- return retVal;
987
+ instance.dataAdapter.select = (data) => {
988
+ const adapter = instance.dataAdapter;
989
+ if (adapter.$element.prop('multiple')) {
990
+ adapter.current(function (currentData) {
991
+ data = [data];
992
+ data.push.apply(data, currentData);
993
+ unselectOthers(getCurrentData(), data.map(p => p.id));
994
+ self.handleChange(data);
995
+ });
996
+ } else {
997
+ if (data == null) {
998
+ unselectOthers(getCurrentData(), []);
999
+ self.handleChange([]);
1000
+ } else {
1001
+ unselectOthers(getCurrentData(), [data.id]);
1002
+ self.handleChange([data]);
1003
+ }
1004
+ }
915
1005
  };
916
- }
917
1006
 
918
- if (this.tagsSortable == true) {
919
- var ul = $(this.$el).find(".select2-container ul");
920
- if (ul.length > 0) {
921
- new Sortable(ul[0], {
922
- animation: 150,
923
- handle: ".select2-selection__choice",
924
- onEnd: (evt) => {
925
- const oldIndex = evt.oldIndex;
926
- let newIndex = evt.newIndex;
927
-
928
- if (newIndex > oldIndex) {
929
- newIndex -= 1;
1007
+ instance.dataAdapter.unselect = (data) => {
1008
+ const adapter = instance.dataAdapter;
1009
+ if (!adapter.$element.prop('multiple')) {
1010
+ return;
1011
+ }
1012
+
1013
+ const selected = getSelected();
1014
+ for (let i = 0, len = selected.length; i < len; i++) {
1015
+ const item = selected[i];
1016
+ if (item.id == data.id) {
1017
+ arrayRemove(selected, item);
1018
+ break;
1019
+ }
1020
+
1021
+ }
1022
+
1023
+ data.selected = false;
1024
+ unselectOthers(getCurrentData(), selected.map(p => p.id));
1025
+ self.handleChange(selected);
1026
+ }
1027
+
1028
+ if (s2Args.tags) {
1029
+ instance.dataAdapter._removeOldTags = () => {
1030
+ const data = getCurrentData();
1031
+ if (data.length > 0) {
1032
+ for (let i = data.length - 1; i >= 0; i--) {
1033
+ const item = data[i];
1034
+ if (item?.newTag == true) {
1035
+ data.splice(i, 1);
1036
+ }
930
1037
  }
1038
+ }
1039
+ };
931
1040
 
932
- const sel = this.currentSelected as any[];
933
- if (sel == null || sel[oldIndex] == null) {
934
- return;
1041
+ if (!isNullOrEmpty(tagsTemplate)) {
1042
+ DropdownSelect2Helper.getSelect2Instance(s2Elem).selection.selectionContainer = function () {
1043
+ let retVal = $(tagsTemplate);
1044
+ if (self.tagsShouldPrependContent != false) {
1045
+ let oldAppend = retVal.append;
1046
+ retVal.append = function (elem) {
1047
+ retVal.prepend(elem);
1048
+ retVal.append = oldAppend;
1049
+ } as any;
935
1050
  }
936
1051
 
937
- const clonedArr = [...sel];
938
- const removedItems = clonedArr.splice(oldIndex, 1);
939
- clonedArr.splice(newIndex, 0, removedItems[0]);
940
- this.changed(clonedArr);
941
- },
942
- });
1052
+ return retVal;
1053
+ };
1054
+ }
1055
+
1056
+ if (this.tagsSortable == true) {
1057
+ var ul = $(this.$el).find(".select2-container ul");
1058
+ if (ul.length > 0) {
1059
+ new Sortable(ul[0], {
1060
+ animation: 150,
1061
+ handle: ".select2-selection__choice",
1062
+ onEnd: (evt) => {
1063
+ const oldIndex = evt.oldIndex;
1064
+ let newIndex = evt.newIndex;
1065
+
1066
+ if (newIndex > oldIndex) {
1067
+ newIndex -= 1;
1068
+ }
1069
+
1070
+ const sel = this.selected as any[];
1071
+ if (sel == null || sel[oldIndex] == null) {
1072
+ return;
1073
+ }
1074
+
1075
+ const clonedArr = [...sel];
1076
+ const removedItems = clonedArr.splice(oldIndex, 1);
1077
+ clonedArr.splice(newIndex, 0, removedItems[0]);
1078
+ this.changed(clonedArr);
1079
+ },
1080
+ });
1081
+ }
1082
+ }
1083
+
1084
+ // var ul = selectElem.prev('.select2-container').first('ul');
1085
+ // ul.sortable({
1086
+ // placeholder: 'ui-state-highlight',
1087
+ // items: 'li:not(.select2-search-field)',
1088
+ // tolerance: 'pointer',
1089
+ // stop: function () {
1090
+ // onElementValueChange(element, valueAccessor, allBindingsAccessor, viewModel);
1091
+ // }
1092
+ // });
943
1093
  }
944
- }
945
1094
 
946
- // var ul = selectElem.prev('.select2-container').first('ul');
947
- // ul.sortable({
948
- // placeholder: 'ui-state-highlight',
949
- // items: 'li:not(.select2-search-field)',
950
- // tolerance: 'pointer',
951
- // stop: function () {
952
- // onElementValueChange(element, valueAccessor, allBindingsAccessor, viewModel);
953
- // }
954
- // });
955
- }
1095
+ if (this.afterBound != null) {
1096
+ this.afterBound(s2Elem, DropdownSelect2Helper.getSelect2Instance(s2Elem));
1097
+ }
956
1098
 
957
- if (this.afterBound != null) {
958
- this.afterBound(s2Elem, DropdownSelect2Helper.getSelect2Instance(s2Elem));
1099
+ if (validTagsButtons) {
1100
+ this.bindSelect2TagsButton(DropdownSelect2Helper.getSelect2Instance(s2Elem));
1101
+ }
1102
+ }
959
1103
  }
960
1104
 
961
- if (validTagsButtons) {
962
- this.bindSelect2TagsButton(DropdownSelect2Helper.getSelect2Instance(s2Elem));
1105
+ DropdownSelect2Helper.getSelect2Instance(s2Elem).dataAccessor.getData = () => {
1106
+ return opts;
963
1107
  }
964
1108
 
965
- if (selected.length > 0) {
966
- let selectedIds = selected.map((p) => p.id);
967
- if (self.multiselect) {
968
- s2Elem.val(selectedIds);
969
- } else {
970
- s2Elem.val(selectedIds[0]);
971
- }
972
- } else {
973
- s2Elem.val(null);
974
- s2Elem[s2Constructor]("val", "");
1109
+ if (this.containerCssClass?.length > 0) {
1110
+ DropdownSelect2Helper.getSelect2Instance(s2Elem).$dropdown.addClass(this.containerCssClass);
975
1111
  }
976
1112
 
1113
+
1114
+
1115
+ DropdownSelect2Helper.getSelect2Instance(s2Elem).dataAdapter.current((initialData) => {
1116
+ DropdownSelect2Helper.getSelect2Instance(s2Elem).trigger('selection:update', {
1117
+ data: initialData
1118
+ });
1119
+ });
1120
+
977
1121
  if (self.searchWasActive == true) {
978
1122
  self.searchWasActive = false;
979
1123
 
@@ -983,9 +1127,6 @@ class DropdownListComponent extends TsxComponent<DropdownListArgs> implements Dr
983
1127
  }, 0);
984
1128
  });
985
1129
  }
986
-
987
- self.skipChange = true;
988
- s2Elem.trigger("change");
989
1130
  }
990
1131
  }
991
1132
 
@@ -998,19 +1139,12 @@ class DropdownListComponent extends TsxComponent<DropdownListArgs> implements Dr
998
1139
  }
999
1140
 
1000
1141
  mounted() {
1001
- this.currentSelected = this.selected;
1002
1142
  this.updateSelect2();
1003
-
1004
1143
  this.$nextTick(() => {
1005
1144
  this.setMobilePickerInputText(this.getSelectedItems());
1006
1145
  });
1007
1146
  }
1008
1147
 
1009
- @Watch("selected")
1010
- updateValue() {
1011
- this.currentSelected = this.selected;
1012
- }
1013
-
1014
1148
  updated() {
1015
1149
  this.updateSelect2();
1016
1150
  }
@@ -40,7 +40,7 @@ import { PortalUtils } from "../../../common/utils/utils";
40
40
  var flattenData = (data): any[] => {
41
41
  const retArr = [];
42
42
  const recCheck = (arr: any[]) => {
43
- for (const item of arr) {
43
+ for (const item of arr || []) {
44
44
  if (item.id != null) {
45
45
  retArr.push(item);
46
46
  }
@@ -86,7 +86,7 @@ import { PortalUtils } from "../../../common/utils/utils";
86
86
  allowClear: true,
87
87
  ajax: {
88
88
  transport: function (params, success, failure) {
89
- success({ results: self.currentData });
89
+ success({ results: self.currentData || [] });
90
90
  }
91
91
  },
92
92
  language: options.language,
@@ -63,6 +63,12 @@ class DropzoneGalleryComponent extends TsxComponent<DropzoneGalleryArgs> impleme
63
63
  this.bindScript();
64
64
  }
65
65
 
66
+ beforeUnmount() {
67
+ try {
68
+ (this.$refs.galleryDropzone as any).dropzone.destroy();
69
+ } catch (error) { }
70
+ }
71
+
66
72
  updateSortOrder(itemArr?: DropzoneGalleryItem[]) {
67
73
  let applySort = false;
68
74
  if (itemArr == null) {
@@ -76,6 +76,7 @@ class WysiwigEditorComponent extends TsxComponent<WysiwigEditorArgs> implements
76
76
  elem["trumbowyg"]({
77
77
  autogrow: true,
78
78
  lang: PowerduckState.getCurrentLanguage(),
79
+ imageWidthModalEdit: true,
79
80
  svgPath: EsModuleImportHelper.getObj(svgIcons), //FIXME: chcek if working
80
81
  tagsToRemove: ["script", "link"],
81
82
  plugins: {
@@ -1,6 +1,7 @@
1
1
  import { toNative, Prop } from "vue-facing-decorator";
2
2
  import TsxComponent, { Component } from "../../app/vuetsx";
3
3
  import './css/index.css';
4
+ import { ModalUtils } from "../modal/modal-utils";
4
5
 
5
6
  interface LongContentContainerArgs {
6
7
  maxHeight?: string
@@ -21,11 +22,15 @@ class LongContentContainerComponent extends TsxComponent<LongContentContainerArg
21
22
  isExpanded: boolean = false;
22
23
 
23
24
  mounted() {
24
- this.reMeasure();
25
+ ModalUtils.handleModalMountDelay(this, () => {
26
+ this.reMeasure();
27
+ })
25
28
  }
26
29
 
27
30
  updated() {
28
- this.reMeasure();
31
+ ModalUtils.handleModalMountDelay(this, () => {
32
+ this.reMeasure();
33
+ })
29
34
  }
30
35
 
31
36
  getRootStyle() {
@@ -4,123 +4,137 @@ type VueType = typeof Vue.prototype;
4
4
 
5
5
  interface IVue extends VueType { }
6
6
  interface ModalDisplayArgs<T> {
7
- modal: BootstrapModal;
8
- data?: T;
9
- onHidden?: (response: ModalResponseData<T>) => void;
10
- onShown?: (e: ModalOnShownArgs) => void;
11
- onBeforeShown?: (e: ModalOnBeforeShownArgs) => void;
7
+ modal: BootstrapModal;
8
+ data?: T;
9
+ onHidden?: (response: ModalResponseData<T>) => void;
10
+ onShown?: (e: ModalOnShownArgs) => void;
11
+ onBeforeShown?: (e: ModalOnBeforeShownArgs) => void;
12
12
  }
13
13
 
14
14
  interface ModalHideArgs {
15
- modal: BootstrapModal;
15
+ modal: BootstrapModal;
16
16
  }
17
17
 
18
18
  interface ModalResponseData<T> {
19
- data?: T;
19
+ data?: T;
20
20
  }
21
21
 
22
22
  export interface ModalOnBeforeShownArgs {
23
- instance: IVue;
23
+ instance: IVue;
24
24
  }
25
25
 
26
26
  export interface ModalOnShownArgs {
27
- instance: IVue;
27
+ instance: IVue;
28
28
  }
29
29
 
30
30
  export class ModalUtils {
31
- private static _onBeforeShownHandlers: ((args: { modalHandler: any, modalSelector: JQuery }) => void)[]
32
-
33
- static addOnBeforeShownHandler(handler: (args: { modalHandler: any, modalSelector: JQuery }) => void) {
34
- if (ModalUtils._onBeforeShownHandlers == null) {
35
- ModalUtils._onBeforeShownHandlers = [];
36
- }
37
-
38
- ModalUtils._onBeforeShownHandlers.push(handler);
39
- }
40
-
41
- static showModal<T>(instance: IVue, dataArgs: ModalDisplayArgs<T> | IVue | Element): void {
42
- var args: ModalDisplayArgs<T> = dataArgs as any;
43
- if (args.modal == null) {
44
- args = { modal: args as any } as ModalDisplayArgs<T>;
45
- }
46
-
47
- var modalContext = args.modal;
48
- if (modalContext == null) {
49
- console.error("Modal context not specified");
50
- return;
51
- }
52
-
53
- let nextTick = instance?.$nextTick;
54
- if (nextTick == null) {
55
- nextTick = (cb) => { cb(); }
56
- }
57
-
58
- nextTick(() => {
59
- var modalSelector = this._getModalJquery(modalContext["_element"]);
60
- modalSelector.off("hidden.bs.modal");
61
- modalSelector.off("shown.bs.modal");
62
-
63
- if (args.onHidden != null) {
64
- modalSelector.on("hidden.bs.modal", function () {
65
- args.onHidden({
66
- data: args.data,
67
- });
68
- });
69
- }
70
-
71
- if (args.onShown != null) {
72
- modalSelector.on("shown.bs.modal", function () {
73
- args.onShown({
74
- instance: instance,
75
- });
76
- });
77
- }
78
-
79
- if (args.onBeforeShown != null) {
80
- args.onBeforeShown({
81
- instance: instance,
82
- });
83
- }
84
-
85
- if ((args.modal as any)._config == null) {
86
- args.modal = BootstrapModal.getOrCreateInstance((args.modal as any)?.length > 0 ? (args.modal as any)[0] : (args.modal as any) as Element)
87
- }
88
-
89
- if (ModalUtils._onBeforeShownHandlers) {
90
- const modalHandler = args.modal;
91
- for (const hook of ModalUtils._onBeforeShownHandlers) {
92
- hook({ modalHandler, modalSelector });
93
- }
94
-
95
- args.modal.show();
96
- } else {
97
- args.modal.show();
98
- }
99
- });
100
- }
101
-
102
- static hideModal(dataArgs: ModalHideArgs | IVue | Element): void {
103
- var args: ModalHideArgs = dataArgs as any;
104
- if (args.modal == null) {
105
- args = { modal: args as any } as ModalHideArgs;
106
- }
107
-
108
- var modalContext = args.modal;
109
- if (modalContext == null) {
110
- console.error("Modal context not found");
111
- return;
112
- }
113
-
114
- if ((args.modal as any)._config == null) {
115
- args.modal = BootstrapModal.getOrCreateInstance((args.modal as any)?.length > 0 ? (args.modal as any)[0] : (args.modal as any) as Element)
116
- }
117
-
118
- setTimeout(() => {
119
- args.modal.hide();
120
- }, 1);
121
- }
122
-
123
- private static _getModalJquery(modalElem: Element | IVue): JQuery {
124
- return window["jQuery"](modalElem as any);
125
- }
31
+ private static _onBeforeShownHandlers: ((args: { modalHandler: any, modalSelector: JQuery }) => void)[]
32
+
33
+ static addOnBeforeShownHandler(handler: (args: { modalHandler: any, modalSelector: JQuery }) => void) {
34
+ if (ModalUtils._onBeforeShownHandlers == null) {
35
+ ModalUtils._onBeforeShownHandlers = [];
36
+ }
37
+
38
+ ModalUtils._onBeforeShownHandlers.push(handler);
39
+ }
40
+
41
+ static showModal<T>(instance: IVue, dataArgs: ModalDisplayArgs<T> | IVue | Element): void {
42
+ var args: ModalDisplayArgs<T> = dataArgs as any;
43
+ if (args.modal == null) {
44
+ args = { modal: args as any } as ModalDisplayArgs<T>;
45
+ }
46
+
47
+ var modalContext = args.modal;
48
+ if (modalContext == null) {
49
+ console.error("Modal context not specified");
50
+ return;
51
+ }
52
+
53
+ let nextTick = instance?.$nextTick;
54
+ if (nextTick == null) {
55
+ nextTick = (cb) => { cb(); }
56
+ }
57
+
58
+ nextTick(() => {
59
+ var modalSelector = this._getModalJquery(modalContext["_element"]);
60
+ modalSelector.off("hidden.bs.modal");
61
+ modalSelector.off("shown.bs.modal");
62
+
63
+ if (args.onHidden != null) {
64
+ modalSelector.on("hidden.bs.modal", function () {
65
+ args.onHidden({
66
+ data: args.data,
67
+ });
68
+ });
69
+ }
70
+
71
+ if (args.onShown != null) {
72
+ modalSelector.on("shown.bs.modal", function () {
73
+ args.onShown({
74
+ instance: instance,
75
+ });
76
+ });
77
+ }
78
+
79
+ if (args.onBeforeShown != null) {
80
+ args.onBeforeShown({
81
+ instance: instance,
82
+ });
83
+ }
84
+
85
+ if ((args.modal as any)._config == null) {
86
+ args.modal = BootstrapModal.getOrCreateInstance((args.modal as any)?.length > 0 ? (args.modal as any)[0] : (args.modal as any) as Element)
87
+ }
88
+
89
+ if (ModalUtils._onBeforeShownHandlers) {
90
+ const modalHandler = args.modal;
91
+ for (const hook of ModalUtils._onBeforeShownHandlers) {
92
+ hook({ modalHandler, modalSelector });
93
+ }
94
+
95
+ args.modal.show();
96
+ } else {
97
+ args.modal.show();
98
+ }
99
+ });
100
+ }
101
+
102
+ static hideModal(dataArgs: ModalHideArgs | IVue | Element): void {
103
+ var args: ModalHideArgs = dataArgs as any;
104
+ if (args.modal == null) {
105
+ args = { modal: args as any } as ModalHideArgs;
106
+ }
107
+
108
+ var modalContext = args.modal;
109
+ if (modalContext == null) {
110
+ console.error("Modal context not found");
111
+ return;
112
+ }
113
+
114
+ if ((args.modal as any)._config == null) {
115
+ args.modal = BootstrapModal.getOrCreateInstance((args.modal as any)?.length > 0 ? (args.modal as any)[0] : (args.modal as any) as Element)
116
+ }
117
+
118
+ setTimeout(() => {
119
+ args.modal.hide();
120
+ }, 1);
121
+ }
122
+
123
+ static handleModalMountDelay(instance: IVue, cb: () => void) {
124
+ if (instance?.$el?.closest('.modal-dialog')) {
125
+ instance.$nextTick(() => {
126
+ instance.$nextTick(() => {
127
+ setTimeout(() => {
128
+ cb();
129
+ }, 100);
130
+ });
131
+ });
132
+ } else {
133
+ cb();
134
+ }
135
+ }
136
+
137
+ private static _getModalJquery(modalElem: Element | IVue): JQuery {
138
+ return window["jQuery"](modalElem as any);
139
+ }
126
140
  }
@@ -8,6 +8,7 @@ import * as LCluster from "leaflet.markercluster";
8
8
  import { isNullOrEmpty } from "../../common/utils/is-null-or-empty";
9
9
  import iconUrl from './img/marker-icon.png';
10
10
  import GestureHandling from "./ts/gesture-handling/gesture-handling";
11
+ import { ModalUtils } from "../modal/modal-utils";
11
12
 
12
13
  interface OpenStreetMapClusterOptions {
13
14
  //A cluster will cover at most this many pixels from its center
@@ -122,11 +123,13 @@ export class OpenStreetMapComponent extends TsxComponent<OpenStreetMapArgs> impl
122
123
  mounted() {
123
124
  this.initIcon()
124
125
  this.waitForLeaflet().then(() => {
125
- this.initGestureHandling();
126
- this.invalidateSize()
127
- if (this.initComplete != null) {
128
- this.initComplete(this.getLeaflet(), this.getMap())
129
- }
126
+ ModalUtils.handleModalMountDelay(this, () => {
127
+ this.initGestureHandling();
128
+ this.invalidateSize()
129
+ if (this.initComplete != null) {
130
+ this.initComplete(this.getLeaflet(), this.getMap())
131
+ }
132
+ });
130
133
  })
131
134
  }
132
135
 
@@ -0,0 +1,4 @@
1
+ .swiper {
2
+ width: 100%;
3
+ overflow: hidden;
4
+ }
@@ -4,9 +4,9 @@ interface SwiperSlideArgs { }
4
4
 
5
5
  @Component
6
6
  class SwiperSlideComponent extends TsxComponent<SwiperSlideArgs> implements SwiperSlideArgs {
7
- render(h) {
8
- return (<div class="swiper-slide">{this.$slots.default}</div>)
9
- }
7
+ render(h) {
8
+ return (<div class="swiper-slide">{this.$slots?.default()}</div>)
9
+ }
10
10
  }
11
11
 
12
12
  const SwiperSlide = toNative(SwiperSlideComponent)
@@ -1,134 +1,202 @@
1
1
  import { toNative, Prop } from "vue-facing-decorator";
2
2
  import TsxComponent, { Component } from "../../app/vuetsx";
3
3
  import SwiperCore from 'swiper';
4
+ import type { Vue } from 'vue-facing-decorator';
5
+ import { Navigation, Pagination } from 'swiper/modules';
4
6
  import 'swiper/css'
5
7
  import 'swiper/css/navigation'
6
8
  import 'swiper/css/pagination'
9
+ import './css/swiper.css';
7
10
 
11
+ type VueType = typeof Vue.prototype;
12
+ interface IVue extends VueType { }
13
+ SwiperCore.use([Navigation, Pagination]);
8
14
 
9
15
  interface SwiperArgs {
10
- hasPagination?: boolean
11
- direction?: 'horizontal' | 'vertical'
12
- spaceBetween?: number
13
- slideChanged?: (e?: SwiperSlideChangedArgs) => void,
14
- zoomChanged?: (scale: number) => void
15
- zoom?: boolean | SwiperZoomArgs
16
+ hasPagination?: boolean
17
+ direction?: 'horizontal' | 'vertical'
18
+ slidesPerView?: 'auto' | number
19
+ slidesPerGroup?: number
20
+ spaceBetween?: number
21
+ freeMode?: boolean
22
+ grabCursor?: boolean
23
+ speed?: number
24
+ autoplay?: boolean
25
+ preventClicks?: boolean
26
+ navigation?: { nextEl: () => HTMLElement | string | IVue, prevEl: () => HTMLElement | string | IVue }
27
+ slideChanged?: (e?: SwiperSlideChangedArgs) => void,
28
+ zoomChanged?: (scale: number) => void
29
+ zoom?: boolean | SwiperZoomArgs
16
30
 
17
31
  }
18
32
 
19
33
  export interface SwiperSlideChangedArgs {
20
- activeIndex: number
21
- previousIndex: number
22
- swiper: any
34
+ activeIndex: number
35
+ previousIndex: number
36
+ swiper: any
23
37
  }
24
38
 
25
39
  export interface SwiperZoomArgs {
26
- enabled: boolean
27
- maxRatio?: number
28
- minRatio?: number
40
+ enabled: boolean
41
+ maxRatio?: number
42
+ minRatio?: number
29
43
  }
30
44
 
31
45
 
32
46
  @Component
33
47
  class SwiperComponent extends TsxComponent<SwiperArgs> implements SwiperArgs {
34
- @Prop() key: string;
35
- @Prop() hasPagination?: boolean
36
- @Prop() direction?: 'horizontal' | 'vertical'
37
- @Prop() spaceBetween?: number
38
- @Prop() zoom?: boolean | SwiperZoomArgs
39
- @Prop() slideChanged?: (e?: SwiperSlideChangedArgs) => void
40
- @Prop() zoomChanged?: (scale: number) => void
41
- zoomed: boolean = false;
42
-
43
- mounted() {
44
- const rootElem = this.$el;
45
- if (rootElem != null) {
46
- let existingInstance = (rootElem as any).swiper;
47
- if (existingInstance == null) {
48
- let args: any = {
49
- zoom: this.getZoomArgs(),
50
- direction: this.direction || 'horizontal',
51
- spaceBetween: this.spaceBetween > 0 ? this.spaceBetween : 0,
52
- pagination: this.shouldRenderPagination() ? {
53
- el: this.$refs.swiperPagination,
54
- type: 'bullets',
55
- } : {
56
- el: null
57
- }
58
- };
59
-
60
- if (this.slideChanged != null) {
61
- args.on = {
62
- slideChange: (swiper: any) => {
63
- this.slideChanged({
64
- activeIndex: swiper.activeIndex,
65
- previousIndex: swiper.previousIndex,
66
- swiper: swiper
67
- });
68
- }
69
- }
70
- }
71
-
72
- if (this.zoomChanged != null) {
73
- args.on = {
74
- ...args.on,
75
- zoomChange: (swiperEvent: any, scale: number) => {
76
- this.zoomed = scale > 1 ? true : false;
77
- this.zoomChanged(scale)
78
- }
79
- }
80
- }
81
-
82
- new SwiperCore(rootElem as any, args);
83
- }
84
- }
85
- }
86
-
87
- getSwiperInstance() {
88
- const rootElem = this.$el;
89
- if (rootElem != null) {
90
- return (rootElem as any).swiper;
91
- }
92
-
93
- return null;
94
- }
95
-
96
- getZoomArgs(): SwiperZoomArgs {
97
- if (this.zoom == true) {
98
- return {
99
- enabled: true
100
- }
101
- }
102
-
103
- return this.zoom as SwiperZoomArgs;
104
- }
105
-
106
- shouldRenderPagination(): boolean {
107
- return this.hasPagination != false;
108
- }
109
-
110
-
111
-
112
- render(h) {
113
- const zoomEnabled = (this.zoom == true || (this.zoom as SwiperZoomArgs)?.enabled == true);
114
-
115
- return (
116
-
117
- <div class="swiper">
118
-
119
- {this.shouldRenderPagination() &&
120
- <div ref="swiperPagination" class={`swiper-pagination swiper-pagination-bullets swiper-pagination-horizontal ${this.zoomed ?
121
- "hide-swiper-pagination-bulets" :
122
- ""}`
123
- }></div>
124
- }
125
-
126
- <div class="swiper-wrapper">
127
- {this.$slots.default}
128
- </div>
129
- </div>
130
- )
131
- }
48
+ @Prop() key: string;
49
+ @Prop() hasPagination?: boolean
50
+ @Prop() direction?: 'horizontal' | 'vertical'
51
+ @Prop() slidesPerView?: 'auto' | number
52
+ @Prop() slidesPerGroup?: number
53
+ @Prop() spaceBetween?: number
54
+ @Prop() freeMode?: boolean
55
+ @Prop() grabCursor?: boolean
56
+ @Prop() speed: number
57
+ @Prop() autoplay: boolean
58
+ @Prop() preventClicks: boolean
59
+ @Prop() navigation?: { nextEl: () => HTMLElement | string | IVue, prevEl: () => HTMLElement | string | IVue }
60
+ @Prop() zoom?: boolean | SwiperZoomArgs
61
+ @Prop() slideChanged?: (e?: SwiperSlideChangedArgs) => void
62
+ @Prop() zoomChanged?: (scale: number) => void
63
+ zoomed: boolean = false;
64
+
65
+ mounted() {
66
+ const rootElem = this.$el;
67
+ if (rootElem != null) {
68
+ let existingInstance = (rootElem as any).swiper;
69
+ if (existingInstance == null) {
70
+ let args: any = {
71
+ zoom: this.getZoomArgs(),
72
+ direction: this.direction || 'horizontal',
73
+ spaceBetween: this.spaceBetween > 0 ? this.spaceBetween : 0,
74
+ pagination: this.shouldRenderPagination() ? {
75
+ el: this.$refs.swiperPagination,
76
+ type: 'bullets',
77
+ } : {
78
+ el: null
79
+ }
80
+ };
81
+
82
+ if (this.slidesPerView != null) {
83
+ args.slidesPerView = this.slidesPerView;
84
+ }
85
+
86
+ if (this.slidesPerGroup != null) {
87
+ args.slidesPerGroup = this.slidesPerGroup;
88
+ }
89
+
90
+ if (this.freeMode != null) {
91
+ args.freeMode = this.freeMode;
92
+ }
93
+
94
+ if (this.grabCursor != null) {
95
+ args.grabCursor = this.grabCursor;
96
+ }
97
+
98
+ if (this.speed != null) {
99
+ args.speed = this.speed;
100
+ }
101
+
102
+ if (this.autoplay != null) {
103
+ args.autoplay = this.autoplay;
104
+ }
105
+
106
+ if (this.preventClicks != null) {
107
+ args.preventClicks = this.preventClicks;
108
+ }
109
+
110
+ if (this.navigation != null) {
111
+ const getForProp = (prop) => {
112
+ if (prop == null) {
113
+ return null;
114
+ }
115
+
116
+ const propVal = prop();
117
+ if (propVal == null) {
118
+ return null;
119
+ }
120
+
121
+ return propVal.$el ?? propVal;
122
+ }
123
+
124
+ args.navigation = {
125
+ prevEl: getForProp(this.navigation.prevEl),
126
+ nextEl: getForProp(this.navigation.nextEl),
127
+ }
128
+ }
129
+
130
+ if (this.slideChanged != null) {
131
+ args.on = {
132
+ slideChange: (swiper: any) => {
133
+ this.slideChanged({
134
+ activeIndex: swiper.activeIndex,
135
+ previousIndex: swiper.previousIndex,
136
+ swiper: swiper
137
+ });
138
+ }
139
+ }
140
+ }
141
+
142
+ if (this.zoomChanged != null) {
143
+ args.on = {
144
+ ...args.on,
145
+ zoomChange: (swiperEvent: any, scale: number) => {
146
+ this.zoomed = scale > 1 ? true : false;
147
+ this.zoomChanged(scale)
148
+ }
149
+ }
150
+ }
151
+
152
+ new SwiperCore(rootElem as any, args);
153
+ }
154
+ }
155
+ }
156
+
157
+ getSwiperInstance() {
158
+ const rootElem = this.$el;
159
+ if (rootElem != null) {
160
+ return (rootElem as any).swiper;
161
+ }
162
+
163
+ return null;
164
+ }
165
+
166
+ getZoomArgs(): SwiperZoomArgs {
167
+ if (this.zoom == true) {
168
+ return {
169
+ enabled: true
170
+ }
171
+ }
172
+
173
+ return this.zoom as SwiperZoomArgs;
174
+ }
175
+
176
+ shouldRenderPagination(): boolean {
177
+ return this.hasPagination != false;
178
+ }
179
+
180
+
181
+
182
+ render(h) {
183
+ const zoomEnabled = (this.zoom == true || (this.zoom as SwiperZoomArgs)?.enabled == true);
184
+
185
+ return (
186
+ <div class="swiper">
187
+ {this.shouldRenderPagination() &&
188
+ <div ref="swiperPagination" class={`swiper-pagination swiper-pagination-bullets swiper-pagination-horizontal ${this.zoomed ?
189
+ "hide-swiper-pagination-bulets" :
190
+ ""}`
191
+ }></div>
192
+ }
193
+
194
+ <div class="swiper-wrapper">
195
+ {this.$slots?.default()}
196
+ </div>
197
+ </div>
198
+ )
199
+ }
132
200
  }
133
201
 
134
202
  const Swiper = toNative(SwiperComponent)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "inviton-powerduck",
3
- "version": "0.0.101",
3
+ "version": "0.0.104",
4
4
  "type": "module",
5
5
  "scripts": {
6
6
  "build": " vite build && vue-tsc --declaration --emitDeclarationOnly",