@eturnity/eturnity_reusable_components 1.2.34-3d-master.5 → 1.2.34-3d-master.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eturnity/eturnity_reusable_components",
3
- "version": "1.2.34-3d-master.5",
3
+ "version": "1.2.34-3d-master.8",
4
4
  "private": false,
5
5
  "scripts": {
6
6
  "dev": "vue-cli-service serve",
package/src/App.vue CHANGED
@@ -3,7 +3,7 @@
3
3
  <page-container>
4
4
  <br />
5
5
 
6
- <modal v-if="false" backdrop="dark" :isLoading="false" :isOpen="true">
6
+ <modal v-if="true" backdrop="dark" :isLoading="false" :isOpen="true">
7
7
 
8
8
  <div :style="{padding:'50px'}">
9
9
 
@@ -53,18 +53,16 @@
53
53
  alignItems="vertical"
54
54
  colorMode="dark"
55
55
  @input-change="value=$event"
56
+ @search-change="searchValue=$event"
56
57
  >
57
58
  <template #selector="{selectedValue}">
58
59
  value selected: {{selectedValue}}
59
60
  </template>
60
61
  <template #dropdown>
61
- <Option value="1">value one</Option>
62
- <Option value="2">value two</Option>
63
- <Option value="3">value three</Option>
64
- <Option value="4">value four</Option>
62
+ <Option v-for="opt in filteredOptionList" :key="opt.id" :value="opt.val">{{ opt.lookFor }}</Option>
65
63
  </template>
66
64
  </Select>
67
-
65
+ {{filteredOptionList }}
68
66
  </div>
69
67
  </modal>
70
68
  <iconCollection/>
@@ -110,7 +108,19 @@ export default {
110
108
  return {
111
109
  value:42,
112
110
  value2:42,
113
- companyName:"toto"
111
+ companyName:"toto",
112
+ optionList:[
113
+ {id:'a',val:'A',lookFor:'babababa'},
114
+ {id:'b',val:'B',lookFor:'abab'},
115
+ {id:'c',val:'C',lookFor:'ccc'},
116
+ {id:'d',val:'D',lookFor:'ddd'}
117
+ ],
118
+ searchValue:""
119
+ }
120
+ },
121
+ computed:{
122
+ filteredOptionList(){
123
+ return this.optionList.filter(opt=>opt.lookFor.includes(this.searchValue))
114
124
  }
115
125
  },
116
126
  methods: {
@@ -6,6 +6,7 @@
6
6
  >
7
7
  <icon-image
8
8
  v-if="isHovered && !isDisabled"
9
+ :hoverBg="hoverBg"
9
10
  :src="require('../../assets/icons/delete_icon.svg')"
10
11
  />
11
12
  <icon-image
@@ -27,9 +28,10 @@ const Wrapper = styled("div", wrapperAttrs)`
27
28
  cursor: ${(props) => (props.isDisabled ? "not-allowed" : "pointer")};
28
29
  `
29
30
 
30
- const IconImage = styled.img`
31
+ const IconImageAttrs = { hoverBg: String }
32
+ const IconImage = styled('img', IconImageAttrs)`
31
33
  &:hover {
32
- background-color: ${(props) => props.theme.colors.grey5};
34
+ background-color: ${(props) => props.hoverBg ? props.hoverBg : props.theme.colors.grey5};
33
35
  border-radius: 4px;
34
36
  }
35
37
  `
@@ -45,6 +47,10 @@ export default {
45
47
  required: false,
46
48
  default: false,
47
49
  },
50
+ hoverBg: {
51
+ required: false,
52
+ default: '',
53
+ }
48
54
  },
49
55
  data() {
50
56
  return {
@@ -2,14 +2,11 @@
2
2
  <component-wrapper>
3
3
  <icon-wrapper :size="size">
4
4
  <icon-img
5
- :isActive="showInfo"
6
- :size="size"
7
- :borderColor="borderColor"
8
5
  @click.prevent="toggleShowInfo()"
9
6
  @mouseenter="openTrigger == 'onHover' ? toggleShowInfo() : ''"
10
7
  @mouseleave="openTrigger == 'onHover' ? toggleShowInfo() : ''"
11
8
  >
12
- <icon :size="size" name="info" :color="iconColor" />
9
+ <icon :size="size" name="info" :color="iconColor" cursor="pointer" />
13
10
  </icon-img>
14
11
  <text-overlay
15
12
  v-if="showInfo"
@@ -54,7 +51,7 @@ const TextOverlay = styled('div', textAttrs)`
54
51
  : props.alignArrow === 'center'
55
52
  ? 'left: calc((-' + props.width + ' + ' + props.iconSize + ') /2 + 2px)'
56
53
  : 'right: calc(' + props.iconSize + ' /2 - 17px)'};
57
- text-align: 'left';
54
+ text-align: left;
58
55
  background: ${(props) => props.theme.colors.black};
59
56
  padding: 10px;
60
57
  width: ${(props) => props.width};
@@ -87,16 +84,14 @@ const TextOverlay = styled('div', textAttrs)`
87
84
  }
88
85
  `
89
86
 
90
- const iconAttrs = { isActive: Boolean, size: String, borderColor: String }
91
-
87
+ const iconAttrs = { size: String }
92
88
  const IconWrapper = styled('div', iconAttrs)`
93
89
  position: relative;
94
- top: 1px;
95
90
  height: ${(props) => props.size};
96
91
  `
97
- const IconImg = styled('div', iconAttrs)`
98
- cursor: pointer;
99
- height: ${(props) => props.size};
92
+
93
+ const IconImg = styled.div`
94
+ line-height: 0;
100
95
  `
101
96
 
102
97
  const ComponentWrapper = styled.div`
@@ -234,6 +234,7 @@ const SlotContainer = styled('span', inputProps)`
234
234
 
235
235
  const LabelWrapper = styled('div',inputProps)`
236
236
  display: flex;
237
+ align-items: center;
237
238
  gap: 10px;
238
239
  margin-bottom: 8px;
239
240
  cursor: ${(props) => (props.isInteractive?'ew-resize':'auto')};
@@ -1,7 +1,6 @@
1
1
  <template>
2
2
  <Container
3
3
  :selectWidth="selectWidth"
4
- v-click-outside="closeDropdown"
5
4
  @mouseenter="mouseEnterHandler"
6
5
  @mouseleave="mouseLeaveHandler"
7
6
  >
@@ -23,26 +22,44 @@
23
22
  </label-wrapper>
24
23
  <div>
25
24
  <selectButton
26
- @click="toggleDropdown"
25
+ ref="select"
26
+ @click="toggleDropdown"
27
27
  :isActive="isActive"
28
28
  :selectHeight="selectHeight"
29
29
  :bgColor="buttonBgColor || colorMode=='dark'?'transparentBlack1':'white'"
30
30
  :fontColor="buttonFontColor || colorMode=='dark'?'white':'black'"
31
-
31
+ @keydown.native="onKeyDown"
32
32
  >
33
- <slot name="selector" :selectedValue="selectedValue"></slot>
34
- <Caret :isUp="isDropdownOpen">
33
+ <inputText
34
+ v-if="isSearchBarVisible"
35
+ ref="searchInput"
36
+ tabindex="0"
37
+ :noBorder="true"
38
+ :inputHeight="selectHeight"
39
+ backgroundColor="transparent"
40
+ :fontColor="buttonFontColor || colorMode=='dark'?'white':'black'"
41
+ :value="textSearch"
42
+ @keydown.stop="onKeyDown"
43
+ @input-change="searchChange" />
44
+ <div v-else>
45
+ <slot name="selector" :selectedValue="selectedValue"></slot>
46
+ </div>
47
+ <Caret :isUp="isDropdownOpen" @click.stop="isSearchBarVisible ? closeDropdown() : toggleDropdown() " >
35
48
  <icon name="arrow_up" size="12px" :color="caretColor || colorMode=='dark'?'white':'transparentBlack1'"/>
36
49
  </Caret>
37
50
  </selectButton>
38
51
  <DropdownWrapper>
39
52
  <selectDropdown
40
- v-if="isDropdownOpen"
53
+ ref="dropdown"
54
+ v-show="isDropdownOpen"
55
+ :hoveredIndex="hoveredIndex"
41
56
  :isActive="isActive"
42
57
  :optionWidth="optionWidth"
43
58
  :bgColor="dropdownBgColor || colorMode=='dark'?'black':'white'"
44
59
  :fontColor="dropdownFontColor || colorMode=='dark'?'white':'black'"
45
- @option-selected="optionSelected">
60
+ :selectedValue="selectedValue"
61
+ @option-selected="optionSelected"
62
+ @option-hovered="optionHovered">
46
63
  <slot name="dropdown"></slot>
47
64
  </selectDropdown>
48
65
  </DropdownWrapper>
@@ -74,7 +91,8 @@
74
91
  import styled from 'vue-styled-components'
75
92
  import InfoText from '../../infoText'
76
93
  import icon from '../../icon'
77
-
94
+ import inputText from '../inputText'
95
+
78
96
  const caretAttrs={isUp:Boolean}
79
97
  const Caret=styled('div', caretAttrs)`
80
98
  position:absolute;
@@ -112,18 +130,19 @@ const selectButton = styled('div',selectButtonAttrs)`
112
130
  box-sizing: border-box;
113
131
  border:1px solid red;
114
132
  border-radius:4px;
115
- padding:10px 15px;
133
+ padding:0px 10px;
116
134
  text-align:left;
117
135
  border-radius:4px;
118
136
  min-height:36px;
119
- display: flex;
137
+ display: grid;
138
+ grid-template-columns:auto 40px;
120
139
  align-items: center;
121
140
  max-height:${props=>props.selectHeight};
122
141
  border:1px solid ${(props)=>props.theme.colors.grey4}
123
142
  background-color:${(props) => props.theme.colors[props.bgColor]?props.theme.colors[props.bgColor]:props.bgColor};
124
143
  color:${(props) => props.theme.colors[props.fontColor]?props.theme.colors[props.fontColor]:props.fontColor};
125
144
  `
126
- const selectDropdownAttrs={bgColor:String,fontColor:String,selectWidth: String, optionWidth: String}
145
+ const selectDropdownAttrs={bgColor:String,fontColor:String,selectWidth: String, optionWidth: String,hoveredIndex:Number,selectedValue:Number | String}
127
146
  const selectDropdown = styled('div',selectDropdownAttrs)`
128
147
  box-sizing: border-box;
129
148
  z-index:${props=>props.isActive?'2':'1'};
@@ -142,6 +161,12 @@ const selectDropdown = styled('div',selectDropdownAttrs)`
142
161
  color:${(props) => props.theme.colors[props.fontColor]?props.theme.colors[props.fontColor]:props.fontColor};
143
162
  max-height:300px;
144
163
  overflow-y:auto;
164
+ & [data-value="${props=>props.selectedValue}"]{
165
+ backdrop-filter: brightness(1.4);
166
+ }
167
+ &>div:nth-child(${props=>props.hoveredIndex}){
168
+ backdrop-filter: brightness(1.2);
169
+ }
145
170
  `
146
171
  const DropdownWrapper=styled('div')`
147
172
  position:relative;
@@ -217,6 +242,14 @@ const InputWrapper = styled('div', inputAttrs)`
217
242
  colorMode:{
218
243
  required:false,
219
244
  default:'light'
245
+ },
246
+ isSearchable:{
247
+ required:false,
248
+ default:true
249
+ },
250
+ isAutoSearch:{
251
+ required:false,
252
+ default:true
220
253
  }
221
254
  },
