@eturnity/eturnity_reusable_components 9.19.12 → 9.22.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.
package/package.json
CHANGED
|
@@ -231,6 +231,11 @@
|
|
|
231
231
|
v-if="!deferDropdownSlotContent || isSelectDropdownShown"
|
|
232
232
|
name="dropdown"
|
|
233
233
|
></slot>
|
|
234
|
+
<slot
|
|
235
|
+
v-if="isCustomOptionVisible"
|
|
236
|
+
name="customOption"
|
|
237
|
+
:custom-option-value="customOptionValue"
|
|
238
|
+
/>
|
|
234
239
|
</SelectDropdown>
|
|
235
240
|
</Component>
|
|
236
241
|
</DropdownWrapper>
|
|
@@ -267,6 +272,10 @@
|
|
|
267
272
|
// <Option value="3">value three</Option>
|
|
268
273
|
// <Option value="4">value four</Option>
|
|
269
274
|
// </template>
|
|
275
|
+
// <!-- optional: with is-customizable, render the typed-value row -->
|
|
276
|
+
// <template #customOption="{ customOptionValue }">
|
|
277
|
+
// <Option data-custom-option :value="customOptionAdapter(customOptionValue)">{{ customOptionValue }} (custom)</Option>
|
|
278
|
+
// </template>
|
|
270
279
|
// </Select>
|
|
271
280
|
|
|
272
281
|
import { Teleport, inject } from 'vue'
|
|
@@ -729,6 +738,16 @@
|
|
|
729
738
|
required: false,
|
|
730
739
|
default: true,
|
|
731
740
|
},
|
|
741
|
+
isCustomizable: {
|
|
742
|
+
required: false,
|
|
743
|
+
type: Boolean,
|
|
744
|
+
default: false,
|
|
745
|
+
},
|
|
746
|
+
customOptionAdapter: {
|
|
747
|
+
type: Function,
|
|
748
|
+
required: false,
|
|
749
|
+
default: null,
|
|
750
|
+
},
|
|
732
751
|
hasError: {
|
|
733
752
|
type: Boolean,
|
|
734
753
|
required: false,
|
|
@@ -891,11 +910,27 @@
|
|
|
891
910
|
optionLength() {
|
|
892
911
|
return this.optionLengthCount
|
|
893
912
|
},
|
|
913
|
+
customOptionValue() {
|
|
914
|
+
return this.textSearch.trim()
|
|
915
|
+
},
|
|
916
|
+
resolvedCustomOption() {
|
|
917
|
+
if (this.customOptionAdapter) {
|
|
918
|
+
return this.customOptionAdapter(this.customOptionValue)
|
|
919
|
+
}
|
|
920
|
+
return this.customOptionValue
|
|
921
|
+
},
|
|
922
|
+
isCustomOptionVisible() {
|
|
923
|
+
return this.isCustomizable && this.customOptionValue.length > 0
|
|
924
|
+
},
|
|
894
925
|
isSearchBarVisible() {
|
|
895
926
|
return (
|
|
896
|
-
this.
|
|
897
|
-
|
|
898
|
-
|
|
927
|
+
(this.isCustomizable ||
|
|
928
|
+
(
|
|
929
|
+
this.searchPlacement !== 'dropdown' &&
|
|
930
|
+
this.isSearchable &&
|
|
931
|
+
this.optionLength >= this.minOptionLength
|
|
932
|
+
)
|
|
933
|
+
) &&
|
|
899
934
|
this.isDropdownOpen
|
|
900
935
|
)
|
|
901
936
|
},
|
|
@@ -934,8 +969,7 @@
|
|
|
934
969
|
isSelectDropdownShown() {
|
|
935
970
|
return (
|
|
936
971
|
this.isDropdownOpen &&
|
|
937
|
-
this.dropdownPosition.left !== null
|
|
938
|
-
(!this.isSearchable || this.isSearchable)
|
|
972
|
+
this.dropdownPosition.left !== null
|
|
939
973
|
)
|
|
940
974
|
},
|
|
941
975
|
isMobileDevice() {
|
|
@@ -1022,7 +1056,7 @@
|
|
|
1022
1056
|
this.isClickOutsideActive = false
|
|
1023
1057
|
}, 10)
|
|
1024
1058
|
}
|
|
1025
|
-
if (val && this.
|
|
1059
|
+
if (val && this.isSearchBarVisible) {
|
|
1026
1060
|
this.$nextTick(() => {
|
|
1027
1061
|
if (this.searchPlacement === 'dropdown') {
|
|
1028
1062
|
const ref = this.$refs.dropdownSearchInput
|
|
@@ -1196,7 +1230,7 @@
|
|
|
1196
1230
|
}
|
|
1197
1231
|
|
|
1198
1232
|
nodes.forEach((el) => {
|
|
1199
|
-
let show = el.textContent.toLowerCase().includes(q)
|
|
1233
|
+
let show = el.textContent.toLowerCase().includes(q) || el.hasAttribute('data-custom-option')
|
|
1200
1234
|
if (
|
|
1201
1235
|
show &&
|
|
1202
1236
|
hideUnassignedWhenOthers &&
|
|
@@ -1278,6 +1312,10 @@
|
|
|
1278
1312
|
} else if (e.key == 'Enter') {
|
|
1279
1313
|
const root = this.$refs.dropdown?.$el
|
|
1280
1314
|
if (!root) return
|
|
1315
|
+
if (this.isCustomOptionVisible) {
|
|
1316
|
+
this.optionSelected(this.resolvedCustomOption)
|
|
1317
|
+
return
|
|
1318
|
+
}
|
|
1281
1319
|
const opts = [...root.querySelectorAll('[data-value]')].filter(
|
|
1282
1320
|
(el) => getComputedStyle(el).display !== 'none'
|
|
1283
1321
|
)
|
|
@@ -1,26 +1,38 @@
|
|
|
1
|
+
import { computed, ref } from 'vue'
|
|
1
2
|
import Select from './index.vue'
|
|
2
3
|
import Option from './option/index.vue'
|
|
3
4
|
|
|
5
|
+
const SELECT_SAMPLE_OPTIONS = [
|
|
6
|
+
{ key: '1', label: 'value one' },
|
|
7
|
+
{ key: '2', label: 'value two' },
|
|
8
|
+
{ key: '3', label: 'value three' },
|
|
9
|
+
{ key: '4', label: 'value four' },
|
|
10
|
+
]
|
|
11
|
+
|
|
4
12
|
export default {
|
|
5
13
|
title: 'select',
|
|
6
14
|
component: Select,
|
|
7
|
-
// argTypes: {},
|
|
8
15
|
}
|
|
9
16
|
|
|
10
|
-
const Template = (args
|
|
17
|
+
const Template = (args) => ({
|
|
11
18
|
// Components used in your story `template` are defined in the `components` object
|
|
12
19
|
components: { Select, Option },
|
|
13
20
|
// The story's `args` need to be mapped into the template through the `setup()` method
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
21
|
+
setup() {
|
|
22
|
+
return { args, selectSampleOptions: SELECT_SAMPLE_OPTIONS }
|
|
23
|
+
},
|
|
24
|
+
template: `<Select v-bind="args">
|
|
25
|
+
<template #selector="{ selectedValue }">
|
|
26
|
+
value selected: {{ selectedValue.label }}
|
|
18
27
|
</template>
|
|
19
28
|
<template #dropdown>
|
|
20
|
-
<Option
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
29
|
+
<Option
|
|
30
|
+
v-for="item in selectSampleOptions"
|
|
31
|
+
:key="item.key"
|
|
32
|
+
:value="item"
|
|
33
|
+
>
|
|
34
|
+
{{ item.label }}
|
|
35
|
+
</Option>
|
|
24
36
|
</template>
|
|
25
37
|
</Select>`,
|
|
26
38
|
|
|
@@ -49,10 +61,82 @@ const Template = (args, { argTypes }) => ({
|
|
|
49
61
|
|
|
50
62
|
export const Default = Template.bind({})
|
|
51
63
|
Default.args = {
|
|
52
|
-
hoverDropdown:
|
|
64
|
+
hoverDropdown: false,
|
|
53
65
|
selectWidth: '100%',
|
|
54
66
|
optionWidth: '50%',
|
|
55
67
|
label: 'that is a label',
|
|
56
68
|
alignItems: 'vertical',
|
|
57
|
-
value:
|
|
69
|
+
value: SELECT_SAMPLE_OPTIONS[1],
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Customizable Select
|
|
74
|
+
*/
|
|
75
|
+
const CustomizableTemplate = (args) => ({
|
|
76
|
+
components: { Select, Option },
|
|
77
|
+
setup() {
|
|
78
|
+
const CUSTOM_OPTION_KEY = 'custom-option'
|
|
79
|
+
const customOption = ref(null)
|
|
80
|
+
const createCustomOption = (customOptionValue) => ({
|
|
81
|
+
key: CUSTOM_OPTION_KEY,
|
|
82
|
+
label: customOptionValue,
|
|
83
|
+
})
|
|
84
|
+
const customizableOptions = computed(() => {
|
|
85
|
+
const options = [...SELECT_SAMPLE_OPTIONS]
|
|
86
|
+
if (customOption.value) {
|
|
87
|
+
options.push(customOption.value)
|
|
88
|
+
}
|
|
89
|
+
return options.filter(
|
|
90
|
+
(item, index, self) =>
|
|
91
|
+
self.findIndex((candidate) => candidate.label === item.label) === index
|
|
92
|
+
)
|
|
93
|
+
})
|
|
94
|
+
const onInputChange = (value) => {
|
|
95
|
+
args.value = value
|
|
96
|
+
if (value?.key === CUSTOM_OPTION_KEY) {
|
|
97
|
+
customOption.value = value
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
return {
|
|
101
|
+
args,
|
|
102
|
+
customizableOptions,
|
|
103
|
+
createCustomOption,
|
|
104
|
+
onInputChange,
|
|
105
|
+
}
|
|
106
|
+
},
|
|
107
|
+
template: `<Select
|
|
108
|
+
v-bind="args"
|
|
109
|
+
:custom-option-adapter="createCustomOption"
|
|
110
|
+
@input-change="onInputChange"
|
|
111
|
+
>
|
|
112
|
+
<template #selector="{ selectedValue }">
|
|
113
|
+
value selected: {{ selectedValue.label }}
|
|
114
|
+
</template>
|
|
115
|
+
<template #dropdown>
|
|
116
|
+
<Option
|
|
117
|
+
v-for="(item) in customizableOptions"
|
|
118
|
+
:key="item.key"
|
|
119
|
+
:value="item"
|
|
120
|
+
>
|
|
121
|
+
{{ item.label }}
|
|
122
|
+
</Option>
|
|
123
|
+
</template>
|
|
124
|
+
<template #customOption="{ customOptionValue }">
|
|
125
|
+
<Option
|
|
126
|
+
data-custom-option
|
|
127
|
+
:value="createCustomOption(customOptionValue)"
|
|
128
|
+
>
|
|
129
|
+
{{ customOptionValue }}
|
|
130
|
+
<div>(custom)</div>
|
|
131
|
+
</Option>
|
|
132
|
+
</template>
|
|
133
|
+
</Select>`,
|
|
134
|
+
})
|
|
135
|
+
|
|
136
|
+
export const Customizable = CustomizableTemplate.bind({})
|
|
137
|
+
Customizable.args = {
|
|
138
|
+
label: 'Customizable select',
|
|
139
|
+
alignItems: 'vertical',
|
|
140
|
+
isCustomizable: true,
|
|
141
|
+
value: SELECT_SAMPLE_OPTIONS[1],
|
|
58
142
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<TagContainer :data-id="dataId" :data-qa-id="dataQaId">
|
|
2
|
+
<TagContainer :data-id="dataId" :data-qa-id="dataQaId" :height="height">
|
|
3
3
|
<RcIcon
|
|
4
|
+
v-if="!noIcon"
|
|
4
5
|
:color="getIconColor"
|
|
5
6
|
:hovered-color="getIconColor"
|
|
6
7
|
name="star"
|
|
@@ -23,6 +24,7 @@
|
|
|
23
24
|
padding: 2px 4px;
|
|
24
25
|
background-color: ${(props) => props.theme.semanticColors.yellow[200]};
|
|
25
26
|
cursor: pointer;
|
|
27
|
+
height: ${(props) => props.height};
|
|
26
28
|
`
|
|
27
29
|
|
|
28
30
|
const TextContainer = styled.div`
|
|
@@ -56,6 +58,15 @@
|
|
|
56
58
|
default: '',
|
|
57
59
|
type: String,
|
|
58
60
|
},
|
|
61
|
+
noIcon: {
|
|
62
|
+
type: Boolean,
|
|
63
|
+
default: false,
|
|
64
|
+
},
|
|
65
|
+
height: {
|
|
66
|
+
required: false,
|
|
67
|
+
type: String,
|
|
68
|
+
default: 'auto',
|
|
69
|
+
},
|
|
59
70
|
},
|
|
60
71
|
computed: {
|
|
61
72
|
getIconColor() {
|