@eturnity/eturnity_reusable_components 7.24.3-EPDM-11320.0 → 7.24.3-EPDM-11143.1

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 (67) hide show
  1. package/.prettierrc +7 -0
  2. package/package.json +20 -6
  3. package/public/favicon.ico +0 -0
  4. package/public/index.html +17 -0
  5. package/src/App.vue +70 -75
  6. package/src/assets/svgIcons/copy.svg +10 -0
  7. package/src/components/addNewButton/index.vue +27 -24
  8. package/src/components/banner/actionBanner/index.vue +30 -32
  9. package/src/components/banner/banner/index.vue +80 -88
  10. package/src/components/banner/infoBanner/index.vue +44 -36
  11. package/src/components/buttons/buttonIcon/index.vue +78 -83
  12. package/src/components/buttons/closeButton/index.vue +26 -26
  13. package/src/components/buttons/mainButton/index.vue +76 -80
  14. package/src/components/card/index.vue +52 -56
  15. package/src/components/collapsableInfoText/index.vue +76 -81
  16. package/src/components/deleteIcon/index.vue +28 -31
  17. package/src/components/draggableInputHandle/index.vue +17 -20
  18. package/src/components/dropdown/Dropdown.stories.js +8 -8
  19. package/src/components/dropdown/index.vue +72 -75
  20. package/src/components/errorMessage/index.vue +23 -23
  21. package/src/components/filter/filterSettings.vue +329 -349
  22. package/src/components/filter/index.vue +130 -130
  23. package/src/components/filter/parentDropdown.vue +40 -43
  24. package/src/components/icon/Icons.stories.js +4 -4
  25. package/src/components/icon/iconCache.js +1 -1
  26. package/src/components/icon/iconCollection.vue +37 -40
  27. package/src/components/icon/index.vue +65 -72
  28. package/src/components/iconWrapper/index.vue +118 -122
  29. package/src/components/infoCard/index.vue +17 -20
  30. package/src/components/infoText/index.vue +82 -88
  31. package/src/components/inputs/checkbox/index.vue +94 -91
  32. package/src/components/inputs/inputNumber/index.vue +488 -508
  33. package/src/components/inputs/inputNumberQuestion/index.vue +124 -127
  34. package/src/components/inputs/inputText/index.vue +252 -265
  35. package/src/components/inputs/radioButton/index.vue +120 -135
  36. package/src/components/inputs/searchInput/index.vue +81 -84
  37. package/src/components/inputs/select/index.vue +631 -644
  38. package/src/components/inputs/select/option/index.vue +91 -91
  39. package/src/components/inputs/select/select.stories.js +7 -7
  40. package/src/components/inputs/slider/index.vue +46 -46
  41. package/src/components/inputs/switchField/index.vue +152 -159
  42. package/src/components/inputs/textAreaInput/index.vue +113 -120
  43. package/src/components/inputs/toggle/index.vue +127 -137
  44. package/src/components/label/index.vue +61 -64
  45. package/src/components/markerItem/index.vue +40 -40
  46. package/src/components/modals/actionModal/index.vue +29 -32
  47. package/src/components/modals/infoModal/index.vue +27 -34
  48. package/src/components/modals/modal/index.vue +80 -88
  49. package/src/components/navigationTabs/index.vue +47 -50
  50. package/src/components/pageSubtitle/index.vue +29 -33
  51. package/src/components/pageTitle/index.vue +39 -47
  52. package/src/components/pagination/index.vue +62 -64
  53. package/src/components/progressBar/index.vue +67 -70
  54. package/src/components/projectMarker/index.vue +163 -172
  55. package/src/components/rangeSlider/Slider.vue +449 -449
  56. package/src/components/rangeSlider/index.vue +270 -282
  57. package/src/components/rangeSlider/utils/dom.js +3 -3
  58. package/src/components/selectedOptions/index.vue +51 -51
  59. package/src/components/sideMenu/index.vue +109 -117
  60. package/src/components/spinner/index.vue +34 -37
  61. package/src/components/tableDropdown/index.vue +326 -343
  62. package/src/components/tables/mainTable/index.vue +106 -109
  63. package/src/components/tables/viewTable/index.vue +92 -105
  64. package/src/components/threeDots/index.vue +171 -174
  65. package/src/components/videoThumbnail/index.vue +59 -67
  66. package/src/components/videoThumbnail/videoThumbnail.stories.js +6 -6
  67. package/.eslintrc.js +0 -125
@@ -1,157 +1,144 @@
1
1
  <template>
2
2
  <Container
3
- :no-relative="noRelative"
4
- :select-width="selectWidth"
3
+ :selectWidth="selectWidth"
4
+ :noRelative="noRelative"
5
5
  @mouseenter="mouseEnterHandler"
6
6
  @mouseleave="mouseLeaveHandler"
7
7
  >
8
- <InputWrapper
9
- :align-items="alignItems"
10
- :has-label="!!label && label.length > 0"
11
- :no-relative="noRelative"
8
+ <input-wrapper
9
+ :hasLabel="!!label && label.length > 0"
10
+ :alignItems="alignItems"
11
+ :noRelative="noRelative"
12
12
  >
13
- <LabelWrapper
14
- v-if="label"
15
- :data-id="labelDataId"
16
- >
17
- <InputLabel
18
- :font-color="
13
+ <label-wrapper v-if="label" :data-id="labelDataId">
14
+ <input-label
15
+ :fontColor="
19
16
  labelFontColor || colorMode == 'dark' ? 'white' : 'eturnityGrey'
20
17
  "
21
- :font-size="fontSize"
22
- >
23
- {{ label }}
24
- <OptionalLabel v-if="labelOptional">
25
- ({{ $gettext('Optional') }})
26
- </OptionalLabel>
27
- </InputLabel>
28
- <InfoText
18
+ :fontSize="fontSize"
19
+ >{{ label }}
20
+ <optionalLabel v-if="labelOptional">
21
+ ({{ $gettext('Optional') }})</optionalLabel
22
+ >
23
+ </input-label>
24
+ <info-text
29
25
  v-if="infoTextMessage"
30
- :size="infoTextSize"
31
26
  :text="infoTextMessage"
27
+ :size="infoTextSize"
32
28
  />
33
- </LabelWrapper>
34
- <SelectButtonWrapper :disabled="disabled">
35
- <SelectButton
29
+ </label-wrapper>
30
+ <select-button-wrapper :disabled="disabled">
31
+ <selectButton
36
32
  ref="select"
37
- :bg-color="
33
+ class="select-button"
34
+ @click="toggleDropdown"
35
+ :selectWidth="selectWidth"
36
+ :selectHeight="selectHeight"
37
+ :height="height"
38
+ :selectMinHeight="selectMinHeight"
39
+ :bgColor="
38
40
  buttonBgColor || colorMode == 'dark' ? 'transparentBlack1' : 'white'
39
41
  "
40
- class="select-button"
41
- :data-id="dataId"
42
- :disabled="disabled"
43
- :font-color="
42
+ :fontColor="
44
43
  buttonFontColor || colorMode == 'dark' ? 'white' : 'black'
