edvoyui-component-library-test-flight 0.0.249 → 0.0.251

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.
@@ -61,6 +61,7 @@ declare function __VLS_template(): {
61
61
  };
62
62
  refs: {
63
63
  componentRef: HTMLDivElement;
64
+ triggerRef: HTMLDivElement;
64
65
  searchInputRef: import('../../../node_modules/vue').CreateComponentPublicInstanceWithMixins<Readonly<import('../../../node_modules/vue').ExtractPropTypes<{
65
66
  modelValue: {
66
67
  type: (StringConstructor | NumberConstructor)[];
@@ -196,7 +197,6 @@ declare function __VLS_template(): {
196
197
  activeOptionId: string;
197
198
  expanded: boolean;
198
199
  }> | null;
199
- triggerButtonRef: HTMLButtonElement;
200
200
  dropdownContentRef: HTMLDivElement;
201
201
  options: HTMLUListElement;
202
202
  };
@@ -257,6 +257,7 @@ declare const __VLS_component: import('../../../node_modules/vue').DefineCompone
257
257
  dropdownWidth: string;
258
258
  }, {}, {}, {}, string, import('../../../node_modules/vue').ComponentProvideOptions, false, {
259
259
  componentRef: HTMLDivElement;
260
+ triggerRef: HTMLDivElement;
260
261
  searchInputRef: import('../../../node_modules/vue').CreateComponentPublicInstanceWithMixins<Readonly<import('../../../node_modules/vue').ExtractPropTypes<{
261
262
  modelValue: {
262
263
  type: (StringConstructor | NumberConstructor)[];
@@ -392,7 +393,6 @@ declare const __VLS_component: import('../../../node_modules/vue').DefineCompone
392
393
  activeOptionId: string;
393
394
  expanded: boolean;
394
395
  }> | null;
395
- triggerButtonRef: HTMLButtonElement;
396
396
  dropdownContentRef: HTMLDivElement;
397
397
  options: HTMLUListElement;
398
398
  }, HTMLDivElement>;
@@ -9,23 +9,7 @@
9
9
  {{ label }} <span v-if="required" class="text-red-500">*</span>
10
10
  </label>
11
11
  </slot>
12
- <Popper
13
- :class="[
14
- `popper-defaultstyle w-full ${popperClasses}`,
15
- { 'search-tag-select--teleported': teleported },
16
- ]"
17
- v-bind="$attrs"
18
- :show="showDropDown"
19
- :arrow="!teleported"
20
- closeDelay="100"
21
- :offsetSkid="offsetSkid"
22
- :offsetDistance="offsetDistance"
23
- :placement="placement"
24
- :interactive="true"
25
- :auto-hide="!teleported"
26
- @open:popper="handleOpen"
27
- @close:popper="handleClose"
28
- >
12
+ <div ref="triggerRef" class="w-full" v-bind="$attrs">
29
13
  <SearchInput
30
14
  v-if="showDropDown || selectedValues.length === 0"
31
15
  ref="searchInputRef"
@@ -44,7 +28,6 @@
44
28
  />
45
29
  <button
46
30
  v-else-if="!showDropDown && selectedValues.length > 0"
47
- ref="triggerButtonRef"
48
31
  type="button"
49
32
  :disabled="disabled"
50
33
  class="flex items-center justify-between w-full h-10 gap-2 px-4 py-2 text-left bg-white border border-gray-200 border-solid cursor-pointer search-textstyle rounded-3xl focus-within:outline-violet-200"
@@ -93,13 +76,19 @@
93
76
  />
94
77
  </div>
95
78
  </button>
96
- <template #content>
97
- <Teleport to="body" :disabled="!teleported">
79
+ </div>
80
+ <Teleport to="body" :disabled="!teleported">
98
81
  <div
99
82
  v-if="showDropDown"
100
83
  ref="dropdownContentRef"
101
- :class="['w-full p-3 text-sm bg-white border-2 border-gray-100 border-solid shadow-lg rounded-3xl min-w-28', confirmSelection && selectType === 'multiple' ? '' : 'overflow-y-auto max-h-72 scrollbar--hide', dropdownWidth, teleported ? 'z-[60]' : '']"
102
- @click.stop
84
+ :class="[
85
+ 'p-3 text-sm bg-white border-2 border-gray-100 border-solid shadow-lg rounded-3xl min-w-28',
86
+ confirmSelection && selectType === 'multiple' ? '' : 'overflow-y-auto max-h-72 scrollbar--hide',
87
+ dropdownWidth,
88
+ teleported ? 'z-[60]' : 'z-50',
89
+ 'transition-opacity duration-150 ease-out',
90
+ dropdownReady ? 'opacity-100' : 'opacity-0 pointer-events-none',
91
+ ]"
103
92
  >
104
93
  <div class="flex items-center justify-between p-2 pb-0 mb-1 -mx-px -mt-3">
