@eturnity/eturnity_reusable_components 7.22.4--EPDM-10563.1 → 7.22.4--EPDM-10563.3

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 (38) hide show
  1. package/babel.config.js +3 -1
  2. package/package.json +2 -1
  3. package/src/assets/svgIcons/anchor.svg +18 -0
  4. package/src/assets/svgIcons/bexio.svg +4 -0
  5. package/src/assets/svgIcons/consumption_tariffs.svg +43 -0
  6. package/src/assets/svgIcons/data_transfer.svg +3 -0
  7. package/src/assets/svgIcons/electricity_tariff.svg +3 -0
  8. package/src/assets/svgIcons/flatten_roof.svg +20 -0
  9. package/src/assets/svgIcons/handle.svg +5 -0
  10. package/src/assets/svgIcons/house_3d-1.svg +8 -0
  11. package/src/assets/svgIcons/house_3d.svg +8 -0
  12. package/src/assets/svgIcons/save.svg +3 -0
  13. package/src/assets/svgIcons/split.svg +6 -88
  14. package/src/assets/svgIcons/summer.svg +3 -0
  15. package/src/components/banner/actionBanner/index.vue +65 -0
  16. package/src/components/banner/banner/banner.stories.js +31 -0
  17. package/src/components/banner/banner/index.vue +188 -0
  18. package/src/components/banner/infoBanner/index.vue +69 -0
  19. package/src/components/buttons/mainButton/index.vue +30 -2
  20. package/src/components/collapsableInfoText/index.vue +125 -0
  21. package/src/components/filter/filterSettings.vue +3 -1
  22. package/src/components/icon/index.vue +13 -1
  23. package/src/components/iconWrapper/index.vue +29 -3
  24. package/src/components/infoCard/index.vue +8 -1
  25. package/src/components/inputs/checkbox/index.vue +5 -0
  26. package/src/components/inputs/inputText/index.vue +20 -4
  27. package/src/components/inputs/radioButton/index.vue +5 -2
  28. package/src/components/inputs/select/index.vue +34 -11
  29. package/src/components/modals/actionModal/index.vue +64 -0
  30. package/src/components/modals/infoModal/index.vue +49 -0
  31. package/src/components/modals/modal/index.vue +1 -1
  32. package/src/components/rangeSlider/Slider.vue +547 -0
  33. package/src/components/rangeSlider/index.vue +517 -0
  34. package/src/components/rangeSlider/utils/dom.js +49 -0
  35. package/src/components/rangeSlider/utils/fns.js +26 -0
  36. package/src/components/threeDots/index.vue +22 -8
  37. package/src/helpers/currencyMapping.js +28 -0
  38. package/src/mixins/inputValidations.js +97 -0
@@ -8,8 +8,12 @@
8
8
  :customColor="customColor"
9
9
  :noWrap="noWrap"
10
10
  :data-id="dataId"
11
+ :fontColor="fontColor"
11
12
  >
12
- {{ text }}
13
+ <Label :hasIcon="Boolean(icon)">
14
+ <icon v-if="icon" :name="icon" size="14px" />
15
+ {{ text }}
16
+ </Label>
13
17
  </button-container>
14
18
  </page-container>
15
19
  </template>
@@ -21,12 +25,14 @@
21
25
  // text="Click Me"
22
26
  // customColor="#ab5348"
23
27
  // type="secondary" // primary, secondary, cancel
28
+ // icon="icon-name" // icon name from icon component
24
29
  // :isDisabled="true"
25
30
  // :minWidth="minWidth"
26
31
  // :data-id="test_data_id"
27
32
  // />
28
33
 
29
34
  import styled from 'vue3-styled-components'
35
+ import Icon from '../../icon'
30
36
 
31
37
  const PageContainer = styled.div``
32
38
 
@@ -35,12 +41,14 @@ const ButtonAttrs = {
35
41
  isDisabled: Boolean,
36
42
  minWidth: String,
37
43
  customColor: String,
44
+ fontColor: String,
38
45
  noWrap: Boolean
39
46
  }
40
47
  const ButtonContainer = styled('div', ButtonAttrs)`
41
48
  padding: 7px 15px;
42
49
  font-size: 13px;
43
- color: ${(props) => props.theme.colors.white};
50
+ color: ${(props) =>
51
+ props.fontColor ? props.fontColor : props.theme.colors.white};
44
52
  background-color: ${(props) =>
45
53
  props.isDisabled
46
54
  ? props.theme.colors.disabled
@@ -69,9 +77,22 @@ const ButtonContainer = styled('div', ButtonAttrs)`
69
77
  }
