@milaboratories/uikit 2.1.1 → 2.1.3

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.
Files changed (35) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/dist/pl-uikit.js +3279 -2982
  3. package/dist/pl-uikit.umd.cjs +10 -10
  4. package/dist/src/components/PlDropdown/PlDropdown.vue.d.ts +5 -1
  5. package/dist/src/components/PlDropdownLegacy/PlDropdownLegacy.vue.d.ts +78 -0
  6. package/dist/src/components/PlDropdownLegacy/__tests__/PlDropdownLegacy.spec.d.ts +1 -0
  7. package/dist/src/components/PlDropdownLegacy/index.d.ts +1 -0
  8. package/dist/src/components/PlDropdownRef/PlDropdownRef.vue.d.ts +12 -2
  9. package/dist/src/composition/useEventListener.d.ts +1 -1
  10. package/dist/src/index.d.ts +1 -0
  11. package/dist/style.css +1 -1
  12. package/dist/tsconfig.lib.tsbuildinfo +1 -1
  13. package/package.json +3 -3
  14. package/src/assets/base.scss +4 -0
  15. package/src/assets/variables.scss +3 -1
  16. package/src/components/PlCheckbox/pl-checkbox.scss +2 -0
  17. package/src/components/PlChip/PlChip.vue +5 -5
  18. package/src/components/PlChip/pl-chip.scss +2 -2
  19. package/src/components/PlDropdown/PlDropdown.vue +86 -27
  20. package/src/components/PlDropdown/__tests__/PlDropdown.spec.ts +7 -6
  21. package/src/components/PlDropdown/pl-dropdown.scss +76 -68
  22. package/src/components/PlDropdownLegacy/PlDropdownLegacy.vue +370 -0
  23. package/src/components/PlDropdownLegacy/__tests__/PlDropdownLegacy.spec.ts +33 -0
  24. package/src/components/PlDropdownLegacy/index.ts +1 -0
  25. package/src/components/PlDropdownLegacy/pl-dropdown-legacy.scss +260 -0
  26. package/src/components/PlDropdownLine/PlDropdownLine.vue +81 -42
  27. package/src/components/PlDropdownLine/pl-dropdown-line.scss +5 -5
  28. package/src/components/PlDropdownMulti/PlDropdownMulti.vue +62 -27
  29. package/src/components/PlDropdownMulti/__tests__/PlDropdownMulti.spec.ts +12 -7
  30. package/src/components/PlDropdownMulti/pl-dropdown-multi.scss +11 -8
  31. package/src/components/PlDropdownRef/PlDropdownRef.vue +16 -3
  32. package/src/components/PlDropdownRef/__tests__/PlDropdownRef.spec.ts +11 -8
  33. package/src/composition/useEventListener.ts +3 -3
  34. package/src/composition/usePosition.ts +2 -2
  35. package/src/index.ts +1 -0
@@ -12,6 +12,7 @@ import DropdownListItem from '@/components/DropdownListItem.vue';
12
12
  import TabItem from '@/components/TabItem.vue';
13
13
  import type { ListOption } from '@/types';
14
14
  import { normalizeListOptions } from '@/helpers/utils';
15
+ import { useElementPosition } from '@/composition/usePosition';
15
16
 
16
17
  const emit = defineEmits(['update:modelValue']); // at the top always
17
18
 
@@ -38,6 +39,7 @@ const props = withDefaults(
38
39
  const data = reactive({
39
40
  isOpen: false,
40
41
  activeOption: -1,
42
+ optionsHeight: 0,
41
43
  });
42
44
 
43
45
  const container = ref<HTMLElement>();
@@ -85,7 +87,7 @@ const placeholderVal = computed(() => {
85
87
  }
86
88
  }
87
89
 
88
- return modelText.value || '...';
90
+ return modelText.value ?? '...';
89
91
  });
90
92
 
