vueless 1.4.7-beta.3 → 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.
|
|
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.
|
|
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
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
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
|
|
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
|
-
|
|
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(
|
|
449
|
+
expect(styleAttr ?? inlineMaxHeight).toContain("max-height:");
|
|
450
|
+
|
|
451
|
+
vi.restoreAllMocks();
|
|
418
452
|
});
|
|
419
453
|
});
|
|
420
454
|
|