vueless 1.4.7-beta.4 → 1.4.7-beta.5

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vueless",
3
- "version": "1.4.7-beta.4",
3
+ "version": "1.4.7-beta.5",
4
4
  "description": "Vue Styleless UI Component Library, powered by Tailwind CSS.",
5
5
  "author": "Johnny Grid <hello@vueless.com> (https://vueless.com)",
6
6
  "homepage": "https://vueless.com",
@@ -58,7 +58,7 @@
58
58
  "@vue/eslint-config-typescript": "^14.7.0",
59
59
  "@vue/test-utils": "^2.4.8",
60
60
  "@vue/tsconfig": "^0.9.1",
61
- "@vueless/storybook": "^1.5.2",
61
+ "@vueless/storybook": "^1.5.3",
62
62
  "eslint": "^10.2.1",
63
63
  "eslint-plugin-storybook": "^10.3.5",
64
64
  "eslint-plugin-vue": "^10.9.0",
@@ -1,5 +1,5 @@
1
1
  <script setup lang="ts">
2
- import { watch, computed, useId, ref, useTemplateRef } from "vue";
2
+ import { watch, computed, useId, ref, useTemplateRef, nextTick } from "vue";
3
3
  import { isEqual } from "lodash-es";
4
4
 
5
5
  import { useUI } from "../composables/useUI";