91
93
  useClickOutside(container, () => {
@@ -169,13 +171,14 @@ function isItemSelected(item: ListOption): boolean {
169
171
  return deepEqual(item.value, props.modelValue);
170
172
  }
171
173
 
172
- function onBlur(event: Event) {
173
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
174
- if (!container?.value?.contains((event as any).relatedTarget)) {
175
- data.isOpen = false;
174
+ const onFocusOut = (event: FocusEvent) => {
175
+ const relatedTarget = event.relatedTarget as Node | null;
176
+
177
+ if (!container.value?.contains(relatedTarget) && !list.value?.contains(relatedTarget)) {
176
178
  searchPhrase.value = '';
179
+ data.isOpen = false;
177
180
  }
178
- }
181
+ };
179
182
 
180
183
  function handleKeydown(e: { code: string; preventDefault(): void }) {
181
184
  const { activeOption } = data;
@@ -223,6 +226,33 @@ function scrollIntoActive() {
223
226
  function clearModel() {
224
227
  emit('update:modelValue', undefined);
225
228
  }
229
+
230
+ const optionsStyle = reactive({
231
+ top: '0px',
232
+ left: '0px',
233
+ });
234
+
235
+ watch(list, (el) => {
236
+ if (el) {
237
+ const rect = el.getBoundingClientRect();
238
+ data.optionsHeight = rect.height;
239
+ window.dispatchEvent(new CustomEvent('adjust'));
240
+ }
241
+ });
242
+
243
+ useElementPosition(container, (pos) => {
244
+ const gap = 2;
245
+
246
+ const downTopOffset = pos.top + pos.height + gap;
247
+
248
+ if (downTopOffset + data.optionsHeight > pos.clientHeight) {
249
+ optionsStyle.top = pos.top - data.optionsHeight - gap + 'px';
250
+ } else {
251
+ optionsStyle.top = downTopOffset + 'px';
252
+ }
253
+
254
+ optionsStyle.left = pos.left + 'px';
255
+ });
226
256
  </script>
227
257
 
228
258
  <template>
@@ -231,53 +261,62 @@ function clearModel() {
231
261
  ref="container"
232
262
  tabindex="0"
233
263
  :class="classes"
234
- class="ui-line-dropdown uc-pointer"
264
+ class="pl-line-dropdown uc-pointer"
235
265
  @keydown="handleKeydown"
236
- @focusout="onBlur"
266
+ @focusout="onFocusOut"
237
267
  @click="toggleList"
238
268
  >
239
- <div class="ui-line-dropdown__prefix">{{ props?.prefix }}</div>
269
+ <div class="pl-line-dropdown__prefix">{{ props?.prefix }}</div>
240
270
 
241
- <ResizableInput v-model="inputModel" :placeholder="placeholderVal" :disabled="props.disabled" class="ui-line-dropdown__input" />
271
+ <ResizableInput v-model="inputModel" :placeholder="placeholderVal" :disabled="props.disabled" class="pl-line-dropdown__input" />
242
272
 
243
- <div class="ui-line-dropdown__icon-wrapper">
244
- <div v-show="!canShowClearBtn" class="ui-line-dropdown__icon" />
245
- <div v-show="canShowClearBtn" class="ui-line-dropdown__icon-clear" @click="clearModel" />
273
+ <div class="pl-line-dropdown__icon-wrapper">
274
+ <div v-show="!canShowClearBtn" class="pl-line-dropdown__icon" />
275
+ <div v-show="canShowClearBtn" class="pl-line-dropdown__icon-clear" @click="clearModel" />
246
276
  </div>
247
- <div v-if="props.mode === 'list'" v-show="data.isOpen" ref="list" class="ui-line-dropdown__items">
248
- <template v-for="(item, index) in options" :key="index">
249
- <slot
250
- name="item"
251
- :item="item"
252
- :text-item="'text'"
253
- :is-selected="isItemSelected(item)"
254
- :is-hovered="data.activeOption == index"
255
- @click.stop="selectItem(item)"
256
- >
257
- <DropdownListItem
258
- :option="item"
277
+ <Teleport v-if="data.isOpen" to="body">
278
+ <div v-if="props.mode === 'list'" ref="list" :style="optionsStyle" tabindex="-1" class="pl-line-dropdown__items" @focusout="onFocusOut">
279
+ <template v-for="(item, index) in options" :key="index">
280
+ <slot
281
+ name="item"
282
+ :item="item"
259
283
  :text-item="'text'"
260
284
  :is-selected="isItemSelected(item)"
261
285
  :is-hovered="data.activeOption == index"
262
- size="medium"
263
286
  @click.stop="selectItem(item)"
264
- />
265
- </slot>
266
- </template>
267
-
268
- <div v-if="options.length === 0" class="ui-line-dropdown__no-item">
269
- <div class="ui-line-dropdown__no-item-title text-s">Didn't find anything that matched</div>
287
+ >
288
+ <DropdownListItem
289
+ :option="item"
290
+ :text-item="'text'"
291
+ :is-selected="isItemSelected(item)"
292
+ :is-hovered="data.activeOption == index"
293
+ size="medium"
294
+ @click.stop="selectItem(item)"
295
+ />
296
+ </slot>
297
+ </template>
298
+
299
+ <div v-if="options.length === 0" class="pl-line-dropdown__no-item">
300
+ <div class="pl-line-dropdown__no-item-title text-s">Didn't find anything that matched</div>
301
+ </div>
270
302
  </div>
271
- </div>
272
- <div v-if="props.mode === 'tabs'" v-show="data.isOpen" ref="list" :style="props.tabsContainerStyles" class="ui-line-dropdown__items-tabs">
273
- <template v-for="(item, index) in options" :key="index">
274
- <slot name="item" :item="item" :is-selected="isItemSelected(item)" :is-hovered="data.activeOption == index" @click.stop="selectItem(item)">
275
- <TabItem :option="item" :is-selected="isItemSelected(item)" :is-hovered="data.activeOption == index" @click.stop="selectItem(item)" />
276
- </slot>
277
- </template>
278
- <div v-if="options.length === 0" class="ui-line-dropdown__no-item">
279
- <div class="ui-line-dropdown__no-item-title text-s">Didn't find anything that matched</div>
303
+ <div
304
+ v-else-if="props.mode === 'tabs'"
305
+ ref="list"
306
+ :style="optionsStyle"
307
+ tabindex="-1"
308
+ class="pl-line-dropdown__items-tabs"
309
+ @focusout="onFocusOut"
310
+ >
311
+ <template v-for="(item, index) in options" :key="index">
312
+ <slot name="item" :item="item" :is-selected="isItemSelected(item)" :is-hovered="data.activeOption == index" @click.stop="selectItem(item)">
313
+ <TabItem :option="item" :is-selected="isItemSelected(item)" :is-hovered="data.activeOption == index" @click.stop="selectItem(item)" />
314
+ </slot>
315
+ </template>
316
+ <div v-if="options.length === 0" class="pl-line-dropdown__no-item">
317
+ <div class="pl-line-dropdown__no-item-title text-s">Didn't find anything that matched</div>
318
+ </div>
280
319
  </div>
281
- </div>
320
+ </Teleport>
282
321
  </div>
283
322
  </template>
@@ -1,6 +1,6 @@
1
1
  @import "@/assets/mixins";
2
2
 
3
- .ui-line-dropdown {
3
+ .pl-line-dropdown {
4
4
  display: flex;
5
5
  align-items: center;
6
6
  width: fit-content;
@@ -113,8 +113,8 @@
113
113
 
114
114
  &__items {
115
115
  position: absolute;
116
- top: 110%;
117
- z-index: 1;
116
+ top: 0;
117
+ z-index: var(--z-dropdown-options);
118
118
  border-radius: 6px;
119
119
  padding: 12px 0;
120
120
  border: 1px solid var(--color-div-grey);
@@ -130,8 +130,8 @@
130
130
  &__items-tabs {
131
131
  display: flex;
132
132
  position: absolute;
133
- top: 110%;
134
- z-index: 1;
133
+ top: 0;
134
+ z-index: var(--z-dropdown-options);
135
135
  background-color: var(--color-div-bw);
136
136
  overflow-x: scroll;
137
137
  max-width: 400px;
@@ -20,6 +20,7 @@ import { scrollIntoView } from '@/helpers/dom';
20
20
  import DropdownListItem from '@/components/DropdownListItem.vue';
21
21
  import { deepEqual, deepIncludes } from '@/helpers/objects';
22
22
  import { normalizeListOptions } from '@/helpers/utils';
23
+ import { useElementPosition } from '@/composition/usePosition';
23
24
 
24
25
  const emit = defineEmits<{
25
26
  (e: 'update:modelValue', v: M[]): void;
@@ -83,6 +84,7 @@ const data = reactive({
83
84
  search: '',
84
85
  activeOption: -1,
85
86
  open: false,
87
+ optionsHeight: 0,
86
88
  });
87
89
 
88
90
  const selectedValuesRef = computed(() => (Array.isArray(props.modelValue) ? props.modelValue : []));
@@ -149,7 +151,9 @@ const setFocusOnInput = () => input.value?.focus();
149
151
  const toggleModel = () => (data.open = !data.open);
150
152
 
151
153
  const onFocusOut = (event: FocusEvent) => {
152
- if (!rootRef?.value?.contains(event.relatedTarget as Node | null)) {
154
+ const relatedTarget = event.relatedTarget as Node | null;
155
+
156
+ if (!rootRef.value?.contains(relatedTarget) && !list.value?.contains(relatedTarget)) {
153
157
  data.search = '';
154
158
  data.open = false;
155
159
  }
@@ -220,20 +224,49 @@ watchPostEffect(() => {
220
224
  scrollIntoActive();
221
225
  }
222
226
  });
227
+
228
+ const optionsStyle = reactive({
229
+ top: '0px',
230
+ left: '0px',
231
+ width: '0px',
232
+ });
233
+
234
+ watch(list, (el) => {
235
+ if (el) {
236
+ const rect = el.getBoundingClientRect();
237
+ data.optionsHeight = rect.height;
238
+ window.dispatchEvent(new CustomEvent('adjust'));
239
+ }
240
+ });
241
+
242
+ useElementPosition(rootRef, (pos) => {
243
+ const focusWidth = 5; // see css
244
+
245
+ const downTopOffset = pos.top + pos.height + focusWidth;
246
+
247
+ if (downTopOffset + data.optionsHeight > pos.clientHeight) {
248
+ optionsStyle.top = pos.top - data.optionsHeight - focusWidth + 'px';
249
+ } else {
250
+ optionsStyle.top = downTopOffset + 'px';
251
+ }
252
+
253
+ optionsStyle.left = pos.left + 'px';
254
+ optionsStyle.width = pos.width + 'px';
255
+ });
223
256
  </script>
224
257
 
225
258
  <template>
226
- <div class="ui-multi-dropdown__envelope">
259
+ <div class="pl-multi-dropdown__envelope">
227
260
  <div
228
261
  ref="rootRef"
229
262
  :tabindex="tabindex"
230
- class="ui-multi-dropdown"
263
+ class="pl-multi-dropdown"
231
264
  :class="{ open: data.open, error, disabled }"
232
265
  @keydown="handleKeydown"
233
266
  @focusout="onFocusOut"
234
267
  >
235
- <div class="ui-multi-dropdown__container">
236
- <div class="ui-multi-dropdown__field">
268
+ <div class="pl-multi-dropdown__container">
269
+ <div class="pl-multi-dropdown__field">
237
270
  <input
238
271
  ref="input"
239
272
  v-model="data.search"
@@ -251,7 +284,7 @@ watchPostEffect(() => {
251
284
  </PlChip>
252
285
  </div>
253
286
  <div class="arrow" @click.stop="toggleModel" />
254
- <div class="ui-multi-dropdown__append">
287
+ <div class="pl-multi-dropdown__append">
255
288
  <slot name="append" />
256
289
  </div>
257
290
  </div>
@@ -264,29 +297,31 @@ watchPostEffect(() => {
264
297
  </template>
265
298
  </PlTooltip>
266
299
  </label>
267
- <div v-if="data.open" ref="list" class="ui-multi-dropdown__options">
268
- <div class="ui-multi-dropdown__open-chips-container">
269
- <PlChip v-for="(opt, i) in selectedOptionsRef" :key="i" closeable small @close="unselectOption(opt.value)">
270
- {{ opt.label || opt.value }}
271
- </PlChip>
300
+ <Teleport v-if="data.open" to="body">
301
+ <div ref="list" class="pl-multi-dropdown__options" :style="optionsStyle" tabindex="-1" @focusout="onFocusOut">
302
+ <div class="pl-multi-dropdown__open-chips-container">
303
+ <PlChip v-for="(opt, i) in selectedOptionsRef" :key="i" closeable small @close="unselectOption(opt.value)">
304
+ {{ opt.label || opt.value }}
305
+ </PlChip>
306
+ </div>
307
+ <DropdownListItem
308
+ v-for="(item, index) in filteredOptionsRef"
309
+ :key="index"
310
+ :option="item"
311
+ :text-item="'text'"
312
+ :is-selected="item.selected"
313
+ :is-hovered="data.activeOption == index"
314
+ size="medium"
315
+ use-checkbox
316
+ @click.stop="selectOption(item.value)"
317
+ />
318
+ <div v-if="!filteredOptionsRef.length" class="nothing-found">Nothing found</div>
272
319
  </div>
273
- <DropdownListItem
274
- v-for="(item, index) in filteredOptionsRef"
275
- :key="index"
276
- :option="item"
277
- :text-item="'text'"
278
- :is-selected="item.selected"
279
- :is-hovered="data.activeOption == index"
280
- size="medium"
281
- use-checkbox
282
- @click.stop="selectOption(item.value)"
283
- />
284
- <div v-if="!filteredOptionsRef.length" class="nothing-found">Nothing found</div>
285
- </div>
286
- <DoubleContour class="ui-multi-dropdown__contour" />
320
+ </Teleport>
321
+ <DoubleContour class="pl-multi-dropdown__contour" />
287
322
  </div>
288
323
  </div>
289
- <div v-if="error" class="ui-multi-dropdown__error">{{ error }}</div>
290
- <div v-else-if="helper" class="ui-multi-dropdown__helper">{{ helper }}</div>
324
+ <div v-if="error" class="pl-multi-dropdown__error">{{ error }}</div>
325
+ <div v-else-if="helper" class="pl-multi-dropdown__helper">{{ helper }}</div>
291
326
  </div>
292
327
  </template>
@@ -2,6 +2,7 @@ import { describe, it, expect } from 'vitest';
2
2
 
3
3
  import { mount } from '@vue/test-utils';
4
4
  import PlDropdown from '../PlDropdownMulti.vue';
5
+ import { delay } from '@milaboratories/helpers';
5
6
 
6
7
  describe('PlDropdownMulti', () => {
7
8
  it('modelValue', async () => {
@@ -18,16 +19,20 @@ describe('PlDropdownMulti', () => {
18
19
 
19
20
  await wrapper.find('input').trigger('focus');
20
21
 
21
- expect(await wrapper.findAll('.dropdown-list-item').length).toBe(2);
22
+ const getOptions = () => [...document.body.querySelectorAll('.dropdown-list-item')] as HTMLElement[];
22
23
 
23
- await wrapper
24
- .findAll('.dropdown-list-item')
25
- .filter((node) => node.text().match(/Option 2/))
26
- .at(0)
27
- ?.trigger('click');
24
+ const options = getOptions();
25
+
26
+ console.log('options', options);
27
+
28
+ expect(options.length).toBe(2);
29
+
30
+ options[1].click();
31
+
32
+ await delay(20);
28
33
 
29
34
  expect(wrapper.props('modelValue')).toEqual([1, 2]);
30
35
 
31
- expect(await wrapper.findAll('.dropdown-list-item').length).toBe(2); // options are not closed after click
36
+ expect(getOptions().length).toBe(2); // options are not closed after click
32
37
  });
33
38
  });
@@ -1,6 +1,6 @@
1
1
  @import "@/assets/mixins";
2
2
 
3
- .ui-multi-dropdown {
3
+ .pl-multi-dropdown {
4
4
  $root: &;
5
5
 
6
6
  --contour-color: var(--txt-01);
@@ -53,11 +53,14 @@
53
53
  }
54
54
 
55
55
  &__options {
56
- position: relative;
57
- background-color: var(--options-bg);
58
- border-radius: 0 0 6px 6px;
56
+ position: absolute;
57
+ top: 0;
58
+ z-index: var(--z-dropdown-options);
59
+ border: 1px solid var(--border-color-div-grey);
60
+ background-color: var(--pl-dropdown-options-bg);
61
+ border-radius: 6px;
59
62
  max-height: 244px;
60
- border-top: 1px solid var(--color-div-black);
63
+ box-shadow: 0px 4px 12px -2px rgba(15, 36, 77, 0.08), 0px 6px 24px -2px rgba(15, 36, 77, 0.08);
61
64
  @include scrollbar;
62
65
 
63
66
  .nothing-found {
@@ -83,7 +86,7 @@
83
86
  --base-icon: url('@/assets/images/24_checkbox-base.svg');
84
87
  --checked-icon: url('@/assets/images/24_checkbox-checked.svg');
85
88
 
86
- .ui-multi-dropdown__checkmark {
89
+ .pl-multi-dropdown__checkmark {
87
90
  cursor: pointer;
88
91
  outline: none;
89
92
  border-radius: 4px;
@@ -106,7 +109,7 @@
106
109
  &.selected {
107
110
  background-color: var(--color-active-select);
108
111
 
109
- .ui-multi-dropdown__checkmark {
112
+ .pl-multi-dropdown__checkmark {
110
113
  @include icon(var(--checked-icon), 24px);
111
114
  }
112
115
  }
@@ -290,7 +293,7 @@
290
293
  &__open-chips-container {
291
294
  padding: 12px;
292
295
 
293
- .ui-chip {
296
+ .pl-chip {
294
297
  margin-right: 4px;
295
298
  margin-bottom: 4px;
296
299
  }
@@ -32,11 +32,15 @@ const props = withDefaults(
32
32
  /**
33
33
  * List of available ref options for the dropdown
34
34
  */
35
- options: Readonly<RefOption[]>;
35
+ options?: Readonly<RefOption[]>;
36
36
  /**
37
37
  * A helper text displayed below the dropdown when there are no errors (optional).
38
38
  */
39
39
  helper?: string;
40
+ /**
41
+ * A helper text displayed below the dropdown when there are no options yet or options is undefined (optional).
42
+ */
43
+ loadingOptionsHelper?: string;
40
44
  /**
41
45
  * Error message displayed below the dropdown (optional)
42
46
  */
@@ -65,6 +69,7 @@ const props = withDefaults(
65
69
  {
66
70
  label: '',
67
71
  helper: undefined,
72
+ loadingOptionsHelper: undefined,
68
73
  error: undefined,
69
74
  placeholder: '...',
70
75
  clearable: false,
@@ -72,11 +77,12 @@ const props = withDefaults(
72
77
  disabled: false,
73
78
  arrowIcon: undefined,
74
79
  optionSize: 'small',
80
+ options: undefined,
75
81
  },
76
82
  );
77
83
 
78
84
  const options = computed(() =>
79
- props.options.map((opt) => ({
85
+ props.options?.map((opt) => ({
80
86
  label: opt.label,
81
87
  value: opt.ref,
82
88
  })),
@@ -86,5 +92,12 @@ const arrowIcon = computed(() => (props.disabled ? 'icon-link-disabled' : 'icon-
86
92
  </script>
87
93
 
88
94
  <template>
89
- <PlDropdown v-bind="props" :options="options" :arrow-icon-large="arrowIcon" @update:model-value="$emit('update:modelValue', $event)"> </PlDropdown>
95
+ <PlDropdown
96
+ v-bind="props"
97
+ :options="options"
98
+ :loading-options-helper="loadingOptionsHelper"
99
+ :arrow-icon-large="arrowIcon"
100
+ @update:model-value="$emit('update:modelValue', $event)"
101
+ >
102
+ </PlDropdown>
90
103
  </template>
@@ -2,6 +2,7 @@ import { describe, it, expect } from 'vitest';
2
2
 
3
3
  import { mount } from '@vue/test-utils';
4
4
  import PlDropdownRef from '../PlDropdownRef.vue';
5
+ import { delay } from '@milaboratories/helpers';
5
6
 
6
7
  describe('PlDropdownRef', () => {
7
8
  it('modelValue', async () => {
@@ -9,8 +10,8 @@ describe('PlDropdownRef', () => {
9
10
  props: {
10
11
  modelValue: {
11
12
  __isRef: true as const,
12
- blockId: '2',
13
- name: 'Ref to block 2',
13
+ blockId: '1',
14
+ name: 'Ref to block 1',
14
15
  },
15
16
  'onUpdate:modelValue': (e) => wrapper.setProps({ modelValue: e }),
16
17
  options: [
@@ -36,13 +37,15 @@ describe('PlDropdownRef', () => {
36
37
 
37
38
  await wrapper.find('input').trigger('focus');
38
39
 
39
- expect(await wrapper.findAll('.dropdown-list-item').length).toBe(2);
40
+ const options = [...document.body.querySelectorAll('.dropdown-list-item')] as HTMLElement[];
40
41
 
41
- await wrapper
42
- .findAll('.dropdown-list-item')
43
- .filter((node) => node.text().match(/Ref 2/))
44
- .at(0)
45
- ?.trigger('click');
42
+ expect(options.length).toBe(2);
43
+
44
+ expect(options.length).toBe(2);
45
+
46
+ options[1].click();
47
+
48
+ await delay(20);
46
49
 
47
50
  expect(wrapper.props('modelValue')).toStrictEqual({
48
51
  __isRef: true as const,
@@ -7,8 +7,8 @@ export function useEventListener<T extends EventTarget, E extends EventMap[K], K
7
7
  target: MaybeRef<T | undefined>,
8
8
  type: K,
9
9
  callback: (this: T, evt: E) => void,
10
- capture = false,
10
+ options?: AddEventListenerOptions | boolean,
11
11
  ) {
12
- onMounted(() => unref(target)?.addEventListener(type, callback as (this: T, evt: Event) => void, capture));
13
- onUnmounted(() => unref(target)?.removeEventListener(type, callback as (this: T, evt: Event) => void, capture));
12
+ onMounted(() => unref(target)?.addEventListener(type, callback as (this: T, evt: Event) => void, options));
13
+ onUnmounted(() => unref(target)?.removeEventListener(type, callback as (this: T, evt: Event) => void, options));
14
14
  }
@@ -33,9 +33,9 @@ export function useElementPosition(el: Ref<HTMLElement | undefined>, cb: (pos: E
33
33
 
34
34
  onMounted(handle);
35
35
 
36
- useEventListener(window, 'scroll', handle, true);
36
+ useEventListener(window, 'scroll', handle, { capture: true, passive: true });
37
37
 
38
- useEventListener(window, 'resize', handle, true);
38
+ useEventListener(window, 'resize', handle, { passive: true });
39
39
 
40
40
  useEventListener(window, 'adjust', handle, true);
41
41
  }
package/src/index.ts CHANGED
@@ -30,6 +30,7 @@ export * from './components/PlTextArea';
30
30
  export * from './components/PlDropdown';
31
31
  export * from './components/PlDropdownRef';
32
32
  export * from './components/PlDropdownLine';
33
+ export * from './components/PlDropdownLegacy';
33
34
  export * from './components/PlTooltip';
34
35
  export * from './components/PlProgressBar';
35
36
  export * from './components/PlNumberField';