Skip to content

Commit afc0d29

Browse files
authored
feat 0.18.0 (#505)
## Fix: * fix(select): avoid overflowing container * whitespace no-wrap caused select to grow beyond its parent * fix(select): fixed shrinking padlock icon * fix(select): position dropdown on scroll ## Performance: * perf(select): removed unnecessary cloning * perf(select): debounce event listeners ## Chore: * chore: small demo board style change * chore: increment version * chore(deps-dev): updated dependencies ## Refactor: * refactor!: change plugin install strategy ## Feature: * feat(transitions): added FadeSlideTransition * feat: (internal) added colour converter * Convert hex colours to tailwind vars ## Documentation: * docs(select): added more select options
1 parent 2aa29d8 commit afc0d29

File tree

14 files changed

+2130
-1992
lines changed

14 files changed

+2130
-1992
lines changed

jest.config.ts

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,7 @@ export default {
2929
reporters: ['default', 'github-actions'],
3030
transform: {
3131
'^.+\\.vue$': '@vue/vue3-jest',
32-
'^.+\\ts$': 'ts-jest'
32+
'^.+\\ts$': ['ts-jest', { tsconfig: 'tsconfig.node.json' }]
3333
},
34-
testMatch: ['<rootDir>/src/**/*.test.ts'],
35-
globals: {
36-
'ts-jest': {
37-
tsconfig: 'tsconfig.node.json'
38-
}
39-
}
34+
testMatch: ['<rootDir>/src/**/*.test.ts']
4035
} as InitialOptionsTsJest;

package-lock.json

Lines changed: 1835 additions & 1891 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@karnama/vueish",
3-
"version": "0.17.5",
3+
"version": "0.18.0",
44
"files": [
55
"dist",
66
"types"
@@ -27,6 +27,7 @@
2727
"lint": "eslint . --fix --ext .ts,.vue,.tsx",
2828
"prepare": "husky install",
2929
"generate:web-types": "ts-node-cwd -P ./tsconfig.node.json utils/web-types/generateWebTypes.ts",
30+
"generate:css-vars": "ts-node-cwd -P ./tsconfig.node.json utils/convertHexObjToVars.ts",
3031
"commit": "commit"
3132
},
3233
"peerDependencies": {
@@ -38,8 +39,8 @@
3839
"@commitlint/prompt-cli": "^17.0.0",
3940
"@commitlint/types": "^17.0.0",
4041
"@types/eslint": "^8.4.1",
41-
"@types/glob": "^7.1.3",
42-
"@types/jest": "^28.1.1",
42+
"@types/glob": "^8.0.0",
43+
"@types/jest": "^29.0.0",
4344
"@types/lodash-es": "^4.17.4",
4445
"@types/minimist": "^1.2.1",
4546
"@types/requestidlecallback": "^0.3.1",
@@ -49,19 +50,19 @@
4950
"@vue/compiler-sfc": "^3.2.11",
5051
"@vue/eslint-config-typescript": "^11.0.0",
5152
"@vue/test-utils": "2.0.0-rc.16",
52-
"@vue/vue3-jest": "^28.0.0",
53+
"@vue/vue3-jest": "^29.0.0",
5354
"autoprefixer": "^10.4.0",
54-
"babel-jest": "^28.1.1",
55+
"babel-jest": "^29.0.2",
5556
"babel-loader": "^8.2.2",
5657
"commitlint": "^17.0.2",
57-
"eslint": "^8.2.0",
58+
"eslint": "~8.22.0",
5859
"eslint-plugin-import": "^2.22.1",
59-
"eslint-plugin-jest": "^26.1.1",
60+
"eslint-plugin-jest": "^27.0.1",
6061
"eslint-plugin-vue": "^9.1.1",
6162
"glob": "^8.0.1",
6263
"husky": "^8.0.1",
63-
"jest": "^28.1.1",
64-
"jest-environment-jsdom": "^28.1.1",
64+
"jest": "^29.0.2",
65+
"jest-environment-jsdom": "^29.0.2",
6566
"jest-junit": "^14.0.0",
6667
"jest-serializer-vue": "^2.0.2",
6768
"lint-staged": "^13.0.1",
@@ -70,12 +71,12 @@
7071
"postcss": "^8.4.4",
7172
"sass": "^1.32.12",
7273
"tailwindcss": "^3.0.0",
73-
"ts-jest": "^28.0.5",
74+
"ts-jest": "^29.0.0-next.1",
7475
"ts-node": "^10.0.0",
7576
"typescript": "^4.3.4",
7677
"vite": "^3.0.0",
7778
"vue": "^3.2.25",
78-
"vue-docgen-api": "4.47.0",
79+
"vue-docgen-api": "^4.52.0",
7980
"vue-router": "^4.0.6",
8081
"vue-template-compiler": "^2.6.12"
8182
},

src/DemoBoard.vue

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,20 @@
55
<div class="menu px-12 shadow-xl dark:bg-gray-600 dark:text-gray-300 z-30 bg-white"
66
:class="[ isOpen ? 'open' : 'closed' ]">
77
<div class="sticky top-0">
8-
<div class="flex items-center justify-between">
8+
<div class="flex items-center justify-between space-x-2">
99
<div class="mt-4 mb-6">
1010
<h1 class="text-2xl whitespace-nowrap">
1111
Vueish UI
1212
</h1>
1313
<small>v{{ version }}</small>
1414
</div>
1515

16-
<UIButton minimal
17-
class="dark:text-gray-200 dark:hover:text-gray-700"
16+
<UIButton outline
17+
theme="gray"
18+
class="!rounded-full w-8 h-8 relative"
1819
@click="isOpen = false">
19-
<span v-html="clearIcon" />
20+
<span class="absolute top-[50%] left-[50%] -translate-x-[50%] -translate-y-[50%]"
21+
v-html="clearIcon" />
2022
</UIButton>
2123
</div>
2224
<div class="flex-col flex">
@@ -151,6 +153,7 @@ export default defineComponent({
151153
transition: margin-left 300ms ease, opacity 300ms ease-out;
152154
opacity: 0;
153155
}
156+
154157
&.open {
155158
transition: margin-left 300ms ease, opacity 300ms ease-out;
156159
opacity: 1;

src/components/button-toggle/UIButtonToggle.test.ts

Lines changed: 29 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import { mount } from '@vue/test-utils';
22
import UIButtonToggle from './UIButtonToggle.vue';
33
import type { Option } from 'types';
4-
import { ref, watch } from 'vue';
54

65
const options: Record<string, any>[] = [
76
{ label: 'Places', value: 'places' },
@@ -58,25 +57,25 @@ describe('UIButtonToggle', () => {
5857
});
5958

6059
it('should be able to select multiple options given the prop', async () => {
61-
const wrapper = mount({
62-
template: '<UIButtonToggle :options="options" multi v-model="model" />',
63-
components: { UIButtonToggle },
64-
setup: () => {
65-
return {
66-
model: ref(null),
67-
options
68-
};
60+
const wrapper = mount(UIButtonToggle, {
61+
props: {
62+
options,
63+
multi: true,
64+
modelValue: null
6965
}
7066
});
67+
await wrapper.setProps({
68+
'onUpdate:modelValue': async (modelValue: any) => await wrapper.setProps({ modelValue })
69+
});
7170

7271
const buttons = wrapper.findAll('button');
7372

7473
await buttons[0]!.trigger('click');
75-
expect(wrapper.vm.model).toStrictEqual([options[0]]);
74+
expect(wrapper.lastEventValue()).toStrictEqual([[options[0]]]);
7675
await buttons[1]!.trigger('click');
77-
expect(wrapper.vm.model).toStrictEqual([options[0], options[1]]);
76+
expect(wrapper.lastEventValue()).toStrictEqual([[options[0], options[1]]]);
7877
await buttons[1]!.trigger('click');
79-
expect(wrapper.vm.model).toStrictEqual([options[0]]);
78+
expect(wrapper.lastEventValue()).toStrictEqual([[options[0]]]);
8079
});
8180

8281
it('should be disabled given the prop', async () => {
@@ -96,10 +95,12 @@ describe('UIButtonToggle', () => {
9695
const wrapper = mount(UIButtonToggle, {
9796
props: {
9897
options,
99-
modelValue: null,
100-
'onUpdate:modelValue': async (modelValue: any) => await wrapper.setProps({ modelValue })
98+
modelValue: null
10199
}
102100
});
101+
await wrapper.setProps({
102+
'onUpdate:modelValue': async (modelValue: any) => await wrapper.setProps({ modelValue })
103+
});
103104

104105
const button = wrapper.get('button');
105106

@@ -114,29 +115,27 @@ describe('UIButtonToggle', () => {
114115
});
115116

116117
it('should clear up to a single value on multi select', async () => {
117-
const wrapper = mount({
118-
template: '<UIButtonToggle :options="options" multi v-model="model" />',
119-
components: { UIButtonToggle },
120-
setup: (_props, ctx) => {
121-
const model = ref(null);
122-
watch(() => model.value, () => ctx.emit('update:modelValue'));
123-
124-
return {
125-
model,
126-
options
127-
};
118+
const wrapper = mount(UIButtonToggle, {
119+
props: {
120+
options,
121+
modelValue: null,
122+
multi: true
128123
}
129124
});
125+
await wrapper.setProps({
126+
'onUpdate:modelValue': async (modelValue: any) => await wrapper.setProps({ modelValue })
127+
});
130128

131129
const buttons = wrapper.findAll('button');
132130

133131
await buttons[0]!.trigger('click');
132+
expect(wrapper.lastEventValue()).toStrictEqual([[options[0]]]);
134133
await buttons[1]!.trigger('click');
135134

136-
expect(wrapper.vm.model).toStrictEqual([options[0], options[1]]);
135+
expect(wrapper.lastEventValue()).toStrictEqual([[options[0], options[1]]]);
137136

138137
await buttons[0]!.trigger('click');
139-
expect(wrapper.vm.model).toStrictEqual([options[1]]);
138+
expect(wrapper.lastEventValue()).toStrictEqual([[options[1]]]);
140139
await buttons[1]!.trigger('click');
141140
expect(wrapper.emitted('update:modelValue')).toHaveLength(4);
142141
});
@@ -146,10 +145,12 @@ describe('UIButtonToggle', () => {
146145
props: {
147146
options,
148147
modelValue: null,
149-
'onUpdate:modelValue': async (modelValue: any) => await wrapper.setProps({ modelValue }),
150148
clearable: true
151149
}
152150
});
151+
await wrapper.setProps({
152+
'onUpdate:modelValue': async (modelValue: any) => await wrapper.setProps({ modelValue })
153+
});
153154

154155
const buttons = wrapper.findAll('button');
155156
await buttons[0]!.trigger('click');

src/components/select/Demo.vue

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,18 @@ const options = [
118118
{
119119
id: 7,
120120
name: 'Bruce Baxter'
121+
},
122+
{
123+
id: 8,
124+
name: 'Bruce The Bear'
125+
},
126+
{
127+
id: 9,
128+
name: 'Bruce Ismay'
129+
},
130+
{
131+
id: 10,
132+
name: 'Bruce Campbell'
121133
}
122134
];
123135

src/components/select/UISelect.vue

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,7 @@
3737
@click="open ? closeList() : openList()">
3838
<template v-if="selectionCount > 0">
3939
<slot name="selected" :selected="selected">
40-
<span :class="{ 'truncate': multi }">
41-
{{ selectionDisplay }}
42-
</span>
40+
{{ selectionDisplay }}
4341
</slot>
4442
</template>
4543
<template v-else>
@@ -52,7 +50,7 @@
5250

5351
<UIFadeTransition duration-out="duration-100" duration-in="duration-100">
5452
<span v-if="disabled"
55-
class="h-5 w-5 text-color-muted"
53+
class="h-5 w-5 text-color-muted shrink-0"
5654
:class="{ '-mr-3.5': large }"
5755
v-html="lockIcon" />
5856

@@ -165,7 +163,7 @@
165163

166164
<script lang="ts">
167165
import { computed, defineComponent, onMounted, ref, onUnmounted, nextTick, onBeforeUpdate } from 'vue';
168-
import { isEqual as _isEqual, cloneDeep } from 'lodash-es';
166+
import { isEqual as _isEqual, cloneDeep, debounce } from 'lodash-es';
169167
import type { PropType } from 'vue';
170168
import {
171169
placeholder,
@@ -309,7 +307,7 @@ export default defineComponent({
309307
return '';
310308
}
311309
312-
const options = wrap<Option | string>(cloneDeep(selected.value));
310+
const options = wrap<Option | string>(selected.value);
313311
314312
return options.map(option => typeof option === 'string' ? option : option[props.optionLabel]).join(', ');
315313
});
@@ -355,7 +353,8 @@ export default defineComponent({
355353
await nextTick();
356354
open.value = false;
357355
search.value = '';
358-
globalThis?.window.removeEventListener('resize', setPosition);
356+
globalThis?.window.removeEventListener('resize', debounce(setPosition, 15));
357+
globalThis?.window.removeEventListener('scroll', debounce(setPosition, 15));
359358
};
360359
const openList = async () => {
361360
if (props.disabled) return;
@@ -364,7 +363,8 @@ export default defineComponent({
364363
await nextTick();
365364
setPosition();
366365
searchInput.value?.focus({ preventScroll: true });
367-
globalThis?.window.addEventListener('resize', setPosition);
366+
globalThis?.window.addEventListener('resize', debounce(setPosition, 15));
367+
globalThis?.window.addEventListener('scroll', debounce(setPosition, 15));
368368
};
369369
const clearSelection = (option?: Option) => {
370370
if (
@@ -465,7 +465,8 @@ export default defineComponent({
465465
466466
onUnmounted(() => {
467467
// in case it's unmounted while open
468-
globalThis?.window.removeEventListener('resize', setPosition);
468+
globalThis?.window.removeEventListener('resize', debounce(setPosition, 15));
469+
globalThis?.window.removeEventListener('scroll', debounce(setPosition, 15));
469470
});
470471
471472
return {

src/components/transitions/Demo.vue

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,15 @@
99
<div class="flex flex-col justify-center"
1010
:style="[ component.name !== 'UIExpandTransition' ? 'min-height: 10rem;' : '' ]">
1111
<component :is="component.name">
12-
<div v-if="singleElement" class="content" />
12+
<div v-show="singleElement" class="content" />
1313
</component>
1414
</div>
1515

1616
<slot name="footer">
1717
<div class="flex justify-end">
1818
<UIButton :label="`${singleElement ? 'Not' : ''} Visible`"
1919
outline
20+
class="min-w-[106px]"
2021
@click="singleElement = !singleElement" />
2122
</div>
2223
</slot>
@@ -76,7 +77,8 @@ export default defineComponent({
7677
const components = [
7778
{ name: 'UIFadeTransition' },
7879
{ name: 'UIFadeScaleTransition' },
79-
{ name: 'UIExpandTransition' }
80+
{ name: 'UIExpandTransition' },
81+
{ name: 'UIFadeSlideTransition' }
8082
];
8183
8284
const component = ref<{ name: string }>({ name: 'UIFadeTransition' });

0 commit comments

Comments
 (0)