105
94
  <h3
@@ -276,9 +265,7 @@
276
265
  </EUIButton>
277
266
  </div>
278
267
  </div>
279
- </Teleport>
280
- </template>
281
- </Popper>
268
+ </Teleport>
282
269
  <template v-if="errors && errors.length && !showDropDown">
283
270
  <EUIErrorMessage :errors="errors" :name="name" class="mt-2" />
284
271
  </template>
@@ -358,8 +345,7 @@ import ChevronDownStroke from "../../assets/svg/ChevronDownStroke.vue";
358
345
  import EUICheckbox from "../checkbox/EUICheckbox.vue";
359
346
  import EUITag from "../tag/EUITag.vue";
360
347
  import EUIButton from "../button/EUIButton.vue";
361
- import Popper from "vue3-popper";
362
- import { createPopper, type Instance } from "@popperjs/core";
348
+ import { createPopper, type Instance, type Placement } from "@popperjs/core";
363
349
  import CheckTick from "../../assets/svg/CheckTick.vue";
364
350
  import { XMarkIcon } from "@heroicons/vue/20/solid";
365
351
  import EUIErrorMessage from "../errorMessage/EUIErrorMessage.vue";
@@ -476,9 +462,10 @@ const draftValues = ref<any[]>([]);
476
462
  const options = ref<HTMLElement>();
477
463
  const searchInputRef = ref<any>();
478
464
  const componentRef = ref<HTMLElement>();
479
- const triggerButtonRef = ref<HTMLButtonElement>();
465
+ const triggerRef = ref<HTMLElement>();
480
466
  const dropdownContentRef = ref<HTMLElement>();
481
- let teleportedPopper: Instance | undefined;
467
+ const dropdownReady = ref(false);
468
+ let popperInstance: Instance | null = null;
482
469
  const tagsExpanded = ref(false);
483
470
  const highlightedIndex = ref(-1);
484
471
  const listboxId = `search-tag-listbox-${getCurrentInstance()?.uid ?? 0}`;
@@ -843,44 +830,58 @@ const handleSearchKeydown = (event: KeyboardEvent) => {
843
830
  else handleSelect(item);
844
831
  };
845
832
 
