@code-coaching/vuetiful 0.22.0 → 0.23.0
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/README.md +1 -1
- package/dist/style.css +2 -2
- package/dist/types/components/VBootstrap.vue.d.ts +15 -0
- package/dist/types/components/atoms/VAvatar.vue.d.ts +37 -10
- package/dist/types/components/atoms/VBadge.vue.d.ts +22 -1
- package/dist/types/components/atoms/VButton.vue.d.ts +27 -0
- package/dist/types/components/atoms/VChip.vue.d.ts +22 -1
- package/dist/types/components/atoms/VRadio/VRadioGroup.vue.d.ts +10 -1
- package/dist/types/components/atoms/VRadio/VRadioItem.vue.d.ts +2 -2
- package/dist/types/components/atoms/VSwitch/VSwitch.vue.d.ts +24 -15
- package/dist/types/components/atoms/index.d.ts +1 -2
- package/dist/types/components/molecules/VAccordion/VAccordion.vue.d.ts +15 -6
- package/dist/types/components/molecules/VAccordion/VAccordionItem.vue.d.ts +11 -1
- package/dist/types/components/molecules/VAlert.vue.d.ts +39 -3
- package/dist/types/components/molecules/VCard/VCard.vue.d.ts +5 -5
- package/dist/types/components/molecules/VCard/VCardBody.vue.d.ts +13 -1
- package/dist/types/components/molecules/VCard/VCardFooter.vue.d.ts +22 -1
- package/dist/types/components/molecules/VCard/VCardHeader.vue.d.ts +22 -1
- package/dist/types/components/{atoms → molecules}/VCodeBlock.vue.d.ts +36 -9
- package/dist/types/components/molecules/VListbox/VListbox.vue.d.ts +51 -14
- package/dist/types/components/molecules/VListbox/VListboxItem.vue.d.ts +13 -3
- package/dist/types/components/molecules/VListbox/VListboxItems.vue.d.ts +9 -0
- package/dist/types/components/molecules/VTabs/VTab.vue.d.ts +9 -0
- package/dist/types/components/molecules/VTabs/VTabs.vue.d.ts +18 -0
- package/dist/types/components/molecules/index.d.ts +4 -3
- package/dist/types/props/index.d.ts +1 -0
- package/dist/types/props/props.d.ts +14 -0
- package/dist/types/services/index.d.ts +5 -3
- package/dist/types/services/settings.service.d.ts +132 -0
- package/dist/types/services/settings.service.test.d.ts +1 -0
- package/dist/types/types/index.d.ts +53 -0
- package/dist/vuetiful.es.mjs +920 -557
- package/dist/vuetiful.umd.js +23 -10
- package/package.json +1 -1
- package/src/components/VBootstrap.vue +62 -0
- package/src/components/atoms/VAvatar.test.ts +98 -28
- package/src/components/atoms/VAvatar.vue +46 -13
- package/src/components/atoms/VBadge.test.ts +10 -0
- package/src/components/atoms/VBadge.vue +13 -1
- package/src/components/atoms/VButton.test.ts +58 -0
- package/src/components/atoms/VButton.vue +31 -2
- package/src/components/atoms/VChip.test.ts +26 -11
- package/src/components/atoms/VChip.vue +13 -1
- package/src/components/atoms/VRadio/VRadioDescription.vue +1 -1
- package/src/components/atoms/VRadio/VRadioGroup.test.ts +7 -7
- package/src/components/atoms/VRadio/VRadioGroup.vue +16 -5
- package/src/components/atoms/VRadio/VRadioItem.vue +12 -8
- package/src/components/atoms/VRadio/VRadioLabel.vue +1 -1
- package/src/components/atoms/VSwitch/VSwitch.test.ts +20 -18
- package/src/components/atoms/VSwitch/VSwitch.vue +29 -17
- package/src/components/atoms/VSwitch/VSwitchDescription.vue +1 -1
- package/src/components/atoms/VSwitch/VSwitchGroup.vue +2 -2
- package/src/components/atoms/VSwitch/VSwitchLabel.vue +1 -1
- package/src/components/atoms/index.ts +0 -2
- package/src/components/molecules/VAccordion/VAccordion.test.ts +11 -0
- package/src/components/molecules/VAccordion/VAccordion.vue +16 -7
- package/src/components/molecules/VAccordion/VAccordionItem.test.ts +65 -16
- package/src/components/molecules/VAccordion/VAccordionItem.vue +53 -32
- package/src/components/molecules/VAlert.test.ts +11 -1
- package/src/components/molecules/VAlert.vue +33 -7
- package/src/components/molecules/VCard/VCard.test.ts +1 -1
- package/src/components/molecules/VCard/VCard.vue +12 -7
- package/src/components/molecules/VCard/VCardBody.test.ts +18 -0
- package/src/components/molecules/VCard/VCardBody.vue +16 -1
- package/src/components/molecules/VCard/VCardFooter.test.ts +18 -0
- package/src/components/molecules/VCard/VCardFooter.vue +21 -3
- package/src/components/molecules/VCard/VCardHeader.test.ts +18 -0
- package/src/components/molecules/VCard/VCardHeader.vue +26 -5
- package/src/components/molecules/VCodeBlock.test.ts +133 -0
- package/src/components/molecules/VCodeBlock.vue +120 -0
- package/src/components/molecules/VListbox/VListbox.test.ts +42 -15
- package/src/components/molecules/VListbox/VListbox.vue +44 -15
- package/src/components/molecules/VListbox/VListboxButton.test.ts +15 -6
- package/src/components/molecules/VListbox/VListboxButton.vue +10 -1
- package/src/components/molecules/VListbox/VListboxItem.test.ts +2 -2
- package/src/components/molecules/VListbox/VListboxItem.vue +18 -7
- package/src/components/molecules/VListbox/VListboxItems.test.ts +2 -2
- package/src/components/molecules/VListbox/VListboxItems.vue +18 -5
- package/src/components/molecules/VListbox/VListboxLabel.test.ts +1 -2
- package/src/components/molecules/VListbox/VListboxLabel.vue +1 -1
- package/src/components/molecules/VPreview.vue +9 -5
- package/src/components/molecules/{VRail.test.ts → VRail/VRail.test.ts} +1 -1
- package/src/components/molecules/{VRail.vue → VRail/VRail.vue} +6 -6
- package/src/components/molecules/VRail/VRailTile.test.ts +99 -0
- package/src/components/molecules/{VRailTile.vue → VRail/VRailTile.vue} +4 -6
- package/src/components/molecules/VTabs/VTab.test.ts +7 -3
- package/src/components/molecules/VTabs/VTab.vue +20 -5
- package/src/components/molecules/VTabs/VTabPanel.vue +2 -2
- package/src/components/molecules/VTabs/VTabs.test.ts +4 -2
- package/src/components/molecules/VTabs/VTabs.vue +32 -8
- package/src/components/molecules/index.ts +5 -2
- package/src/props/index.ts +1 -0
- package/src/props/props.ts +62 -0
- package/src/services/index.ts +5 -3
- package/src/services/settings.service.test.ts +17 -0
- package/src/services/settings.service.ts +136 -0
- package/src/types/index.ts +58 -0
- package/src/components/atoms/VCodeBlock.test.ts +0 -14
- package/src/components/atoms/VCodeBlock.vue +0 -92
- package/src/components/molecules/VRailTile.test.ts +0 -14
- /package/dist/types/components/{atoms → molecules}/VCodeBlock.test.d.ts +0 -0
- /package/dist/types/components/molecules/{VRail.test.d.ts → VRail/VRail.test.d.ts} +0 -0
- /package/dist/types/components/molecules/{VRail.vue.d.ts → VRail/VRail.vue.d.ts} +0 -0
- /package/dist/types/components/molecules/{VRailTile.test.d.ts → VRail/VRailTile.test.d.ts} +0 -0
- /package/dist/types/components/molecules/{VRailTile.vue.d.ts → VRail/VRailTile.vue.d.ts} +0 -0
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
+
import { CssClasses, useSettings } from "@/index";
|
|
2
3
|
import { Listbox } from "@headlessui/vue";
|
|
3
4
|
import { computed, provide, ref, watch } from "vue";
|
|
4
5
|
import VListboxButton from "./VListboxButton.vue";
|
|
5
6
|
import VListboxItems from "./VListboxItems.vue";
|
|
6
7
|
import VListboxLabel from "./VListboxLabel.vue";
|
|
8
|
+
import { unstyledProp } from "@/props";
|
|
7
9
|
|
|
8
10
|
const emit = defineEmits(["update:modelValue"]);
|
|
9
11
|
const props = defineProps({
|
|
12
|
+
modelValue: Listbox.props["modelValue"],
|
|
13
|
+
|
|
10
14
|
by: {
|
|
11
15
|
type: String,
|
|
12
16
|
},
|
|
@@ -14,20 +18,32 @@ const props = defineProps({
|
|
|
14
18
|
type: String,
|
|
15
19
|
},
|
|
16
20
|
|
|
17
|
-
|
|
21
|
+
textLabel: {
|
|
18
22
|
type: String,
|
|
19
23
|
},
|
|
20
|
-
|
|
21
|
-
type:
|
|
22
|
-
default:
|
|
24
|
+
classLabel: {
|
|
25
|
+
type: String as () => CssClasses,
|
|
26
|
+
default: "",
|
|
23
27
|
},
|
|
24
28
|
|
|
25
|
-
|
|
29
|
+
textButton: {
|
|
26
30
|
type: String,
|
|
27
31
|
default: "Select an option",
|
|
28
32
|
},
|
|
33
|
+
classButton: {
|
|
34
|
+
type: String as () => CssClasses,
|
|
35
|
+
default: "",
|
|
36
|
+
},
|
|
37
|
+
|
|
38
|
+
classItem: {
|
|
39
|
+
type: String as () => CssClasses,
|
|
40
|
+
default: "",
|
|
41
|
+
},
|
|
42
|
+
classItems: {
|
|
43
|
+
type: String as () => CssClasses,
|
|
44
|
+
default: "",
|
|
45
|
+
},
|
|
29
46
|
|
|
30
|
-
modelValue: Listbox.props["modelValue"],
|
|
31
47
|
horizontal: {
|
|
32
48
|
type: Boolean,
|
|
33
49
|
default: false,
|
|
@@ -43,7 +59,7 @@ const props = defineProps({
|
|
|
43
59
|
},
|
|
44
60
|
hover: {
|
|
45
61
|
type: String,
|
|
46
|
-
default: "variant-ghost",
|
|
62
|
+
default: "hover:variant-ghost",
|
|
47
63
|
},
|
|
48
64
|
|
|
49
65
|
background: {
|
|
@@ -54,6 +70,8 @@ const props = defineProps({
|
|
|
54
70
|
type: String,
|
|
55
71
|
default: "text-surface-900 dark:text-surface-50",
|
|
56
72
|
},
|
|
73
|
+
|
|
74
|
+
unstyled: unstyledProp,
|
|
57
75
|
});
|
|
58
76
|
|
|
59
77
|
const parentModelValue = ref(props.modelValue);
|
|
@@ -75,33 +93,40 @@ provide("hover", props.hover);
|
|
|
75
93
|
provide("background", props.background);
|
|
76
94
|
provide("text", props.text);
|
|
77
95
|
provide("horizontal", props.horizontal);
|
|
96
|
+
provide("unstyled", props.unstyled);
|
|
97
|
+
provide("classItem", props.classItem);
|
|
98
|
+
provide("classItems", props.classItems);
|
|
78
99
|
|
|
79
100
|
const showText = computed(() => {
|
|
80
101
|
if (props.display && parentModelValue.value) return parentModelValue.value[props.display];
|
|
81
102
|
|
|
82
103
|
const length = parentModelValue.value?.length;
|
|
83
|
-
if (props.multiple && length === 0) return props.
|
|
104
|
+
if (props.multiple && length === 0) return props.textButton;
|
|
84
105
|
if (props.multiple && length === 1) return parentModelValue.value[0];
|
|
85
106
|
if (props.multiple && length > 1) return `${length} options selected`; // TODO: i18n
|
|
86
107
|
|
|
87
108
|
if (parentModelValue.value) return parentModelValue.value;
|
|
88
109
|
|
|
89
|
-
return props.
|
|
110
|
+
return props.textButton;
|
|
90
111
|
});
|
|
112
|
+
|
|
113
|
+
const { settings } = useSettings();
|
|
114
|
+
const isUnstyled =
|
|
115
|
+
settings.global.unstyled || settings.components.listbox.unstyled || props.unstyled;
|
|
91
116
|
</script>
|
|
92
117
|
|
|
93
118
|
<template>
|
|
94
|
-
<!-- There is some odd behavior with test
|
|
119
|
+
<!-- There is some odd behavior with test coverage, v-model must be the last property in this component -->
|
|
95
120
|
<Listbox
|
|
96
|
-
data-test="
|
|
121
|
+
data-test="listbox"
|
|
97
122
|
as="div"
|
|
98
123
|
:by="by"
|
|
99
124
|
:multiple="multiple"
|
|
100
|
-
class="vuetiful-listbox relative rounded-container-token"
|
|
125
|
+
:class="`vuetiful-listbox ${isUnstyled ? '' : 'relative rounded-container-token'}`"
|
|
101
126
|
v-model="parentModelValue"
|
|
102
127
|
>
|
|
103
|
-
<v-listbox-label v-if="
|
|
104
|
-
<v-listbox-button data-test="
|
|
128
|
+
<v-listbox-label v-if="textLabel" :class="classLabel">{{ textLabel }}</v-listbox-label>
|
|
129
|
+
<v-listbox-button data-test="listbox-button" :class="`${background} ${text} ${classButton}`">
|
|
105
130
|
{{ showText }}
|
|
106
131
|
</v-listbox-button>
|
|
107
132
|
<!-- TODO: Add configurable transition -->
|
|
@@ -113,7 +138,11 @@ const showText = computed(() => {
|
|
|
113
138
|
leave-from-class="opacity-100"
|
|
114
139
|
leave-to-class="opacity-0"
|
|
115
140
|
>
|
|
116
|
-
<v-listbox-items
|
|
141
|
+
<v-listbox-items
|
|
142
|
+
data-test="listbox-items"
|
|
143
|
+
:unstyled="unstyled"
|
|
144
|
+
:class="`${isUnstyled ? '' : 'absolute mt-1 min-w-full'}`"
|
|
145
|
+
>
|
|
117
146
|
<slot />
|
|
118
147
|
</v-listbox-items>
|
|
119
148
|
</transition>
|
|
@@ -6,9 +6,12 @@ import VListboxButton from "./VListboxButton.vue";
|
|
|
6
6
|
describe("VListboxButton props", () => {
|
|
7
7
|
test("defaults", () => {
|
|
8
8
|
const wrapper = mount({
|
|
9
|
+
provide: {
|
|
10
|
+
unstyled: false,
|
|
11
|
+
},
|
|
9
12
|
template: /* html */ `
|
|
10
13
|
<Listbox>
|
|
11
|
-
<v-listbox-button data-test="
|
|
14
|
+
<v-listbox-button data-test="listbox-button">John Duck</v-listbox-button>
|
|
12
15
|
</Listbox>
|
|
13
16
|
`,
|
|
14
17
|
components: {
|
|
@@ -17,15 +20,18 @@ describe("VListboxButton props", () => {
|
|
|
17
20
|
},
|
|
18
21
|
});
|
|
19
22
|
|
|
20
|
-
const listboxButton = wrapper.find("[data-test='
|
|
23
|
+
const listboxButton = wrapper.find("[data-test='listbox-button']");
|
|
21
24
|
expect(listboxButton.element.tagName).toBe("BUTTON");
|
|
22
25
|
});
|
|
23
26
|
|
|
24
27
|
test("custom 'as' prop", () => {
|
|
25
28
|
const wrapper = mount({
|
|
29
|
+
provide: {
|
|
30
|
+
unstyled: false,
|
|
31
|
+
},
|
|
26
32
|
template: /* html */ `
|
|
27
33
|
<Listbox>
|
|
28
|
-
<v-listbox-button as="div" data-test="
|
|
34
|
+
<v-listbox-button as="div" data-test="listbox-button">John Duck</v-listbox-button>
|
|
29
35
|
</Listbox>
|
|
30
36
|
`,
|
|
31
37
|
components: {
|
|
@@ -34,15 +40,18 @@ describe("VListboxButton props", () => {
|
|
|
34
40
|
},
|
|
35
41
|
});
|
|
36
42
|
|
|
37
|
-
const listboxButton = wrapper.find("[data-test='
|
|
43
|
+
const listboxButton = wrapper.find("[data-test='listbox-button']");
|
|
38
44
|
expect(listboxButton.element.tagName).toBe("DIV");
|
|
39
45
|
});
|
|
40
46
|
|
|
41
47
|
test("should hide icon", () => {
|
|
42
48
|
const wrapper = mount({
|
|
49
|
+
provide: {
|
|
50
|
+
unstyled: false,
|
|
51
|
+
},
|
|
43
52
|
template: /* html */ `
|
|
44
53
|
<Listbox>
|
|
45
|
-
<v-listbox-button hide-icon data-test="
|
|
54
|
+
<v-listbox-button hide-icon data-test="listbox-button">John Duck</v-listbox-button>
|
|
46
55
|
</Listbox>
|
|
47
56
|
`,
|
|
48
57
|
components: {
|
|
@@ -51,7 +60,7 @@ describe("VListboxButton props", () => {
|
|
|
51
60
|
},
|
|
52
61
|
});
|
|
53
62
|
|
|
54
|
-
const listboxButton = wrapper.find("[data-test='
|
|
63
|
+
const listboxButton = wrapper.find("[data-test='listbox-button']");
|
|
55
64
|
expect(listboxButton.find("svg").exists()).toBe(false);
|
|
56
65
|
});
|
|
57
66
|
});
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
+
import { useSettings } from "@/index";
|
|
2
3
|
import { ListboxButton } from "@headlessui/vue";
|
|
4
|
+
import { inject } from "vue";
|
|
3
5
|
|
|
4
6
|
defineProps({
|
|
5
7
|
as: {
|
|
@@ -11,13 +13,20 @@ defineProps({
|
|
|
11
13
|
default: false,
|
|
12
14
|
},
|
|
13
15
|
});
|
|
16
|
+
|
|
17
|
+
const unstyled = inject("unstyled") as boolean;
|
|
18
|
+
|
|
19
|
+
const { settings } = useSettings();
|
|
20
|
+
const isUnstyled = settings.global.unstyled || settings.components.listbox.unstyled || unstyled;
|
|
14
21
|
</script>
|
|
15
22
|
|
|
16
23
|
<template>
|
|
17
24
|
<ListboxButton
|
|
18
25
|
v-slot="{ open }"
|
|
19
26
|
:as="as"
|
|
20
|
-
class="
|
|
27
|
+
:class="`vuetiful-listbox-button ${
|
|
28
|
+
isUnstyled ? 'flex' : 'variant-filled btn flex w-full justify-between active:scale-[100%]'
|
|
29
|
+
}`"
|
|
21
30
|
>
|
|
22
31
|
<slot />
|
|
23
32
|
<span v-if="!hideIcon">
|
|
@@ -23,10 +23,10 @@ describe("VListboxItem props", () => {
|
|
|
23
23
|
},
|
|
24
24
|
});
|
|
25
25
|
|
|
26
|
-
const listbox = wrapper.find("[data-test='
|
|
26
|
+
const listbox = wrapper.find("[data-test='listbox']");
|
|
27
27
|
await listbox.find("button").trigger("click");
|
|
28
28
|
|
|
29
|
-
const listboxItems = listbox.findAll("[data-test='
|
|
29
|
+
const listboxItems = listbox.findAll("[data-test='listbox-item']");
|
|
30
30
|
const selectedItem = listboxItems[0];
|
|
31
31
|
const normalItem = listboxItems[1];
|
|
32
32
|
expect(selectedItem.classes()).toEqual([
|
|
@@ -1,27 +1,38 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
+
import { useSettings } from "@/services";
|
|
2
3
|
import { ListboxOption } from "@headlessui/vue";
|
|
3
4
|
import { inject } from "vue";
|
|
4
5
|
|
|
5
|
-
defineProps({
|
|
6
|
+
const props = defineProps({
|
|
6
7
|
value: {
|
|
7
8
|
type: [String, Number, Boolean, Object],
|
|
8
9
|
required: true,
|
|
9
10
|
},
|
|
11
|
+
|
|
12
|
+
unstyled: {
|
|
13
|
+
type: Boolean,
|
|
14
|
+
default: false,
|
|
15
|
+
},
|
|
10
16
|
});
|
|
11
17
|
|
|
12
18
|
const activeClass = inject("active") as string;
|
|
13
19
|
const hoverClass = inject("hover") as string;
|
|
20
|
+
const classItem = inject("classItem") as string;
|
|
21
|
+
|
|
22
|
+
const { settings } = useSettings();
|
|
23
|
+
const isUnstyled =
|
|
24
|
+
settings.global.unstyled || settings.components.listboxItem.unstyled || props.unstyled;
|
|
14
25
|
</script>
|
|
15
26
|
|
|
16
27
|
<template>
|
|
17
28
|
<ListboxOption v-slot="{ selected, disabled, active }" :value="value">
|
|
18
29
|
<div
|
|
19
|
-
data-test="
|
|
20
|
-
:class="`vuetiful-listbox-item px-4 py-1 text-base rounded-token
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
}`"
|
|
30
|
+
data-test="listbox-item"
|
|
31
|
+
:class="`vuetiful-listbox-item ${isUnstyled ? '' : 'px-4 py-1 text-base rounded-token'}
|
|
32
|
+
${selected ? activeClass : hoverClass}
|
|
33
|
+
${disabled ? 'cursor-not-allowed opacity-50' : 'cursor-pointer'}
|
|
34
|
+
${active && !selected ? hoverClass : ''}
|
|
35
|
+
${classItem}`"
|
|
25
36
|
>
|
|
26
37
|
<slot />
|
|
27
38
|
</div>
|
|
@@ -16,7 +16,7 @@ test("VListboxItems defaults", async () => {
|
|
|
16
16
|
},
|
|
17
17
|
});
|
|
18
18
|
|
|
19
|
-
const listbox = wrapper.find("[data-test='
|
|
19
|
+
const listbox = wrapper.find("[data-test='listbox']");
|
|
20
20
|
await listbox.find("button").trigger("click");
|
|
21
21
|
|
|
22
22
|
const listboxItems = listbox.find("[data-test='listbox-items']");
|
|
@@ -36,7 +36,7 @@ test("VListboxItems horizontal", async () => {
|
|
|
36
36
|
},
|
|
37
37
|
});
|
|
38
38
|
|
|
39
|
-
const listbox = wrapper.find("[data-test='
|
|
39
|
+
const listbox = wrapper.find("[data-test='listbox']");
|
|
40
40
|
await listbox.find("button").trigger("click");
|
|
41
41
|
|
|
42
42
|
const listboxItems = listbox.find("[data-test='listbox-items']");
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
+
import { useSettings } from "@/index";
|
|
2
3
|
import { ListboxOptions } from "@headlessui/vue";
|
|
3
4
|
import { inject } from "vue";
|
|
4
5
|
|
|
5
|
-
defineProps({
|
|
6
|
+
const props = defineProps({
|
|
6
7
|
as: {
|
|
7
8
|
type: String,
|
|
8
9
|
default: "ul",
|
|
@@ -11,21 +12,33 @@ defineProps({
|
|
|
11
12
|
type: Boolean,
|
|
12
13
|
default: false,
|
|
13
14
|
},
|
|
15
|
+
|
|
16
|
+
unstyled: {
|
|
17
|
+
type: Boolean,
|
|
18
|
+
default: false,
|
|
19
|
+
},
|
|
14
20
|
});
|
|
15
21
|
|
|
16
22
|
const background = inject("background") as string;
|
|
17
23
|
const text = inject("text") as string;
|
|
18
24
|
const horizontal = inject("horizontal") as boolean;
|
|
25
|
+
const classItems = inject("classItems") as string;
|
|
26
|
+
|
|
27
|
+
const { settings } = useSettings();
|
|
28
|
+
const isUnstyled = settings.global.unstyled || settings.components.listbox.unstyled || props.unstyled;
|
|
19
29
|
</script>
|
|
20
30
|
|
|
21
31
|
<template>
|
|
22
32
|
<ListboxOptions
|
|
23
33
|
:as="as"
|
|
24
34
|
:static="static"
|
|
25
|
-
:class="`
|
|
35
|
+
:class="`z-10 ${
|
|
36
|
+
isUnstyled
|
|
37
|
+
? ''
|
|
38
|
+
: `rounded-container-token' gap-1 p-4 border-token border-surface-400-500-token`
|
|
39
|
+
} ${background} ${text} ${horizontal ? 'flex' : 'flex-col'} ${classItems}`"
|
|
40
|
+
data-test="listbox-items"
|
|
26
41
|
>
|
|
27
|
-
<
|
|
28
|
-
<slot />
|
|
29
|
-
</div>
|
|
42
|
+
<slot />
|
|
30
43
|
</ListboxOptions>
|
|
31
44
|
</template>
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { mount } from "@vue/test-utils";
|
|
2
2
|
import { expect, test } from "vitest";
|
|
3
|
-
import { ref } from "vue";
|
|
4
3
|
import VListbox from "./VListbox.vue";
|
|
5
4
|
|
|
6
5
|
test("VListboxLabel using slot", () => {
|
|
@@ -19,7 +18,7 @@ test("VListboxLabel using slot", () => {
|
|
|
19
18
|
test("VListboxLabel custom label", () => {
|
|
20
19
|
const wrapper = mount({
|
|
21
20
|
template: `
|
|
22
|
-
<v-listbox label
|
|
21
|
+
<v-listbox text-label="John Duck"></v-listbox>
|
|
23
22
|
`,
|
|
24
23
|
components: {
|
|
25
24
|
"v-listbox": VListbox,
|
|
@@ -135,9 +135,13 @@ const toggleSwatches = () => (swatches.value = !swatches.value);
|
|
|
135
135
|
<v-button
|
|
136
136
|
v-if="!hideSwatches"
|
|
137
137
|
data-test="swatch-button"
|
|
138
|
-
:
|
|
139
|
-
|
|
140
|
-
|
|
138
|
+
:variant="swatches ? 'filled' : ''"
|
|
139
|
+
class="px-4 py-1 border-token border-surface-400-500-token"
|
|
140
|
+
:class="
|
|
141
|
+
swatches
|
|
142
|
+
? ''
|
|
143
|
+
: 'text-center text-base rounded-token hover:variant-ghost hover:text-surface-900 dark:hover:text-surface-50'
|
|
144
|
+
"
|
|
141
145
|
@click="toggleSwatches"
|
|
142
146
|
title="Backgrounds"
|
|
143
147
|
>
|
|
@@ -152,7 +156,7 @@ const toggleSwatches = () => (swatches.value = !swatches.value);
|
|
|
152
156
|
</v-button>
|
|
153
157
|
</header>
|
|
154
158
|
|
|
155
|
-
<!-- There is some odd behavior with test
|
|
159
|
+
<!-- There is some odd behavior with test coverage, v-model must be the last property in this component -->
|
|
156
160
|
<v-radio-group
|
|
157
161
|
v-if="swatches"
|
|
158
162
|
data-test="swatches"
|
|
@@ -216,7 +220,7 @@ const toggleSwatches = () => (swatches.value = !swatches.value);
|
|
|
216
220
|
<template v-if="tabView === 'code'">
|
|
217
221
|
<div
|
|
218
222
|
data-test="previewer-source"
|
|
219
|
-
:class="`vuetiful-previewer-source p-4 ${backgrounds['neutral']} ${regionSource}`"
|
|
223
|
+
:class="`vuetiful-previewer-source p-4 md:p-10 ${backgrounds['neutral']} ${regionSource}`"
|
|
220
224
|
>
|
|
221
225
|
<slot name="source">(source)</slot>
|
|
222
226
|
</div>
|
|
@@ -16,17 +16,17 @@ const props = defineProps({
|
|
|
16
16
|
},
|
|
17
17
|
});
|
|
18
18
|
|
|
19
|
-
provide("
|
|
20
|
-
provide("
|
|
19
|
+
provide("activeRail", props.active);
|
|
20
|
+
provide("hoverRail", props.hover);
|
|
21
21
|
</script>
|
|
22
22
|
|
|
23
23
|
<template>
|
|
24
24
|
<v-radio-group
|
|
25
|
-
unstyled
|
|
26
|
-
:active="active"
|
|
27
|
-
:hover="hover"
|
|
28
25
|
v-model="selectedRailTile"
|
|
29
|
-
|
|
26
|
+
unstyled
|
|
27
|
+
hover=""
|
|
28
|
+
active=""
|
|
29
|
+
class="flex h-full w-[70px] flex-col overflow-y-auto"
|
|
30
30
|
>
|
|
31
31
|
<slot />
|
|
32
32
|
</v-radio-group>
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { mount } from "@vue/test-utils";
|
|
2
|
+
import { expect, test, describe } from "vitest";
|
|
3
|
+
import { VRadioGroup, VRail, VRailTile, useRail } from "@/index";
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
describe("VRailTile", () => {
|
|
7
|
+
// TODO: add tests
|
|
8
|
+
test("default slot", () => {
|
|
9
|
+
const wrapper = mount({
|
|
10
|
+
provide: {
|
|
11
|
+
activeRail: null,
|
|
12
|
+
hoverRail: null,
|
|
13
|
+
},
|
|
14
|
+
template: /*html*/`
|
|
15
|
+
<v-radio-group>
|
|
16
|
+
<v-rail-tile>John Duck</v-rail-tile>
|
|
17
|
+
</v-radio-group>
|
|
18
|
+
`,
|
|
19
|
+
components: {
|
|
20
|
+
"v-rail-tile": VRailTile,
|
|
21
|
+
"v-radio-group": VRadioGroup,
|
|
22
|
+
},
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
expect(wrapper).toBeTruthy();
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
test("label prop", () => {
|
|
29
|
+
const wrapper = mount({
|
|
30
|
+
provide: {
|
|
31
|
+
activeRail: null,
|
|
32
|
+
hoverRail: null,
|
|
33
|
+
},
|
|
34
|
+
template: /*html*/`
|
|
35
|
+
<v-radio-group>
|
|
36
|
+
<v-rail-tile label="John Duck label">
|
|
37
|
+
John Duck
|
|
38
|
+
</v-rail-tile>
|
|
39
|
+
</v-radio-group>
|
|
40
|
+
`,
|
|
41
|
+
components: {
|
|
42
|
+
"v-rail-tile": VRailTile,
|
|
43
|
+
"v-radio-group": VRadioGroup,
|
|
44
|
+
},
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
const label = wrapper.find('.vuetiful-rail-tile-label');
|
|
48
|
+
expect(label.text()).toContain('John Duck label');
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
test("no default slot", () => {
|
|
52
|
+
const wrapper = mount({
|
|
53
|
+
provide: {
|
|
54
|
+
activeRail: null,
|
|
55
|
+
hoverRail: null,
|
|
56
|
+
},
|
|
57
|
+
template: /*html*/`
|
|
58
|
+
<v-radio-group>
|
|
59
|
+
<v-rail-tile label="John Duck label">
|
|
60
|
+
</v-rail-tile>
|
|
61
|
+
</v-radio-group>
|
|
62
|
+
`,
|
|
63
|
+
components: {
|
|
64
|
+
"v-rail-tile": VRailTile,
|
|
65
|
+
"v-radio-group": VRadioGroup,
|
|
66
|
+
},
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
const icon = wrapper.find('.vuetiful-rail-tile-icon');
|
|
70
|
+
expect(icon.exists()).toBeFalsy();
|
|
71
|
+
})
|
|
72
|
+
|
|
73
|
+
test("selected rail tile", async () => {
|
|
74
|
+
const wrapper = mount({
|
|
75
|
+
provide: {
|
|
76
|
+
activeRail: 'fake-active-class',
|
|
77
|
+
hoverRail: null,
|
|
78
|
+
},
|
|
79
|
+
template: /*html*/`
|
|
80
|
+
<v-rail data-test="rail">
|
|
81
|
+
<v-rail-tile data-test='rail-tile' label="John Duck label" value="John Duck">
|
|
82
|
+
John Duck
|
|
83
|
+
</v-rail-tile>
|
|
84
|
+
</v-rail>
|
|
85
|
+
`,
|
|
86
|
+
components: {
|
|
87
|
+
"v-rail-tile": VRailTile,
|
|
88
|
+
"v-rail": VRail,
|
|
89
|
+
},
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
const { selectedRailTile } = useRail();
|
|
93
|
+
expect(selectedRailTile.value).toBe("");
|
|
94
|
+
const railTile = wrapper.find('.vuetiful-rail-tile');
|
|
95
|
+
await railTile.trigger('click');
|
|
96
|
+
expect(selectedRailTile.value).toBe('John Duck');
|
|
97
|
+
})
|
|
98
|
+
})
|
|
99
|
+
|
|
@@ -25,17 +25,15 @@ defineProps({
|
|
|
25
25
|
});
|
|
26
26
|
|
|
27
27
|
const { selectedRailTile } = useRail();
|
|
28
|
-
const
|
|
29
|
-
const
|
|
28
|
+
const activeRail = inject("activeRail");
|
|
29
|
+
const hoverRail = inject("hoverRail");
|
|
30
30
|
</script>
|
|
31
31
|
|
|
32
32
|
<template>
|
|
33
33
|
<v-radio-item
|
|
34
|
-
:value="value"
|
|
35
34
|
unstyled
|
|
36
|
-
:
|
|
37
|
-
|
|
38
|
-
}`"
|
|
35
|
+
:value="value"
|
|
36
|
+
:class="`vuetiful-rail-tile grid aspect-square w-full cursor-pointer place-content-center place-items-center ${ selectedRailTile === value ? `${activeRail}` : `${hoverRail}` }`"
|
|
39
37
|
>
|
|
40
38
|
<template v-if="$slots.default">
|
|
41
39
|
<div :class="`vuetiful-rail-tile-icon ${regionIcon}`"><slot /></div>
|
|
@@ -20,8 +20,9 @@ describe("VTab", () => {
|
|
|
20
20
|
|
|
21
21
|
const vuetiful = wrapper.find("[data-test='vuetiful']");
|
|
22
22
|
const slotContainer = vuetiful.find("[data-test='slot-container']");
|
|
23
|
-
expect(vuetiful.classes()).toEqual(["flex", "flex-col"]);
|
|
23
|
+
expect(vuetiful.classes()).toEqual(["vuetiful-tab", "flex", "flex-col"]);
|
|
24
24
|
expect(slotContainer.classes()).toEqual([
|
|
25
|
+
"vuetiful-tab-content",
|
|
25
26
|
"text-base",
|
|
26
27
|
"rounded-token",
|
|
27
28
|
"w-full",
|
|
@@ -46,7 +47,7 @@ describe("VTab", () => {
|
|
|
46
47
|
});
|
|
47
48
|
|
|
48
49
|
const vuetiful = wrapper.find("[data-test='vuetiful']");
|
|
49
|
-
expect(vuetiful.classes()).toEqual(["flex", "flex-row", "justify-between"]);
|
|
50
|
+
expect(vuetiful.classes()).toEqual(["vuetiful-tab", "flex", "flex-row", "justify-between"]);
|
|
50
51
|
});
|
|
51
52
|
|
|
52
53
|
test("class-tab", async () => {
|
|
@@ -66,7 +67,7 @@ describe("VTab", () => {
|
|
|
66
67
|
|
|
67
68
|
const vuetiful = wrapper.find("[data-test='vuetiful']");
|
|
68
69
|
const slotContainer = vuetiful.find("[data-test='slot-container']");
|
|
69
|
-
expect(slotContainer.classes()).toEqual(["text-base", "rounded-token", "my-custom-class"]);
|
|
70
|
+
expect(slotContainer.classes()).toEqual(["vuetiful-tab-content", "text-base", "rounded-token", "my-custom-class"]);
|
|
70
71
|
});
|
|
71
72
|
|
|
72
73
|
test("hover/active", async () => {
|
|
@@ -95,6 +96,7 @@ describe("VTab", () => {
|
|
|
95
96
|
.find("[data-test='slot-container']");
|
|
96
97
|
|
|
97
98
|
expect(vuetifulSlotContainer.classes()).toEqual([
|
|
99
|
+
"vuetiful-tab-content",
|
|
98
100
|
"text-base",
|
|
99
101
|
"rounded-token",
|
|
100
102
|
"my-custom-active-class",
|
|
@@ -103,6 +105,7 @@ describe("VTab", () => {
|
|
|
103
105
|
"py-2",
|
|
104
106
|
]);
|
|
105
107
|
expect(isSlotContainer.classes()).toEqual([
|
|
108
|
+
"vuetiful-tab-content",
|
|
106
109
|
"text-base",
|
|
107
110
|
"rounded-token",
|
|
108
111
|
"hover:variant-ghost",
|
|
@@ -111,6 +114,7 @@ describe("VTab", () => {
|
|
|
111
114
|
"py-2",
|
|
112
115
|
]);
|
|
113
116
|
expect(beautifulSlotContainer.classes()).toEqual([
|
|
117
|
+
"vuetiful-tab-content",
|
|
114
118
|
"text-base",
|
|
115
119
|
"rounded-token",
|
|
116
120
|
"hover:variant-ghost",
|