@eturnity/eturnity_reusable_components 7.45.5-EPDM-10609.0 → 7.45.5-EPDM-11692.0
Sign up to get free protection for your applications and to get access to all the features.
- package/package.json +1 -1
- package/src/assets/theme.js +0 -1
- package/src/components/infoCard/InfoCard.stories.js +144 -0
- package/src/components/infoCard/defaultProps.js +7 -0
- package/src/components/infoCard/index.vue +95 -22
- package/src/components/infoCard/infoCard.spec.js +56 -0
- package/src/components/infoText/index.vue +18 -113
- package/src/components/inputs/radioButton/defaultProps.js +0 -2
- package/src/components/inputs/select/index.vue +9 -2
- package/src/components/modals/modal/index.vue +9 -3
- package/src/assets/svgIcons/checkmark.svg +0 -3
- package/src/components/infoText/constants.js +0 -4
package/package.json
CHANGED
package/src/assets/theme.js
CHANGED
@@ -0,0 +1,144 @@
|
|
1
|
+
import defaultInfoCardProps from './defaultProps'
|
2
|
+
import InfoCard from './index.vue'
|
3
|
+
import theme from '@/assets/theme'
|
4
|
+
|
5
|
+
export default {
|
6
|
+
title: 'InfoCard',
|
7
|
+
component: InfoCard,
|
8
|
+
tags: ['autodocs'],
|
9
|
+
argTypes: {
|
10
|
+
type: {
|
11
|
+
description: 'Defines preset styles',
|
12
|
+
control: 'select',
|
13
|
+
options: ['info', 'warning'],
|
14
|
+
},
|
15
|
+
minWidth: {
|
16
|
+
description: '',
|
17
|
+
},
|
18
|
+
color: {
|
19
|
+
description: 'Color of text and icon (can overwrite preset styles)',
|
20
|
+
control: {
|
21
|
+
type: 'color',
|
22
|
+
presetColors: [
|
23
|
+
theme.colors.grey3,
|
24
|
+
theme.colors.grey4,
|
25
|
+
theme.colors.red,
|
26
|
+
],
|
27
|
+
},
|
28
|
+
},
|
29
|
+
alignItems: {
|
30
|
+
description: 'Icon and text alignment (can overwrite preset styles)',
|
31
|
+
control: 'select',
|
32
|
+
options: ['flex-start', 'flex-end', 'center'],
|
33
|
+
},
|
34
|
+
padding: {
|
35
|
+
description: 'Info card padding (can overwrite preset styles)',
|
36
|
+
},
|
37
|
+
borderColor: {
|
38
|
+
description: 'Info card border color (can overwrite preset styles)',
|
39
|
+
control: {
|
40
|
+
type: 'color',
|
41
|
+
presetColors: [
|
42
|
+
theme.colors.grey3,
|
43
|
+
theme.colors.grey4,
|
44
|
+
theme.colors.red,
|
45
|
+
],
|
46
|
+
},
|
47
|
+
},
|
48
|
+
borderStyle: {
|
49
|
+
description: 'Info card border style (can overwrite preset styles)',
|
50
|
+
control: 'select',
|
51
|
+
options: ['dashed', 'dotted', 'inset', 'dashed solid', 'none'],
|
52
|
+
},
|
53
|
+
|
54
|
+
// info card content slot
|
55
|
+
default: {
|
56
|
+
description: 'Info card slot content',
|
57
|
+
},
|
58
|
+
},
|
59
|
+
}
|
60
|
+
|
61
|
+
// To use:
|
62
|
+
// <InfoCard
|
63
|
+
// type="warning"
|
64
|
+
// min-width="auto'
|
65
|
+
// color="red"
|
66
|
+
// align-items="center"
|
67
|
+
// padding="100px"
|
68
|
+
// border-color="red"
|
69
|
+
// border-style="solid"
|
70
|
+
// >
|
71
|
+
// Some Text
|
72
|
+
// </InfoCard>
|
73
|
+
// all props after "min-width" are used to overwrite the preset styles set by "type"
|
74
|
+
|
75
|
+
const Template = (args) => {
|
76
|
+
return {
|
77
|
+
components: { InfoCard },
|
78
|
+
setup() {
|
79
|
+
return { args }
|
80
|
+
},
|
81
|
+
template: `
|
82
|
+
<InfoCard v-bind="args">
|
83
|
+
{{ args.default }}
|
84
|
+
</InfoCard>
|
85
|
+
`,
|
86
|
+
}
|
87
|
+
}
|
88
|
+
|
89
|
+
export const Default = Template.bind({})
|
90
|
+
Default.args = {
|
91
|
+
...defaultInfoCardProps,
|
92
|
+
}
|
93
|
+
|
94
|
+
export const InfoCardTypeWarning = Template.bind({})
|
95
|
+
InfoCardTypeWarning.args = {
|
96
|
+
...defaultInfoCardProps,
|
97
|
+
type: 'warning',
|
98
|
+
}
|
99
|
+
|
100
|
+
export const InfoCardTypeInfoMinWidth = Template.bind({})
|
101
|
+
InfoCardTypeInfoMinWidth.args = {
|
102
|
+
...defaultInfoCardProps,
|
103
|
+
|
104
|
+
minWidth: '250px',
|
105
|
+
}
|
106
|
+
|
107
|
+
export const InfoCardTypeInfoColorOverwritten = Template.bind({})
|
108
|
+
InfoCardTypeInfoColorOverwritten.args = {
|
109
|
+
...defaultInfoCardProps,
|
110
|
+
|
111
|
+
color: theme.colors.red,
|
112
|
+
}
|
113
|
+
|
114
|
+
export const InfoCardTypeWarningAlignItemsOverwritten = Template.bind({})
|
115
|
+
InfoCardTypeWarningAlignItemsOverwritten.args = {
|
116
|
+
...defaultInfoCardProps,
|
117
|
+
type: 'warning',
|
118
|
+
default:
|
119
|
+
'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.',
|
120
|
+
|
121
|
+
alignItems: 'center',
|
122
|
+
}
|
123
|
+
|
124
|
+
export const InfoCardTypeWarningPaddingOverwritten = Template.bind({})
|
125
|
+
InfoCardTypeWarningPaddingOverwritten.args = {
|
126
|
+
...defaultInfoCardProps,
|
127
|
+
type: 'warning',
|
128
|
+
|
129
|
+
padding: '50px',
|
130
|
+
}
|
131
|
+
|
132
|
+
export const InfoCardTypeInfoBorderColorOverwritten = Template.bind({})
|
133
|
+
InfoCardTypeInfoBorderColorOverwritten.args = {
|
134
|
+
...defaultInfoCardProps,
|
135
|
+
|
136
|
+
borderColor: theme.colors.red,
|
137
|
+
}
|
138
|
+
|
139
|
+
export const InfoCardTypeInfoBorderStyleOverwritten = Template.bind({})
|
140
|
+
InfoCardTypeInfoBorderStyleOverwritten.args = {
|
141
|
+
...defaultInfoCardProps,
|
142
|
+
|
143
|
+
borderStyle: 'solid none',
|
144
|
+
}
|
@@ -0,0 +1,7 @@
|
|
1
|
+
const defaultInfoCardProps = {
|
2
|
+
// info card content slot
|
3
|
+
default:
|
4
|
+
'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.',
|
5
|
+
}
|
6
|
+
|
7
|
+
export default defaultInfoCardProps
|
@@ -1,11 +1,21 @@
|
|
1
1
|
<template>
|
2
2
|
<InfoContainer
|
3
|
-
|
3
|
+
:align-items="alignItems"
|
4
4
|
:border-color="borderColor"
|
5
|
-
:
|
5
|
+
:border-style="borderStyle"
|
6
|
+
:color="color"
|
7
|
+
data-test-id="info_card_wrapper"
|
8
|
+
:min-width="minWidth"
|
9
|
+
:padding="padding"
|
10
|
+
:preset-styles="presetStyles"
|
6
11
|
>
|
7
|
-
<RCIcon
|
8
|
-
|
12
|
+
<RCIcon
|
13
|
+
:color="color ? color : presetStyles.iconColor"
|
14
|
+
data-test-id="info_card_icon"
|
15
|
+
name="info"
|
16
|
+
size="24px"
|
17
|
+
/>
|
18
|
+
<TextContainer data-test-id="info_card_text_container">
|
9
19
|
<slot></slot>
|
10
20
|
</TextContainer>
|
11
21
|
</InfoContainer>
|
@@ -13,26 +23,37 @@
|
|
13
23
|
|
14
24
|
<script>
|
15
25
|
import styled from 'vue3-styled-components'
|
26
|
+
import theme from '../../assets/theme.js'
|
16
27
|
import RCIcon from '../icon'
|
17
|
-
|
18
|
-
|
19
|
-
|
28
|
+
|
29
|
+
const infoContainerAttrs = {
|
30
|
+
minWidth: String,
|
31
|
+
color: String,
|
32
|
+
alignItems: String,
|
33
|
+
padding: String,
|
20
34
|
borderColor: String,
|
35
|
+
borderStyle: String,
|
36
|
+
presetStyles: Object,
|
21
37
|
}
|
22
|
-
const InfoContainer = styled('div',
|
38
|
+
const InfoContainer = styled('div', infoContainerAttrs)`
|
23
39
|
display: flex;
|
40
|
+
align-items: ${(props) =>
|
41
|
+
props.alignItems ? props.alignItems : props.presetStyles.alignItems};
|
24
42
|
gap: 15px;
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
? props.theme.colors[props.borderColor]
|
30
|
-
: props.borderColor};
|
31
|
-
background-color: ${(props) =>
|
32
|
-
props.theme.colors[props.backgroundColor]
|
33
|
-
? props.theme.colors[props.backgroundColor]
|
34
|
-
: props.backgroundColor};
|
43
|
+
min-width: ${(props) => props.minWidth};
|
44
|
+
padding: ${(props) =>
|
45
|
+
props.padding ? props.padding : props.presetStyles.padding};
|
46
|
+
color: ${(props) => (props.color ? props.color : props.presetStyles.color)};
|
35
47
|
border-radius: 4px;
|
48
|
+
background-color: ${(props) =>
|
49
|
+
props.backgroundColor
|
50
|
+
? props.backgroundColor
|
51
|
+
: props.presetStyles.backgroundColor};
|
52
|
+
border-width: ${(props) => props.presetStyles.borderWidth};
|
53
|
+
border-style: ${(props) =>
|
54
|
+
props.borderStyle ? props.borderStyle : props.presetStyles.borderStyle};
|
55
|
+
border-color: ${(props) =>
|
56
|
+
props.borderColor ? props.borderColor : props.presetStyles.borderColor};
|
36
57
|
`
|
37
58
|
|
38
59
|
const TextContainer = styled.div`
|
@@ -48,19 +69,71 @@
|
|
48
69
|
TextContainer,
|
49
70
|
},
|
50
71
|
props: {
|
72
|
+
type: {
|
73
|
+
required: false,
|
74
|
+
type: String,
|
75
|
+
default: 'info',
|
76
|
+
},
|
77
|
+
minWidth: {
|
78
|
+
required: false,
|
79
|
+
type: String,
|
80
|
+
default: '',
|
81
|
+
},
|
51
82
|
color: {
|
52
83
|
required: false,
|
84
|
+
type: String,
|
85
|
+
default: '',
|
53
86
|
},
|
54
|
-
|
87
|
+
alignItems: {
|
55
88
|
required: false,
|
89
|
+
type: String,
|
90
|
+
default: '',
|
56
91
|
},
|
57
|
-
|
92
|
+
padding: {
|
58
93
|
required: false,
|
59
|
-
|
94
|
+
type: String,
|
95
|
+
default: '',
|
60
96
|
},
|
61
97
|
borderColor: {
|
62
98
|
required: false,
|
63
|
-
|
99
|
+
type: String,
|
100
|
+
default: '',
|
101
|
+
},
|
102
|
+
borderStyle: {
|
103
|
+
required: false,
|
104
|
+
type: String,
|
105
|
+
default: '',
|
106
|
+
},
|
107
|
+
},
|
108
|
+
computed: {
|
109
|
+
isInfo() {
|
110
|
+
// this property is used for tests
|
111
|
+
return this.type === 'info'
|
112
|
+
},
|
113
|
+
isWarning() {
|
114
|
+
return this.type === 'warning'
|
115
|
+
},
|
116
|
+
presetStyles() {
|
117
|
+
// the types that doesn't have explicit border anyway have it transparent
|
118
|
+
// to avoid flickering in case the same info card would switch the types
|
119
|
+
let stylesCollection = {
|
120
|
+
alignItems: 'flex-start',
|
121
|
+
padding: '20px',
|
122
|
+
borderWidth: '1px',
|
123
|
+
borderStyle: 'solid',
|
124
|
+
borderColor: 'transparent',
|
125
|
+
}
|
126
|
+
|
127
|
+
if (this.isWarning) {
|
128
|
+
stylesCollection.color = theme.colors.white
|
129
|
+
stylesCollection.backgroundColor = theme.colors.yellow
|
130
|
+
stylesCollection.iconColor = theme.colors.white
|
131
|
+
} else {
|
132
|
+
stylesCollection.borderStyle = 'dashed'
|
133
|
+
stylesCollection.borderColor = theme.colors.grey4
|
134
|
+
}
|
135
|
+
|
136
|
+
return stylesCollection
|
64
137
|
},
|
65
138
|
},
|
66
139
|
}
|
@@ -0,0 +1,56 @@
|
|
1
|
+
import { mount } from '@vue/test-utils'
|
2
|
+
import RCInfoCard from '@/components/infoCard'
|
3
|
+
import RCIcon from '@/components/icon'
|
4
|
+
import defaultInfoCardProps from './defaultProps'
|
5
|
+
import theme from '@/assets/theme'
|
6
|
+
|
7
|
+
jest.mock('@/components/icon/iconCache.mjs', () => ({
|
8
|
+
// need to mock this due to how jest handles import.meta
|
9
|
+
fetchIcon: jest.fn(() => Promise.resolve('mocked-icon-url.svg')),
|
10
|
+
}))
|
11
|
+
|
12
|
+
describe('RCInfoCard.vue', () => {
|
13
|
+
it('info card is rendered with icon and correct text', async () => {
|
14
|
+
const wrapper = mount(RCInfoCard, {
|
15
|
+
props: { ...defaultInfoCardProps },
|
16
|
+
slots: {
|
17
|
+
default: defaultInfoCardProps.default,
|
18
|
+
},
|
19
|
+
global: {
|
20
|
+
provide: {
|
21
|
+
theme,
|
22
|
+
},
|
23
|
+
},
|
24
|
+
})
|
25
|
+
|
26
|
+
const iconComponent = wrapper.findComponent(RCIcon)
|
27
|
+
const infoCardText = wrapper.find(
|
28
|
+
'[data-test-id="info_card_text_container"]'
|
29
|
+
)
|
30
|
+
|
31
|
+
expect(iconComponent.exists()).toBe(true)
|
32
|
+
expect(infoCardText.exists()).toBe(true)
|
33
|
+
expect(infoCardText.text()).toContain(defaultInfoCardProps.default)
|
34
|
+
}),
|
35
|
+
it('info card rendered with type info have correct computed values', async () => {
|
36
|
+
const wrapper = mount(RCInfoCard, {
|
37
|
+
props: { ...defaultInfoCardProps },
|
38
|
+
slots: {
|
39
|
+
default: defaultInfoCardProps.default,
|
40
|
+
},
|
41
|
+
global: {
|
42
|
+
provide: {
|
43
|
+
theme,
|
44
|
+
},
|
45
|
+
},
|
46
|
+
})
|
47
|
+
|
48
|
+
expect(wrapper.vm.isInfo).toBe(true)
|
49
|
+
expect(wrapper.vm.isWarning).toBe(false)
|
50
|
+
|
51
|
+
await wrapper.setProps({ type: 'warning' })
|
52
|
+
|
53
|
+
expect(wrapper.vm.isInfo).toBe(false)
|
54
|
+
expect(wrapper.vm.isWarning).toBe(true)
|
55
|
+
})
|
56
|
+
})
|
@@ -1,50 +1,30 @@
|
|
1
1
|
<template>
|
2
2
|
<ComponentWrapper>
|
3
|
-
<IconWrapper :size="
|
3
|
+
<IconWrapper :size="size">
|
4
4
|
<IconImg
|
5
|
-
ref="iconImg"
|
6
5
|
data-test-id="infoText_trigger"
|
7
6
|
@click.prevent="toggleShowInfo()"
|
8
7
|
@mouseenter="openTrigger == 'onHover' ? toggleShowInfo() : ''"
|
9
8
|
@mouseleave="openTrigger == 'onHover' ? toggleShowInfo() : ''"
|
10
9
|
>
|
11
|
-
<Dot v-if="type === 'dot'" :color="dotColor" />
|
12
10
|
<IconComponent
|
13
|
-
v-else
|
14
11
|
:color="iconColor"
|
15
12
|
cursor="pointer"
|
16
13
|
name="info"
|
17
14
|
:size="size"
|
18
15
|
/>
|
19
16
|
</IconImg>
|
20
|
-
<
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
</TextOverlay>
|
32
|
-
</template>
|
33
|
-
<Teleport v-else to="#portal-target">
|
34
|
-
<TextOverlay
|
35
|
-
v-if="showInfo"
|
36
|
-
:align-arrow="alignArrow"
|
37
|
-
:half-computed-text-info-width="halfComputedTextInfoWidth"
|
38
|
-
:icon-size="size"
|
39
|
-
:info-position="infoPosition"
|
40
|
-
:max-width="maxWidth"
|
41
|
-
:width="width"
|
42
|
-
:top="position.top"
|
43
|
-
:left="position.left"
|
44
|
-
><slot></slot>
|
45
|
-
<span v-html="text"></span>
|
46
|
-
</TextOverlay>
|
47
|
-
</Teleport>
|
17
|
+
<TextOverlay
|
18
|
+
v-if="showInfo"
|
19
|
+
:align-arrow="alignArrow"
|
20
|
+
:half-computed-text-info-width="halfComputedTextInfoWidth"
|
21
|
+
:icon-size="size"
|
22
|
+
:info-position="infoPosition"
|
23
|
+
:max-width="maxWidth"
|
24
|
+
:width="width"
|
25
|
+
><slot></slot>
|
26
|
+
<span v-if="text.length > 0" v-html="text"></span>
|
27
|
+
</TextOverlay>
|
48
28
|
</IconWrapper>
|
49
29
|
</ComponentWrapper>
|
50
30
|
</template>
|
@@ -57,39 +37,29 @@
|
|
57
37
|
// size="20px"
|
58
38
|
// alignArrow="right" // which side the arrow should be on
|
59
39
|
// />
|
60
|
-
import { Teleport } from 'vue'
|
61
40
|
import theme from '../../assets/theme.js'
|
62
41
|
import styled from 'vue3-styled-components'
|
63
42
|
import IconComponent from '../icon'
|
64
|
-
import {
|
65
|
-
TEXT_OVERLAY_ARROW_LEFT_OFFSET,
|
66
|
-
TEXT_OVERLAY_ARROW_RIGHT_NEGATIVE_OFFSET,
|
67
|
-
TEXT_OVERLAY_TOP_OFFSET,
|
68
|
-
} from './constants.js'
|
69
43
|
|
70
44
|
const textAttrs = {
|
71
45
|
iconSize: String,
|
72
46
|
alignArrow: String,
|
73
47
|
width: String,
|
74
48
|
halfComputedTextInfoWidth: Number,
|
75
|
-
top: String,
|
76
|
-
left: String,
|
77
49
|
infoPosition: String,
|
78
50
|
}
|
79
51
|
const TextOverlay = styled('div', textAttrs)`
|
80
52
|
position: absolute;
|
81
|
-
${(props) => (props.infoPosition === 'top' ? 'bottom' : 'top')} : ${(
|
82
|
-
props
|
83
|
-
) => (props.top ? props.top : 'calc(' + props.iconSize + ' + 5px)')};
|
84
53
|
${(props) =>
|
85
|
-
props.
|
86
|
-
? '
|
87
|
-
: props.
|
54
|
+
props.infoPosition == 'top'
|
55
|
+
? 'bottom : calc(' + props.iconSize + ' + 15px)'
|
56
|
+
: 'top : calc(' + props.iconSize + ' + 15px)'};
|
57
|
+
${(props) =>
|
58
|
+
props.alignArrow === 'left'
|
88
59
|
? 'left: calc(' + props.iconSize + ' /2 - 18px)'
|
89
60
|
: props.alignArrow === 'center'
|
90
61
|
? 'left: calc((-' + props.width + ' + ' + props.iconSize + ') /2 + 2px)'
|
91
62
|
: 'right: calc(' + props.iconSize + ' /2 - 17px)'};
|
92
|
-
|
93
63
|
text-align: left;
|
94
64
|
background: ${(props) => props.theme.colors.black};
|
95
65
|
padding: 10px;
|
@@ -133,14 +103,6 @@
|
|
133
103
|
height: ${(props) => props.size};
|
134
104
|
`
|
135
105
|
|
136
|
-
const Dot = styled('div')`
|
137
|
-
width: 5px;
|
138
|
-
height: 5px;
|
139
|
-
background-color: ${(props) => props.color};
|
140
|
-
border-radius: 50%;
|
141
|
-
display: inline-block;
|
142
|
-
`
|
143
|
-
|
144
106
|
const IconImg = styled.div`
|
145
107
|
line-height: 0;
|
146
108
|
`
|
@@ -152,22 +114,19 @@
|
|
152
114
|
export default {
|
153
115
|
name: 'InfoText',
|
154
116
|
components: {
|
155
|
-
Dot,
|
156
117
|
IconWrapper,
|
157
118
|
TextOverlay,
|
158
119
|
ComponentWrapper,
|
159
120
|
IconImg,
|
160
121
|
IconComponent,
|
161
|
-
Teleport,
|
162
122
|
},
|
163
123
|
props: {
|
164
124
|
text: {
|
165
|
-
type: String,
|
166
125
|
required: false,
|
167
126
|
default: '',
|
127
|
+
type: String,
|
168
128
|
},
|
169
129
|
size: {
|
170
|
-
type: String,
|
171
130
|
required: false,
|
172
131
|
default: '14px',
|
173
132
|
type: String,
|
@@ -178,19 +137,16 @@
|
|
178
137
|
type: String,
|
179
138
|
},
|
180
139
|
alignArrow: {
|
181
|
-
type: String,
|
182
140
|
required: false,
|
183
141
|
default: 'center',
|
184
142
|
type: String,
|
185
143
|
},
|
186
144
|
openTrigger: {
|
187
|
-
type: String,
|
188
145
|
required: false,
|
189
146
|
default: 'onHover', // onHover, onClick
|
190
147
|
type: String,
|
191
148
|
},
|
192
149
|
width: {
|
193
|
-
type: String,
|
194
150
|
required: false,
|
195
151
|
default: '165px',
|
196
152
|
type: String,
|
@@ -199,28 +155,10 @@
|
|
199
155
|
default: '400px',
|
200
156
|
type: String,
|
201
157
|
},
|
202
|
-
shouldUseTeleport: {
|
203
|
-
type: Boolean,
|
204
|
-
default: false,
|
205
|
-
},
|
206
|
-
dotColor: {
|
207
|
-
type: String,
|
208
|
-
required: false,
|
209
|
-
default: theme.colors.blue2,
|
210
|
-
},
|
211
|
-
type: {
|
212
|
-
type: String,
|
213
|
-
required: false,
|
214
|
-
default: 'info', // info, dot
|
215
|
-
},
|
216
158
|
},
|
217
159
|
data() {
|
218
160
|
return {
|
219
161
|
showInfo: false,
|
220
|
-
position: {
|
221
|
-
top: null,
|
222
|
-
left: null,
|
223
|
-
},
|
224
162
|
}
|
225
163
|
},
|
226
164
|
computed: {
|
@@ -240,10 +178,6 @@
|
|
240
178
|
} else {
|
241
179
|
document.removeEventListener('click', this.clickOutside)
|
242
180
|
}
|
243
|
-
|
244
|
-
if (this.shouldUseTeleport && this.showInfo) {
|
245
|
-
this.getTeleportPosition()
|
246
|
-
}
|
247
181
|
},
|
248
182
|
clickOutside(event) {
|
249
183
|
if (this.$el.contains(event.target)) {
|
@@ -251,35 +185,6 @@
|
|
251
185
|
}
|
252
186
|
this.toggleShowInfo()
|
253
187
|
},
|
254
|
-
getTextOverlayTop() {
|
255
|
-
const iconImg = this.$refs.iconImg.$el
|
256
|
-
const iconImgTop = iconImg.getBoundingClientRect().top
|
257
|
-
const iconImgHeight = iconImg.clientHeight
|
258
|
-
const textOverlayTop =
|
259
|
-
iconImgTop - iconImgHeight / 2 + TEXT_OVERLAY_TOP_OFFSET
|
260
|
-
|
261
|
-
console.log(textOverlayTop)
|
262
|
-
|
263
|
-
return `${textOverlayTop}px`
|
264
|
-
},
|
265
|
-
getTextOverlayLeft() {
|
266
|
-
const iconImg = this.$refs.iconImg.$el
|
267
|
-
const iconImgLeft = iconImg.getBoundingClientRect().left
|
268
|
-
const iconImgWidth = iconImg.clientWidth
|
269
|
-
const textOverlayLeft = iconImgLeft + iconImgWidth / 2 - 100 + 3
|
270
|
-
|
271
|
-
if (this.alignArrow === 'center') {
|
272
|
-
return `${textOverlayLeft}px`
|
273
|
-
} else if (this.alignArrow === 'left') {
|
274
|
-
return `${textOverlayLeft + TEXT_OVERLAY_ARROW_LEFT_OFFSET}px`
|
275
|
-
}
|
276
|
-
|
277
|
-
return `${textOverlayLeft - TEXT_OVERLAY_ARROW_RIGHT_NEGATIVE_OFFSET}px`
|
278
|
-
},
|
279
|
-
getTeleportPosition() {
|
280
|
-
this.position.top = this.getTextOverlayTop()
|
281
|
-
this.position.left = this.getTextOverlayLeft()
|
282
|
-
},
|
283
188
|
},
|
284
189
|
}
|
285
190
|
</script>
|
@@ -86,6 +86,7 @@
|
|
86
86
|
/>
|
87
87
|
<Selector
|
88
88
|
v-else
|
89
|
+
:disabled="disabled"
|
89
90
|
:padding-left="paddingLeft"
|
90
91
|
:select-width="selectWidth"
|
91
92
|
:show-border="showBorder"
|
@@ -96,7 +97,9 @@
|
|
96
97
|
<Icon
|
97
98
|
v-if="isDropdownOpen"
|
98
99
|
:color="
|
99
|
-
caretColor ||
|
100
|
+
caretColor || disabled
|
101
|
+
? 'grey2'
|
102
|
+
: colorMode == 'dark'
|
100
103
|
? 'white'
|
101
104
|
: 'transparentBlack1'
|
102
105
|
"
|
@@ -106,7 +109,9 @@
|
|
106
109
|
<Icon
|
107
110
|
v-else
|
108
111
|
:color="
|
109
|
-
caretColor ||
|
112
|
+
caretColor || disabled
|
113
|
+
? 'grey2'
|
114
|
+
: colorMode == 'dark'
|
110
115
|
? 'white'
|
111
116
|
: 'transparentBlack1'
|
112
117
|
"
|
@@ -199,11 +204,13 @@
|
|
199
204
|
`
|
200
205
|
|
201
206
|
const selectorProps = {
|
207
|
+
disabled: String,
|
202
208
|
selectWidth: String,
|
203
209
|
paddingLeft: String,
|
204
210
|
showBorder: Boolean,
|
205
211
|
}
|
206
212
|
const Selector = styled('div', selectorProps)`
|
213
|
+
color: ${(props) => (props.disabled ? props.theme.colors.grey2 : '')};
|
207
214
|
${(props) =>
|
208
215
|
props.selectWidth === '100%'
|
209
216
|
? 'width: 100%;'
|
@@ -5,7 +5,7 @@
|
|
5
5
|
:is-open="isOpen"
|
6
6
|
:position="position"
|
7
7
|
>
|
8
|
-
<ModalContainer @click="onClickModalContainer">
|
8
|
+
<ModalContainer :overflow="overflowRule" @click="onClickModalContainer">
|
9
9
|
<Spinner v-if="isLoading" :limited-to-modal="true" size="50px" />
|
10
10
|
<ContentContainer :visible="!isLoading">
|
11
11
|
<slot></slot>
|
@@ -67,7 +67,8 @@
|
|
67
67
|
}
|
68
68
|
`
|
69
69
|
|
70
|
-
const
|
70
|
+
const modalContainerAttrs = { overflow: String }
|
71
|
+
const ModalContainer = styled('div', modalContainerAttrs)`
|
71
72
|
align-self: center;
|
72
73
|
justify-self: center;
|
73
74
|
position: relative;
|
@@ -75,7 +76,7 @@
|
|
75
76
|
border-radius: 4px;
|
76
77
|
background: white;
|
77
78
|
margin: 0 auto;
|
78
|
-
overflow:
|
79
|
+
overflow: ${(props) => props.overflow};
|
79
80
|
max-width: 95%;
|
80
81
|
max-height: 95%;
|
81
82
|
min-width: 100px;
|
@@ -152,6 +153,11 @@
|
|
152
153
|
type: Boolean,
|
153
154
|
default: true,
|
154
155
|
},
|
156
|
+
overflowRule: {
|
157
|
+
required: false,
|
158
|
+
type: String,
|
159
|
+
default: 'auto',
|
160
|
+
},
|
155
161
|
},
|
156
162
|
watch: {
|
157
163
|
isOpen: {
|