@weni/unnnic-system 3.2.9-alpha.12 → 3.2.9-alpha.13
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/dist/components/Button/Button.vue.d.ts.map +1 -1
- package/dist/components/ChartFunnel/DefaultFunnel/ChartDefaultFunnelBase.vue.d.ts.map +1 -1
- package/dist/components/Input/TextInput.vue.d.ts.map +1 -1
- package/dist/components/ModalDialog/ModalDialog.vue.d.ts +1 -1
- package/dist/components/ModalDialog/ModalDialog.vue.d.ts.map +1 -1
- package/dist/components/TemplatePreview/TemplatePreview.vue.d.ts.map +1 -1
- package/dist/components/index.d.ts +2 -2
- package/dist/{es-66126ef1.mjs → es-5aa232c1.mjs} +1 -1
- package/dist/{index-f6e9b879.mjs → index-69d07468.mjs} +353 -352
- package/dist/{pt-br-3b5a8852.mjs → pt-br-5f8a4e67.mjs} +1 -1
- package/dist/style.css +1 -1
- package/dist/unnnic.mjs +1 -1
- package/dist/unnnic.umd.js +7 -7
- package/package.json +2 -2
- package/src/components/Button/Button.vue +7 -4
- package/src/components/ChartFunnel/DefaultFunnel/ChartDefaultFunnelBase.vue +1 -2
- package/src/components/ChartFunnel/SvgFunnel/ChartFunnelTwoRows.vue +60 -61
- package/src/components/Chip/Chip.vue +1 -1
- package/src/components/Input/BaseInput.vue +4 -4
- package/src/components/Input/Input.vue +1 -1
- package/src/components/Input/TextInput.vue +2 -3
- package/src/components/ModalDialog/ModalDialog.vue +29 -26
- package/src/components/Popover/__tests__/Popover.spec.js +18 -18
- package/src/components/Popover/index.vue +93 -78
- package/src/components/Select/SelectOption.vue +43 -37
- package/src/components/Select/__tests__/Select.spec.js +41 -36
- package/src/components/Select/__tests__/SelectItem.spec.js +35 -15
- package/src/components/Select/__tests__/SelectOption.spec.js +6 -3
- package/src/components/Select/index.vue +192 -142
- package/src/components/TemplatePreview/TemplatePreview.vue +30 -27
- package/src/components/TemplatePreview/TemplatePreviewModal.vue +11 -11
- package/src/components/TemplatePreview/types.d.ts +3 -3
- package/src/stories/Button.stories.js +1 -7
- package/src/stories/Input.stories.js +4 -4
- package/src/stories/Popover.stories.js +9 -9
- package/src/stories/Select.stories.js +39 -39
- package/src/stories/TemplatePreview.stories.js +27 -27
- package/src/stories/TemplatePreviewModal.stories.js +31 -31
|
@@ -1,131 +1,146 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
2
|
+
<section
|
|
3
|
+
ref="popover"
|
|
4
|
+
class="unnnic-popover"
|
|
5
|
+
>
|
|
6
|
+
<div
|
|
7
|
+
class="unnnic-popover__trigger"
|
|
8
|
+
data-testid="popover-trigger"
|
|
9
|
+
@click="toggleOpen()"
|
|
10
|
+
>
|
|
11
|
+
<slot name="trigger" />
|
|
12
|
+
</div>
|
|
13
|
+
<div
|
|
14
|
+
v-if="open"
|
|
15
|
+
class="unnnic-popover__balloon"
|
|
16
|
+
data-testid="popover-balloon"
|
|
17
|
+
>
|
|
18
|
+
<slot name="content" />
|
|
19
|
+
</div>
|
|
20
|
+
</section>
|
|
10
21
|
</template>
|
|
11
22
|
|
|
12
23
|
<script setup lang="ts">
|
|
13
24
|
import { computed, onMounted, ref, useTemplateRef, watch } from 'vue';
|
|
14
25
|
import { onClickOutside, useResizeObserver } from '@vueuse/core';
|
|
15
26
|
|
|
16
|
-
const target = useTemplateRef<HTMLDivElement>('popover')
|
|
27
|
+
const target = useTemplateRef<HTMLDivElement>('popover');
|
|
17
28
|
|
|
18
|
-
const popoverWidth = ref<string>('')
|
|
29
|
+
const popoverWidth = ref<string>('');
|
|
19
30
|
|
|
20
31
|
useResizeObserver(target, (entries) => {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
})
|
|
32
|
+
const entry = entries[0];
|
|
33
|
+
const { width } = entry.contentRect;
|
|
34
|
+
popoverWidth.value = `${width}px`;
|
|
35
|
+
});
|
|
25
36
|
|
|
26
37
|
onClickOutside(target, () => {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
})
|
|
38
|
+
if (props.persistent) return;
|
|
39
|
+
open.value = false;
|
|
40
|
+
});
|
|
30
41
|
|
|
31
42
|
defineOptions({
|
|
32
|
-
|
|
33
|
-
})
|
|
43
|
+
name: 'UnnnicPopover',
|
|
44
|
+
});
|
|
34
45
|
|
|
35
46
|
interface PopoverBalloonProps {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
47
|
+
width?: string;
|
|
48
|
+
height?: string;
|
|
49
|
+
maxHeight?: string;
|
|
39
50
|
}
|
|
40
51
|
|
|
41
52
|
interface PopoverProps {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
53
|
+
modelValue?: boolean;
|
|
54
|
+
persistent?: boolean;
|
|
55
|
+
popoverBalloonProps?: PopoverBalloonProps;
|
|
45
56
|
}
|
|
46
57
|
|
|
47
58
|
const props = withDefaults(defineProps<PopoverProps>(), {
|
|
48
|
-
|
|
49
|
-
|
|
59
|
+
modelValue: undefined,
|
|
60
|
+
persistent: false,
|
|
50
61
|
});
|
|
51
62
|
|
|
52
63
|
const emit = defineEmits<{
|
|
53
|
-
|
|
54
|
-
}>()
|
|
64
|
+
'update:modelValue': [value: boolean];
|
|
65
|
+
}>();
|
|
55
66
|
|
|
56
67
|
const useModelValue = computed(() => props.modelValue !== undefined);
|
|
57
68
|
|
|
58
|
-
const open = ref<boolean>(
|
|
69
|
+
const open = ref<boolean>(
|
|
70
|
+
useModelValue.value ? Boolean(props.modelValue) : false,
|
|
71
|
+
);
|
|
59
72
|
|
|
60
73
|
const toggleOpen = () => {
|
|
61
|
-
|
|
62
|
-
}
|
|
74
|
+
open.value = !open.value;
|
|
75
|
+
};
|
|
63
76
|
|
|
64
77
|
const calculatedPopoverWidth = computed(() => {
|
|
65
|
-
|
|
66
|
-
})
|
|
78
|
+
return props.popoverBalloonProps?.width || popoverWidth.value;
|
|
79
|
+
});
|
|
67
80
|
|
|
68
81
|
const popoverHeight = computed(() => {
|
|
69
|
-
|
|
70
|
-
})
|
|
82
|
+
return props.popoverBalloonProps?.height || 'unset';
|
|
83
|
+
});
|
|
71
84
|
|
|
72
85
|
const popoverMaxHeight = computed(() => {
|
|
73
|
-
|
|
74
|
-
})
|
|
86
|
+
return props.popoverBalloonProps?.maxHeight || 'unset';
|
|
87
|
+
});
|
|
75
88
|
|
|
76
89
|
onMounted(() => {
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
})
|
|
90
|
+
if (useModelValue.value) {
|
|
91
|
+
open.value = Boolean(props.modelValue);
|
|
92
|
+
}
|
|
93
|
+
});
|
|
81
94
|
|
|
82
95
|
watch(open, (value) => {
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
})
|
|
96
|
+
if (useModelValue.value) {
|
|
97
|
+
emit('update:modelValue', value);
|
|
98
|
+
}
|
|
99
|
+
});
|
|
87
100
|
|
|
88
|
-
watch(
|
|
101
|
+
watch(
|
|
102
|
+
() => props.modelValue,
|
|
103
|
+
(value) => {
|
|
89
104
|
open.value = !!value;
|
|
90
|
-
}
|
|
91
|
-
|
|
105
|
+
},
|
|
106
|
+
);
|
|
92
107
|
</script>
|
|
93
108
|
|
|
94
109
|
<style lang="scss" scoped>
|
|
95
110
|
@use '@/assets/scss/unnnic' as *;
|
|
96
111
|
|
|
97
112
|
* {
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
113
|
+
margin: 0;
|
|
114
|
+
padding: 0;
|
|
115
|
+
box-sizing: border-box;
|
|
101
116
|
}
|
|
102
117
|
|
|
103
118
|
.unnnic-popover {
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
}
|
|
119
|
+
&__balloon {
|
|
120
|
+
border-radius: $unnnic-radius-2;
|
|
121
|
+
padding: $unnnic-space-4;
|
|
122
|
+
background: $unnnic-color-bg-base;
|
|
123
|
+
box-shadow: 0 4px 16px 0 rgba(0, 0, 0, 0.16);
|
|
124
|
+
// margin-top: $unnnic-space-1;
|
|
125
|
+
position: fixed;
|
|
126
|
+
width: v-bind(calculatedPopoverWidth);
|
|
127
|
+
height: v-bind(popoverHeight);
|
|
128
|
+
max-height: v-bind(popoverMaxHeight);
|
|
129
|
+
overflow: auto;
|
|
130
|
+
|
|
131
|
+
&::-webkit-scrollbar {
|
|
132
|
+
width: $unnnic-spacing-inline-nano;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
&::-webkit-scrollbar-thumb {
|
|
136
|
+
background: $unnnic-color-neutral-cleanest;
|
|
137
|
+
border-radius: $unnnic-border-radius-pill;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
&::-webkit-scrollbar-track {
|
|
141
|
+
background: $unnnic-color-neutral-soft;
|
|
142
|
+
border-radius: $unnnic-border-radius-pill;
|
|
129
143
|
}
|
|
144
|
+
}
|
|
130
145
|
}
|
|
131
|
-
</style>
|
|
146
|
+
</style>
|
|
@@ -1,59 +1,65 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
|
|
2
|
+
<div
|
|
3
|
+
:class="[
|
|
4
|
+
'unnnic-select-option',
|
|
5
|
+
{
|
|
3
6
|
'unnnic-select-option--disabled': props.disabled,
|
|
4
7
|
'unnnic-select-option--active': props.active,
|
|
5
8
|
'unnnic-select-option--focused': props.focused,
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
+
},
|
|
10
|
+
]"
|
|
11
|
+
>
|
|
12
|
+
<p class="unnnic-select-option__label">{{ props.label }}</p>
|
|
13
|
+
</div>
|
|
9
14
|
</template>
|
|
10
15
|
|
|
11
16
|
<script setup lang="ts">
|
|
12
17
|
defineOptions({
|
|
13
|
-
|
|
14
|
-
})
|
|
18
|
+
name: 'UnnnicSelectOption',
|
|
19
|
+
});
|
|
15
20
|
|
|
16
21
|
interface SelectOptionProps {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
22
|
+
label: string;
|
|
23
|
+
disabled?: boolean;
|
|
24
|
+
active?: boolean;
|
|
25
|
+
focused?: boolean;
|
|
21
26
|
}
|
|
22
27
|
|
|
23
28
|
const props = withDefaults(defineProps<SelectOptionProps>(), {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
})
|
|
29
|
+
disabled: false,
|
|
30
|
+
active: false,
|
|
31
|
+
focused: false,
|
|
32
|
+
});
|
|
28
33
|
</script>
|
|
29
34
|
|
|
30
35
|
<style lang="scss" scoped>
|
|
31
36
|
@use '@/assets/scss/unnnic' as *;
|
|
32
37
|
* {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
38
|
+
margin: 0;
|
|
39
|
+
padding: 0;
|
|
40
|
+
box-sizing: border-box;
|
|
36
41
|
}
|
|
37
42
|
|
|
38
43
|
.unnnic-select-option {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
44
|
+
cursor: pointer;
|
|
45
|
+
border-radius: $unnnic-radius-1;
|
|
46
|
+
padding: $unnnic-space-2 $unnnic-space-4;
|
|
47
|
+
font: $unnnic-font-emphasis;
|
|
48
|
+
|
|
49
|
+
&:hover:not(&--active):not(&--disabled),
|
|
50
|
+
&--focused {
|
|
51
|
+
background-color: $unnnic-color-bg-soft;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
&--active {
|
|
55
|
+
background-color: $unnnic-color-bg-active;
|
|
56
|
+
color: $unnnic-color-fg-inverted;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
&--disabled {
|
|
60
|
+
color: $unnnic-color-fg-muted;
|
|
61
|
+
background-color: $unnnic-color-bg-muted;
|
|
62
|
+
cursor: not-allowed;
|
|
63
|
+
}
|
|
58
64
|
}
|
|
59
|
-
</style>
|
|
65
|
+
</style>
|
|
@@ -5,9 +5,9 @@ import UnnnicSelect from '../index.vue';
|
|
|
5
5
|
vi.mock('../../mixins/i18n', () => ({
|
|
6
6
|
default: {
|
|
7
7
|
methods: {
|
|
8
|
-
$t: (key) => key
|
|
9
|
-
}
|
|
10
|
-
}
|
|
8
|
+
$t: (key) => key,
|
|
9
|
+
},
|
|
10
|
+
},
|
|
11
11
|
}));
|
|
12
12
|
|
|
13
13
|
describe('UnnnicSelect.vue', () => {
|
|
@@ -17,23 +17,23 @@ describe('UnnnicSelect.vue', () => {
|
|
|
17
17
|
options: [
|
|
18
18
|
{ label: 'Option 1', value: 'option1' },
|
|
19
19
|
{ label: 'Option 2', value: 'option2' },
|
|
20
|
-
{ label: 'Option 3', value: 'option3' }
|
|
20
|
+
{ label: 'Option 3', value: 'option3' },
|
|
21
21
|
],
|
|
22
|
-
modelValue: null
|
|
22
|
+
modelValue: null,
|
|
23
23
|
};
|
|
24
24
|
|
|
25
25
|
const mountWrapper = (props = {}, slots = {}) => {
|
|
26
26
|
return mount(UnnnicSelect, {
|
|
27
27
|
props: {
|
|
28
28
|
...defaultProps,
|
|
29
|
-
...props
|
|
29
|
+
...props,
|
|
30
30
|
},
|
|
31
31
|
global: {
|
|
32
32
|
mocks: {
|
|
33
|
-
$t: (key) => key
|
|
34
|
-
}
|
|
33
|
+
$t: (key) => key,
|
|
34
|
+
},
|
|
35
35
|
},
|
|
36
|
-
slots
|
|
36
|
+
slots,
|
|
37
37
|
});
|
|
38
38
|
};
|
|
39
39
|
|
|
@@ -119,10 +119,10 @@ describe('UnnnicSelect.vue', () => {
|
|
|
119
119
|
|
|
120
120
|
test('input shows correct icon based on popover state', async () => {
|
|
121
121
|
const input = wrapper.findComponent({ name: 'UnnnicInput' });
|
|
122
|
-
|
|
122
|
+
|
|
123
123
|
// Initially closed
|
|
124
124
|
expect(input.props('iconRight')).toBe('keyboard_arrow_down');
|
|
125
|
-
|
|
125
|
+
|
|
126
126
|
// When popover is open
|
|
127
127
|
wrapper.vm.openPopover = true;
|
|
128
128
|
await wrapper.vm.$nextTick();
|
|
@@ -135,9 +135,9 @@ describe('UnnnicSelect.vue', () => {
|
|
|
135
135
|
wrapper.vm.openPopover = true;
|
|
136
136
|
await wrapper.vm.$nextTick();
|
|
137
137
|
const options = wrapper.findAllComponents({ name: 'UnnnicSelectOption' });
|
|
138
|
-
|
|
138
|
+
|
|
139
139
|
await options[0].vm.$emit('click');
|
|
140
|
-
|
|
140
|
+
|
|
141
141
|
expect(wrapper.emitted('update:modelValue')).toBeTruthy();
|
|
142
142
|
expect(wrapper.emitted('update:modelValue')[0]).toEqual(['option1']);
|
|
143
143
|
});
|
|
@@ -147,10 +147,12 @@ describe('UnnnicSelect.vue', () => {
|
|
|
147
147
|
wrapper.vm.openPopover = true;
|
|
148
148
|
await wrapper.vm.$nextTick();
|
|
149
149
|
const options = wrapper.findAllComponents({ name: 'UnnnicSelectOption' });
|
|
150
|
-
|
|
150
|
+
|
|
151
151
|
await options[0].vm.$emit('click');
|
|
152
|
-
|
|
153
|
-
expect(wrapper.emitted('update:modelValue')[0]).toEqual([
|
|
152
|
+
|
|
153
|
+
expect(wrapper.emitted('update:modelValue')[0]).toEqual([
|
|
154
|
+
{ label: 'Option 1', value: 'option1' },
|
|
155
|
+
]);
|
|
154
156
|
});
|
|
155
157
|
|
|
156
158
|
test('does not emit when same option is selected', async () => {
|
|
@@ -158,25 +160,25 @@ describe('UnnnicSelect.vue', () => {
|
|
|
158
160
|
wrapper.vm.openPopover = true;
|
|
159
161
|
await wrapper.vm.$nextTick();
|
|
160
162
|
const options = wrapper.findAllComponents({ name: 'UnnnicSelectOption' });
|
|
161
|
-
|
|
163
|
+
|
|
162
164
|
await options[0].vm.$emit('click');
|
|
163
|
-
|
|
165
|
+
|
|
164
166
|
expect(wrapper.emitted('update:modelValue')).toBeFalsy();
|
|
165
167
|
});
|
|
166
168
|
|
|
167
169
|
test('does not emit when disabled option is clicked', async () => {
|
|
168
170
|
const disabledOptions = [
|
|
169
171
|
{ label: 'Option 1', value: 'option1' },
|
|
170
|
-
{ label: 'Disabled Option', value: 'disabled', disabled: true }
|
|
172
|
+
{ label: 'Disabled Option', value: 'disabled', disabled: true },
|
|
171
173
|
];
|
|
172
|
-
|
|
174
|
+
|
|
173
175
|
await wrapper.setProps({ options: disabledOptions });
|
|
174
176
|
wrapper.vm.openPopover = true;
|
|
175
177
|
await wrapper.vm.$nextTick();
|
|
176
178
|
const options = wrapper.findAllComponents({ name: 'UnnnicSelectOption' });
|
|
177
|
-
|
|
179
|
+
|
|
178
180
|
await options[1].vm.$emit('click');
|
|
179
|
-
|
|
181
|
+
|
|
180
182
|
expect(wrapper.emitted('update:modelValue')).toBeFalsy();
|
|
181
183
|
});
|
|
182
184
|
});
|
|
@@ -197,20 +199,20 @@ describe('UnnnicSelect.vue', () => {
|
|
|
197
199
|
});
|
|
198
200
|
|
|
199
201
|
test('emits update:search when search input changes', async () => {
|
|
200
|
-
await wrapper.setProps({ enableSearch: true});
|
|
202
|
+
await wrapper.setProps({ enableSearch: true });
|
|
201
203
|
wrapper.vm.openPopover = true;
|
|
202
204
|
await wrapper.vm.$nextTick();
|
|
203
205
|
const searchInput = wrapper.findAllComponents({ name: 'UnnnicInput' })[1];
|
|
204
|
-
|
|
206
|
+
|
|
205
207
|
await searchInput.vm.$emit('update:modelValue', 'test search');
|
|
206
|
-
|
|
208
|
+
|
|
207
209
|
expect(wrapper.emitted('update:search')).toBeTruthy();
|
|
208
210
|
expect(wrapper.emitted('update:search')[0]).toEqual(['test search']);
|
|
209
211
|
});
|
|
210
212
|
|
|
211
213
|
test('filters options based on search term', async () => {
|
|
212
214
|
await wrapper.setProps({ enableSearch: true, search: 'Option 1' });
|
|
213
|
-
|
|
215
|
+
|
|
214
216
|
const filteredOptions = wrapper.vm.filteredOptions;
|
|
215
217
|
expect(filteredOptions.length).toBe(1);
|
|
216
218
|
expect(filteredOptions[0].label).toBe('Option 1');
|
|
@@ -218,7 +220,7 @@ describe('UnnnicSelect.vue', () => {
|
|
|
218
220
|
|
|
219
221
|
test('filters options by both label and value', async () => {
|
|
220
222
|
await wrapper.setProps({ enableSearch: true, search: 'option1' });
|
|
221
|
-
|
|
223
|
+
|
|
222
224
|
const filteredOptions = wrapper.vm.filteredOptions;
|
|
223
225
|
expect(filteredOptions.length).toBe(1);
|
|
224
226
|
expect(filteredOptions[0].value).toBe('option1');
|
|
@@ -226,7 +228,7 @@ describe('UnnnicSelect.vue', () => {
|
|
|
226
228
|
|
|
227
229
|
test('shows all options when search is empty', async () => {
|
|
228
230
|
await wrapper.setProps({ enableSearch: true, search: '' });
|
|
229
|
-
|
|
231
|
+
|
|
230
232
|
const filteredOptions = wrapper.vm.filteredOptions;
|
|
231
233
|
expect(filteredOptions.length).toBe(3);
|
|
232
234
|
});
|
|
@@ -259,7 +261,10 @@ describe('UnnnicSelect.vue', () => {
|
|
|
259
261
|
|
|
260
262
|
test('selectedItem returns modelValue for returnObject true', async () => {
|
|
261
263
|
const selectedOption = { label: 'Option 2', value: 'option2' };
|
|
262
|
-
await wrapper.setProps({
|
|
264
|
+
await wrapper.setProps({
|
|
265
|
+
returnObject: true,
|
|
266
|
+
modelValue: selectedOption,
|
|
267
|
+
});
|
|
263
268
|
const selectedItem = wrapper.vm.selectedItem;
|
|
264
269
|
expect(selectedItem).toStrictEqual(selectedOption);
|
|
265
270
|
});
|
|
@@ -326,16 +331,16 @@ describe('UnnnicSelect.vue', () => {
|
|
|
326
331
|
test('uses custom itemLabel and itemValue', async () => {
|
|
327
332
|
const customOptions = [
|
|
328
333
|
{ name: 'Custom 1', id: 'custom1' },
|
|
329
|
-
{ name: 'Custom 2', id: 'custom2' }
|
|
334
|
+
{ name: 'Custom 2', id: 'custom2' },
|
|
330
335
|
];
|
|
331
|
-
|
|
332
|
-
await wrapper.setProps({
|
|
333
|
-
options: customOptions,
|
|
334
|
-
itemLabel: 'name',
|
|
336
|
+
|
|
337
|
+
await wrapper.setProps({
|
|
338
|
+
options: customOptions,
|
|
339
|
+
itemLabel: 'name',
|
|
335
340
|
itemValue: 'id',
|
|
336
|
-
modelValue: 'custom1'
|
|
341
|
+
modelValue: 'custom1',
|
|
337
342
|
});
|
|
338
|
-
|
|
343
|
+
|
|
339
344
|
const inputValue = wrapper.vm.inputValue;
|
|
340
345
|
expect(inputValue).toBe('Custom 1');
|
|
341
346
|
});
|
|
@@ -3,9 +3,9 @@ import { beforeEach, describe, expect, test } from 'vitest';
|
|
|
3
3
|
import SelectItem from '../SelectItem.vue';
|
|
4
4
|
|
|
5
5
|
const createWrapper = (props = {}, slots = {}) => {
|
|
6
|
-
return mount(SelectItem, {
|
|
6
|
+
return mount(SelectItem, {
|
|
7
7
|
props,
|
|
8
|
-
slots: slots.default ? { default: slots.default } : {}
|
|
8
|
+
slots: slots.default ? { default: slots.default } : {},
|
|
9
9
|
});
|
|
10
10
|
};
|
|
11
11
|
|
|
@@ -76,8 +76,12 @@ describe('SelectItem.vue', () => {
|
|
|
76
76
|
test('does not apply size class when size is empty', async () => {
|
|
77
77
|
await wrapper.setProps({ size: '' });
|
|
78
78
|
const labelElement = wrapper.find('.unnnic-select-item__label');
|
|
79
|
-
expect(labelElement.classes()).not.toContain(
|
|
80
|
-
|
|
79
|
+
expect(labelElement.classes()).not.toContain(
|
|
80
|
+
'unnnic-select-item__label--md',
|
|
81
|
+
);
|
|
82
|
+
expect(labelElement.classes()).not.toContain(
|
|
83
|
+
'unnnic-select-item__label--sm',
|
|
84
|
+
);
|
|
81
85
|
});
|
|
82
86
|
});
|
|
83
87
|
|
|
@@ -128,7 +132,10 @@ describe('SelectItem.vue', () => {
|
|
|
128
132
|
});
|
|
129
133
|
|
|
130
134
|
test('emits click event even when selectable is false', async () => {
|
|
131
|
-
const clickWrapper = createWrapper(
|
|
135
|
+
const clickWrapper = createWrapper(
|
|
136
|
+
{ selectable: false },
|
|
137
|
+
{ default: 'Test Item' },
|
|
138
|
+
);
|
|
132
139
|
await clickWrapper.trigger('click');
|
|
133
140
|
expect(clickWrapper.emitted('click')).toBeTruthy();
|
|
134
141
|
expect(clickWrapper.emitted('click').length).toBeGreaterThanOrEqual(1);
|
|
@@ -194,7 +201,7 @@ describe('SelectItem.vue', () => {
|
|
|
194
201
|
test('has proper semantic structure', () => {
|
|
195
202
|
const div = wrapper.find('.unnnic-select-item');
|
|
196
203
|
const span = wrapper.find('.unnnic-select-item__label');
|
|
197
|
-
|
|
204
|
+
|
|
198
205
|
expect(div.exists()).toBe(true);
|
|
199
206
|
expect(span.exists()).toBe(true);
|
|
200
207
|
expect(span.element.tagName).toBe('SPAN');
|
|
@@ -214,7 +221,8 @@ describe('SelectItem.vue', () => {
|
|
|
214
221
|
});
|
|
215
222
|
|
|
216
223
|
test('handles long slot content', async () => {
|
|
217
|
-
const longText =
|
|
224
|
+
const longText =
|
|
225
|
+
'This is a very long text content that should be handled properly by the component';
|
|
218
226
|
const longWrapper = createWrapper({}, { default: longText });
|
|
219
227
|
const labelElement = longWrapper.find('.unnnic-select-item__label');
|
|
220
228
|
expect(labelElement.text()).toBe(longText);
|
|
@@ -237,8 +245,12 @@ describe('SelectItem.vue', () => {
|
|
|
237
245
|
|
|
238
246
|
describe('CSS class combinations', () => {
|
|
239
247
|
test('applies correct classes for non-selectable inactive item', async () => {
|
|
240
|
-
await wrapper.setProps({
|
|
241
|
-
|
|
248
|
+
await wrapper.setProps({
|
|
249
|
+
selectable: false,
|
|
250
|
+
active: false,
|
|
251
|
+
textFocused: false,
|
|
252
|
+
});
|
|
253
|
+
|
|
242
254
|
expect(wrapper.classes()).toContain('unnnic-select-item');
|
|
243
255
|
expect(wrapper.classes()).not.toContain('unnnic-select-item--selectable');
|
|
244
256
|
expect(wrapper.classes()).not.toContain('unnnic--clickable');
|
|
@@ -247,8 +259,12 @@ describe('SelectItem.vue', () => {
|
|
|
247
259
|
});
|
|
248
260
|
|
|
249
261
|
test('applies correct classes for selectable active item', async () => {
|
|
250
|
-
await wrapper.setProps({
|
|
251
|
-
|
|
262
|
+
await wrapper.setProps({
|
|
263
|
+
selectable: true,
|
|
264
|
+
active: true,
|
|
265
|
+
textFocused: false,
|
|
266
|
+
});
|
|
267
|
+
|
|
252
268
|
expect(wrapper.classes()).toContain('unnnic-select-item');
|
|
253
269
|
expect(wrapper.classes()).toContain('unnnic-select-item--selectable');
|
|
254
270
|
expect(wrapper.classes()).toContain('unnnic--clickable');
|
|
@@ -257,8 +273,12 @@ describe('SelectItem.vue', () => {
|
|
|
257
273
|
});
|
|
258
274
|
|
|
259
275
|
test('applies correct classes for text-focused item', async () => {
|
|
260
|
-
await wrapper.setProps({
|
|
261
|
-
|
|
276
|
+
await wrapper.setProps({
|
|
277
|
+
selectable: true,
|
|
278
|
+
active: false,
|
|
279
|
+
textFocused: true,
|
|
280
|
+
});
|
|
281
|
+
|
|
262
282
|
expect(wrapper.classes()).toContain('unnnic-select-item');
|
|
263
283
|
expect(wrapper.classes()).toContain('unnnic-select-item--selectable');
|
|
264
284
|
expect(wrapper.classes()).toContain('unnnic--clickable');
|
|
@@ -298,11 +318,11 @@ describe('SelectItem.vue', () => {
|
|
|
298
318
|
});
|
|
299
319
|
|
|
300
320
|
test('matches snapshot with all states combined', async () => {
|
|
301
|
-
await wrapper.setProps({
|
|
321
|
+
await wrapper.setProps({
|
|
302
322
|
size: 'md',
|
|
303
323
|
selectable: true,
|
|
304
324
|
active: true,
|
|
305
|
-
textFocused: true
|
|
325
|
+
textFocused: true,
|
|
306
326
|
});
|
|
307
327
|
expect(wrapper.html()).toMatchSnapshot();
|
|
308
328
|
});
|
|
@@ -89,7 +89,9 @@ describe('SelectOption.vue', () => {
|
|
|
89
89
|
disabled: false,
|
|
90
90
|
});
|
|
91
91
|
|
|
92
|
-
expect(wrapper.find('.unnnic-select-option__label').text()).toBe(
|
|
92
|
+
expect(wrapper.find('.unnnic-select-option__label').text()).toBe(
|
|
93
|
+
'Complex Option',
|
|
94
|
+
);
|
|
93
95
|
expect(wrapper.classes()).toContain('unnnic-select-option--active');
|
|
94
96
|
expect(wrapper.classes()).not.toContain('unnnic-select-option--disabled');
|
|
95
97
|
});
|
|
@@ -114,7 +116,7 @@ describe('SelectOption.vue', () => {
|
|
|
114
116
|
test('has proper semantic structure', () => {
|
|
115
117
|
const div = wrapper.find('.unnnic-select-option');
|
|
116
118
|
const p = wrapper.find('.unnnic-select-option__label');
|
|
117
|
-
|
|
119
|
+
|
|
118
120
|
expect(div.exists()).toBe(true);
|
|
119
121
|
expect(p.exists()).toBe(true);
|
|
120
122
|
expect(p.element.tagName).toBe('P');
|
|
@@ -134,7 +136,8 @@ describe('SelectOption.vue', () => {
|
|
|
134
136
|
});
|
|
135
137
|
|
|
136
138
|
test('handles long label text', async () => {
|
|
137
|
-
const longText =
|
|
139
|
+
const longText =
|
|
140
|
+
'This is a very long label text that should be handled properly by the component';
|
|
138
141
|
await wrapper.setProps({ label: longText });
|
|
139
142
|
const labelElement = wrapper.find('.unnnic-select-option__label');
|
|
140
143
|
expect(labelElement.text()).toBe(longText);
|