@eturnity/eturnity_reusable_components 7.18.0--EPDM-9013.1 → 7.18.0-EPDM-10335.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/.storybook/preview.js +1 -1
- package/package.json +19 -23
- package/src/App.vue +2 -2
- package/src/components/addNewButton/index.vue +5 -3
- package/src/components/buttons/buttonIcon/index.vue +1 -1
- package/src/components/buttons/closeButton/index.vue +1 -1
- package/src/components/buttons/mainButton/index.vue +6 -1
- package/src/components/deleteIcon/DeleteIcon.stories.js +7 -7
- package/src/components/deleteIcon/index.vue +25 -21
- package/src/components/draggableInputHandle/index.vue +24 -25
- package/src/components/dropdown/index.vue +129 -110
- package/src/components/errorMessage/index.vue +10 -5
- package/src/components/filter/filterSettings.vue +58 -97
- package/src/components/filter/index.vue +3 -3
- package/src/components/filter/parentDropdown.vue +2 -2
- package/src/components/icon/iconCache.js +23 -0
- package/src/components/icon/iconCollection.vue +2 -2
- package/src/components/icon/index.vue +67 -75
- package/src/components/iconWrapper/index.vue +1 -4
- package/src/components/infoCard/index.vue +2 -3
- package/src/components/infoText/index.vue +1 -1
- package/src/components/inputs/checkbox/index.vue +21 -6
- package/src/components/inputs/inputNumber/index.vue +8 -11
- package/src/components/inputs/inputNumberQuestion/index.vue +1 -1
- package/src/components/inputs/inputText/index.vue +3 -3
- package/src/components/inputs/radioButton/index.vue +1 -1
- package/src/components/inputs/searchInput/index.vue +28 -11
- package/src/components/inputs/select/index.vue +199 -55
- package/src/components/inputs/select/option/index.vue +36 -11
- package/src/components/inputs/slider/index.vue +16 -16
- package/src/components/inputs/switchField/index.vue +2 -2
- package/src/components/inputs/textAreaInput/index.vue +1 -1
- package/src/components/inputs/toggle/index.vue +2 -2
- package/src/components/label/index.vue +27 -31
- package/src/components/modals/modal/index.vue +2 -6
- package/src/components/navigationTabs/index.vue +27 -20
- package/src/components/pageSubtitle/index.vue +1 -1
- package/src/components/pageTitle/index.vue +4 -4
- package/src/components/pagination/index.vue +1 -1
- package/src/components/progressBar/index.vue +1 -1
- package/src/components/projectMarker/index.vue +16 -9
- package/src/components/sideMenu/index.vue +1 -1
- package/src/components/spinner/index.vue +7 -11
- package/src/components/tableDropdown/index.vue +30 -37
- package/src/components/tables/mainTable/exampleNested.vue +1 -1
- package/src/components/tables/mainTable/index.vue +10 -9
- package/src/components/tables/viewTable/index.vue +2 -2
- package/src/components/threeDots/index.vue +1 -1
- package/src/components/videoThumbnail/index.vue +95 -100
- package/src/main.js +4 -11
- package/src/assets/svgIcons/bexio.svg +0 -4
- package/src/assets/svgIcons/data_transfer.svg +0 -3
@@ -47,7 +47,6 @@
|
|
47
47
|
:fontSize="fontSize"
|
48
48
|
:fontColor="fontColor"
|
49
49
|
:backgroundColor="backgroundColor"
|
50
|
-
v-on="$listeners"
|
51
50
|
:hasSlot="hasSlot"
|
52
51
|
:hasLabelSlot="hasLabelSlot"
|
53
52
|
:slotSize="slotSize"
|
@@ -101,7 +100,7 @@
|
|
101
100
|
// >
|
102
101
|
//<template name=label><img>....</template>
|
103
102
|
//</inputNumber>
|
104
|
-
import styled from '
|
103
|
+
import styled from 'vue3-styled-components'
|
105
104
|
import {
|
106
105
|
stringToNumber,
|
107
106
|
numberToString
|
@@ -469,7 +468,7 @@ export default {
|
|
469
468
|
}
|
470
469
|
},
|
471
470
|
methods: {
|
472
|
-
onEnterPress(){
|
471
|
+
onEnterPress() {
|
473
472
|
this.$emit('on-enter-click')
|
474
473
|
this.$refs.inputField1.$el.blur()
|
475
474
|
},
|
@@ -488,9 +487,10 @@ export default {
|
|
488
487
|
// Need to return an integer rather than a string
|
489
488
|
this.$emit('input-change', event)
|
490
489
|
},
|
491
|
-
onEvaluateCode(
|
490
|
+
onEvaluateCode(event) {
|
492
491
|
// function to perform math on the code
|
493
492
|
// filter the string in case of any malicious content
|
493
|
+
const val = event.target.value
|
494
494
|
let filtered = val.replace('(auto)', '').replace(/[^-()\d/*+.,]/g, '')
|
495
495
|
filtered = filtered.split(/([-+*/()])/)
|
496
496
|
let formatted = filtered.map((item) => {
|
@@ -548,20 +548,17 @@ export default {
|
|
548
548
|
}
|
549
549
|
return array
|
550
550
|
},
|
551
|
-
onInput(
|
552
|
-
// if(!this.isFocused){
|
553
|
-
// return
|
554
|
-
// }
|
551
|
+
onInput(event) {
|
555
552
|
if (this.isBlurred) {
|
556
553
|
this.isBlurred = false
|
557
554
|
return
|
558
555
|
}
|
559
|
-
if (value === '') {
|
556
|
+
if (event.target.value === '') {
|
560
557
|
this.$emit('on-input', '')
|
561
558
|
}
|
562
559
|
let evaluatedVal
|
563
560
|
try {
|
564
|
-
evaluatedVal = this.onEvaluateCode(
|
561
|
+
evaluatedVal = this.onEvaluateCode(event)
|
565
562
|
} finally {
|
566
563
|
if (evaluatedVal) {
|
567
564
|
this.$emit('on-input', evaluatedVal)
|
@@ -573,7 +570,7 @@ export default {
|
|
573
570
|
// setting isBlurred so we don't trigger onInput as well
|
574
571
|
this.isBlurred = true
|
575
572
|
let value = e.target.value
|
576
|
-
let evaluatedInput = this.onEvaluateCode(
|
573
|
+
let evaluatedInput = this.onEvaluateCode(e)
|
577
574
|
this.onChangeHandler(evaluatedInput ? evaluatedInput : value)
|
578
575
|
if ((evaluatedInput && value.length) || this.minNumber !== null) {
|
579
576
|
this.textInput = numberToString({
|
@@ -66,7 +66,7 @@
|
|
66
66
|
</template>
|
67
67
|
|
68
68
|
<script>
|
69
|
-
import styled from '
|
69
|
+
import styled from 'vue3-styled-components'
|
70
70
|
import InfoText from '../../infoText'
|
71
71
|
import Icon from '../../icon'
|
72
72
|
import ErrorMessage from '../../errorMessage'
|
@@ -332,8 +332,8 @@ export default {
|
|
332
332
|
this.$emit('on-enter-click')
|
333
333
|
this.$refs.inputElement.$el.blur()
|
334
334
|
},
|
335
|
-
onChangeHandler(
|
336
|
-
this.$emit('input-change',
|
335
|
+
onChangeHandler(event) {
|
336
|
+
this.$emit('input-change', event.target.value)
|
337
337
|
},
|
338
338
|
onInputBlur($event) {
|
339
339
|
this.$emit('input-blur', $event.target.value)
|
@@ -1,6 +1,7 @@
|
|
1
1
|
<template>
|
2
2
|
<container :inputWidth="inputWidth">
|
3
|
-
<input-wrapper>
|
3
|
+
<input-wrapper :iconPosition="iconPosition" :iconColor="iconColor">
|
4
|
+
<SearchIconSvg class="search-icn" />
|
4
5
|
<input-container
|
5
6
|
ref="inputElement"
|
6
7
|
:placeholder="placeholder"
|
@@ -13,10 +14,6 @@
|
|
13
14
|
:hasFocus="hasFocus"
|
14
15
|
:data-id="dataId"
|
15
16
|
/>
|
16
|
-
<img
|
17
|
-
class="search-icn"
|
18
|
-
:src="require('../../../assets/icons/search_icon_black.svg')"
|
19
|
-
/>
|
20
17
|
</input-wrapper>
|
21
18
|
</container>
|
22
19
|
</template>
|
@@ -32,8 +29,11 @@
|
|
32
29
|
// @on-change="function($event)"
|
33
30
|
// :isFilter="true" // to set the height at 30px
|
34
31
|
// data-id="test-data-id"
|
32
|
+
// iconPosition="left"
|
33
|
+
// iconColor="grey2"
|
35
34
|
// />
|
36
|
-
import styled from '
|
35
|
+
import styled from 'vue3-styled-components'
|
36
|
+
import SearchIconSvg from '../../../assets/icons/search_icon_black.svg'
|
37
37
|
|
38
38
|
const inputAttrs = {
|
39
39
|
isDisabled: Boolean,
|
@@ -68,11 +68,18 @@ const InputContainer = styled('input', inputAttrs)`
|
|
68
68
|
const InputWrapper = styled.span`
|
69
69
|
position: relative;
|
70
70
|
|
71
|
-
|
71
|
+
svg {
|
72
72
|
position: absolute;
|
73
|
-
right: 10px;
|
74
|
-
top: 50%;
|
75
73
|
transform: translateY(-50%);
|
74
|
+
top: 50%;
|
75
|
+
${(props) => (props.iconPosition === 'right' ? 'right' : 'left')}: 10px;
|
76
|
+
|
77
|
+
path {
|
78
|
+
fill: ${(props) =>
|
79
|
+
props.theme.colors[props.iconColor]
|
80
|
+
? props.theme.colors[props.iconColor]
|
81
|
+
: props.iconColor};
|
82
|
+
}
|
76
83
|
}
|
77
84
|
`
|
78
85
|
|
@@ -81,7 +88,8 @@ export default {
|
|
81
88
|
components: {
|
82
89
|
InputContainer,
|
83
90
|
InputWrapper,
|
84
|
-
Container
|
91
|
+
Container,
|
92
|
+
SearchIconSvg
|
85
93
|
},
|
86
94
|
props: {
|
87
95
|
value: {
|
@@ -110,11 +118,20 @@ export default {
|
|
110
118
|
dataId: {
|
111
119
|
required: false,
|
112
120
|
default: ''
|
121
|
+
},
|
122
|
+
iconPosition: {
|
123
|
+
type: String,
|
124
|
+
default: 'right'
|
125
|
+
},
|
126
|
+
iconColor: {
|
127
|
+
type: String,
|
128
|
+
default: 'black'
|
113
129
|
}
|
114
130
|
},
|
131
|
+
emits: ['on-change'],
|
115
132
|
methods: {
|
116
133
|
onChangeHandler(event) {
|
117
|
-
this.$emit('on-change', event)
|
134
|
+
this.$emit('on-change', event.target.value)
|
118
135
|
},
|
119
136
|
focusInputElement() {
|
120
137
|
this.$nextTick(() => {
|
@@ -28,7 +28,9 @@
|
|
28
28
|
<select-button-wrapper :disabled="disabled">
|
29
29
|
<selectButton
|
30
30
|
ref="select"
|
31
|
+
class="select-button"
|
31
32
|
@click="toggleDropdown"
|
33
|
+
:selectWidth="selectWidth"
|
32
34
|
:selectHeight="selectHeight"
|
33
35
|
:height="height"
|
34
36
|
:selectMinHeight="selectMinHeight"
|
@@ -39,9 +41,9 @@
|
|
39
41
|
buttonFontColor || colorMode == 'dark' ? 'white' : 'black'
|
40
42
|
"
|
41
43
|
:hasError="hasError"
|
42
|
-
:
|
44
|
+
:hasNoPadding="isSearchBarVisible || !hasSelectButtonPadding"
|
43
45
|
:disabled="disabled"
|
44
|
-
@keydown
|
46
|
+
@keydown="onKeyDown"
|
45
47
|
:showBorder="showBorder"
|
46
48
|
:data-id="dataId"
|
47
49
|
:paddingLeft="paddingLeft"
|
@@ -64,7 +66,7 @@
|
|
64
66
|
:value="textSearch"
|
65
67
|
@keydown.stop="onKeyDown"
|
66
68
|
@input-change="searchChange"
|
67
|
-
@click.
|
69
|
+
@click.stop
|
68
70
|
/>
|
69
71
|
<selector
|
70
72
|
v-else
|
@@ -97,26 +99,33 @@
|
|
97
99
|
/>
|
98
100
|
</Caret>
|
99
101
|
</selectButton>
|
100
|
-
<DropdownWrapper>
|
101
|
-
<
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
102
|
+
<DropdownWrapper ref="dropdownWrapperRef">
|
103
|
+
<Teleport to="#portal-target">
|
104
|
+
<selectDropdown
|
105
|
+
ref="dropdown"
|
106
|
+
v-show="isSelectDropdownShown"
|
107
|
+
:dropdownPosition="dropdownPosition"
|
108
|
+
:hoveredIndex="hoveredIndex"
|
109
|
+
:hoveredValue="hoveredValue"
|
110
|
+
:isActive="isActive"
|
111
|
+
:optionWidth="getOptionWidth"
|
112
|
+
:hoveredBgColor="
|
113
|
+
colorMode == 'dark' ? '#000000' : dropdownBgColor
|
114
|
+
"
|
115
|
+
:bgColor="
|
116
|
+
dropdownBgColor || colorMode == 'dark' ? 'black' : 'white'
|
117
|
+
"
|
118
|
+
:fontColor="
|
119
|
+
dropdownFontColor || colorMode == 'dark' ? 'white' : 'black'
|
120
|
+
"
|
121
|
+
:fontSize="fontSize"
|
122
|
+
:selectedValue="selectedValue"
|
123
|
+
@option-selected="optionSelected"
|
124
|
+
@option-hovered="optionHovered"
|
125
|
+
>
|
126
|
+
<slot name="dropdown"></slot>
|
127
|
+
</selectDropdown>
|
128
|
+
</Teleport>
|
120
129
|
</DropdownWrapper>
|
121
130
|
</select-button-wrapper>
|
122
131
|
</input-wrapper>
|
@@ -131,8 +140,9 @@
|
|
131
140
|
// optionWidth="50%"
|
132
141
|
// label="that is a label"
|
133
142
|
// alignItems="vertical"
|
134
|
-
// label-data-id="test-
|
143
|
+
// label-data-id="test-label-data-id"
|
135
144
|
// data-id="test-data-id"
|
145
|
+
// :hasSelectButtonPadding="false"
|
136
146
|
// >
|
137
147
|
// <template #selector="{selectedValue}">
|
138
148
|
// value selected: {{selectedValue}}
|
@@ -145,7 +155,8 @@
|
|
145
155
|
// </template>
|
146
156
|
// </Select>
|
147
157
|
|
148
|
-
import
|
158
|
+
import { Teleport } from 'vue'
|
159
|
+
import styled from 'vue3-styled-components'
|
149
160
|
import InfoText from '../../infoText'
|
150
161
|
import icon from '../../icon'
|
151
162
|
import inputText from '../inputText'
|
@@ -161,7 +172,7 @@ const Caret = styled.div`
|
|
161
172
|
width: ${CARET_WIDTH};
|
162
173
|
min-width: ${CARET_WIDTH};
|
163
174
|
height: 100%;
|
164
|
-
align-items:
|
175
|
+
align-items: center;
|
165
176
|
cursor: pointer;
|
166
177
|
margin-left: auto;
|
167
178
|
`
|
@@ -172,7 +183,10 @@ const selectorProps = {
|
|
172
183
|
showBorder: Boolean
|
173
184
|
}
|
174
185
|
const Selector = styled('div', selectorProps)`
|
175
|
-
${(props) =>
|
186
|
+
${(props) =>
|
187
|
+
props.selectWidth === '100%'
|
188
|
+
? 'width: 100%;'
|
189
|
+
: `width: calc(${props.selectWidth} -
|
176
190
|
(
|
177
191
|
${CARET_WIDTH} +
|
178
192
|
${props.paddingLeft}
|
@@ -181,8 +195,7 @@ const Selector = styled('div', selectorProps)`
|
|
181
195
|
);
|
182
196
|
white-space: nowrap;
|
183
197
|
text-overflow: ellipsis;
|
184
|
-
overflow: hidden;`
|
185
|
-
}
|
198
|
+
overflow: hidden;`}
|
186
199
|
`
|
187
200
|
|
188
201
|
const labelAttrs = { fontSize: String, fontColor: String }
|
@@ -197,7 +210,10 @@ const InputLabel = styled('div', labelAttrs)`
|
|
197
210
|
const optionalLabel = styled.span`
|
198
211
|
font-weight: 300;
|
199
212
|
`
|
200
|
-
const inputProps = {
|
213
|
+
const inputProps = {
|
214
|
+
selectWidth: String,
|
215
|
+
optionWidth: String
|
216
|
+
}
|
201
217
|
const Container = styled('div', inputProps)`
|
202
218
|
width: ${(props) => props.selectWidth};
|
203
219
|
position: relative;
|
@@ -224,9 +240,10 @@ const selectButtonAttrs = {
|
|
224
240
|
hasError: Boolean,
|
225
241
|
disabled: Boolean,
|
226
242
|
selectHeight: String,
|
243
|
+
selectWidth: String,
|
227
244
|
height: String,
|
228
245
|
selectMinHeight: String,
|
229
|
-
|
246
|
+
hasNoPadding: Boolean,
|
230
247
|
showBorder: Boolean,
|
231
248
|
paddingLeft: String
|
232
249
|
}
|
@@ -234,8 +251,9 @@ const selectButton = styled('div', selectButtonAttrs)`
|
|
234
251
|
position: relative;
|
235
252
|
box-sizing: border-box;
|
236
253
|
border-radius: 4px;
|
254
|
+
max-width: ${(props) => (props.selectWidth ? props.selectWidth : '100%')};
|
237
255
|
${(props) =>
|
238
|
-
props.
|
256
|
+
props.hasNoPadding ? '' : `padding-left: ${props.paddingLeft}`};
|
239
257
|
text-align: left;
|
240
258
|
min-height: ${(props) =>
|
241
259
|
props.selectHeight
|
@@ -247,7 +265,7 @@ const selectButton = styled('div', selectButtonAttrs)`
|
|
247
265
|
: '36px'};
|
248
266
|
display: flex;
|
249
267
|
align-items: center;
|
250
|
-
|
268
|
+
height: ${(props) => props.selectHeight};
|
251
269
|
${({ showBorder, theme, hasError }) =>
|
252
270
|
showBorder &&
|
253
271
|
`
|
@@ -279,14 +297,17 @@ const selectDropdownAttrs = {
|
|
279
297
|
fontColor: String,
|
280
298
|
optionWidth: String,
|
281
299
|
hoveredIndex: Number,
|
300
|
+
fontSize: String,
|
301
|
+
dropdownPosition: Object,
|
282
302
|
hoveredValue: Number | String,
|
283
303
|
selectedValue: Number | String
|
284
304
|
}
|
285
305
|
const selectDropdown = styled('div', selectDropdownAttrs)`
|
286
306
|
box-sizing: border-box;
|
287
|
-
z-index: ${(props) => (props.isActive ? '2' : '
|
307
|
+
z-index: ${(props) => (props.isActive ? '2' : '99999')};
|
288
308
|
position: absolute;
|
289
|
-
top:
|
309
|
+
top: ${(props) => props.dropdownPosition?.top}px;
|
310
|
+
left: ${(props) => props.dropdownPosition?.left}px;
|
290
311
|
border: ${BORDER_WIDTH} solid ${(props) => props.theme.colors.grey4};
|
291
312
|
border-radius: 4px;
|
292
313
|
display: flex;
|
@@ -311,7 +332,9 @@ const selectDropdown = styled('div', selectDropdownAttrs)`
|
|
311
332
|
? props.theme.colors[props.hoveredBgColor]
|
312
333
|
: props.hoveredBgColor};
|
313
334
|
}
|
335
|
+
font-size: ${(props) => props.fontSize};
|
314
336
|
`
|
337
|
+
selectDropdown.emits = ['option-hovered', 'option-selected']
|
315
338
|
const DropdownWrapper = styled('div')`
|
316
339
|
position: relative;
|
317
340
|
`
|
@@ -324,6 +347,10 @@ const InputWrapper = styled('div', inputAttrs)`
|
|
324
347
|
grid-template-columns: ${(props) =>
|
325
348
|
props.alignItems === 'vertical' || !props.hasLabel ? '1fr' : 'auto 1fr'};
|
326
349
|
`
|
350
|
+
|
351
|
+
const DROPDOWN_HEIGHT_OFFSET = 4
|
352
|
+
const DROPDOWN_TOP_OFFSET = 21
|
353
|
+
|
327
354
|
export default {
|
328
355
|
name: 'RCselect',
|
329
356
|
|
@@ -435,6 +462,10 @@ export default {
|
|
435
462
|
type: String,
|
436
463
|
default: ''
|
437
464
|
},
|
465
|
+
hasSelectButtonPadding: {
|
466
|
+
type: Boolean,
|
467
|
+
default: true
|
468
|
+
},
|
438
469
|
isDraggable: {
|
439
470
|
type: Boolean,
|
440
471
|
default: false
|
@@ -456,6 +487,7 @@ export default {
|
|
456
487
|
Caret,
|
457
488
|
Selector,
|
458
489
|
inputText,
|
490
|
+
Teleport,
|
459
491
|
draggableInputHandle
|
460
492
|
},
|
461
493
|
|
@@ -467,23 +499,38 @@ export default {
|
|
467
499
|
isActive: false,
|
468
500
|
textSearch: '',
|
469
501
|
hoveredIndex: 0,
|
470
|
-
|
471
|
-
|
502
|
+
isClickOutsideActive: false,
|
503
|
+
dropdownPosition: {
|
504
|
+
left: null,
|
505
|
+
top: null
|
506
|
+
},
|
507
|
+
dropdownWidth: null,
|
508
|
+
hoveredValue: null
|
472
509
|
}
|
473
510
|
},
|
474
511
|
mounted() {
|
512
|
+
this.observeDropdownHeight()
|
513
|
+
this.observeSelectWidth()
|
514
|
+
window.addEventListener('resize', this.handleSetDropdownOffet)
|
515
|
+
},
|
516
|
+
beforeMount() {
|
475
517
|
this.selectedValue = this.value
|
476
518
|
document.addEventListener('click', this.clickOutside)
|
519
|
+
this.getDropdownPosition()
|
520
|
+
window.removeEventListener('resize', this.handleSetDropdownOffet)
|
521
|
+
if (this.dropdownResizeObserver) this.dropdownResizeObserver.disconnect()
|
522
|
+
if (this.selectResizeObserver) this.selectResizeObserver.disconnect()
|
477
523
|
},
|
478
|
-
|
524
|
+
unmounted() {
|
479
525
|
document.removeEventListener('click', this.clickOutside)
|
480
526
|
},
|
481
527
|
methods: {
|
482
528
|
focus() {
|
483
529
|
this.isActive = true
|
484
530
|
},
|
485
|
-
blur() {
|
531
|
+
blur(e) {
|
486
532
|
this.isActive = false
|
533
|
+
this.$emit('blur', e)
|
487
534
|
},
|
488
535
|
toggleDropdown() {
|
489
536
|
this.isDropdownOpen = !this.isDropdownOpen
|
@@ -499,6 +546,9 @@ export default {
|
|
499
546
|
this.blur()
|
500
547
|
this.isDropdownOpen = false
|
501
548
|
},
|
549
|
+
clearSearch() {
|
550
|
+
this.textSearch = ''
|
551
|
+
},
|
502
552
|
optionSelected(e) {
|
503
553
|
this.selectedValue = e
|
504
554
|
this.closeDropdown()
|
@@ -527,15 +577,15 @@ export default {
|
|
527
577
|
searchChange(value) {
|
528
578
|
this.textSearch = value
|
529
579
|
this.$emit('search-change', value)
|
530
|
-
this.$refs.dropdown.$children
|
531
|
-
|
532
|
-
.
|
533
|
-
|
534
|
-
|
535
|
-
|
536
|
-
|
537
|
-
|
538
|
-
|
580
|
+
const dropdownChildren = [...this.$refs.dropdown.$el.children]
|
581
|
+
dropdownChildren.forEach((el) => {
|
582
|
+
if (!el.textContent.toLowerCase().includes(value.toLowerCase())) {
|
583
|
+
el.style.display = 'none'
|
584
|
+
|
585
|
+
return
|
586
|
+
}
|
587
|
+
el.style.display = 'inherit'
|
588
|
+
})
|
539
589
|
},
|
540
590
|
clickOutside(event) {
|
541
591
|
const dropdownRef = this.$refs.dropdown
|
@@ -545,6 +595,7 @@ export default {
|
|
545
595
|
if (
|
546
596
|
this.$refs.select.$el == event.target ||
|
547
597
|
this.$refs.select.$el.contains(event.target) ||
|
598
|
+
event.target.id === 'more-button' ||
|
548
599
|
event.target.parentNode === dropdownRef.$el
|
549
600
|
) {
|
550
601
|
return
|
@@ -558,13 +609,92 @@ export default {
|
|
558
609
|
} else if (e.key == 'ArrowUp') {
|
559
610
|
this.onArrowPress(-1)
|
560
611
|
} else if (e.key == 'Enter') {
|
561
|
-
const optionHoveredComponent =
|
562
|
-
this
|
563
|
-
|
564
|
-
]
|
612
|
+
const optionHoveredComponent = [...this.$refs.dropdown.$el.children][
|
613
|
+
(this.hoveredIndex - 1 + this.optionLength) % this.optionLength
|
614
|
+
]
|
565
615
|
this.optionSelected(optionHoveredComponent.$el.dataset.value)
|
566
616
|
}
|
567
617
|
},
|
618
|
+
// If some part of the dropdown menu is outside viewport of the bottom of the screen,
|
619
|
+
// we need to offset it and display it at the top of the select dropdown instead
|
620
|
+
async getDropdownPosition() {
|
621
|
+
if (
|
622
|
+
!this.$refs.dropdownWrapperRef ||
|
623
|
+
!this.$refs.select ||
|
624
|
+
!this.$refs.dropdown
|
625
|
+
) {
|
626
|
+
return
|
627
|
+
}
|
628
|
+
await this.$nextTick()
|
629
|
+
const isDisplayedAtBottom = await this.generateDropdownPosition()
|
630
|
+
await this.$nextTick()
|
631
|
+
// If the dropdown menu is going to be displayed at the bottom,
|
632
|
+
// we need reverify its position after a dom update (nextTick)
|
633
|
+
if (isDisplayedAtBottom) this.generateDropdownPosition()
|
634
|
+
},
|
635
|
+
async generateDropdownPosition() {
|
636
|
+
const isDropdownNotCompletelyVisible =
|
637
|
+
await this.isBottomOfDropdownOutOfViewport()
|
638
|
+
const dropdownWrapperEl = this.$refs.dropdownWrapperRef.$el
|
639
|
+
const selectButtonHeight = this.$refs.select.$el.clientHeight
|
640
|
+
const dropdownHeight = this.$refs.dropdown.$el.clientHeight
|
641
|
+
const dropdownWrapperRelativeHeight =
|
642
|
+
dropdownWrapperEl.getBoundingClientRect().top +
|
643
|
+
window.scrollY +
|
644
|
+
DROPDOWN_HEIGHT_OFFSET
|
645
|
+
|
646
|
+
const top = isDropdownNotCompletelyVisible
|
647
|
+
? dropdownWrapperRelativeHeight
|
648
|
+
: dropdownWrapperRelativeHeight -
|
649
|
+
dropdownHeight -
|
650
|
+
selectButtonHeight -
|
651
|
+
DROPDOWN_TOP_OFFSET
|
652
|
+
const left = this.dropdownPosition.left
|
653
|
+
? this.dropdownPosition.left
|
654
|
+
: dropdownWrapperEl.getBoundingClientRect().left + window.scrollX
|
655
|
+
|
656
|
+
this.dropdownPosition = { left: Math.floor(left), top: Math.floor(top) }
|
657
|
+
|
658
|
+
return isDropdownNotCompletelyVisible
|
659
|
+
},
|
660
|
+
async isBottomOfDropdownOutOfViewport() {
|
661
|
+
if (!this.$refs.dropdown) {
|
662
|
+
return false
|
663
|
+
}
|
664
|
+
await this.$nextTick()
|
665
|
+
const rect = this.$refs.dropdown.$el.getBoundingClientRect()
|
666
|
+
const windowHeight =
|
667
|
+
window.innerHeight || document.documentElement.clientHeight
|
668
|
+
|
669
|
+
// using Math.floor because the offsets may contain decimals we are not going to consider here
|
670
|
+
return Math.floor(rect.top) + Math.floor(rect.height) <= windowHeight
|
671
|
+
},
|
672
|
+
observeDropdownHeight() {
|
673
|
+
if (!this.$refs.dropdown) return
|
674
|
+
this.dropdownResizeObserver = new ResizeObserver(() => {
|
675
|
+
this.$nextTick(() => this.getDropdownPosition())
|
676
|
+
})
|
677
|
+
this.dropdownResizeObserver.observe(this.$refs.dropdown.$el)
|
678
|
+
},
|
679
|
+
handleSetDropdownOffet() {
|
680
|
+
if (!this.$refs.select) return
|
681
|
+
this.dropdownPosition.left = Math.floor(
|
682
|
+
this.$refs.select.$el.getBoundingClientRect().left
|
683
|
+
)
|
684
|
+
this.getDropdownWidth()
|
685
|
+
},
|
686
|
+
observeSelectWidth() {
|
687
|
+
if (!this.$refs.select) return
|
688
|
+
this.selectResizeObserver = new ResizeObserver(() =>
|
689
|
+
this.$nextTick(() => this.getDropdownWidth())
|
690
|
+
)
|
691
|
+
this.selectResizeObserver.observe(this.$refs.dropdown.$el)
|
692
|
+
},
|
693
|
+
async getDropdownWidth() {
|
694
|
+
if (!this.$refs.select) return
|
695
|
+
await this.$nextTick()
|
696
|
+
this.dropdownWidth = `${this.$refs.select.$el.clientWidth}px`
|
697
|
+
},
|
568
698
|
onArrowPress(dir) {
|
569
699
|
let newHoveredElem
|
570
700
|
const currentHoveredElem = this.$refs.dropdown.$el.querySelector(
|
@@ -596,20 +726,34 @@ export default {
|
|
596
726
|
return 0
|
597
727
|
},
|
598
728
|
isSearchBarVisible() {
|
599
|
-
return this.isSearchable && this.isDropdownOpen
|
729
|
+
return this.isSearchable && this.optionLength >= 5 && this.isDropdownOpen
|
730
|
+
},
|
731
|
+
getOptionWidth() {
|
732
|
+
if (this.optionWidth) return this.optionWidth
|
733
|
+
|
734
|
+
return this.dropdownWidth
|
735
|
+
},
|
736
|
+
isSelectDropdownShown() {
|
737
|
+
return (
|
738
|
+
this.isDropdownOpen &&
|
739
|
+
this.dropdownPosition.left !== null &&
|
740
|
+
(!this.isSearchable || this.isSearchable)
|
741
|
+
)
|
600
742
|
}
|
601
743
|
},
|
602
744
|
watch: {
|
603
745
|
value(val) {
|
604
746
|
this.selectedValue = val
|
605
747
|
},
|
606
|
-
isDropdownOpen(val) {
|
607
|
-
this.$emit('is-dropdown-open', val)
|
748
|
+
async isDropdownOpen(val) {
|
608
749
|
if (val) {
|
609
750
|
setTimeout(() => {
|
610
751
|
this.isClickOutsideActive = true
|
611
752
|
}, 10)
|
753
|
+
await this.$nextTick()
|
754
|
+
this.handleSetDropdownOffet()
|
612
755
|
} else {
|
756
|
+
this.dropdownPosition.left = null
|
613
757
|
setTimeout(() => {
|
614
758
|
this.isClickOutsideActive = false
|
615
759
|
}, 10)
|