45
44
  "
46
- :font-size="fontSize"
47
- :has-error="hasError"
48
- :has-no-padding="isSearchBarVisible || !hasSelectButtonPadding"
49
- :height="height"
50
- :no-relative="noRelative"
51
- :padding-left="paddingLeft"
52
- :select-height="selectHeight"
53
- :select-min-height="selectMinHeight"
54
- :select-width="selectWidth"
55
- :show-border="showBorder"
56
- :show-disabled-background="showDisabledBackground"
57
- :table-padding-left="tablePaddingLeft"
58
- @click="toggleDropdown"
45
+ :fontSize="fontSize"
46
+ :hasError="hasError"
47
+ :hasNoPadding="isSearchBarVisible || !hasSelectButtonPadding"
48
+ :disabled="disabled"
59
49
  @keydown="onKeyDown"
50
+ :showBorder="showBorder"
51
+ :data-id="dataId"
52
+ :paddingLeft="paddingLeft"
53
+ :tablePaddingLeft="tablePaddingLeft"
54
+ :noRelative="noRelative"
55
+ :showDisabledBackground="showDisabledBackground"
60
56
  >
61
- <DraggableInputHandle
57
+ <draggableInputHandle
62
58
  v-if="isDraggable && !isSearchBarVisible"
63
59
  :height="selectHeight"
64
60
  />
65
- <InputText
61
+ <inputText
66
62
  v-if="isSearchBarVisible"
67
63
  ref="searchInput"
68
- background-color="transparent"
69
- :font-color="
64
+ tabindex="0"
65
+ inputHeight="34px"
66
+ :noBorder="true"
67
+ :fontSize="fontSize"
68
+ backgroundColor="transparent"
69
+ :fontColor="
70
70
  buttonFontColor || colorMode == 'dark' ? 'white' : 'black'
71
71
  "
72
- :font-size="fontSize"
73
- input-height="34px"
74
- :input-width="computedWidth"
75
- :no-border="true"
76
- tabindex="0"
77
72
  :value="textSearch"
78
- @click.stop
79
- @input-change="searchChange"
73
+ :inputWidth="computedWidth"
80
74
  @keydown.stop="onKeyDown"
75
+ @input-change="searchChange"
76
+ @click.stop
81
77
  />
82
- <Selector
78
+ <selector
83
79
  v-else
84
- :padding-left="paddingLeft"
85
- :select-width="selectWidth"
86
- :show-border="showBorder"
87
- >
88
- <slot
89
- name="selector"
90
- :selected-value="selectedValue"
91
- ></slot>
92
- </Selector>
93
- <Caret
94
- class="caret_dropdown"
95
- @click.stop="toggleCaretDropdown"
80
+ :showBorder="showBorder"
81
+ :selectWidth="selectWidth"
82
+ :paddingLeft="paddingLeft"
96
83
  >
97
- <RCIcon
84
+ <slot name="selector" :selectedValue="selectedValue"></slot>
85
+ </selector>
86
+ <Caret @click.stop="toggleCaretDropdown" class="caret_dropdown">
87
+ <icon
98
88
  v-if="isDropdownOpen"
89
+ name="arrow_up"
90
+ size="12px"
99
91
  :color="
100
92
  caretColor || colorMode == 'dark'
101
93
  ? 'white'
102
94
  : 'transparentBlack1'
103
95
  "
104
- name="arrow_up"
105
- size="12px"
106
96
  />
107
- <RCIcon
97
+ <icon
108
98
  v-else
99
+ name="arrow_down"
100
+ size="12px"
109
101
  :color="
110
102
  caretColor || colorMode == 'dark'
111
103
  ? 'white'
112
104
  : 'transparentBlack1'
113
105
  "
114
- name="arrow_down"
115
- size="12px"
116
106
  />
117
107
  </Caret>
118
- </SelectButton>
119
- <DropdownWrapper
120
- ref="dropdownWrapperRef"
121
- :no-relative="noRelative"
122
- >
108
+ </selectButton>
109
+ <DropdownWrapper ref="dropdownWrapperRef" :noRelative="noRelative">
123
110
  <Teleport to="#portal-target">
124
- <SelectDropdown
125
- v-show="isSelectDropdownShown"
111
+ <selectDropdown
126
112
  ref="dropdown"
127
- :bg-color="
113
+ v-show="isSelectDropdownShown"
114
+ :dropdownPosition="dropdownPosition"
115
+ :hoveredIndex="hoveredIndex"
116
+ :hoveredValue="hoveredValue"
117
+ :isActive="isActive"
118
+ :optionWidth="getOptionWidth"
119
+ :hoveredBgColor="
120
+ colorMode == 'dark' ? '#000000' : dropdownBgColor
121
+ "
122
+ :bgColor="
128
123
  dropdownBgColor || colorMode == 'dark' ? 'black' : 'white'
129
124
  "
130
- :dropdown-position="dropdownPosition"
131
- :font-color="
125
+ :fontColor="
132
126
  dropdownFontColor || colorMode == 'dark' ? 'white' : 'black'
133
127
  "
134
- :font-size="fontSize"
135
- :hovered-bg-color="
136
- colorMode == 'dark' ? '#000000' : dropdownBgColor
137
- "
138
- :hovered-index="hoveredIndex"
139
- :hovered-value="hoveredValue"
140
- :is-active="isActive"
141
- :min-width="minWidth"
142
- :no-relative="noRelative"
143
- :option-width="getOptionWidth"
144
- :selected-value="selectedValue"
145
- @mouseleave="optionLeave"
146
- @option-hovered="optionHovered"
128
+ :noRelative="noRelative"
129
+ :fontSize="fontSize"
130
+ :minWidth="minWidth"
131
+ :selectedValue="selectedValue"
147
132
  @option-selected="optionSelected"
133
+ @option-hovered="optionHovered"
134
+ @mouseleave="optionLeave"
148
135
  >
149
136
  <slot name="dropdown"></slot>
150
- </SelectDropdown>
137
+ </selectDropdown>
151
138
  </Teleport>
152
139
  </DropdownWrapper>
153
- </SelectButtonWrapper>
154
- </InputWrapper>
140
+ </select-button-wrapper>
141
+ </input-wrapper>
155
142
  </Container>
156
143
  </template>
157
144
 
@@ -179,17 +166,17 @@
179
166
  // </template>
180
167
  // </Select>
181
168
 
182
- import { Teleport } from 'vue'
183
- import styled from 'vue3-styled-components'
184
- import InfoText from '../../infoText'
185
- import RCIcon from '../../icon'
186
- import InputText from '../inputText'
187
- import DraggableInputHandle from '../../draggableInputHandle'
169
+ import { Teleport } from 'vue'
170
+ import styled from 'vue3-styled-components'
171
+ import InfoText from '../../infoText'
172
+ import icon from '../../icon'
173
+ import inputText from '../inputText'
174
+ import draggableInputHandle from '../../draggableInputHandle'
188
175
 