70
78
  `
71
79
 
80
+ const LabelAttrs = {
81
+ hasIcon: Boolean
82
+ }
83
+
84
+ const Label = styled('span', LabelAttrs)`
85
+ display: flex;
86
+ align-items: center;
87
+ justify-content: center;
88
+ gap: ${(props) => (props.hasIcon ? '5px' : '0')};
89
+ `
90
+
72
91
  export default {
73
92
  name: 'main-button',
74
93
  components: {
94
+ Icon,
95
+ Label,
75
96
  PageContainer,
76
97
  ButtonContainer
77
98
  },
@@ -84,6 +105,10 @@ export default {
84
105
  required: false,
85
106
  default: false
86
107
  },
108
+ icon: {
109
+ required: false,
110
+ default: null
111
+ },
87
112
  text: {
88
113
  required: true
89
114
  },
@@ -91,6 +116,9 @@ export default {
91
116
  required: false,
92
117
  default: null
93
118
  },
119
+ fontColor: {
120
+ required: false
121
+ },
94
122
  noWrap: {
95
123
  required: false,
96
124
  default: false
@@ -0,0 +1,125 @@
1
+ <template>
2
+ <div>
3
+ <Text :expand="showButton && showAll" :fontSize="fontSize">{{ text }}</Text>
4
+ <ToggleContainer>
5
+ <ToggleButton
6
+ @click="toggleHandler"
7
+ v-if="showButton && !showAll"
8
+ :fontSize="fontSize"
9
+ >
10
+ {{ $gettext('Show more') }}
11
+ </ToggleButton>
12
+ <ToggleButton
13
+ @click="toggleHandler"
14
+ v-if="showButton && showAll"
15
+ :fontSize="fontSize"
16
+ >
17
+ {{ $gettext('Show less') }}
18
+ </ToggleButton>
19
+ </ToggleContainer>
20
+ </div>
21
+ </template>
22
+
23
+ <script>
24
+ import styled from 'vue3-styled-components'
25
+ import theme from '@/assets/theme.js'
26
+
27
+ const TextAttrs = {
28
+ expand: Boolean,
29
+ fontSize: String
30
+ }
31
+ const Text = styled('p', TextAttrs)`
32
+ display: block;
33
+ display: -webkit-box;
34
+ line-height: 1.3em;
35
+ -webkit-line-clamp: ${(props) => (props.expand ? 'unset' : '4')};
36
+ -webkit-box-orient: vertical;
37
+ overflow: hidden;
38
+ font-size: ${(props) => props.fontSize}px;
39
+ text-overflow: ellipsis;
40
+ `
41
+
42
+ const ToggleContainer = styled.div`
43
+ display: flex;
44
+ width: 100%;
45
+ `
46
+
47
+ const ToggleButton = styled('p', TextAttrs)`
48
+ font-size: ${(props) => props.fontSize}px;
49
+ cursor: pointer;
50
+ color: ${(props) => props.theme.colors.blue};
51
+ `
52
+
53
+ export default {
54
+ name: 'collapsable-info-text',
55
+ props: {
56
+ text: {
57
+ type: String,
58
+ required: true
59
+ },
60
+ fontSize: {
61
+ type: String,
62
+ default: '16px'
63
+ },
64
+ lineCount: {
65
+ type: Number,
66
+ default: 3
67
+ },
68
+ minWidth: {
69
+ type: String,
70
+ default: '100%'
71
+ }
72
+ },
73
+ components: {
74
+ Text,
75
+ ToggleButton,
76
+ ToggleContainer
77
+ },
78
+ data() {
79
+ return {
80
+ showButton: true,
81
+ showAll: false,
82
+ lineBreaks: []
83
+ }
84
+ },
85
+ computed: {
86
+ theme() {
87
+ return theme
88
+ }
89
+ },
90
+ methods: {
91
+ displayText() {
92
+ if (!this.showButton) {
93
+ return this.text
94
+ }
95
+ if (!this.showAll) {
96
+ let countIndex = 0
97
+ this.lineBreaks.forEach((el, index) => {
98
+ if (index < this.lineCount) {
99
+ countIndex += el.length
100
+ }
101
+ })
102
+
103
+ return this.text.slice(0, countIndex + 2) + '...'
104
+ } else {
105
+ return this.text
106
+ }
107
+ },
108
+ toggleHandler() {
109
+ this.showAll = !this.showAll
110
+ }
111
+ },
112
+ created() {
113
+ // TODO: this should divide the text into lines based on with. Currently it's just splitting by line breaks
114
+ // this.lineBreaks = this.text.split('\n')
115
+
116
+ // if (this.lineBreaks.length <= this.lineCount) {
117
+ // this.showButton = false
118
+ // }
119
+
120
+ if (this.text.length <= 170) {
121
+ this.showButton = false
122
+ }
123
+ }
124
+ }
125
+ </script>
@@ -92,6 +92,7 @@
92
92
  fontSize="13px"
93
93
  :label="filter.label"
94
94
  :labelDataId="filter.dataId"
95
+ :isSearchable="filter.choices.length > 7"
95
96
  alignItems="vertical"
96
97
  :disabled="!filter.choices.length"
97
98
  :minOptionLength="1"
@@ -225,6 +226,7 @@
225
226
  fontSize="13px"
226
227
  :label="filter.label"
227
228
  alignItems="vertical"
229
+ :isSearchable="filter.choices.length > 7"
228
230
  :disabled="!filter.choices.length"
229
231
  >
230
232
  <template #selector="{ selectedValue }">
@@ -302,7 +304,7 @@ const ContainerWrapper = styled.div`
302
304
  width: max-content;
