@vcita/design-system 1.3.2 → 1.3.4
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/config/locales/ds.en.yml +4 -0
- package/dist/@vcita/design-system.esm.js +1882 -1140
- package/dist/@vcita/design-system.min.js +2 -2
- package/dist/@vcita/design-system.ssr.js +1688 -965
- package/init/DesignSystem.js +3 -1
- package/init/initI18n.js +24 -16
- package/package.json +2 -1
- package/src/components/VcActionList/VcActionList.spec.js +16 -7
- package/src/components/VcActionList/VcActionList.stories.js +16 -3
- package/src/components/VcActionList/VcActionList.vue +35 -11
- package/src/components/VcBottomActions/VcBottomActions.vue +2 -1
- package/src/components/VcBottomSheet/VcBottomSheet.stories.js +6 -13
- package/src/components/VcBottomSheet/VcBottomSheet.vue +2 -3
- package/src/components/VcButton/VcButton.vue +1 -1
- package/src/components/VcCheckbox/VcCheckbox.vue +8 -1
- package/src/components/VcColorPicker/VcColorPicker.spec.js +206 -0
- package/src/components/VcColorPicker/VcColorPicker.stories.js +107 -0
- package/src/components/VcColorPicker/VcColorPicker.vue +270 -0
- package/src/components/VcFilterPanel/VcFilterPanel.spec.js +15 -0
- package/src/components/VcFilterPanel/VcFilterPanel.stories.js +9 -1
- package/src/components/VcFilterPanel/VcFilterPanel.vue +24 -3
- package/src/components/VcGalleryItem/VcGalleryItem.stories.js +2 -0
- package/src/components/VcGroupedItems/VcGroupedItems.spec.js +148 -0
- package/src/components/VcGroupedItems/VcGroupedItems.stories.js +135 -0
- package/src/components/VcGroupedItems/VcGroupedItems.vue +155 -0
- package/src/components/VcLink/VcLink.spec.js +3 -3
- package/src/components/VcLink/VcLink.stories.js +2 -6
- package/src/components/VcLink/VcLink.vue +1 -18
- package/src/components/VcMenu/VcDropdown.spec.js +120 -0
- package/src/components/VcMenu/VcDropdown.stories.js +272 -0
- package/src/components/VcMenu/VcDropdown.vue +93 -0
- package/src/components/VcMenu/VcMenu.spec.js +61 -10
- package/src/components/VcMenu/VcMenu.stories.js +38 -33
- package/src/components/VcMenu/VcMenu.vue +19 -3
- package/src/components/VcPopover/VcPopover.stories.js +2 -2
- package/src/components/VcRadioGroup/VcRadioGroup.spec.js +28 -0
- package/src/components/VcRadioGroup/VcRadioGroup.stories.js +3 -1
- package/src/components/VcRadioGroup/VcRadioGroup.vue +6 -1
- package/src/components/VcSearchPicker/VcSearchPicker.stories.js +3 -4
- package/src/components/VcSelectField/VcSelectField.vue +6 -0
- package/src/components/VcSideNav/VcSideNav.spec.js +1 -1
- package/src/components/VcSideNav/VcSideNav.vue +21 -104
- package/src/components/VcTextField/VcTextField.spec.js +13 -0
- package/src/components/VcTextField/VcTextField.stories.js +2 -1
- package/src/components/VcTextField/VcTextField.vue +11 -0
- package/src/components/VcTooltip/VcTooltip.stories.js +3 -1
- package/src/components/VcTooltip/VcTooltip.vue +6 -1
- package/src/components/index.js +4 -0
- package/src/components/list/VcBaseListItem/VcBaseListItem.stories.js +22 -13
- package/src/components/list/VcBaseListItem/VcBaseListItem.vue +4 -1
- package/src/components/list/VcList/VcList.stories.js +245 -240
- package/src/components/list/VcList/VcList.vue +11 -4
- package/src/components/page/layouts/centeredPage/CenteredPageLayout.stories.js +17 -16
- package/styles/variables.scss +1 -0
- package/styles/vuetify-variables.scss +9 -1
- package/CHANGELOG.md +0 -342
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<VcMenu :offset-y="true" v-bind="$attrs" v-on="$listeners" :close-on-content-click="false"
|
|
3
|
+
:data-qa="dataQa">
|
|
4
|
+
<template v-slot:activator="activatorObj">
|
|
5
|
+
<slot v-bind="activatorObj" name="activator"/>
|
|
6
|
+
</template>
|
|
7
|
+
<VcLayout column :style="{maxHeight: `${maxHeight}px`}" :data-qa="dataQa">
|
|
8
|
+
<VcLayout class="header-area" :data-qa="`${dataQa}-header`">
|
|
9
|
+
<slot name="header">
|
|
10
|
+
</slot>
|
|
11
|
+
</VcLayout>
|
|
12
|
+
<VcLayout class="content-area" :data-qa="`${dataQa}-content`">
|
|
13
|
+
<slot></slot>
|
|
14
|
+
</VcLayout>
|
|
15
|
+
<VcLayout class="footer-area" :data-qa="`${dataQa}-footer`">
|
|
16
|
+
<slot name="footer">
|
|
17
|
+
<VcLayout column v-if="showAddAnother">
|
|
18
|
+
<v-divider></v-divider>
|
|
19
|
+
<VcBaseListItem @click="data => $emit('onAddItem', data)" :data-qa="`${dataQa}-add`">
|
|
20
|
+
<VcIcon size="12" class="add-another-icon" dense>$plus</VcIcon>
|
|
21
|
+
<span class="add-another-label">{{ getAddAnotherLabel }}</span>
|
|
22
|
+
</VcBaseListItem>
|
|
23
|
+
</VcLayout>
|
|
24
|
+
</slot>
|
|
25
|
+
</VcLayout>
|
|
26
|
+
</VcLayout>
|
|
27
|
+
</VcMenu>
|
|
28
|
+
</template>
|
|
29
|
+
|
|
30
|
+
<script>
|
|
31
|
+
import VcLayout from "@/components/VcLayout/VcLayout.vue";
|
|
32
|
+
import VcMenu from "@/components/VcMenu/VcMenu.vue";
|
|
33
|
+
import VcBaseListItem from "@/components/list/VcBaseListItem/VcBaseListItem.vue";
|
|
34
|
+
import VcIcon from "@/components/VcIcon/VcIcon.vue";
|
|
35
|
+
|
|
36
|
+
export default {
|
|
37
|
+
name: "VcDropdown",
|
|
38
|
+
components: {VcBaseListItem, VcLayout, VcMenu, VcIcon},
|
|
39
|
+
props: {
|
|
40
|
+
/**
|
|
41
|
+
* If set to true and no content has been placed inside the footer slot, it will contain a separator and an "add another" item, as an easy shortcut.
|
|
42
|
+
*/
|
|
43
|
+
showAddAnother: {
|
|
44
|
+
type: Boolean,
|
|
45
|
+
default: false,
|
|
46
|
+
},
|
|
47
|
+
/**
|
|
48
|
+
* If you use the built in "add another" footer element, this will allow you to customize the label
|
|
49
|
+
*/
|
|
50
|
+
addAnotherLabel: {
|
|
51
|
+
type: String,
|
|
52
|
+
default: ""
|
|
53
|
+
},
|
|
54
|
+
/**
|
|
55
|
+
* Max height in pixels. additional content will be scrolled.
|
|
56
|
+
*/
|
|
57
|
+
maxHeight: {
|
|
58
|
+
type: Number,
|
|
59
|
+
default: 297,
|
|
60
|
+
},
|
|
61
|
+
dataQa: {
|
|
62
|
+
type: String,
|
|
63
|
+
default: 'VcDropdown',
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
computed: {
|
|
67
|
+
getAddAnotherLabel() {
|
|
68
|
+
return this.addAnotherLabel || this.$dst('ds.menu.add')
|
|
69
|
+
},
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
</script>
|
|
73
|
+
|
|
74
|
+
<style scoped lang="scss">
|
|
75
|
+
|
|
76
|
+
.content-area {
|
|
77
|
+
overflow: scroll;
|
|
78
|
+
min-width: 220px;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
.add-another-label {
|
|
82
|
+
font-weight: var(--font-weight-medium2);
|
|
83
|
+
font-size: var(--font-size-x-small);
|
|
84
|
+
line-height: var(--size-value5);
|
|
85
|
+
color: var(--gray-darken-5);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
.add-another-icon {
|
|
89
|
+
margin-inline-end: var(--size-value3);
|
|
90
|
+
cursor: pointer;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
</style>
|
|
@@ -2,37 +2,88 @@ import '@testing-library/jest-dom'
|
|
|
2
2
|
import VcMenu from "./VcMenu.vue";
|
|
3
3
|
import init from "../../../testing-library.config"
|
|
4
4
|
import Vuetify from 'vuetify'
|
|
5
|
-
import {render} from "@testing-library/vue";
|
|
5
|
+
import {render, waitFor} from "@testing-library/vue";
|
|
6
|
+
import userEvent from "@testing-library/user-event";
|
|
6
7
|
|
|
7
8
|
init();
|
|
8
9
|
|
|
9
10
|
describe("VcMenu.vue", () => {
|
|
10
11
|
|
|
11
|
-
const renderWithVuetify = (component, options, callback) => {
|
|
12
|
-
const root = document.createElement('div')
|
|
13
|
-
root.setAttribute('data-app', 'true')
|
|
12
|
+
const renderWithVuetify = (component, options, callback, isMobile = false) => {
|
|
13
|
+
const root = document.createElement('div');
|
|
14
|
+
root.setAttribute('data-app', 'true');
|
|
15
|
+
root.setAttribute('id', 'root');
|
|
16
|
+
|
|
17
|
+
const vuetify = new Vuetify()
|
|
18
|
+
if (isMobile) {
|
|
19
|
+
const breakpoint = {
|
|
20
|
+
init: jest.fn(),
|
|
21
|
+
framework: {},
|
|
22
|
+
smAndDown: true,
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
vuetify.framework.breakpoint = breakpoint;
|
|
26
|
+
}
|
|
14
27
|
|
|
15
28
|
return render(
|
|
16
29
|
component,
|
|
17
30
|
{
|
|
18
31
|
container: document.body.appendChild(root),
|
|
19
32
|
// for Vuetify components that use the vuetify instance property
|
|
20
|
-
vuetify
|
|
33
|
+
vuetify,
|
|
21
34
|
...options,
|
|
22
|
-
mocks: {
|
|
35
|
+
mocks: {
|
|
36
|
+
$t: value => value,
|
|
37
|
+
$dst: value => value, // <- for the design system
|
|
38
|
+
},
|
|
23
39
|
},
|
|
24
40
|
callback,
|
|
25
41
|
)
|
|
26
42
|
}
|
|
27
43
|
|
|
28
|
-
it("mounts", () => {
|
|
44
|
+
it("mounts", async () => {
|
|
29
45
|
// Queries: https://testing-library.com/docs/queries/about#types-of-queries
|
|
30
|
-
const {container} = renderWithVuetify(VcMenu, {
|
|
31
|
-
props: {
|
|
46
|
+
const {container, getByText, findByRole} = renderWithVuetify(VcMenu, {
|
|
47
|
+
props: {
|
|
48
|
+
attach: '#root',
|
|
49
|
+
value: true,
|
|
50
|
+
},
|
|
51
|
+
slots: {
|
|
52
|
+
'activator': '<div>activator</div>',
|
|
53
|
+
default: '<div>menu content</div>'
|
|
54
|
+
},
|
|
32
55
|
})
|
|
33
56
|
|
|
34
57
|
// Expect options: https://github.com/testing-library/jest-dom
|
|
35
|
-
expect(container).toHaveAttribute('data-app', 'true')
|
|
58
|
+
expect(container).toHaveAttribute('data-app', 'true');
|
|
59
|
+
|
|
60
|
+
const activator = getByText('activator');
|
|
61
|
+
expect(activator).toBeInTheDocument();
|
|
62
|
+
await userEvent.click(activator);
|
|
63
|
+
|
|
64
|
+
await waitFor(async () => {
|
|
65
|
+
const menu = await findByRole('menu');
|
|
66
|
+
expect(menu).toBeInTheDocument();
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
expect(getByText('menu content')).toBeInTheDocument();
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
it("shows VcBottomSheet in mobile", async () => {
|
|
73
|
+
// Queries: https://testing-library.com/docs/queries/about#types-of-queries
|
|
74
|
+
const {getByText,getByTestId} = renderWithVuetify(VcMenu, {
|
|
75
|
+
props: {
|
|
76
|
+
attach: '#root',
|
|
77
|
+
value: true,
|
|
78
|
+
},
|
|
79
|
+
slots: {
|
|
80
|
+
'activator': '<div>activator</div>',
|
|
81
|
+
default: '<div>menu content</div>'
|
|
82
|
+
},
|
|
83
|
+
}, undefined, true);
|
|
84
|
+
|
|
85
|
+
expect(getByTestId('VcMenu-sheet')).toBeInTheDocument();
|
|
86
|
+
expect(getByText('menu content')).toBeInTheDocument();
|
|
36
87
|
});
|
|
37
88
|
|
|
38
89
|
});
|
|
@@ -1,27 +1,22 @@
|
|
|
1
1
|
import VcMenuCmp from './VcMenu';
|
|
2
2
|
import VcButton from "@/components/VcButton/VcButton";
|
|
3
|
+
import VcLayout from "@/components/VcLayout/VcLayout";
|
|
3
4
|
import VcBaseDocs from "@/stories/VcBaseDocs.mdx";
|
|
4
5
|
|
|
5
6
|
const Template = (args, {argTypes}) => ({
|
|
6
|
-
components: {VcMenu: VcMenuCmp, VcButton},
|
|
7
|
+
components: {VcMenu: VcMenuCmp, VcButton, VcLayout},
|
|
7
8
|
props: Object.keys(argTypes),
|
|
8
9
|
template: `
|
|
9
10
|
<div>
|
|
10
|
-
<
|
|
11
|
+
Please note: for desktop, this component will display a menu item, for mobile, it will use a bottom sheet. <br>
|
|
12
|
+
<VcMenu :offset-y="offsetY" :offset-x="offsetX" :data-qa="dataQa" @input="onInput">
|
|
11
13
|
<template #activator="{ on, attrs }">
|
|
12
|
-
|
|
14
|
+
${args.activator}
|
|
13
15
|
</template>
|
|
14
|
-
<
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
<v-list-item disabled>
|
|
19
|
-
<v-list-item-title>Option 2</v-list-item-title>
|
|
20
|
-
</v-list-item>
|
|
21
|
-
<v-list-item>
|
|
22
|
-
<v-list-item-title>Option 3</v-list-item-title>
|
|
23
|
-
</v-list-item>
|
|
24
|
-
</v-list>
|
|
16
|
+
<VcLayout align-center justify-center
|
|
17
|
+
:style="{ minHeight: '300px', backgroundColor: 'var(--green-lighten-2)', padding: '12px'}">
|
|
18
|
+
Your content goes here
|
|
19
|
+
</VcLayout>
|
|
25
20
|
</VcMenu>
|
|
26
21
|
</div>`,
|
|
27
22
|
})
|
|
@@ -29,23 +24,33 @@ const Template = (args, {argTypes}) => ({
|
|
|
29
24
|
export const Playground = Template.bind({});
|
|
30
25
|
|
|
31
26
|
// Set default values
|
|
32
|
-
Playground.args = {
|
|
27
|
+
Playground.args = {
|
|
28
|
+
activator: `<VcButton v-bind='attrs' v-on='on'>Click me</VcButton>`,
|
|
29
|
+
offsetX: false,
|
|
30
|
+
offsetY: true,
|
|
31
|
+
dataQa: 'VcMenu'
|
|
32
|
+
}
|
|
33
33
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
34
|
+
export default {
|
|
35
|
+
title: 'Containers / menu / VcMenu',
|
|
36
|
+
id: 'VcMenu',
|
|
37
|
+
component: VcMenuCmp,
|
|
38
|
+
argTypes: {
|
|
39
|
+
onInput: {action: 'input', table: {disable: true}},
|
|
40
|
+
},
|
|
41
|
+
parameters: {
|
|
42
|
+
design: {
|
|
43
|
+
type: 'figma',
|
|
44
|
+
url: 'https://www.figma.com/file/xIOY6fBoA1wpy1tHv3i5js/vcita---ui-library?node-id=12711%3A263160',
|
|
45
|
+
},
|
|
46
|
+
status: {
|
|
47
|
+
type: 'beta', // 'beta' | 'stable' | 'deprecated' | 'releaseCandidate'
|
|
48
|
+
url: 'https://vuetifyjs.com/en/components/menus/', // will make the tag a link
|
|
49
|
+
},
|
|
50
|
+
docs: {
|
|
51
|
+
page: VcBaseDocs,
|
|
52
|
+
inlineStories: false,
|
|
53
|
+
iframeHeight: 400,
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
};
|
|
@@ -1,12 +1,28 @@
|
|
|
1
1
|
<script>
|
|
2
|
+
import VcBottomSheet from "@/components/VcBottomSheet/VcBottomSheet.vue";
|
|
3
|
+
|
|
2
4
|
export default {
|
|
3
5
|
name: "VcMenu",
|
|
6
|
+
props: {
|
|
7
|
+
dataQa: {
|
|
8
|
+
type: String,
|
|
9
|
+
default: 'VcMenu'
|
|
10
|
+
},
|
|
11
|
+
},
|
|
4
12
|
render: function (createElement) {
|
|
5
|
-
// `<v-menu><slot></slot></v-menu>`
|
|
6
13
|
const props = {
|
|
7
|
-
|
|
14
|
+
...this.$props,
|
|
15
|
+
...this.$attrs,
|
|
16
|
+
...this.$listeners,
|
|
8
17
|
};
|
|
9
|
-
|
|
18
|
+
|
|
19
|
+
return createElement(
|
|
20
|
+
this.$vuetify.breakpoint.mdAndUp ? 'v-menu' : VcBottomSheet,
|
|
21
|
+
{
|
|
22
|
+
props,
|
|
23
|
+
scopedSlots: this.$scopedSlots
|
|
24
|
+
},
|
|
25
|
+
);
|
|
10
26
|
}
|
|
11
27
|
}
|
|
12
28
|
</script>
|
|
@@ -28,8 +28,8 @@ const GeneralTemplate = (args, {argTypes}) => ({
|
|
|
28
28
|
</VcIcon>
|
|
29
29
|
</template>
|
|
30
30
|
<template>
|
|
31
|
-
<VcLayout align-center justify-center
|
|
32
|
-
:style="{ minHeight: '200px', backgroundColor: 'var(--green-lighten-2)'}">
|
|
31
|
+
<VcLayout align-center justify-center
|
|
32
|
+
:style="{ minHeight: '200px', backgroundColor: 'var(--green-lighten-2)', padding: '12px'}">
|
|
33
33
|
Place any content in the default slot
|
|
34
34
|
</VcLayout>
|
|
35
35
|
</template>
|
|
@@ -138,4 +138,32 @@ describe("VcRadioGroup.vue", () => {
|
|
|
138
138
|
expect(customDataQaEl).toBeInTheDocument();
|
|
139
139
|
});
|
|
140
140
|
|
|
141
|
+
it("passing disabled prop transfers to radio", async () => {
|
|
142
|
+
const {container, getByTestId } = renderWithVuetify(VcRadioGroup, {
|
|
143
|
+
props: {
|
|
144
|
+
dataQa: 'vc-radio-group',
|
|
145
|
+
items: generalItems,
|
|
146
|
+
value: 'all_of_em',
|
|
147
|
+
disabled: true
|
|
148
|
+
}
|
|
149
|
+
})
|
|
150
|
+
|
|
151
|
+
const currentSelected = getByTestId('radio-all_of_em');
|
|
152
|
+
expect(currentSelected.parentElement.parentElement).toHaveClass("v-radio--is-disabled")
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
it("renders as horizontal", async () => {
|
|
156
|
+
const {container, getByTestId } = renderWithVuetify(VcRadioGroup, {
|
|
157
|
+
props: {
|
|
158
|
+
dataQa: 'vc-radio-group',
|
|
159
|
+
items: generalItems,
|
|
160
|
+
value: 'all_of_em',
|
|
161
|
+
isHorizontal: true,
|
|
162
|
+
}
|
|
163
|
+
})
|
|
164
|
+
|
|
165
|
+
const VcRadioGroupCmp = container.querySelector('.vc-radio-buttons');
|
|
166
|
+
expect(VcRadioGroupCmp).toHaveClass('v-input--radio-group--row');
|
|
167
|
+
});
|
|
168
|
+
|
|
141
169
|
});
|
|
@@ -54,6 +54,7 @@ const GeneralTemplate = (args, {argTypes}) => ({
|
|
|
54
54
|
:data-qa="dataQa"
|
|
55
55
|
@change="onChange"
|
|
56
56
|
:disabled="disabled"
|
|
57
|
+
:is-horizontal="isHorizontal"
|
|
57
58
|
>
|
|
58
59
|
<template v-slot:label-custom>
|
|
59
60
|
custom label by using a slot!
|
|
@@ -72,7 +73,8 @@ Playground.args = {
|
|
|
72
73
|
items: generalItems,
|
|
73
74
|
dataQa: 'VcRadioGroup',
|
|
74
75
|
title: 'radio group title',
|
|
75
|
-
disabled: false
|
|
76
|
+
disabled: false,
|
|
77
|
+
isHorizontal: false
|
|
76
78
|
}
|
|
77
79
|
|
|
78
80
|
export default {
|
|
@@ -7,7 +7,8 @@
|
|
|
7
7
|
:value="value"
|
|
8
8
|
@change="val => $emit('change', val)"
|
|
9
9
|
hide-details="auto"
|
|
10
|
-
class="vc-radio-buttons"
|
|
10
|
+
class="vc-radio-buttons"
|
|
11
|
+
:row="isHorizontal">
|
|
11
12
|
<VcRadio v-bind="item" v-for="item in items" :key="item.value" :disabled="disabled">
|
|
12
13
|
<template v-slot:label>
|
|
13
14
|
<slot :name="`label-${item.value}`"></slot>
|
|
@@ -56,6 +57,10 @@ export default {
|
|
|
56
57
|
disabled: {
|
|
57
58
|
type: Boolean,
|
|
58
59
|
default: false
|
|
60
|
+
},
|
|
61
|
+
isHorizontal: {
|
|
62
|
+
type: Boolean,
|
|
63
|
+
default: false
|
|
59
64
|
}
|
|
60
65
|
},
|
|
61
66
|
|
|
@@ -84,7 +84,7 @@ const TemplateWithSlot = (args, {argTypes}) => ({
|
|
|
84
84
|
@onMenuToggled="onMenuToggled"
|
|
85
85
|
>
|
|
86
86
|
<template #customItem="data">
|
|
87
|
-
${args.
|
|
87
|
+
${args.customItem}
|
|
88
88
|
</template>
|
|
89
89
|
</VcSearchPicker>`
|
|
90
90
|
})
|
|
@@ -99,7 +99,7 @@ DocumentItem.args = {
|
|
|
99
99
|
noDataText: 'No documents found',
|
|
100
100
|
iconType: 'folder',
|
|
101
101
|
menuContentClass: 'custom- content- class',
|
|
102
|
-
|
|
102
|
+
customItem: `<VcDocItem :title='data.item.text' :uid='data.item.value' :allowActions='false'/>`
|
|
103
103
|
}
|
|
104
104
|
|
|
105
105
|
export const AvatarItem = TemplateWithSlot.bind({});
|
|
@@ -110,7 +110,7 @@ AvatarItem.args = {
|
|
|
110
110
|
placeholderFocus: 'Select characters',
|
|
111
111
|
errorLabelText: 'Please select A character',
|
|
112
112
|
noDataText: 'No characters found',
|
|
113
|
-
|
|
113
|
+
customItem: `<VcAvatar :imagePath='data.item.image' :uid='data.item.value' size='sm'/>
|
|
114
114
|
<span :style="{'marginLeft': '12px', 'fontSize': '12px'}">{{ data.item.text }}</span>`,
|
|
115
115
|
}
|
|
116
116
|
|
|
@@ -170,7 +170,6 @@ export default {
|
|
|
170
170
|
placeholderFocus: {table: {category: 'placeholder'}},
|
|
171
171
|
error: {table: {category: 'error'}},
|
|
172
172
|
errorLabelText: {table: {category: 'error'}},
|
|
173
|
-
slotContent: {table: {disable: true}},
|
|
174
173
|
},
|
|
175
174
|
parameters: {
|
|
176
175
|
design: {
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
hide-details="auto"
|
|
6
6
|
class="VcSelectField"
|
|
7
7
|
:class="{'with-tooltip': tooltipContent}"
|
|
8
|
+
:readonly="readonly"
|
|
8
9
|
:label="label"
|
|
9
10
|
:items="items"
|
|
10
11
|
:rules="rules"
|
|
@@ -17,6 +18,7 @@
|
|
|
17
18
|
:placeholder="placeholder"
|
|
18
19
|
@change="selectionChanged">
|
|
19
20
|
<template v-slot:append>
|
|
21
|
+
<slot name="prepend"></slot>
|
|
20
22
|
<div class="dropdown-arrow d-flex align-center justify-center">
|
|
21
23
|
<VcIcon size="9" class="icon">$caret_down</VcIcon>
|
|
22
24
|
</div>
|
|
@@ -63,6 +65,10 @@ export default {
|
|
|
63
65
|
type: String,
|
|
64
66
|
default: '',
|
|
65
67
|
},
|
|
68
|
+
readonly: {
|
|
69
|
+
type: Boolean,
|
|
70
|
+
default: false,
|
|
71
|
+
},
|
|
66
72
|
tooltipHeader: {
|
|
67
73
|
type: String,
|
|
68
74
|
default: '',
|
|
@@ -62,7 +62,7 @@ describe("VcSideNav.vue", () => {
|
|
|
62
62
|
expect(component).toBeInTheDocument()
|
|
63
63
|
navGroupsData.forEach((group) => {
|
|
64
64
|
// Verify Groups
|
|
65
|
-
let groupElement = getByTestId(group.id)
|
|
65
|
+
let groupElement = getByTestId(`group-${group.id}`)
|
|
66
66
|
expect(groupElement).toBeInTheDocument()
|
|
67
67
|
group.items.forEach((item) => {
|
|
68
68
|
// Verify Items
|
|
@@ -1,41 +1,22 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<
|
|
3
|
-
|
|
4
|
-
<
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
<
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
</slot>
|
|
12
|
-
</div>
|
|
13
|
-
<div class="side-nav__group__container d-flex flex-column mb-5">
|
|
14
|
-
<div @click="$emit('change',item.id)"
|
|
15
|
-
:data-qa="`item-${item.id}`"
|
|
16
|
-
v-if="group.items"
|
|
17
|
-
v-for="(item) in group.items"
|
|
18
|
-
:key="item.id"
|
|
19
|
-
:class="{selected: item.id === selected, disabled: item.disabled, mobile: isMobile, 'rtl': $vuetify.rtl}"
|
|
20
|
-
class="side-nav__group__container__menu-item d-flex align-center flex-grow-1">
|
|
21
|
-
<slot :name="`item-${item.id}`" :item="item">
|
|
22
|
-
<div class="d-flex justify-space-between px-4 align-center flex-grow-1">
|
|
23
|
-
<span>{{item.label}}</span>
|
|
24
|
-
<vcIcon size="12" v-if="isMobile">$chevron_right</vcIcon>
|
|
25
|
-
</div>
|
|
26
|
-
</slot>
|
|
27
|
-
</div>
|
|
28
|
-
</div>
|
|
29
|
-
</div>
|
|
30
|
-
</div>
|
|
2
|
+
<VcGroupedItems :item-groups="navGroups" :selected="selected" flavor="elevated" :data-qa="dataQa"
|
|
3
|
+
@change="data => $emit('change', data)">
|
|
4
|
+
<template v-for="group in navGroups" #[getGroupSlotName(group.id)]>
|
|
5
|
+
<slot :name="`group-${group.id}-header`"></slot>
|
|
6
|
+
</template>
|
|
7
|
+
<template v-for="item in allItems" #[getItemSlotName(item.id)]>
|
|
8
|
+
<slot :name="`item-${item.id}`" :item="item"></slot>
|
|
9
|
+
</template>
|
|
10
|
+
</VcGroupedItems>
|
|
31
11
|
</template>
|
|
32
12
|
<script>
|
|
33
13
|
|
|
34
14
|
import VcIcon from "@/components/VcIcon/VcIcon.vue";
|
|
15
|
+
import VcGroupedItems from "@/components/VcGroupedItems/VcGroupedItems.vue";
|
|
35
16
|
|
|
36
17
|
export default {
|
|
37
18
|
name: "VcSideNav",
|
|
38
|
-
components: {VcIcon},
|
|
19
|
+
components: {VcGroupedItems, VcIcon},
|
|
39
20
|
props: {
|
|
40
21
|
dataQa: {
|
|
41
22
|
type: String,
|
|
@@ -54,85 +35,21 @@ export default {
|
|
|
54
35
|
prop: 'selected',
|
|
55
36
|
event: 'change'
|
|
56
37
|
},
|
|
38
|
+
methods: {
|
|
39
|
+
getGroupSlotName(groupId) {
|
|
40
|
+
return `group-${groupId}-header`;
|
|
41
|
+
},
|
|
42
|
+
getItemSlotName(itemId) {
|
|
43
|
+
return `item-${itemId}`;
|
|
44
|
+
},
|
|
45
|
+
},
|
|
57
46
|
computed: {
|
|
58
|
-
|
|
59
|
-
return
|
|
47
|
+
allItems() {
|
|
48
|
+
return this.navGroups.reduce((acc, group) => acc.concat(group.items), []);
|
|
60
49
|
}
|
|
61
50
|
}
|
|
62
51
|
}
|
|
63
52
|
</script>
|
|
64
53
|
|
|
65
54
|
<style lang="scss" scoped>
|
|
66
|
-
.side-nav{
|
|
67
|
-
&__group{
|
|
68
|
-
&__header{
|
|
69
|
-
font-size: var(--font-size-xx-small);
|
|
70
|
-
font-weight: var(--font-weight-large);
|
|
71
|
-
line-height: var(--size-value5);
|
|
72
|
-
color: var(--gray-darken-2);
|
|
73
|
-
}
|
|
74
|
-
&__container{
|
|
75
|
-
border-radius: var(--border-radius);
|
|
76
|
-
background-color: var(--modal-bg-color);
|
|
77
|
-
box-shadow: var(--shadow-1);
|
|
78
|
-
&__menu-item{
|
|
79
|
-
cursor: pointer;
|
|
80
|
-
box-sizing: border-box;
|
|
81
|
-
height: var(--size-value11);
|
|
82
|
-
font-weight: var(--font-weight-medium2);
|
|
83
|
-
font-size: var(--font-size-x-small);
|
|
84
|
-
border-inline-start: 3px solid var(--modal-bg-color);
|
|
85
|
-
transition: 0.3s;
|
|
86
|
-
transition-property: border-color, background-color;
|
|
87
|
-
&:first-of-type{
|
|
88
|
-
margin-top: var(--size-value1);
|
|
89
|
-
}
|
|
90
|
-
&:last-of-type{
|
|
91
|
-
margin-bottom: var(--size-value1);
|
|
92
|
-
}
|
|
93
|
-
&:hover{
|
|
94
|
-
border-color: var(--gray-lighten-3);
|
|
95
|
-
background-color: var(--gray-lighten-3);
|
|
96
|
-
}
|
|
97
|
-
&:focus{
|
|
98
|
-
border: 3px solid var(--v-secondary-lighten1);
|
|
99
|
-
}
|
|
100
|
-
&:active:not(.mobile){
|
|
101
|
-
border-color: var(--gray-lighten-1);
|
|
102
|
-
background-color: var(--gray-lighten-1);
|
|
103
|
-
}
|
|
104
|
-
&.selected{
|
|
105
|
-
font-weight: var(--font-weight-large);
|
|
106
|
-
}
|
|
107
|
-
&.selected:not(.mobile){
|
|
108
|
-
border-inline-start: 3px solid var(--v-secondary-base);
|
|
109
|
-
}
|
|
110
|
-
&.disabled{
|
|
111
|
-
cursor: unset;
|
|
112
|
-
pointer-events: none;
|
|
113
|
-
border-color: var(--gray-lighten-3);
|
|
114
|
-
background-color: var(--gray-lighten-3);
|
|
115
|
-
color: var(--gray-darken-2);
|
|
116
|
-
}
|
|
117
|
-
&.mobile{
|
|
118
|
-
color: var(--gray-darken-5);
|
|
119
|
-
height: var(--size-value13);
|
|
120
|
-
::v-deep{
|
|
121
|
-
svg.vc-chevron-right {
|
|
122
|
-
fill: var(--gray-darken-2);
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
&.rtl{
|
|
126
|
-
::v-deep{
|
|
127
|
-
svg.vc-chevron-right {
|
|
128
|
-
-webkit-transform: scaleX(-1);
|
|
129
|
-
transform: scaleX(-1);
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
55
|
</style>
|
|
@@ -274,4 +274,17 @@ describe("VcTextField.vue", () => {
|
|
|
274
274
|
userEvent.click(textField);
|
|
275
275
|
expect(emitted().click.length).toBe(1);
|
|
276
276
|
});
|
|
277
|
+
|
|
278
|
+
it("emitted onKeydownEnter event", () => {
|
|
279
|
+
const {getByTestId, emitted} = renderWithVuetify(VcTextField, {
|
|
280
|
+
|
|
281
|
+
props: {
|
|
282
|
+
label: "labelText"
|
|
283
|
+
}
|
|
284
|
+
});
|
|
285
|
+
|
|
286
|
+
const textField = getByTestId('vc-text-field');
|
|
287
|
+
userEvent.type(textField, '{enter}');
|
|
288
|
+
expect(emitted().onKeydownEnter.length).toBe(1);
|
|
289
|
+
});
|
|
277
290
|
});
|
|
@@ -64,7 +64,8 @@ const TextFieldTemplate = (args, {argTypes}) => ({
|
|
|
64
64
|
:google-address-country-options="googleAddressCountryOptions"
|
|
65
65
|
@click="onClick"
|
|
66
66
|
@input="onInput"
|
|
67
|
-
@onPlaceSelected="onPlaceSelected"
|
|
67
|
+
@onPlaceSelected="onPlaceSelected"
|
|
68
|
+
@onKeydownEnter="onKeydownEnter"/>
|
|
68
69
|
</v-layout>`,
|
|
69
70
|
})
|
|
70
71
|
|