@eturnity/eturnity_reusable_components 7.12.7--EPDM-5518.2 → 7.12.7-EPDM-7951.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 +1 -1
- package/src/components/filter/filterSettings.vue +54 -113
- 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 -70
- 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 +24 -16
- package/src/components/inputs/inputNumber/index.vue +7 -10
- package/src/components/inputs/inputNumberQuestion/index.vue +1 -1
- package/src/components/inputs/inputText/index.vue +4 -4
- package/src/components/inputs/radioButton/index.vue +1 -1
- package/src/components/inputs/searchInput/index.vue +7 -8
- package/src/components/inputs/select/index.vue +208 -66
- package/src/components/inputs/select/option/index.vue +5 -5
- 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 +2 -2
- 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 +5 -3
- package/src/components/progressBar/index.vue +1 -1
- package/src/components/projectMarker/index.vue +11 -8
- package/src/components/sideMenu/index.vue +1 -1
- package/src/components/spinner/index.vue +6 -11
- package/src/components/tableDropdown/index.vue +21 -26
- 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/components/markerItem/index.vue +0 -96
- package/src/components/selectedOptions/index.vue +0 -145
@@ -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
|
@@ -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'
|
@@ -328,12 +328,12 @@ export default {
|
|
328
328
|
}
|
329
329
|
},
|
330
330
|
methods: {
|
331
|
-
onEnterPress()
|
331
|
+
onEnterPress(event){
|
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)
|
@@ -13,10 +13,7 @@
|
|
13
13
|
:hasFocus="hasFocus"
|
14
14
|
:data-id="dataId"
|
15
15
|
/>
|
16
|
-
<
|
17
|
-
class="search-icn"
|
18
|
-
:src="require('../../../assets/icons/search_icon_black.svg')"
|
19
|
-
/>
|
16
|
+
<SearchIconSvg class="search-icn" />
|
20
17
|
</input-wrapper>
|
21
18
|
</container>
|
22
19
|
</template>
|
@@ -33,7 +30,8 @@
|
|
33
30
|
// :isFilter="true" // to set the height at 30px
|
34
31
|
// data-id="test-data-id"
|
35
32
|
// />
|
36
|
-
import styled from '
|
33
|
+
import styled from 'vue3-styled-components'
|
34
|
+
import SearchIconSvg from '../../../assets/icons/search_icon_black.svg'
|
37
35
|
|
38
36
|
const inputAttrs = {
|
39
37
|
isDisabled: Boolean,
|
@@ -68,7 +66,7 @@ const InputContainer = styled('input', inputAttrs)`
|
|
68
66
|
const InputWrapper = styled.span`
|
69
67
|
position: relative;
|
70
68
|
|
71
|
-
|
69
|
+
svg {
|
72
70
|
position: absolute;
|
73
71
|
right: 10px;
|
74
72
|
top: 50%;
|
@@ -81,7 +79,8 @@ export default {
|
|
81
79
|
components: {
|
82
80
|
InputContainer,
|
83
81
|
InputWrapper,
|
84
|
-
Container
|
82
|
+
Container,
|
83
|
+
SearchIconSvg
|
85
84
|
},
|
86
85
|
props: {
|
87
86
|
value: {
|
@@ -114,7 +113,7 @@ export default {
|
|
114
113
|
},
|
115
114
|
methods: {
|
116
115
|
onChangeHandler(event) {
|
117
|
-
this.$emit('on-change', event)
|
116
|
+
this.$emit('on-change', event.target.value)
|
118
117
|
},
|
119
118
|
focusInputElement() {
|
120
119
|
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,14 +66,13 @@
|
|
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
|
73
|
+
:showBorder="showBorder"
|
71
74
|
:selectWidth="selectWidth"
|
72
75
|
:paddingLeft="paddingLeft"
|
73
|
-
:noMaxWidth="noMaxWidth"
|
74
|
-
:showBorder="showBorder"
|
75
76
|
>
|
76
77
|
<slot name="selector" :selectedValue="selectedValue"></slot>
|
77
78
|
</selector>
|
@@ -98,26 +99,33 @@
|
|
98
99
|
/>
|
99
100
|
</Caret>
|
100
101
|
</selectButton>
|
101
|
-
<DropdownWrapper>
|
102
|
-
<
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
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>
|
121
129
|
</DropdownWrapper>
|
122
130
|
</select-button-wrapper>
|
123
131
|
</input-wrapper>
|
@@ -132,8 +140,9 @@
|
|
132
140
|
// optionWidth="50%"
|
133
141
|
// label="that is a label"
|
134
142
|
// alignItems="vertical"
|
135
|
-
// label-data-id="test-
|
143
|
+
// label-data-id="test-label-data-id"
|
136
144
|
// data-id="test-data-id"
|
145
|
+
// :hasSelectButtonPadding="false"
|
137
146
|
// >
|
138
147
|
// <template #selector="{selectedValue}">
|
139
148
|
// value selected: {{selectedValue}}
|
@@ -146,7 +155,8 @@
|
|
146
155
|
// </template>
|
147
156
|
// </Select>
|
148
157
|
|
149
|
-
import
|
158
|
+
import { Teleport } from 'vue'
|
159
|
+
import styled from 'vue3-styled-components'
|
150
160
|
import InfoText from '../../infoText'
|
151
161
|
import icon from '../../icon'
|
152
162
|
import inputText from '../inputText'
|
@@ -162,7 +172,7 @@ const Caret = styled.div`
|
|
162
172
|
width: ${CARET_WIDTH};
|
163
173
|
min-width: ${CARET_WIDTH};
|
164
174
|
height: 100%;
|
165
|
-
align-items:
|
175
|
+
align-items: center;
|
166
176
|
cursor: pointer;
|
167
177
|
margin-left: auto;
|
168
178
|
`
|
@@ -170,17 +180,22 @@ const Caret = styled.div`
|
|
170
180
|
const selectorProps = {
|
171
181
|
selectWidth: String,
|
172
182
|
paddingLeft: String,
|
173
|
-
showBorder: Boolean
|
174
|
-
noMaxWidth: Boolean
|
183
|
+
showBorder: Boolean
|
175
184
|
}
|
176
185
|
const Selector = styled('div', selectorProps)`
|
177
|
-
|
178
|
-
props.
|
179
|
-
? '100
|
180
|
-
: `calc(${props.selectWidth} -
|
181
|
-
|
182
|
-
|
183
|
-
|
186
|
+
${(props) =>
|
187
|
+
props.selectWidth === '100%'
|
188
|
+
? 'width: 100%;'
|
189
|
+
: `width: calc(${props.selectWidth} -
|
190
|
+
(
|
191
|
+
${CARET_WIDTH} +
|
192
|
+
${props.paddingLeft}
|
193
|
+
${props.showBorder ? `+ (${BORDER_WIDTH} * 2)` : ''}
|
194
|
+
)
|
195
|
+
);
|
196
|
+
white-space: nowrap;
|
197
|
+
text-overflow: ellipsis;
|
198
|
+
overflow: hidden;`}
|
184
199
|
`
|
185
200
|
|
186
201
|
const labelAttrs = { fontSize: String, fontColor: String }
|
@@ -195,7 +210,10 @@ const InputLabel = styled('div', labelAttrs)`
|
|
195
210
|
const optionalLabel = styled.span`
|
196
211
|
font-weight: 300;
|
197
212
|
`
|
198
|
-
const inputProps = {
|
213
|
+
const inputProps = {
|
214
|
+
selectWidth: String,
|
215
|
+
optionWidth: String
|
216
|
+
}
|
199
217
|
const Container = styled('div', inputProps)`
|
200
218
|
width: ${(props) => props.selectWidth};
|
201
219
|
position: relative;
|
@@ -222,9 +240,10 @@ const selectButtonAttrs = {
|
|
222
240
|
hasError: Boolean,
|
223
241
|
disabled: Boolean,
|
224
242
|
selectHeight: String,
|
243
|
+
selectWidth: String,
|
225
244
|
height: String,
|
226
245
|
selectMinHeight: String,
|
227
|
-
|
246
|
+
hasNoPadding: Boolean,
|
228
247
|
showBorder: Boolean,
|
229
248
|
paddingLeft: String
|
230
249
|
}
|
@@ -232,8 +251,9 @@ const selectButton = styled('div', selectButtonAttrs)`
|
|
232
251
|
position: relative;
|
233
252
|
box-sizing: border-box;
|
234
253
|
border-radius: 4px;
|
254
|
+
max-width: ${(props) => (props.selectWidth ? props.selectWidth : '100%')};
|
235
255
|
${(props) =>
|
236
|
-
props.
|
256
|
+
props.hasNoPadding ? '' : `padding-left: ${props.paddingLeft}`};
|
237
257
|
text-align: left;
|
238
258
|
min-height: ${(props) =>
|
239
259
|
props.selectHeight
|
@@ -245,7 +265,7 @@ const selectButton = styled('div', selectButtonAttrs)`
|
|
245
265
|
: '36px'};
|
246
266
|
display: flex;
|
247
267
|
align-items: center;
|
248
|
-
|
268
|
+
height: ${(props) => props.selectHeight};
|
249
269
|
${({ showBorder, theme, hasError }) =>
|
250
270
|
showBorder &&
|
251
271
|
`
|
@@ -277,14 +297,17 @@ const selectDropdownAttrs = {
|
|
277
297
|
fontColor: String,
|
278
298
|
optionWidth: String,
|
279
299
|
hoveredIndex: Number,
|
300
|
+
fontSize: String,
|
301
|
+
dropdownPosition: Object,
|
280
302
|
hoveredValue: Number | String,
|
281
303
|
selectedValue: Number | String
|
282
304
|
}
|
283
305
|
const selectDropdown = styled('div', selectDropdownAttrs)`
|
284
306
|
box-sizing: border-box;
|
285
|
-
z-index: ${(props) => (props.isActive ? '2' : '
|
307
|
+
z-index: ${(props) => (props.isActive ? '2' : '99999')};
|
286
308
|
position: absolute;
|
287
|
-
top:
|
309
|
+
top: ${(props) => props.dropdownPosition?.top}px;
|
310
|
+
left: ${(props) => props.dropdownPosition?.left}px;
|
288
311
|
border: ${BORDER_WIDTH} solid ${(props) => props.theme.colors.grey4};
|
289
312
|
border-radius: 4px;
|
290
313
|
display: flex;
|
@@ -309,7 +332,9 @@ const selectDropdown = styled('div', selectDropdownAttrs)`
|
|
309
332
|
? props.theme.colors[props.hoveredBgColor]
|
310
333
|
: props.hoveredBgColor};
|
311
334
|
}
|
335
|
+
font-size: ${(props) => props.fontSize};
|
312
336
|
`
|
337
|
+
selectDropdown.emits = ['option-hovered', 'option-selected']
|
313
338
|
const DropdownWrapper = styled('div')`
|
314
339
|
position: relative;
|
315
340
|
`
|
@@ -322,6 +347,10 @@ const InputWrapper = styled('div', inputAttrs)`
|
|
322
347
|
grid-template-columns: ${(props) =>
|
323
348
|
props.alignItems === 'vertical' || !props.hasLabel ? '1fr' : 'auto 1fr'};
|
324
349
|
`
|
350
|
+
|
351
|
+
const DROPDOWN_HEIGHT_OFFSET = 4
|
352
|
+
const DROPDOWN_TOP_OFFSET = 21
|
353
|
+
|
325
354
|
export default {
|
326
355
|
name: 'RCselect',
|
327
356
|
|
@@ -433,11 +462,11 @@ export default {
|
|
433
462
|
type: String,
|
434
463
|
default: ''
|
435
464
|
},
|
436
|
-
|
465
|
+
hasSelectButtonPadding: {
|
437
466
|
type: Boolean,
|
438
|
-
default:
|
467
|
+
default: true
|
439
468
|
},
|
440
|
-
|
469
|
+
isDraggable: {
|
441
470
|
type: Boolean,
|
442
471
|
default: false
|
443
472
|
}
|
@@ -458,6 +487,7 @@ export default {
|
|
458
487
|
Caret,
|
459
488
|
Selector,
|
460
489
|
inputText,
|
490
|
+
Teleport,
|
461
491
|
draggableInputHandle
|
462
492
|
},
|
463
493
|
|
@@ -469,23 +499,38 @@ export default {
|
|
469
499
|
isActive: false,
|
470
500
|
textSearch: '',
|
471
501
|
hoveredIndex: 0,
|
472
|
-
|
473
|
-
|
502
|
+
isClickOutsideActive: false,
|
503
|
+
dropdownPosition: {
|
504
|
+
left: null,
|
505
|
+
top: null
|
506
|
+
},
|
507
|
+
dropdownWidth: null,
|
508
|
+
hoveredValue: null
|
474
509
|
}
|
475
510
|
},
|
476
511
|
mounted() {
|
512
|
+
this.observeDropdownHeight()
|
513
|
+
this.observeSelectWidth()
|
514
|
+
window.addEventListener('resize', this.handleSetDropdownOffet)
|
515
|
+
},
|
516
|
+
beforeMount() {
|
477
517
|
this.selectedValue = this.value
|
478
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()
|
479
523
|
},
|
480
|
-
|
524
|
+
unmounted() {
|
481
525
|
document.removeEventListener('click', this.clickOutside)
|
482
526
|
},
|
483
527
|
methods: {
|
484
528
|
focus() {
|
485
529
|
this.isActive = true
|
486
530
|
},
|
487
|
-
blur() {
|
531
|
+
blur(e) {
|
488
532
|
this.isActive = false
|
533
|
+
this.$emit('blur', e)
|
489
534
|
},
|
490
535
|
toggleDropdown() {
|
491
536
|
this.isDropdownOpen = !this.isDropdownOpen
|
@@ -501,6 +546,9 @@ export default {
|
|
501
546
|
this.blur()
|
502
547
|
this.isDropdownOpen = false
|
503
548
|
},
|
549
|
+
clearSearch() {
|
550
|
+
this.textSearch = ''
|
551
|
+
},
|
504
552
|
optionSelected(e) {
|
505
553
|
this.selectedValue = e
|
506
554
|
this.closeDropdown()
|
@@ -529,15 +577,15 @@ export default {
|
|
529
577
|
searchChange(value) {
|
530
578
|
this.textSearch = value
|
531
579
|
this.$emit('search-change', value)
|
532
|
-
this.$refs.dropdown.$children
|
533
|
-
|
534
|
-
.
|
535
|
-
|
536
|
-
|
537
|
-
|
538
|
-
|
539
|
-
|
540
|
-
|
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
|
+
})
|
541
589
|
},
|
542
590
|
clickOutside(event) {
|
543
591
|
const dropdownRef = this.$refs.dropdown
|
@@ -547,6 +595,7 @@ export default {
|
|
547
595
|
if (
|
548
596
|
this.$refs.select.$el == event.target ||
|
549
597
|
this.$refs.select.$el.contains(event.target) ||
|
598
|
+
event.target.id === 'more-button' ||
|
550
599
|
event.target.parentNode === dropdownRef.$el
|
551
600
|
) {
|
552
601
|
return
|
@@ -560,13 +609,92 @@ export default {
|
|
560
609
|
} else if (e.key == 'ArrowUp') {
|
561
610
|
this.onArrowPress(-1)
|
562
611
|
} else if (e.key == 'Enter') {
|
563
|
-
const optionHoveredComponent =
|
564
|
-
this
|
565
|
-
|
566
|
-
]
|
612
|
+
const optionHoveredComponent = [...this.$refs.dropdown.$el.children][
|
613
|
+
(this.hoveredIndex - 1 + this.optionLength) % this.optionLength
|
614
|
+
]
|
567
615
|
this.optionSelected(optionHoveredComponent.$el.dataset.value)
|
568
616
|
}
|
569
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
|
+
},
|
570
698
|
onArrowPress(dir) {
|
571
699
|
let newHoveredElem
|
572
700
|
const currentHoveredElem = this.$refs.dropdown.$el.querySelector(
|
@@ -598,20 +726,34 @@ export default {
|
|
598
726
|
return 0
|
599
727
|
},
|
600
728
|
isSearchBarVisible() {
|
601
|
-
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
|
+
)
|
602
742
|
}
|
603
743
|
},
|
604
744
|
watch: {
|
605
745
|
value(val) {
|
606
746
|
this.selectedValue = val
|
607
747
|
},
|
608
|
-
isDropdownOpen(val) {
|
609
|
-
this.$emit('is-dropdown-open', val)
|
748
|
+
async isDropdownOpen(val) {
|
610
749
|
if (val) {
|
611
750
|
setTimeout(() => {
|
612
751
|
this.isClickOutsideActive = true
|
613
752
|
}, 10)
|
753
|
+
await this.$nextTick()
|
754
|
+
this.handleSetDropdownOffet()
|
614
755
|
} else {
|
756
|
+
this.dropdownPosition.left = null
|
615
757
|
setTimeout(() => {
|
616
758
|
this.isClickOutsideActive = false
|
617
759
|
}, 10)
|
@@ -22,7 +22,7 @@
|
|
22
22
|
<script>
|
23
23
|
// import selectButton from './selectButton'
|
24
24
|
// import selectDropdown from './selectDropDown'
|
25
|
-
import styled from '
|
25
|
+
import styled from 'vue3-styled-components'
|
26
26
|
const optionProps = {
|
27
27
|
isDisabled: Boolean,
|
28
28
|
hoveredBgColor: String,
|
@@ -59,7 +59,7 @@ const optionContainer = styled('div', optionProps)`
|
|
59
59
|
|
60
60
|
export default {
|
61
61
|
name: 'RCoption',
|
62
|
-
|
62
|
+
emits: ['option-hovered', 'option-selected'],
|
63
63
|
props: {
|
64
64
|
value: {
|
65
65
|
required: true
|
@@ -73,7 +73,7 @@ export default {
|
|
73
73
|
},
|
74
74
|
cursorType: {
|
75
75
|
required: false,
|
76
|
-
default: '
|
76
|
+
default: 'pointer'
|
77
77
|
},
|
78
78
|
backgroundColor: {
|
79
79
|
required: false,
|
@@ -94,12 +94,12 @@ export default {
|
|
94
94
|
return {}
|
95
95
|
},
|
96
96
|
methods: {
|
97
|
-
clickHandler() {
|
97
|
+
clickHandler(e) {
|
98
98
|
if (this.isDisabled) {
|
99
99
|
// prevent emitter if the option is disabled
|
100
100
|
return
|
101
101
|
} else {
|
102
|
-
this.$parent.$emit('option-selected', this.value)
|
102
|
+
this.$parent.$emit('option-selected', this.value, e)
|
103
103
|
}
|
104
104
|
},
|
105
105
|
hoverHandler() {
|