189
- const CARET_WIDTH = '30px'
190
- const BORDER_WIDTH = '1px'
176
+ const CARET_WIDTH = '30px'
177
+ const BORDER_WIDTH = '1px'
191
178
 
192
- const Caret = styled.div`
179
+ const Caret = styled.div`
193
180
  display: flex;
194
181
  align-items: center;
195
182
  justify-content: center;
@@ -201,12 +188,12 @@
201
188
  margin-left: auto;
202
189
  `
203
190
 
204
- const selectorProps = {
205
- selectWidth: String,
206
- paddingLeft: String,
207
- showBorder: Boolean
208
- }
209
- const Selector = styled('div', selectorProps)`
191
+ const selectorProps = {
192
+ selectWidth: String,
193
+ paddingLeft: String,
194
+ showBorder: Boolean
195
+ }
196
+ const Selector = styled('div', selectorProps)`
210
197
  ${(props) =>
211
198
  props.selectWidth === '100%'
212
199
  ? 'width: 100%;'
@@ -222,29 +209,29 @@
222
209
  overflow: hidden;`}
223
210
  `
224
211
 
225
- const labelAttrs = { fontSize: String, fontColor: String }
226
- const InputLabel = styled('div', labelAttrs)`
212
+ const labelAttrs = { fontSize: String, fontColor: String }
213
+ const InputLabel = styled('div', labelAttrs)`
227
214
  color: ${(props) =>
228
215
  props.theme.colors[props.fontColor]
229
216
  ? props.theme.colors[props.fontColor]
230
- : props.fontColor};
217
+ : props.fontColor};
231
218
  font-size: ${(props) => props.fontSize};
232
219
  font-weight: 700;
233
220
  `
234
- const OptionalLabel = styled.span`
221
+ const optionalLabel = styled.span`
235
222
  font-weight: 300;
236
223
  `
237
- const inputProps = {
238
- selectWidth: String,
239
- optionWidth: String,
240
- noRelative: Boolean
241
- }
242
- const Container = styled('div', inputProps)`
224
+ const inputProps = {
225
+ selectWidth: String,
226
+ optionWidth: String,
227
+ noRelative: Boolean
228
+ }
229
+ const Container = styled('div', inputProps)`
243
230
  width: ${(props) => props.selectWidth};
244
231
  position: ${(props) => (props.noRelative ? 'static' : 'relative')};
245
232
  display: inline-block;
246
233
  `
247
- const LabelWrapper = styled.div`
234
+ const LabelWrapper = styled.div`
248
235
  display: inline-grid;
249
236
  grid-template-columns: auto auto;
250
237
  grid-gap: 12px;
@@ -252,30 +239,30 @@
252
239
  justify-content: start;
253
240
  `
254
241
 
255
- const SelectButtonWrapperAttrs = {
256
- disabled: Boolean
257
- }
258
- const SelectButtonWrapper = styled('div', SelectButtonWrapperAttrs)`
242
+ const SelectButtonWrapperAttrs = {
243
+ disabled: Boolean
244
+ }
245
+ const SelectButtonWrapper = styled('div', SelectButtonWrapperAttrs)`
259
246
  ${(props) => (props.disabled ? 'cursor: not-allowed' : 'cursor: pointer')};
260
247
  `
261
248
 
262
- const selectButtonAttrs = {
263
- bgColor: String,
264
- fontColor: String,
265
- hasError: Boolean,
266
- disabled: Boolean,
267
- selectHeight: String,
268
- selectWidth: String,
269
- height: String,
270
- selectMinHeight: String,
271
- hasNoPadding: Boolean,
272
- showBorder: Boolean,
273
- paddingLeft: String,
274
- noRelative: Boolean,
275
- tablePaddingLeft: String,
276
- showDisabledBackground: Boolean
277
- }
278
- const SelectButton = styled('div', selectButtonAttrs)`
249
+ const selectButtonAttrs = {
250
+ bgColor: String,
251
+ fontColor: String,
252
+ hasError: Boolean,
253
+ disabled: Boolean,
254
+ selectHeight: String,
255
+ selectWidth: String,
256
+ height: String,
257
+ selectMinHeight: String,
258
+ hasNoPadding: Boolean,
259
+ showBorder: Boolean,
260
+ paddingLeft: String,
261
+ noRelative: Boolean,
262
+ tablePaddingLeft: String,
263
+ showDisabledBackground: Boolean
264
+ }
265
+ const selectButton = styled('div', selectButtonAttrs)`
279
266
  position: ${(props) => (props.noRelative ? 'static' : 'relative')};
280
267
  box-sizing: border-box;
281
268
  border-radius: 4px;
@@ -289,7 +276,7 @@
289
276
  : props.tablePaddingLeft
290
277
  ? props.tablePaddingLeft
291
278
  : props.paddingLeft
292
- }`};
279
+ }`};
293
280
  text-align: left;
294
281
  min-height: ${(props) =>
295
282
  props.selectHeight
@@ -298,7 +285,7 @@
298
285
  ? props.selectMinHeight
299
286
  : props.height
300
287
  ? props.height
301
- : '36px'};
288
+ : '36px'};
302
289
  display: flex;
303
290
  align-items: center;
304
291
  height: ${(props) => props.selectHeight};
@@ -314,38 +301,38 @@
314
301
  ? props.theme.colors.grey5
315
302
  : props.theme.colors[props.bgColor]
316
303
  ? props.theme.colors[props.bgColor]
317
- : props.bgColor};
304
+ : props.bgColor};
318
305
  color: ${(props) =>
319
306
  props.theme.colors[props.fontColor]
320
307
  ? props.theme.colors[props.fontColor]
321
- : props.fontColor};
308
+ : props.fontColor};
322
309
  ${(props) => (props.disabled ? 'pointer-events: none' : '')};
323
310
  overflow: hidden;
324
311
  & > .handle {
325
312
  border-right: ${(props) =>
326
- props.hasError ? props.theme.colors.red : props.theme.colors.grey4}
313
+ props.hasError ? props.theme.colors.red : props.theme.colors.grey4}
327
314
  1px solid;
328
315
  }