222
255
 
@@ -230,7 +263,8 @@ const InputWrapper = styled('div', inputAttrs)`
230
263
  InputWrapper,
231
264
  DropdownWrapper,
232
265
  icon,
233
- Caret
266
+ Caret,
267
+ inputText
234
268
  },
235
269
 
236
270
  data() {
@@ -238,9 +272,11 @@ const InputWrapper = styled('div', inputAttrs)`
238
272
  selectedValue: null,
239
273
  isDropdownOpen:false,
240
274
  isActive:false,
275
+ textSearch:"",
276
+ hoveredIndex:0,
241
277
  }
242
278
  },
243
- created(){
279
+ mounted(){
244
280
  this.selectedValue=this.value
245
281
  },
246
282
  methods:{
@@ -250,13 +286,25 @@ const InputWrapper = styled('div', inputAttrs)`
250
286
  blur(){
251
287
  this.isActive=false
252
288
  },
253
- toggleDropdown(){
254
- this.focus()
289
+ toggleDropdown(e){
290
+ if(this.isSearchBarVisible){return}
255
291
  this.isDropdownOpen=!this.isDropdownOpen
292
+ if (this.isDropdownOpen) {
293
+ setTimeout(()=>document.addEventListener('click', this.clickOutside),10)
294
+ } else {
295
+ document.removeEventListener('click', this.clickOutside)
296
+ }
297
+
298
+ },
299
+ openDropdown(){
300
+ this.focus()
301
+ this.isDropdownOpen=true
302
+ setTimeout(()=>document.addEventListener('click', this.clickOutside),10)
256
303
  },
257
304
  closeDropdown(){
258
305
  this.blur()
259
306
  this.isDropdownOpen=false
307
+ document.removeEventListener('click', this.clickOutside)
260
308
  },
261
309
  optionSelected(e){
262
310
  this.selectedValue=e
@@ -264,21 +312,74 @@ const InputWrapper = styled('div', inputAttrs)`
264
312
  this.blur()
265
313
  this.$emit('input-change',e)
266
314
  },
315
+ optionHovered(e){
316
+ const optionElement=this.$el.querySelector(`[data-value="${e}"]`)
317
+ if(this.$refs.dropdown){
318
+ this.hoveredIndex=this.$refs.dropdown.$children.map(component=>component.$el).indexOf(optionElement)+1
319
+ }
320
+ },
267
321
  mouseEnterHandler(){
268
- this.focus()
269
322
  if(this.hoverDropdown){
323
+ this.focus()
270
324
  this.isDropdownOpen=true
271
325
  }
272
326
  },
273
327
  mouseLeaveHandler(){
274
- this.blur()
328
+ if(this.hoverDropdown){
329
+ this.blur()
330
+ }
331
+ },
332
+ searchChange(value){
333
+ this.textSearch=value
334
+ this.$emit('search-change',value)
335
+ this.$refs.dropdown.$children.map(component=>component.$el).forEach((el=>{
336
+ if(!el.textContent.toLowerCase().includes(value.toLowerCase())){el.style.display='none'}else{el.style.display='inherit'}
337
+ }))
338
+ },
339
+ clickOutside(event) {
340
+ if (this.$el==event.target || this.$el.contains(event.target)) {
341
+ return
342
+ }
343
+ this.closeDropdown()
275
344
  },
345
+ onKeyDown(e){
346
+ if(e.key=='ArrowDown'){
347
+ this.onArrowPress(1)
348
+ } else if(e.key=='ArrowUp'){
349
+ this.onArrowPress(-1)
350
+ } else if(e.key=='Enter'){
351
+ const optionHoveredComponent=this.$refs.dropdown.$children[(this.hoveredIndex-1+this.optionLength)%this.optionLength]
352
+ this.optionSelected(optionHoveredComponent.$el.dataset.value)
353
+ }
354
+
355
+ },
356
+ onArrowPress(dir){
357
+ this.hoveredIndex=((this.hoveredIndex+dir+this.optionLength-1)%this.optionLength)+1
358
+ const optionHoveredComponent=this.$refs.dropdown.$children[(this.hoveredIndex-1+this.optionLength)%this.optionLength]
359
+ const topPos = optionHoveredComponent.$el.offsetTop;
360
+ this.$refs.dropdown.$el.scrollTop = topPos;
361
+ }
276
362
  },