@@ -144,77 +144,78 @@ const filteredOptions = computed(() => {
144
144
  watch(
145
145
  () => [props.options, props.size, props.visibleOptions, props.searchable, searchModel.value],
146
146
  () => {
147
- const options = [
148
- ...(optionsRef.value || []),
149
- ...(addOptionRef.value ? [addOptionRef.value] : []),
150
- ...(emptyOptionRef.value ? [emptyOptionRef.value] : []),
151
- ];
152
-
153
- if (props.visibleOptions) {
154
- options.slice(0, props.visibleOptions);
155
- }
156
-
157
- const maxHeight = options
158
- .slice(0, props.visibleOptions)
159
- .map((el) => {
160
- const styles = window.getComputedStyle(el);
161
- const height = parseFloat(styles.height || "0");
162
- const marginTop = parseFloat(styles.marginTop || "0");
163
- const marginBottom = parseFloat(styles.marginBottom || "0");
164
-
165
- return height + marginTop + marginBottom;
166
- })
167
- .reduce((acc, cur) => acc + cur, 0);
168
-
169
- const wrapperEl = wrapperRef.value;
170
- const wrapperStyle = wrapperEl ? getComputedStyle(wrapperEl) : null;
171
- const wrapperPaddingTop = parseFloat(wrapperStyle?.paddingTop || "0");
172
- const wrapperPaddingBottom = parseFloat(wrapperStyle?.paddingBottom || "0");
173
- const wrapperBorderTop = parseFloat(wrapperStyle?.borderTopWidth || "0");
174
- const wrapperBorderBottom = parseFloat(wrapperStyle?.borderBottomWidth || "0");
175
- const wrapperGap = parseFloat(wrapperStyle?.gap || "0");
176
-
177
- const addOptionHeight = addOptionRef.value?.getBoundingClientRect().height || 0;
178
-
179
- const inputEl = listboxInputRef.value?.input as HTMLInputElement | undefined;
180
- let listboxInputHeight = 0;
181
-
182
- let listboxInputWrapperPaddingTop = 0;
183
- let listboxInputBorderTop = 0;
184
- let listboxInputBorderBottom = 0;
185
-
186
- if (inputEl) {
187
- const listboxInputStyle = getComputedStyle(inputEl);
188
- const listboxInputLabelStyle = inputEl.parentElement
189
- ? getComputedStyle(inputEl.parentElement)
190
- : undefined;
191
- const listboxInputWrapperStyle = getComputedStyle(
192
- inputEl.parentElement?.parentElement?.parentElement as Element,
193
- );
194
-
195
- listboxInputHeight = parseFloat(listboxInputStyle.height || "0");
196
-
197
- listboxInputWrapperPaddingTop = parseFloat(listboxInputWrapperStyle.paddingTop || "0");
198
-
199
- listboxInputBorderTop = parseFloat(listboxInputLabelStyle?.borderTop || "0");
200
- listboxInputBorderBottom = parseFloat(listboxInputLabelStyle?.borderBottom || "0");
201
- }
202
-
203
- wrapperMaxHeight.value = `${
204
- maxHeight +
205
- addOptionHeight +
206
- (props.searchable ? wrapperGap : 0) +
207
- wrapperPaddingTop +
208
- wrapperPaddingBottom +
209
- wrapperBorderTop +
210
- wrapperBorderBottom +
211
- listboxInputHeight +
212
- listboxInputBorderTop +
213
- listboxInputBorderBottom +
214
- listboxInputWrapperPaddingTop
215
- }px`;
147
+ nextTick(() => {
148
+ const options = [
149
+ ...(optionsRef.value || []),
150
+ ...(addOptionRef.value ? [addOptionRef.value] : []),
151
+ ...(emptyOptionRef.value ? [emptyOptionRef.value] : []),
152
+ ];
153
+
154
+ if (props.visibleOptions) {
155
+ options.slice(0, props.visibleOptions);
156
+ }
157
+
158
+ const maxHeight = options
159
+ .slice(0, props.visibleOptions)
160
+ .map((el) => {
161
+ const styles = window.getComputedStyle(el);
162
+ const height = parseFloat(styles.height || "0");
163
+ const marginTop = parseFloat(styles.marginTop || "0");
164
+ const marginBottom = parseFloat(styles.marginBottom || "0");
165
+
166
+ return height + marginTop + marginBottom;
167
+ })
168
+ .reduce((acc, cur) => acc + cur, 0);
169
+
170
+ const wrapperStyle = getComputedStyle(wrapperRef.value as Element);
171
+ const wrapperPaddingTop = parseFloat(wrapperStyle.paddingTop || "0");
172
+ const wrapperPaddingBottom = parseFloat(wrapperStyle.paddingBottom || "0");
173
+ const wrapperBorderTop = parseFloat(wrapperStyle.borderTopWidth || "0");
174
+ const wrapperBorderBottom = parseFloat(wrapperStyle.borderBottomWidth || "0");
175
+ const wrapperGap = parseFloat(wrapperStyle.gap || "0");
176
+
177
+ const addOptionHeight = addOptionRef.value?.getBoundingClientRect().height || 0;
178
+
179
+ const inputEl = listboxInputRef.value?.input as HTMLInputElement | undefined;
180
+ let listboxInputHeight = 0;
181
+
182
+ let listboxInputWrapperPaddingTop = 0;
183
+ let listboxInputBorderTop = 0;
184
+ let listboxInputBorderBottom = 0;
185
+
186
+ if (inputEl) {
187
+ const listboxInputStyle = getComputedStyle(inputEl);
188
+ const listboxInputLabelStyle = inputEl.parentElement
189
+ ? getComputedStyle(inputEl.parentElement)
190
+ : undefined;
191
+ const listboxInputWrapperStyle = getComputedStyle(
192
+ inputEl.parentElement?.parentElement?.parentElement as Element,
193
+ );
194
+
195
+ listboxInputHeight = parseFloat(listboxInputStyle.height || "0");
196
+
197
+ listboxInputWrapperPaddingTop = parseFloat(listboxInputWrapperStyle.paddingTop || "0");
198
+
199
+ listboxInputBorderTop = parseFloat(listboxInputLabelStyle?.borderTop || "0");
200
+ listboxInputBorderBottom = parseFloat(listboxInputLabelStyle?.borderBottom || "0");
201
+ }
202
+
203
+ wrapperMaxHeight.value = `${
204
+ maxHeight +
205
+ addOptionHeight +
206
+ (props.searchable ? wrapperGap : 0) +
207
+ wrapperPaddingTop +
208
+ wrapperPaddingBottom +
209
+ wrapperBorderTop +
210
+ wrapperBorderBottom +
211
+ listboxInputHeight +
212
+ listboxInputBorderTop +
213
+ listboxInputBorderBottom +
214
+ listboxInputWrapperPaddingTop
215
+ }px`;
216
+ });
216
217
  },
217
- { immediate: true, flush: "post" },
218
+ { immediate: true },
218
219
  );
219
220
 
220
221
  watch(
@@ -1,5 +1,6 @@
1
+ import { nextTick } from "vue";
1
2
  import { flushPromises, mount } from "@vue/test-utils";
2
- import { describe, it, expect } from "vitest";
3
+ import { describe, it, expect, vi } from "vitest";
3
4
 
4
5
  import UListbox from "../UListbox.vue";
5
6
  import UIcon from "../../ui.image-icon/UIcon.vue";
@@ -399,7 +400,37 @@ describe("UListbox.vue", () => {
399
400
  id: `option-${i}`,
400
401
  }));
401
402
 
402
- const expectedStyle = "max-height:";
403
+ // Mock getComputedStyle to return non-zero heights for option elements
404
+ const originalGetComputedStyle = window.getComputedStyle;
405
+
406
+ vi.spyOn(window, "getComputedStyle").mockImplementation((el) => {
407
+ const real = originalGetComputedStyle(el);
408
+
409
+ return {
410
+ ...real,
411
+ height: "40px",
412
+ marginTop: "0px",
413
+ marginBottom: "4px",
414
+ paddingTop: "4px",
415
+ paddingBottom: "4px",
416
+ borderTopWidth: "1px",
417
+ borderBottomWidth: "1px",
418
+ gap: "4px",
419
+ } as CSSStyleDeclaration;
420
+ });
421
+
422
+ // Mock getBoundingClientRect for option elements
423
+ vi.spyOn(HTMLElement.prototype, "getBoundingClientRect").mockReturnValue({
424
+ height: 40,
425
+ width: 100,
426
+ top: 0,
427
+ left: 0,
428
+ bottom: 40,
429
+ right: 100,
430
+ x: 0,
431
+ y: 0,
432
+ toJSON: () => {},
433
+ });
403
434
 
404
435
  const component = mount(UListbox, {
405
436
  props: {
@@ -409,12 +440,15 @@ describe("UListbox.vue", () => {
409
440
  });
410
441
 
411
442
  await flushPromises();
443
+ await nextTick();
412
444
 
413
445
  const wrapper = component.find('[vl-key="wrapper"]');
414
446
  const styleAttr = wrapper.attributes("style");
415
447
  const inlineMaxHeight = (wrapper.element as HTMLElement).style.maxHeight;
416
448
 
417
- expect(styleAttr ?? inlineMaxHeight).toContain(expectedStyle);
449
+ expect(styleAttr ?? inlineMaxHeight).toContain("max-height:");
450
+
451
+ vi.restoreAllMocks();
418
452
  });
419
453
  });
420
454