303
305
  border: 1px solid ${(props) => props.theme.colors.grey4};
304
306
  border-radius: 4px;
305
- z-index: 9999;
307
+ z-index: 99999;
306
308
  font-size: 13px;
307
309
  `
308
310
 
@@ -4,6 +4,7 @@
4
4
  :color="color"
5
5
  :background-color="backgroundColor"
6
6
  :hovered-color="hoveredColor"
7
+ :animation="animation"
7
8
  >
8
9
  <i v-html="icon.html" />
9
10
  </icon-image>
@@ -56,6 +57,10 @@ const props = defineProps({
56
57
  backgroundColor: {
57
58
  required: false,
58
59
  default: null
60
+ },
61
+ animation: {
62
+ required: false,
63
+ default: 'none'
59
64
  }
60
65
  })
61
66
 
@@ -94,8 +99,10 @@ const StrikedLine = styled('div', { color: String })`
94
99
  const IconImage = styled('div', {
95
100
  color: String,
96
101
  backgroundColor: String,
97
- hoveredColor: String
102
+ hoveredColor: String,
103
+ animation: String
98
104
  })`
105
+ animation: ${(props) => props.animation};
99
106
  width: 100%;
100
107
  svg {
101
108
  width: 100%;
@@ -114,6 +121,11 @@ const IconImage = styled('div', {
114
121
  &:hover + div {
115
122
  background-color: ${(props) => props.hoveredColor};
116
123
  }
124
+ @keyframes fade {
125
+ 50% {
126
+ opacity: 0.3;
127
+ }
128
+ }
117
129
  `
118
130
 
119
131
  const icon = reactive({ html: '' })
@@ -9,6 +9,7 @@
9
9
  :hoveredBackgroundColor="hoveredBackgroundColor"
10
10
  :isHovered="isHovered"
11
11
  :data-id="dataId"
12
+ :noCursor="noCursor"
12
13
  >
13
14
  <icon
14
15
  :disabled="disabled"
@@ -17,6 +18,7 @@
17
18
  :color="iconColor"
18
19
  :hoveredColor="hoveredIconColor"
19
20
  :isStriked="isStriked"
21
+ :animation="isLoading ? 'fade 3s infinite' : 'none'"
20
22
  />
21
23
 
22
24
  <caret v-if="hasCaret">
@@ -29,6 +31,9 @@
29
31
  borderRadius="1px"
30
32
  />
31
33
  </caret>
34
+ <lockContainer v-if="hasLock">
35
+ <icon size="9px" name="lock" color="yellow" />
36
+ </lockContainer>
32
37
  </Wrapper>
33
38
  </template>
34
39
 
@@ -44,6 +49,7 @@
44
49
 
45
50
  import styled from 'vue3-styled-components'