277
363
  computed: {
364
+ optionLength(){
365
+ if(this.isDropdownOpen){
366
+ return this.$refs.dropdown.$children.length
367
+ }else{
368
+ return 0
369
+ }
370
+ },
371
+ isSearchBarVisible(){
372
+ return this.isSearchable && this.optionLength>=5 && this.isDropdownOpen
373
+ }
278
374
  },
279
375
  watch:{
280
376
  value(val){
281
377
  this.selectedValue=val
378
+ },
379
+ isDropdownOpen(val){
380
+ if(val && this.isSearchable){
381
+ this.$nextTick(()=>{if(this.$refs.searchInput){this.$refs.searchInput.$el.querySelector('input').focus()}})
382
+ }
282
383
  }
283
384
  }
284
385
  }
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <optionContainer :hoveredBgColor="hoveredBgColor || colorMode=='dark'?'#000000':'grey5'" @click="clickHandler">
2
+ <optionContainer :data-value="value" :hoveredBgColor="hoveredBgColor || colorMode=='dark'?'#000000':'grey5'" @click="clickHandler" @mouseover="hoverHandler">
3
3
  <slot></slot>
4
4
  </optionContainer>
5
5
  </template>
@@ -48,6 +48,9 @@
48
48
  methods:{
49
49
  clickHandler(){
50
50
  this.$parent.$emit('option-selected',this.value)
51
+ },
52
+ hoverHandler(){
53
+ this.$parent.$emit('option-hovered',this.value)
51
54
  }
52
55
  },
53
56
  computed: {
@@ -77,7 +77,7 @@ const ModalContainer = styled.div`
77
77
  border-radius: 4px;
78
78
  background: white;
79
79
  margin: 0 auto;
80
- overflow: initial;
80
+ overflow: auto;
81
81
  max-width: 95%;
82
82
  max-height: 95%;
83
83
  min-width: 100px;
@@ -156,4 +156,4 @@ export default {
156
156
  }
157
157
  }
158
158
  }
159
- </script>
159
+ </script>