@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.
Files changed (52) hide show
  1. package/.storybook/preview.js +1 -1
  2. package/package.json +19 -23
  3. package/src/App.vue +2 -2
  4. package/src/components/addNewButton/index.vue +5 -3
  5. package/src/components/buttons/buttonIcon/index.vue +1 -1
  6. package/src/components/buttons/closeButton/index.vue +1 -1
  7. package/src/components/buttons/mainButton/index.vue +6 -1
  8. package/src/components/deleteIcon/DeleteIcon.stories.js +7 -7
  9. package/src/components/deleteIcon/index.vue +25 -21
  10. package/src/components/draggableInputHandle/index.vue +24 -25
  11. package/src/components/dropdown/index.vue +129 -110
  12. package/src/components/errorMessage/index.vue +1 -1
  13. package/src/components/filter/filterSettings.vue +54 -113
  14. package/src/components/filter/index.vue +3 -3
  15. package/src/components/filter/parentDropdown.vue +2 -2
  16. package/src/components/icon/iconCache.js +23 -0
  17. package/src/components/icon/iconCollection.vue +2 -2
  18. package/src/components/icon/index.vue +67 -70
  19. package/src/components/iconWrapper/index.vue +1 -4
  20. package/src/components/infoCard/index.vue +2 -3
  21. package/src/components/infoText/index.vue +1 -1
  22. package/src/components/inputs/checkbox/index.vue +24 -16
  23. package/src/components/inputs/inputNumber/index.vue +7 -10
  24. package/src/components/inputs/inputNumberQuestion/index.vue +1 -1
  25. package/src/components/inputs/inputText/index.vue +4 -4
  26. package/src/components/inputs/radioButton/index.vue +1 -1
  27. package/src/components/inputs/searchInput/index.vue +7 -8
  28. package/src/components/inputs/select/index.vue +208 -66
  29. package/src/components/inputs/select/option/index.vue +5 -5
  30. package/src/components/inputs/slider/index.vue +16 -16
  31. package/src/components/inputs/switchField/index.vue +2 -2
  32. package/src/components/inputs/textAreaInput/index.vue +2 -2
  33. package/src/components/inputs/toggle/index.vue +2 -2
  34. package/src/components/label/index.vue +27 -31
  35. package/src/components/modals/modal/index.vue +2 -6
  36. package/src/components/navigationTabs/index.vue +27 -20
  37. package/src/components/pageSubtitle/index.vue +1 -1
  38. package/src/components/pageTitle/index.vue +4 -4
  39. package/src/components/pagination/index.vue +5 -3
  40. package/src/components/progressBar/index.vue +1 -1
  41. package/src/components/projectMarker/index.vue +11 -8
  42. package/src/components/sideMenu/index.vue +1 -1
  43. package/src/components/spinner/index.vue +6 -11
  44. package/src/components/tableDropdown/index.vue +21 -26
  45. package/src/components/tables/mainTable/exampleNested.vue +1 -1
  46. package/src/components/tables/mainTable/index.vue +10 -9
  47. package/src/components/tables/viewTable/index.vue +2 -2
  48. package/src/components/threeDots/index.vue +1 -1
  49. package/src/components/videoThumbnail/index.vue +95 -100
  50. package/src/main.js +4 -11
  51. package/src/components/markerItem/index.vue +0 -96
  52. 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 'vue-styled-components'
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(val) {
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(value) {
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(value)
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(value)
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({
@@ -44,7 +44,7 @@
44
44
  // number_max_allowed: 10,
45
45
  // unit_short_name: "cm",
46
46
  // },
47
- import styled from "vue-styled-components"
47
+ import styled from "vue3-styled-components"
48
48
  import {
49
49
  stringToNumber,
50
50
  numberToString,
@@ -66,7 +66,7 @@
66
66
  </template>
67
67
 
68
68
  <script>
69
- import styled from 'vue-styled-components'
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($event) {
336
- this.$emit('input-change', $event)
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)
@@ -60,7 +60,7 @@
60
60
  // { label: 'Button 4', value: 'button_4', disabled: true }
61
61
  // ]
62
62
 
63
- import styled from 'vue-styled-components'
63
+ import styled from 'vue3-styled-components'
64
64
  import Modal from '../../modals/modal'
65
65
  import InfoText from '../../infoText'
66
66
 
@@ -13,10 +13,7 @@
13
13
  :hasFocus="hasFocus"
14
14
  :data-id="dataId"
15
15
  />
16
- <img
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 'vue-styled-components'
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
- img {
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
- :isSearchBarVisible="isSearchBarVisible"
44
+ :hasNoPadding="isSearchBarVisible || !hasSelectButtonPadding"
43
45
  :disabled="disabled"
44
- @keydown.native="onKeyDown"
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.native.stop
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
- <selectDropdown
103
- ref="dropdown"
104
- v-show="isDropdownOpen"
105
- :hoveredIndex="hoveredIndex"
106
- :hoveredValue="hoveredValue"
107
- :isActive="isActive"
108
- :optionWidth="optionWidth"
109
- :hoveredBgColor="colorMode == 'dark' ? '#000000' : dropdownBgColor"
110
- :bgColor="colorMode == 'dark' ? 'black' : dropdownBgColor"
111
- :fontColor="
112
- dropdownFontColor || colorMode == 'dark' ? 'white' : 'black'
113
- "
114
- :selectedValue="selectedValue"
115
- @option-selected="optionSelected"
116
- @option-hovered="optionHovered"
117
- @mouseleave="optionLeave"
118
- >
119
- <slot name="dropdown"></slot>
120
- </selectDropdown>
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-label0data-id"
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 styled from 'vue-styled-components'
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: stretch;
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
- max-width: ${(props) =>
178
- props.noMaxWidth
179
- ? '100%'
180
- : `calc(${props.selectWidth} - (${CARET_WIDTH} + ${props.paddingLeft} + (${BORDER_WIDTH} * 2)))`};
181
- white-space: nowrap;
182
- text-overflow: ellipsis;
183
- overflow: hidden;
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 = { selectWidth: String, optionWidth: String }
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
- isSearchBarVisible: Boolean,
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.isSearchBarVisible ? '' : `padding-left: ${props.paddingLeft}`};
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
- max-height: ${(props) => props.selectHeight};
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' : '1')};
307
+ z-index: ${(props) => (props.isActive ? '2' : '99999')};
286
308
  position: absolute;
287
- top: 5px;
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
- isDraggable: {
465
+ hasSelectButtonPadding: {
437
466
  type: Boolean,
438
- default: false
467
+ default: true
439
468
  },
440
- noMaxWidth: {
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
- hoveredValue: null,
473
- isClickOutsideActive: false
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
- beforeDestroy() {
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
- .map((component) => component.$el)
534
- .forEach((el) => {
535
- if (!el.textContent.toLowerCase().includes(value.toLowerCase())) {
536
- el.style.display = 'none'
537
- } else {
538
- el.style.display = 'grid'
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.$refs.dropdown.$children[
565
- (this.hoveredIndex - 1 + this.optionLength) % this.optionLength
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 'vue-styled-components'
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: 'cursor'
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() {