46
51
  import icon from '../icon'
52
+
47
53
  const wrapperAttrs = {
48
54
  color: String,
49
55
  isHovered: Boolean,
@@ -52,8 +58,14 @@ const wrapperAttrs = {
52
58
  size: String,
53
59
  backgroundColor: String,
54
60
  hoveredBackgroundColor: String,
55
- hasBorder: Boolean
61
+ hasBorder: Boolean,
62
+ noCursor: Boolean
56
63
  }
64
+ const lockContainer = styled.div`
65
+ position: absolute;
66
+ bottom: 6px;
67
+ right: 6px;
68
+ `
57
69
  const Wrapper = styled('div', wrapperAttrs)`
58
70
  position: relative;
59
71
  display: inline-flex;
@@ -65,7 +77,8 @@ const Wrapper = styled('div', wrapperAttrs)`
65
77
  : ''};
66
78
  justify-content: center;
67
79
  align-items: center;
68
- cursor: ${(props) => (props.disabled ? 'not-allowed' : 'pointer')};
80
+ cursor: ${(props) =>
81
+ props.noCursor ? 'auto' : props.disabled ? 'not-allowed' : 'pointer'};
69
82
  background-color: ${(props) =>
70
83
  props.theme.colors[props.backgroundColor] || props.backgroundColor};
71
84
  border-radius: ${(props) => props.borderRadius};