846
- const destroyTeleportedPopper = () => {
847
- teleportedPopper?.destroy();
848
- teleportedPopper = undefined;
833
+ const destroyPopper = () => {
834
+ popperInstance?.destroy();
835
+ popperInstance = null;
849
836
  };
850
837
 
851
- const createTeleportedPopper = () => {
852
- if (!props.teleported || !dropdownContentRef.value) return;
853
-
854
- const trigger =
855
- (searchInputRef.value?.$el as HTMLElement | undefined) ||
856
- triggerButtonRef.value;
857
- if (!trigger) return;
838
+ const createDropdownPopper = async () => {
839
+ await nextTick();
840
+ if (!showDropDown.value || !triggerRef.value || !dropdownContentRef.value)
841
+ return;
858
842
 
859
- destroyTeleportedPopper();
860
- teleportedPopper = createPopper(trigger, dropdownContentRef.value, {
861
- placement: props.placement,
862
- strategy: "fixed",
843
+ destroyPopper();
844
+ popperInstance = createPopper(triggerRef.value, dropdownContentRef.value, {
845
+ placement: props.placement as Placement,
846
+ strategy: props.teleported ? "fixed" : "absolute",
863
847
  modifiers: [
864
848
  {
865
849
  name: "offset",
866
850
  options: { offset: [Number(props.offsetSkid), Number(props.offsetDistance)] },
867
851
  },
868
- { name: "flip", options: { padding: 8 } },
869
- { name: "preventOverflow", options: { padding: 8 } },
852
+ {
853
+ name: "flip",
854
+ options: {
855
+ padding: 8,
856
+ fallbackPlacements: ["bottom-start", "top-start", "bottom-end", "top-end"],
857
+ },
858
+ },
859
+ {
860
+ name: "preventOverflow",
861
+ options: {
862
+ boundary: "viewport",
863
+ rootBoundary: "viewport",
864
+ padding: 8,
865
+ altAxis: true,
866
+ tether: true,
867
+ },
868
+ },
870
869
  {
871
870
  name: "sameWidth",
872
- enabled: true,
871
+ enabled: !props.dropdownWidth,
873
872
  phase: "beforeWrite",
874
873
  requires: ["computeStyles"],
875
874
  fn: ({ state }) => {
876
875
  state.styles.popper.width = `${state.rects.reference.width}px`;
877
876
  },
878
877
  },
878
+ { name: "eventListeners", options: { scroll: true, resize: true } },
879
879
  ],
880
880
  });
881
+ await popperInstance.update();
881
882
  };
882
883
 
883
- const handleOpen = () => {
884
+ const handleOpen = async () => {
884
885
  if (props.disabled || showDropDown.value) return;
885
886
 
886
887
  highlightedIndex.value = -1;
@@ -893,13 +894,15 @@ const handleOpen = () => {
893
894
  if (props.selectType === "single") {
894
895
  internalSearch.value = "";
895
896
  }
897
+ dropdownReady.value = false;
896
898
  showDropDown.value = true;
897
- window.addEventListener("scroll", handleScroll, true);
899
+ await createDropdownPopper();
900
+ if (!showDropDown.value) return;
901
+ dropdownReady.value = true;
898
902
  emit("open");
899
903
 
900
904
  nextTick(() => {
901
905
  if (!showDropDown.value) return;
902
- createTeleportedPopper();
903
906
  focusTimer = setTimeout(() => {
904
907
  focusTimer = undefined;
905
908
  if (!showDropDown.value) return;
@@ -930,8 +933,8 @@ const handleApply = () => {
930
933
 
931
934
  const handleClose = () => {
932
935
  highlightedIndex.value = -1;
933
- window.removeEventListener("scroll", handleScroll, true);
934
- destroyTeleportedPopper();
936
+ destroyPopper();
937
+ dropdownReady.value = false;
935
938
  if (focusTimer) {
936
939
  clearTimeout(focusTimer);
937
940
  focusTimer = undefined;
@@ -962,40 +965,25 @@ const handleSearchFocus = () => {
962
965
  };
963
966
 
964
967
  // Document click handler for outside clicks
965
- const handleDocumentClick = (event: MouseEvent) => {
966
- // The trigger can be replaced during this click. composedPath retains its
967
- // original ancestors, so an inside click stays inside after that DOM update.
968
+ const handleDocumentPointerDown = (event: PointerEvent) => {
969
+ if (!showDropDown.value) return;
970
+ const target = event.target as Node;
968
971
  if (
969
- showDropDown.value &&
970
- componentRef.value &&
971
- !event.composedPath().includes(componentRef.value) &&
972
- !event.composedPath().includes(dropdownContentRef.value as EventTarget)
973
- ) {
974
- handleDismiss();
975
- }
976
- };
972
+ componentRef.value?.contains(target) ||
973
+ dropdownContentRef.value?.contains(target)
974
+ ) return;
977
975
 
978
- const handleScroll = (event: Event) => {
979
- if (!showDropDown.value) return;
980
- if (props.teleported) {
981
- teleportedPopper?.update();
982
- return;
983
- }
984
- const target = event.target;
985
- // Keep the options usable; scrolling any ancestor or the page closes them.
986
- if (target instanceof Node && componentRef.value?.contains(target)) return;
987
976
  handleDismiss();
988
977
  };
989
978
 
990
979
  // Lifecycle hooks
991
980
  onMounted(() => {
992
- document.addEventListener("click", handleDocumentClick);
981
+ document.addEventListener("pointerdown", handleDocumentPointerDown);
993
982
  });
994
983
 
995
984
  onUnmounted(() => {
996
- document.removeEventListener("click", handleDocumentClick);
997
- window.removeEventListener("scroll", handleScroll, true);
998
- destroyTeleportedPopper();
985
+ document.removeEventListener("pointerdown", handleDocumentPointerDown);
986
+ destroyPopper();
999
987
  if (focusTimer) clearTimeout(focusTimer);
1000
988
  });
1001
989
 
@@ -1004,23 +992,19 @@ watch(internalSearch, (value: string) => {
1004
992
  emit("search", value);
1005
993
  });
1006
994
 
995
+ watch(
996
+ () => [props.placement, props.offsetDistance, props.offsetSkid, props.teleported],
997
+ async () => {
998
+ if (!showDropDown.value) return;
999
+ dropdownReady.value = false;
1000
+ await createDropdownPopper();
1001
+ if (showDropDown.value) dropdownReady.value = true;
1002
+ },
1003
+ );
1004
+
1007
1005
  </script>
1008
1006
 
1009
1007
  <style lang="scss">
1010
- .popper-defaultstyle {
1011
- border: 0px solid transparent !important;
1012
- margin: 0px !important;
1013
- @apply w-full;
1014
-
1015
- & > div.popper {
1016
- width: 100% !important;
1017
- }
1018
-
1019
- &.search-tag-select--teleported > div.popper {
1020
- display: none !important;
1021
- }
1022
- }
1023
-
1024
1008
  .show-count {
1025
1009
  @apply min-w-5 h-5 inline-flex items-center justify-center text-xss font-semibold bg-white rounded-xl;
1026
1010
  }
@@ -470,7 +470,7 @@ const headerStyle = (header: Header) => ({
470
470
  });
471
471
 
472
472
  const bodyStyle = (header: Header) => ({
473
- width: `${header.width || 300}px`,
473
+ minWidth: `${header.width || 300}px`,
474
474
  maxWidth: `${header.width || 300}px`,
475
475
  // flex: `${header.width || 300} 0 auto`,
476
476
  });