329
316
  `
330
- const selectDropdownAttrs = {
331
- hoveredBgColor: String,
332
- bgColor: String,
333
- fontColor: String,
334
- optionWidth: String,
335
- hoveredIndex: Number,
336
- fontSize: String,
337
- dropdownPosition: Object,
338
- hoveredValue: Number | String,
339
- selectedValue: Number | String,
340
- noRelative: Boolean,
341
- minWidth: String
342
- }
343
- const SelectDropdown = styled('div', selectDropdownAttrs)`
317
+ const selectDropdownAttrs = {
318
+ hoveredBgColor: String,
319
+ bgColor: String,
320
+ fontColor: String,
321
+ optionWidth: String,
322
+ hoveredIndex: Number,
323
+ fontSize: String,
324
+ dropdownPosition: Object,
325
+ hoveredValue: Number | String,
326
+ selectedValue: Number | String,
327
+ noRelative: Boolean,
328
+ minWidth: String
329
+ }
330
+ const selectDropdown = styled('div', selectDropdownAttrs)`
344
331
  box-sizing: border-box;
345
332
  z-index: ${(props) => (props.isActive ? '2' : '99999')};
346
333
  position: absolute;
347
334
  top: ${(props) =>
348
- props.noRelative ? 'auto' : props.dropdownPosition?.top + 'px'};
335
+ props.noRelative ? 'auto' : props.dropdownPosition?.top + 'px'};
349
336
  left: ${(props) => props.dropdownPosition?.left}px;
350
337
  border: ${BORDER_WIDTH} solid ${(props) => props.theme.colors.grey4};
351
338
  border-radius: 4px;
@@ -360,36 +347,36 @@
360
347
  ? props.minWidth
361
348
  : props.optionWidth
362
349
  ? props.optionWidth
363
- : '100%'};
350
+ : '100%'};
364
351
  background-color: ${(props) =>
365
352
  props.theme.colors[props.bgColor]
366
353
  ? props.theme.colors[props.bgColor]
367
- : props.bgColor};
354
+ : props.bgColor};
368
355
  color: ${(props) =>
369
356
  props.theme.colors[props.fontColor]
370
357
  ? props.theme.colors[props.fontColor]
371
- : props.fontColor};
358
+ : props.fontColor};
372
359
  max-height: 300px;
373
360
  overflow-y: auto;
374
361
  & > div[data-value='${(props) => props.hoveredValue}'] {
375
362
  background-color: ${(props) =>
376
363
  props.theme.colors[props.hoveredBgColor]
377
364
  ? props.theme.colors[props.hoveredBgColor]
378
- : props.hoveredBgColor};
365
+ : props.hoveredBgColor};
379
366
  }
380
367
  font-size: ${(props) => props.fontSize};
381
368
  `
382
- selectDropdown.emits = ['option-hovered', 'option-selected']
383
- const DropdownAttrs = { noRelative: Boolean }
384
- const DropdownWrapper = styled('div', DropdownAttrs)`
369
+ selectDropdown.emits = ['option-hovered', 'option-selected']
370
+ const DropdownAttrs = { noRelative: Boolean }
371
+ const DropdownWrapper = styled('div', DropdownAttrs)`
385
372
  position: ${(props) => (props.noRelative ? 'static' : 'relative')};
386
373
  `
387
- const inputAttrs = {
388
- alignItems: String,
389
- hasLabel: Boolean,
390
- noRelative: Boolean
391
- }
392
- const InputWrapper = styled('div', inputAttrs)`
374
+ const inputAttrs = {
375
+ alignItems: String,
376
+ hasLabel: Boolean,
377
+ noRelative: Boolean
378
+ }
379
+ const InputWrapper = styled('div', inputAttrs)`
393
380
  position: ${(props) => (props.noRelative ? 'static' : 'relative')};
394
381
  display: grid;
395
382
  width: 100%;
@@ -397,502 +384,502 @@
397
384
  align-items: center;
398
385
  gap: 8px;
399
386
  grid-template-columns: ${(props) =>
400
- props.alignItems === 'vertical' || !props.hasLabel ? '1fr' : 'auto 1fr'};
387
+ props.alignItems === 'vertical' || !props.hasLabel ? '1fr' : 'auto 1fr'};
401
388
  `
402
389
 
403
- const DROPDOWN_HEIGHT_OFFSET = 4
404
- const DROPDOWN_TOP_OFFSET = 21
405
- const MIN_OPTION_LENGTH = 5
390
+ const DROPDOWN_HEIGHT_OFFSET = 4
391
+ const DROPDOWN_TOP_OFFSET = 21
392
+ const MIN_OPTION_LENGTH = 5
406
393
 
407
- const DROPDOWN_MENU_POSITIONS = {
408
- Automatic: 'automatic',
409
- Bottom: 'bottom'
410
- }
394
+ const DROPDOWN_MENU_POSITIONS = {
395
+ Automatic: 'automatic',
396
+ Bottom: 'bottom'
397
+ }
411
398
 