@@ -93,7 +106,8 @@ export default {
93
106
  components: {
94
107
  Wrapper,
95
108
  icon,
96
- caret
109
+ caret,
110
+ lockContainer
97
111
  },
98
112
  props: {
99
113
  disabled: {
@@ -147,6 +161,18 @@ export default {
147
161
  isStriked: {
148
162
  required: false,
149
163
  default: false
164
+ },
165
+ isLoading: {
166
+ required: false,
167
+ default: false
168
+ },
169
+ noCursor: {
170
+ required: false,
171
+ default: false
172
+ },
173
+ hasLock: {
174
+ required: false,
175
+ default: false
150
176
  }
151
177
  }
152
178
  }
@@ -1,6 +1,6 @@
1
1
  <template>
2
2
  <info-container>
3
- <icon name="info" size="24px" />
3
+ <icon name="info" size="24px" :color="color" />
4
4
  <text-container>
5
5
  <slot />
6
6
  </text-container>
@@ -8,11 +8,13 @@
8
8
  </template>
9
9
 
10
10
  <script>
11
+ // import InfoCard from '@eturnity/eturnity_reusable_components/src/components/infoCard'
11
12
  import styled from 'vue3-styled-components'
12
13
  import Icon from '../icon'
13
14
 
14
15
  const InfoContainer = styled.div`
15
16
  display: flex;
17
+ align-items: center;
16
18
  gap: 15px;
17
19
  padding: 20px;
18
20
  border: 1px dashed ${(props) => props.theme.colors.grey4};
@@ -30,6 +32,11 @@ export default {
30
32
  Icon,
31
33
  InfoContainer,
32
34
  TextContainer
35
+ },
36
+ props: {
37
+ color: {
38
+ required: false
39
+ }
33
40
  }
34
41
  }
35
42
  </script>
@@ -197,6 +197,11 @@ export default {
197
197
  return !!this.label.length
198
198
  }
199
199
  },
200
+ computed: {
201
+ hasLabel() {
202
+ return !!this.label.length
203
+ }
204
+ },
200
205
  methods: {
201
206
  onChangeHandler(value) {
202
207
  if (this.isDisabled) {
@@ -26,7 +26,7 @@
26
26
  <input-container
27
27
  ref="inputElement"
28
28
  :placeholder="placeholder"
29
- :isError="isError"
29
+ :isError="hasError"
30
30
  :inputWidth="inputWidth"
31
31
  :minWidth="minWidth"
32
32
  :inputHeight="inputHeight"
@@ -53,12 +53,12 @@
53
53
  >
54
54
  <icon name="current_variant" size="20px" />
55
55
  </icon-wrapper>
56
- <icon-wrapper v-if="isError" size="16px">
56
+ <icon-wrapper v-if="hasError" size="16px">
57
57
  <icon name="warning" size="16px" cursor="default" />
58
58
  </icon-wrapper>
59
59
  </icon-container>
60
- <error-message v-if="isError && errorMessage">{{
61
- errorMessage
60
+ <error-message v-if="hasError && hasErrorMessage">{{
61
+ dynamicErrorMessage
62
62
  }}</error-message>
63
63
  </input-error-wrapper>
64
64
  </input-wrapper>
@@ -70,6 +70,7 @@ import styled from 'vue3-styled-components'
70
70
  import InfoText from '../../infoText'
71
71
  import Icon from '../../icon'
72
72
  import ErrorMessage from '../../errorMessage'
73
+ import InputValidations from '../../../mixins/inputValidations.js'
73
74
 
74
75
  const Container = styled.div`
75
76
  width: 100%;
@@ -229,11 +230,25 @@ export default {
229
230
  InputErrorWrapper,
230
231
  optionalLabel
231
232
  },
233
+ mixins: [InputValidations],
232
234
  data() {
233
235
  return {
234
236
  inputTypeData: 'text'
235
237
  }
236
238
  },
239
+ computed: {
240
+ hasError() {
241
+ return this.isError || this.error
242
+ },
243
+ hasErrorMessage() {
244
+ return (
245
+ (this.errorMessage && this.errorMessage.length > 0) || this.errMessage
246
+ )
247
+ },
248
+ dynamicErrorMessage() {
249
+ return this.errMessage || this.errorMessage
250
+ }
251
+ },
237
252
  props: {
238
253
  placeholder: {
239
254
  required: false,
@@ -336,6 +351,7 @@ export default {
336
351
  this.$emit('input-change', event.target.value)
337
352
  },
338
353
  onInputBlur($event) {
354
+ this.validateInput($event.target.value)
339
355
  this.$emit('input-blur', $event.target.value)
340
356
  },
341
357
  toggleShowPassword() {
@@ -3,6 +3,7 @@
3
3
  <radio-wrapper v-for="(item, index) in options" :key="item.value">
4
4
  <label-container
5
5
  :size="size"
6
+ :hasLabel="item.label"
6
7
  :isDisabled="item.disabled"
7
8
  :isChecked="selectedOption === item.value"
8
9
  :checkmarkColor="checkmarkColor"
@@ -17,7 +18,7 @@
17
18
  :data-id="`radio_button_${dataId}_option_${item.value}`"
18
19
  />
19
20
  <span class="checkmark"></span>
20
- <label-text :isDisabled="item.disabled">{{ item.label }}</label-text>
21
+ <label-text :isDisabled="item.disabled" v-if="item.label">{{ item.label }}</label-text>
21
22
  <info-text v-if="item.infoText" :text="item.infoText" size="16px" />
22
23
  </label-container>
23
24
  <image-container v-if="item.img">
@@ -98,7 +99,9 @@ const containerProps = {
98
99
  const LabelContainer = styled('label', containerProps)`
99
100
  display: grid;
100
101
  grid-template-columns: auto 1fr auto;
101
- grid-gap: 15px;
102
+ grid-gap: ${(props) =>
103
+ props.hasLabel
104
+ ? '15px' : 0 };
102
105
  align-items: center;
103
106
  color: ${(props) =>
104
107
  props.isDisabled ? props.theme.colors.grey2 : props.theme.colors.black};
@@ -46,6 +46,7 @@
46
46
  :fontColor="
47
47
  buttonFontColor || colorMode == 'dark' ? 'white' : 'black'
48
48
  "
49
+ :fontSize="fontSize"
49
50
  :hasError="hasError"
50
51
  :hasNoPadding="hasNoPadding"
51
52
  :disabled="disabled"
@@ -73,6 +74,7 @@
73
74
  buttonFontColor || colorMode == 'dark' ? 'white' : 'black'
74
75
  "
75
76
  :value="textSearch"
77
+ :inputWidth="computedWidth"
76
78
  @keydown.stop="onKeyDown"
77
79
  @input-change="searchChange"
78
80
  @click.stop
@@ -149,6 +151,7 @@
149
151
  // <Select
150
152
  // hoverDropdown="true"
151
153
  // selectWidth="100%"
154
+ // minWidth="220px"
152
155
  // optionWidth="50%"
153
156
  // label="that is a label"
154
157
  // alignItems="vertical"
@@ -383,6 +386,8 @@ const inputAttrs = {
383
386
  const InputWrapper = styled('div', inputAttrs)`
384
387
  position: ${(props) => (props.noRelative ? 'static' : 'relative')};
385
388
  display: grid;
389
+ width: 100%;
390
+ min-width: ${(props) => (props.minWidth ? props.minWidth : '150px')};
386
391
  align-items: center;
387
392
  gap: 8px;
388
393
  grid-template-columns: ${(props) =>
@@ -433,6 +438,12 @@ export default {
433
438
  required: false,
434
439
  default: '100%'
435
440
  },
441
+ minWidth: {
442
+ required: false
443
+ },
444
+ maxWidth: {
445
+ required: false
446
+ },
436
447
  selectHeight: {
437
448
  type: String,
438
449
  required: false,
@@ -446,9 +457,6 @@ export default {
446
457
  required: false,
447
458
  default: '36px'
448
459
  },
449
- minWidth: {
450
- required: false
451
- },
452
460
  optionWidth: {
453
461
  required: false,
454
462
  default: null
@@ -478,6 +486,10 @@ export default {
478
486
  dropdownFontColor: {
479
487
  required: false
480
488
  },
489
+ dropDownArrowVisible: {
490
+ required: false,
491
+ default: true
492
+ },
481
493
  caretColor: {
482
494
  required: false
483
495
  },
@@ -520,6 +532,10 @@ export default {
520
532
  type: Boolean,
521
533
  default: false
522
534
  },
535
+ leftPadding: {
536
+ type: String,
537
+ default: '15px'
538
+ },
523
539
  tablePaddingLeft: {
524
540
  required: false
525
541
  },
@@ -564,7 +580,7 @@ export default {
564
580
  data() {
565
581
  return {
566
582
  selectedValue: null,
567
- paddingLeft: this.isDraggable ? '30px' : '15px',
583
+ paddingLeft: this.isDraggable ? '30px' : this.leftPadding,
568
584
  isDropdownOpen: false,
569
585
  isActive: false,
570
586
  textSearch: '',
@@ -608,16 +624,14 @@ export default {
608
624
  toggleCaretDropdown() {
609
625
  this.isDropdownOpen = !this.isDropdownOpen
610
626
  },
611
- openDropdown() {
612
- this.focus()
613
- this.isDropdownOpen = true
614
- },
615
627
  closeDropdown() {
616
628
  this.blur()
629
+ this.clearSearch()
617
630
  this.isDropdownOpen = false
618
631
  },
619
632
  clearSearch() {
620
633
  this.textSearch = ''
634
+ this.searchChange('')
621
635
  },
622
636
  optionSelected(e) {
623
637
  this.selectedValue = e
@@ -654,6 +668,7 @@ export default {
654
668
 
655
669
  return
656
670
  }
671
+
657
672
  el.style.display = 'inherit'
658
673
  })
659
674
  },
@@ -765,6 +780,7 @@ export default {
765
780
  observeSelectWidth() {
766
781
  if (!this.$refs.select) return
767
782
  this.selectResizeObserver = new ResizeObserver(() =>
783
+ // eslint-disable-next-line vue/valid-next-tick
768
784
  this.$nextTick(() => this.getDropdownWidth())
769
785
  )
770
786
  this.selectResizeObserver.observe(this.$refs.dropdown.$el)
@@ -791,9 +807,6 @@ export default {
791
807
  this.$refs.dropdown.$el.scrollTop = topPos
792
808
  }
793
809
  }
794
- },
795
- clearSearch() {
796
- this.textSearch = ''
797
810
  }
798
811
  },
799
812
  computed: {
@@ -813,6 +826,15 @@ export default {
813
826
  this.isDropdownOpen
814
827
  )
815
828
  },
829
+ computedWidth() {
830
+ function removePX(item) {
831
+ return Number(item.replace('px', ''))
832
+ }
833
+
834
+ return this.selectWidth === '100%'
835
+ ? '100%'
836
+ : removePX(this.selectWidth) - removePX(CARET_WIDTH) + 'px'
837
+ },
816
838
  getOptionWidth() {
817
839
  if (this.optionWidth) return this.optionWidth
818
840
 
@@ -846,6 +868,7 @@ export default {
846
868
  },
847
869
  async isDropdownOpen(val) {
848
870
  if (val) {
871
+ this.$emit('on-dropdown-open')
849
872
  setTimeout(() => {
850
873
  this.isClickOutsideActive = true
851
874
  }, 10)