412
- export default {
413
- name: 'RCselect',
399
+ export default {
400
+ name: 'RCselect',
414
401
 
415
- components: {
416
- SelectButton,
417
- SelectButtonWrapper,
418
- SelectDropdown,
419
- Container,
420
- InputLabel,
421
- LabelWrapper,
422
- OptionalLabel,
423
- InfoText,
424
- InputWrapper,
425
- DropdownWrapper,
426
- RCIcon,
427
- Caret,
428
- Selector,
429
- InputText,
430
- Teleport,
431
- DraggableInputHandle
402
+ props: {
403
+ value: {
404
+ required: false,
405
+ default: null
406
+ },
407
+ fontSize: {
408
+ required: false,
409
+ default: '13px'
410
+ },
411
+ noRelative: {
412
+ required: false,
413
+ default: false
414
+ },
415
+ label: {
416
+ required: false
417
+ },
418
+ labelOptional: {
419
+ required: false,
420
+ default: false
421
+ },
422
+ labelDataId: {
423
+ required: false,
424
+ default: ''
425
+ },
426
+ infoTextMessage: {
427
+ required: false
428
+ },
429
+ selectWidth: {
430
+ type: String,
431
+ required: false,
432
+ default: '100%'
433
+ },
434
+ minWidth: {
435
+ required: false
436
+ },
437
+ maxWidth: {
438
+ required: false
439
+ },
440
+ selectHeight: {
441
+ type: String,
442
+ required: false,
443
+ default: null
432
444
  },
445
+ height: {
446
+ required: false,
447
+ default: null
448
+ },
449
+ selectMinHeight: {
450
+ required: false,
451
+ default: '36px'
452
+ },
453
+ optionWidth: {
454
+ required: false,
455
+ default: null
456
+ },
457
+ hoverDropdown: {
458
+ required: false,
459
+ default: false
460
+ },
461
+ dropdownAutoClose: {
462
+ required: false,
463
+ default: false
464
+ },
465
+ alignItems: {
466
+ required: false,
467
+ default: 'horizontal'
468
+ },
469
+ buttonBgColor: {
470
+ required: false
471
+ },
472
+ buttonFontColor: {
473
+ required: false
474
+ },
475
+ dropdownBgColor: {
476
+ required: false,
477
+ default: 'grey5'
478
+ },
479
+ dropdownFontColor: {
480
+ required: false
481
+ },
482
+ dropDownArrowVisible: {
483
+ required: false,
484
+ default: true
485
+ },
486
+ caretColor: {
487
+ required: false
488
+ },
489
+ labelFontColor: {
490
+ required: false
491
+ },
492
+ colorMode: {
493
+ required: false,
494
+ default: 'light'
495
+ },
496
+ isSearchable: {
497
+ required: false,
498
+ default: true
499
+ },
500
+ hasError: {
501
+ required: false,
502
+ default: false
503
+ },
504
+ disabled: {
505
+ required: false,
506
+ default: false
507
+ },
508
+ isAutoSearch: {
509
+ required: false,
510
+ default: true
511
+ },
512
+ showBorder: {
513
+ required: false,
514
+ default: true
515
+ },
516
+ infoTextSize: {
517
+ required: false,
518
+ default: '14px'
519
+ },
520
+ dataId: {
521
+ type: String,
522
+ default: ''
523
+ },
524
+ hasSelectButtonPadding: {
525
+ type: Boolean,
526
+ default: true
527
+ },
528
+ isDraggable: {
529
+ type: Boolean,
530
+ default: false
531
+ },
532
+ leftPadding: {
533
+ type: String,
534
+ default: '15px'
535
+ },
536
+ tablePaddingLeft: {
537
+ required: false
538
+ },
539
+ showDisabledBackground: {
540
+ required: false,
541
+ default: true
542
+ },
543
+ minOptionLength: {
544
+ type: Number,
545
+ default: MIN_OPTION_LENGTH
546
+ },
547
+ dropdownMenuPosition: {
548
+ type: String,
549
+ default: DROPDOWN_MENU_POSITIONS.Automatic // options: ['automatic', bottom]
550
+ }
551
+ },
433
552
 
434
- props: {
435
- value: {
436
- required: false,
437
- default: null
438
- },
439
- fontSize: {
440
- required: false,
441
- default: '13px'
442
- },
443
- noRelative: {
444
- required: false,
445
- default: false
446
- },
447
- label: {
448
- required: false
449
- },
450
- labelOptional: {
451
- required: false,
452
- default: false
453
- },
454
- labelDataId: {
455
- required: false,
456
- default: ''
457
- },
458
- infoTextMessage: {
459
- required: false
460
- },
461
- selectWidth: {
462
- type: String,
463
- required: false,
464
- default: '100%'
465
- },
466
- minWidth: {
467
- required: false
468
- },
469
- maxWidth: {
470
- required: false
471
- },
472
- selectHeight: {
473
- type: String,
474
- required: false,
475
- default: null
476
- },
477
- height: {
478
- required: false,
479
- default: null
480
- },
481
- selectMinHeight: {
482
- required: false,
483
- default: '36px'
484
- },
485
- optionWidth: {
486
- required: false,
487
- default: null
488
- },
489
- hoverDropdown: {
490
- required: false,
491
- default: false
492
- },
493
- dropdownAutoClose: {
494
- required: false,
495
- default: false
496
- },
497
- alignItems: {
498
- required: false,
499
- default: 'horizontal'
500
- },
501
- buttonBgColor: {
502
- required: false
503
- },
504
- buttonFontColor: {
505
- required: false
506
- },
507
- dropdownBgColor: {
508
- required: false,
509
- default: 'grey5'
510
- },
511
- dropdownFontColor: {
512
- required: false
513
- },
514
- dropDownArrowVisible: {
515
- required: false,
516
- default: true
517
- },
518
- caretColor: {
519
- required: false
520
- },
521
- labelFontColor: {
522
- required: false
523
- },
524
- colorMode: {
525
- required: false,
526
- default: 'light'
527
- },
528
- isSearchable: {
529
- required: false,
530
- default: true
531
- },
532
- hasError: {
533
- required: false,
534
- default: false
535
- },
536
- disabled: {
537
- required: false,
538
- default: false
539
- },
540
- isAutoSearch: {
541
- required: false,
542
- default: true
543
- },
544
- showBorder: {
545
- required: false,
546
- default: true
547
- },
548
- infoTextSize: {
549
- required: false,
550
- default: '14px'
551
- },
552
- dataId: {
553
- type: String,
554
- default: ''
555
- },
556
- hasSelectButtonPadding: {
557
- type: Boolean,
558
- default: true
559
- },
560
- isDraggable: {
561
- type: Boolean,
562
- default: false
563
- },
564
- leftPadding: {
565
- type: String,
566
- default: '15px'
567
- },
568
- tablePaddingLeft: {
569
- required: false
570
- },
571
- showDisabledBackground: {
572
- required: false,
573
- default: true
574
- },
575
- minOptionLength: {
576
- type: Number,
577
- default: MIN_OPTION_LENGTH
578
- },
579
- dropdownMenuPosition: {
580
- type: String,
581
- default: DROPDOWN_MENU_POSITIONS.Automatic // options: ['automatic', bottom]
553
+ components: {
554
+ selectButton,
555
+ SelectButtonWrapper,
556
+ selectDropdown,
557
+ Container,
558
+ InputLabel,
559
+ LabelWrapper,
560
+ optionalLabel,
561
+ InfoText,
562
+ InputWrapper,
563
+ DropdownWrapper,
564
+ icon,
565
+ Caret,
566
+ Selector,
567
+ inputText,
568
+ Teleport,
569
+ draggableInputHandle
570
+ },
571
+
572
+ data() {
573
+ return {
574
+ selectedValue: null,
575
+ paddingLeft: this.isDraggable ? '30px' : this.leftPadding,
576
+ isDropdownOpen: false,
577
+ isActive: false,
578
+ textSearch: '',
579
+ hoveredIndex: 0,
580
+ isClickOutsideActive: false,
581
+ dropdownPosition: {
582
+ left: null,
583
+ top: null
584
+ },
585
+ dropdownWidth: null,
586
+ hoveredValue: null
587
+ }
588
+ },
589
+ mounted() {
590
+ this.observeDropdownHeight()
591
+ this.observeSelectWidth()
592
+ window.addEventListener('resize', this.handleSetDropdownOffet)
593
+ },
594
+ beforeMount() {
595
+ this.selectedValue = this.value
596
+ document.addEventListener('click', this.clickOutside)
597
+ this.getDropdownPosition()
598
+ window.removeEventListener('resize', this.handleSetDropdownOffet)
599
+ if (this.dropdownResizeObserver) this.dropdownResizeObserver.disconnect()
600
+ if (this.selectResizeObserver) this.selectResizeObserver.disconnect()
601
+ },
602
+ unmounted() {
603
+ document.removeEventListener('click', this.clickOutside)
604
+ },
605
+ methods: {
606
+ focus() {
607
+ this.isActive = true
608
+ },
609
+ blur(e) {
610
+ this.isActive = false
611
+ this.$emit('blur', e)
612
+ },
613
+ toggleDropdown() {
614
+ this.isDropdownOpen = !this.isDropdownOpen
615
+ },
616
+ toggleCaretDropdown() {
617
+ this.isDropdownOpen = !this.isDropdownOpen
618
+ },
619
+ closeDropdown() {
620
+ this.blur()
621
+ this.clearSearch()
622
+ this.isDropdownOpen = false
623
+ },
624
+ clearSearch() {
625
+ this.textSearch = ''
626
+ this.searchChange('')
627
+ },
628
+ optionSelected(e) {
629
+ this.selectedValue = e
630
+ this.closeDropdown()
631
+ this.blur()
632
+ this.$emit('input-change', e)
633
+ },
634
+ optionHovered(e) {
635
+ this.hoveredValue = e
636
+ },
637
+ mouseEnterHandler() {
638
+ if (this.hoverDropdown) {
639
+ this.focus()
640
+ this.isDropdownOpen = true
582
641
  }
583
642
  },
584
-
585
- data() {
586
- return {
587
- selectedValue: null,
588
- paddingLeft: this.isDraggable ? '30px' : this.leftPadding,
589
- isDropdownOpen: false,
590
- isActive: false,
591
- textSearch: '',
592
- hoveredIndex: 0,
593
- isClickOutsideActive: false,
594
- dropdownPosition: {
595
- left: null,
596
- top: null
597
- },
598
- dropdownWidth: null,
599
- hoveredValue: null
643
+ mouseLeaveHandler() {
644
+ if (this.hoverDropdown) {
645
+ this.blur()
600
646
  }
601
647
  },
602
- computed: {
603
- optionLength() {
604
- if (this.isDropdownOpen) {
605
- return this.$refs.dropdown.$el.childElementCount > 1
606
- ? this.$refs.dropdown.$el.childElementCount
607
- : this.$refs.dropdown.$el.children[0].childElementCount
608
- }
648
+ optionLeave() {
649
+ if (this.dropdownAutoClose) {
650
+ this.isDropdownOpen = false
651
+ }
652
+ },
653
+ searchChange(value) {
654
+ this.textSearch = value
655
+ this.$emit('search-change', value)
656
+ const dropdownChildren = [...this.$refs.dropdown.$el.children]
657
+ dropdownChildren.forEach((el) => {
658
+ if (!el.textContent.toLowerCase().includes(value.toLowerCase())) {
659
+ el.style.display = 'none'
609
660
 
610
- return 0
611
- },
612
- isSearchBarVisible() {
613
- return (
614
- this.isSearchable &&
615
- this.optionLength >= this.minOptionLength &&
616
- this.isDropdownOpen
617
- )
618
- },
619
- computedWidth() {
620
- function removePX(item) {
621
- return Number(item.replace('px', ''))
661
+ return
622
662
  }
623
663
 
624
- return this.selectWidth === '100%'
625
- ? '100%'
626
- : removePX(this.selectWidth) - removePX(CARET_WIDTH) + 'px'
627
- },
628
- getOptionWidth() {
629
- if (this.optionWidth) return this.optionWidth
630
-
631
- return this.dropdownWidth
632
- },
633
- isSelectDropdownShown() {
634
- return (
635
- this.isDropdownOpen &&
636
- this.dropdownPosition.left !== null &&
637
- (!this.isSearchable || this.isSearchable)
638
- )
639
- },
640
- isMobileDevice() {
641
- const userAgent = navigator.userAgent || navigator.vendor || window.opera
642
- const touchCapable =
643
- 'ontouchstart' in window ||
644
- navigator.maxTouchPoints > 0 ||
645
- navigator.msMaxTouchPoints > 0
646
-
647
- return (
648
- /Android/i.test(userAgent) ||
649
- /iPad|iPhone|iPod/.test(userAgent) ||
650
- (/Macintosh/.test(userAgent) && touchCapable) ||
651
- /windows phone/i.test(userAgent)
652
- )
664
+ el.style.display = 'inherit'
665
+ })
666
+ },
667
+ clickOutside(event) {
668
+ const dropdownRef = this.$refs.dropdown
669
+ // we need to prevent closing on selecting an option, because in the case of
670
+ // a disabled option, we don't want to close the dropdown
671
+ if (!this.isClickOutsideActive) return
672
+ if (
673
+ this.$refs.select.$el == event.target ||
674
+ this.$refs.select.$el.contains(event.target) ||
675
+ event.target.id === 'more-button' ||
676
+ event.target.parentNode === dropdownRef.$el
677
+ ) {
678
+ return
679
+ } else {
680
+ this.closeDropdown()
653
681
  }
654
682
  },
655
- watch: {
656
- value(val) {
657
- this.selectedValue = val
658
- },
659
- async isDropdownOpen(val) {
660
- if (val) {
661
- this.$emit('on-dropdown-open')
662
- setTimeout(() => {
663
- this.isClickOutsideActive = true
664
- }, 10)
665
- await this.$nextTick()
666
- this.handleSetDropdownOffet()
667
- } else {
668
- this.dropdownPosition.left = null
669
- setTimeout(() => {
670
- this.isClickOutsideActive = false
671
- }, 10)
672
- }
673
- if (val && this.isSearchable) {
674
- this.$nextTick(() => {
675
- if (this.$refs.searchInput && !this.isMobileDevice) {
676
- this.$refs.searchInput.$el.querySelector('input').focus()
677
- }
678
- })
679
- }
683
+ onKeyDown(e) {
684
+ if (e.key == 'ArrowDown') {
685
+ this.onArrowPress(1)
686
+ } else if (e.key == 'ArrowUp') {
687
+ this.onArrowPress(-1)
688
+ } else if (e.key == 'Enter') {
689
+ const optionHoveredComponent = [...this.$refs.dropdown.$el.children][
690
+ (this.hoveredIndex - 1 + this.optionLength) % this.optionLength
691
+ ]
692
+ this.optionSelected(optionHoveredComponent.$el.dataset.value)
680
693
  }
681
694
  },
682
- mounted() {
683
- this.observeDropdownHeight()
684
- this.observeSelectWidth()
685
- window.addEventListener('resize', this.handleSetDropdownOffet)
686
- },
687
- beforeMount() {
688
- this.selectedValue = this.value
689
- document.addEventListener('click', this.clickOutside)
690
- this.getDropdownPosition()
691
- window.removeEventListener('resize', this.handleSetDropdownOffet)
692
- if (this.dropdownResizeObserver) this.dropdownResizeObserver.disconnect()
693
- if (this.selectResizeObserver) this.selectResizeObserver.disconnect()
694
- },
695
- unmounted() {
696
- document.removeEventListener('click', this.clickOutside)
697
- },
698
- methods: {
699
- focus() {
700
- this.isActive = true
701
- },
702
- blur(e) {
703
- this.isActive = false
704
- this.$emit('blur', e)
705
- },
706
- toggleDropdown() {
707
- this.isDropdownOpen = !this.isDropdownOpen
708
- },
709
- toggleCaretDropdown() {
710
- this.isDropdownOpen = !this.isDropdownOpen
711
- },
712
- closeDropdown() {
713
- this.blur()
714
- this.clearSearch()
715
- this.isDropdownOpen = false
716
- },
717
- clearSearch() {
718
- this.textSearch = ''
719
- this.searchChange('')
720
- },
721
- optionSelected(e) {
722
- this.selectedValue = e
723
- this.closeDropdown()
724
- this.blur()
725
- this.$emit('input-change', e)
726
- },
727
- optionHovered(e) {
728
- this.hoveredValue = e
729
- },
730
- mouseEnterHandler() {
731
- if (this.hoverDropdown) {
732
- this.focus()
733
- this.isDropdownOpen = true
734
- }
735
- },
736
- mouseLeaveHandler() {
737
- if (this.hoverDropdown) {
738
- this.blur()
739
- }
740
- },
741
- optionLeave() {
742
- if (this.dropdownAutoClose) {
743
- this.isDropdownOpen = false
744
- }
745
- },
746
- searchChange(value) {
747
- this.textSearch = value
748
- this.$emit('search-change', value)
749
- const dropdownChildren = [...this.$refs.dropdown.$el.children]
750
- dropdownChildren.forEach((el) => {
751
- if (!el.textContent.toLowerCase().includes(value.toLowerCase())) {
752
- el.style.display = 'none'
695
+ // If some part of the dropdown menu is outside viewport of the bottom of the screen,
696
+ // we need to offset it and display it at the top of the select dropdown instead
697
+ async getDropdownPosition() {
698
+ if (
699
+ !this.$refs.dropdownWrapperRef ||
700
+ !this.$refs.select ||
701
+ !this.$refs.dropdown
702
+ ) {
703
+ return
704
+ }
705
+ await this.$nextTick()
706
+ const isDisplayedAtBottom = await this.generateDropdownPosition()
707
+ // If the dropdown menu is going to be displayed at the bottom,
708
+ // we need reverify its position after a dom update (nextTick)
709
+ await this.$nextTick()
710
+ if (isDisplayedAtBottom) this.generateDropdownPosition()
711
+ },
712
+ async generateDropdownPosition() {
713
+ const isDropdownNotCompletelyVisible =
714
+ await this.isBottomOfDropdownOutOfViewport()
715
+ const dropdownWrapperEl = this.$refs.dropdownWrapperRef.$el
716
+ const selectButtonHeight = this.$refs.select.$el.clientHeight
717
+ const dropdownHeight = this.$refs.dropdown.$el.clientHeight
718
+ const dropdownWrapperRelativeHeight =
719
+ dropdownWrapperEl.getBoundingClientRect().top +
720
+ window.scrollY +
721
+ DROPDOWN_HEIGHT_OFFSET
753
722
 
754
- return
755
- }
723
+ const top =
724
+ isDropdownNotCompletelyVisible ||
725
+ (!isDropdownNotCompletelyVisible &&
726
+ this.dropdownMenuPosition === DROPDOWN_MENU_POSITIONS.Bottom)
727
+ ? dropdownWrapperRelativeHeight
728
+ : dropdownWrapperRelativeHeight -
729
+ dropdownHeight -
730
+ selectButtonHeight -
731
+ DROPDOWN_TOP_OFFSET
732
+ const left = this.dropdownPosition.left
733
+ ? this.dropdownPosition.left
734
+ : dropdownWrapperEl.getBoundingClientRect().left + window.scrollX
756
735
 
757
- el.style.display = 'inherit'
758
- })
759
- },
760
- clickOutside(event) {
761
- const dropdownRef = this.$refs.dropdown
762
- // we need to prevent closing on selecting an option, because in the case of
763
- // a disabled option, we don't want to close the dropdown
764
- if (!this.isClickOutsideActive) return
765
- if (
766
- this.$refs.select.$el == event.target ||
767
- this.$refs.select.$el.contains(event.target) ||
768
- event.target.id === 'more-button' ||
769
- event.target.parentNode === dropdownRef.$el
770
- ) {
771
- return
772
- } else {
773
- this.closeDropdown()
774
- }
775
- },
776
- onKeyDown(e) {
777
- if (e.key == 'ArrowDown') {
778
- this.onArrowPress(1)
779
- } else if (e.key == 'ArrowUp') {
780
- this.onArrowPress(-1)
781
- } else if (e.key == 'Enter') {
782
- const optionHoveredComponent = [...this.$refs.dropdown.$el.children][
783
- (this.hoveredIndex - 1 + this.optionLength) % this.optionLength
784
- ]
785
- this.optionSelected(optionHoveredComponent.$el.dataset.value)
786
- }
787
- },
788
- // If some part of the dropdown menu is outside viewport of the bottom of the screen,
789
- // we need to offset it and display it at the top of the select dropdown instead
790
- async getDropdownPosition() {
791
- if (
792
- !this.$refs.dropdownWrapperRef ||
793
- !this.$refs.select ||
794
- !this.$refs.dropdown
795
- ) {
796
- return
797
- }
798
- await this.$nextTick()
799
- const isDisplayedAtBottom = await this.generateDropdownPosition()
800
- // If the dropdown menu is going to be displayed at the bottom,
801
- // we need reverify its position after a dom update (nextTick)
802
- await this.$nextTick()
803
- if (isDisplayedAtBottom) this.generateDropdownPosition()
804
- },
805
- async generateDropdownPosition() {
806
- const isDropdownNotCompletelyVisible =
807
- await this.isBottomOfDropdownOutOfViewport()
808
- const dropdownWrapperEl = this.$refs.dropdownWrapperRef.$el
809
- const selectButtonHeight = this.$refs.select.$el.clientHeight
810
- const dropdownHeight = this.$refs.dropdown.$el.clientHeight
811
- const dropdownWrapperRelativeHeight =
812
- dropdownWrapperEl.getBoundingClientRect().top +
813
- window.scrollY +
814
- DROPDOWN_HEIGHT_OFFSET
736
+ this.dropdownPosition = { left: Math.floor(left), top: Math.floor(top) }
815
737
 
816
- const top =
817
- isDropdownNotCompletelyVisible ||
818
- (!isDropdownNotCompletelyVisible &&
819
- this.dropdownMenuPosition === DROPDOWN_MENU_POSITIONS.Bottom)
820
- ? dropdownWrapperRelativeHeight
821
- : dropdownWrapperRelativeHeight -
822
- dropdownHeight -
823
- selectButtonHeight -
824
- DROPDOWN_TOP_OFFSET
825
- const left = this.dropdownPosition.left
826
- ? this.dropdownPosition.left
827
- : dropdownWrapperEl.getBoundingClientRect().left + window.scrollX
738
+ return isDropdownNotCompletelyVisible
739
+ },
740
+ async isBottomOfDropdownOutOfViewport() {
741
+ if (
742
+ !this.$refs.dropdown ||
743
+ this.dropdownMenuPosition === DROPDOWN_MENU_POSITIONS.Bottom
744
+ ) {
745
+ return false
746
+ }
828
747
 
829
- this.dropdownPosition = { left: Math.floor(left), top: Math.floor(top) }
748
+ await this.$nextTick()
749
+ const rect = this.$refs.dropdown.$el.getBoundingClientRect()
750
+ const windowHeight =
751
+ window.innerHeight || document.documentElement.clientHeight
830
752
 
831
- return isDropdownNotCompletelyVisible
832
- },
833
- async isBottomOfDropdownOutOfViewport() {
834
- if (
835
- !this.$refs.dropdown ||
836
- this.dropdownMenuPosition === DROPDOWN_MENU_POSITIONS.Bottom
837
- ) {
838
- return false
753
+ if (windowHeight <= 650) return true
754
+
755
+ // using Math.floor because the offsets may contain decimals we are not going to consider here
756
+ return Math.floor(rect.top) + Math.floor(rect.height) <= windowHeight
757
+ },
758
+ observeDropdownHeight() {
759
+ if (!this.$refs.dropdown) return
760
+ this.dropdownResizeObserver = new ResizeObserver(() => {
761
+ this.$nextTick(() => this.getDropdownPosition())
762
+ })
763
+ this.dropdownResizeObserver.observe(this.$refs.dropdown.$el)
764
+ },
765
+ handleSetDropdownOffet() {
766
+ if (!this.$refs.select) return
767
+ this.dropdownPosition.left = Math.floor(
768
+ this.$refs.select.$el.getBoundingClientRect().left
769
+ )
770
+ this.getDropdownWidth()
771
+ },
772
+ observeSelectWidth() {
773
+ if (!this.$refs.select) return
774
+ this.selectResizeObserver = new ResizeObserver(() =>
775
+ // eslint-disable-next-line vue/valid-next-tick
776
+ this.$nextTick(() => this.getDropdownWidth())
777
+ )
778
+ this.selectResizeObserver.observe(this.$refs.dropdown.$el)
779
+ },
780
+ async getDropdownWidth() {
781
+ if (!this.$refs.select) return
782
+ await this.$nextTick()
783
+ this.dropdownWidth = `${this.$refs.select.$el.clientWidth}px`
784
+ },
785
+ onArrowPress(dir) {
786
+ let newHoveredElem
787
+ const currentHoveredElem = this.$refs.dropdown.$el.querySelector(
788
+ `[data-value="${this.hoveredValue}"]`
789
+ )
790
+ if (currentHoveredElem) {
791
+ if (dir > 0) {
792
+ newHoveredElem = currentHoveredElem.nextElementSibling
793
+ } else {
794
+ newHoveredElem = currentHoveredElem.previousElementSibling
795
+ }
796
+ if (newHoveredElem) {
797
+ this.hoveredValue = newHoveredElem.getAttribute('data-value')
798
+ const topPos = newHoveredElem.offsetTop
799
+ this.$refs.dropdown.$el.scrollTop = topPos
839
800
  }
801
+ }
802
+ }
803
+ },
804
+ computed: {
805
+ optionLength() {
806
+ if (this.isDropdownOpen) {
807
+ return this.$refs.dropdown.$el.childElementCount > 1
808
+ ? this.$refs.dropdown.$el.childElementCount
809
+ : this.$refs.dropdown.$el.children[0].childElementCount
810
+ }
840
811
 
841
- await this.$nextTick()
842
- const rect = this.$refs.dropdown.$el.getBoundingClientRect()
843
- const windowHeight =
844
- window.innerHeight || document.documentElement.clientHeight
812
+ return 0
813
+ },
814
+ isSearchBarVisible() {
815
+ return (
816
+ this.isSearchable &&
817
+ this.optionLength >= this.minOptionLength &&
818
+ this.isDropdownOpen
819
+ )
820
+ },
821
+ computedWidth() {
822
+ function removePX(item) {
823
+ return Number(item.replace('px', ''))
824
+ }
845
825
 
846
- if (windowHeight <= 650) return true
826
+ return this.selectWidth === '100%'
827
+ ? '100%'
828
+ : removePX(this.selectWidth) - removePX(CARET_WIDTH) + 'px'
829
+ },
830
+ getOptionWidth() {
831
+ if (this.optionWidth) return this.optionWidth
847
832
 
848
- // using Math.floor because the offsets may contain decimals we are not going to consider here
849
- return Math.floor(rect.top) + Math.floor(rect.height) <= windowHeight
850
- },
851
- observeDropdownHeight() {
852
- if (!this.$refs.dropdown) return
853
- this.dropdownResizeObserver = new ResizeObserver(() => {
854
- this.$nextTick(() => this.getDropdownPosition())
855
- })
856
- this.dropdownResizeObserver.observe(this.$refs.dropdown.$el)
857
- },
858
- handleSetDropdownOffet() {
859
- if (!this.$refs.select) return
860
- this.dropdownPosition.left = Math.floor(
861
- this.$refs.select.$el.getBoundingClientRect().left
862
- )
863
- this.getDropdownWidth()
864
- },
865
- observeSelectWidth() {
866
- if (!this.$refs.select) return
867
- this.selectResizeObserver = new ResizeObserver(() =>
868
- // eslint-disable-next-line vue/valid-next-tick
869
- this.$nextTick(() => this.getDropdownWidth())
870
- )
871
- this.selectResizeObserver.observe(this.$refs.dropdown.$el)
872
- },
873
- async getDropdownWidth() {
874
- if (!this.$refs.select) return
833
+ return this.dropdownWidth
834
+ },
835
+ isSelectDropdownShown() {
836
+ return (
837
+ this.isDropdownOpen &&
838
+ this.dropdownPosition.left !== null &&
839
+ (!this.isSearchable || this.isSearchable)
840
+ )
841
+ },
842
+ isMobileDevice() {
843
+ const userAgent = navigator.userAgent || navigator.vendor || window.opera
844
+ const touchCapable =
845
+ 'ontouchstart' in window ||
846
+ navigator.maxTouchPoints > 0 ||
847
+ navigator.msMaxTouchPoints > 0
848
+
849
+ return (
850
+ /Android/i.test(userAgent) ||
851
+ /iPad|iPhone|iPod/.test(userAgent) ||
852
+ (/Macintosh/.test(userAgent) && touchCapable) ||
853
+ /windows phone/i.test(userAgent)
854
+ )
855
+ }
856
+ },
857
+ watch: {
858
+ value(val) {
859
+ this.selectedValue = val
860
+ },
861
+ async isDropdownOpen(val) {
862
+ if (val) {
863
+ this.$emit('on-dropdown-open')
864
+ setTimeout(() => {
865
+ this.isClickOutsideActive = true
866
+ }, 10)
875
867
  await this.$nextTick()
876
- this.dropdownWidth = `${this.$refs.select.$el.clientWidth}px`
877
- },
878
- onArrowPress(dir) {
879
- let newHoveredElem
880
- const currentHoveredElem = this.$refs.dropdown.$el.querySelector(
881
- `[data-value="${this.hoveredValue}"]`
882
- )
883
- if (currentHoveredElem) {
884
- if (dir > 0) {
885
- newHoveredElem = currentHoveredElem.nextElementSibling
886
- } else {
887
- newHoveredElem = currentHoveredElem.previousElementSibling
888
- }
889
- if (newHoveredElem) {
890
- this.hoveredValue = newHoveredElem.getAttribute('data-value')
891
- const topPos = newHoveredElem.offsetTop
892
- this.$refs.dropdown.$el.scrollTop = topPos
868
+ this.handleSetDropdownOffet()
869
+ } else {
870
+ this.dropdownPosition.left = null
871
+ setTimeout(() => {
872
+ this.isClickOutsideActive = false
873
+ }, 10)
874
+ }
875
+ if (val && this.isSearchable) {
876
+ this.$nextTick(() => {
877
+ if (this.$refs.searchInput && !this.isMobileDevice) {
878
+ this.$refs.searchInput.$el.querySelector('input').focus()
893
879
  }
894
- }
880
+ })
895
881
  }
896
882
  }
897
883
  }
884
+ }
898
885
  </script>