PluginProbe
The Innovative Form Builder – IvyForms / 0.1.2
The Innovative Form Builder – IvyForms v0.1.2
1.5.1 1.5 1.4.1 1.4 trunk 0.1.2 0.2 0.2.1 0.3 0.3.1 0.4 0.5 0.6 0.6.1 0.6.1-backup 0.6.1.1 0.7 0.8 0.8.1 0.8.2 0.9 0.9.1 1.0 1.1 1.1.1 All 27 releases
ivyforms / frontend / src / views / _components / input / IvySelectInput.vue

IvySelectInput.vue in The Innovative Form Builder – IvyForms 0.1.2, at frontend/src/views/_components/input/IvySelectInput.vue

275 lines 6.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <template>
2 <ElSelect
3 ref="elInputRef"
4 v-bind="{ ...$attrs, ...$props }"
5 v-model="model"
6 :placeholder="props.placeholder"
7 :disabled="props.disabled"
8 :multiple="props.multiple"
9 :collapse-tags="props.multiple"
10 :clearable="props.clearable"
11 :class="[
12 {
13 'is-clearable': props.clearable,
14 'is-filled': props.filled,
15 'is-secondary': isSecondary,
16 },
17 'ivyforms-form-item-select',
18 ]"
19 :max-collapse-tags="props.maxTags"
20 >
21 <template v-if="!!slots['prefix'] || iconStart" #prefix>
22 <slot name="prefix">
23 <IvyIcon
24 v-if="iconStart"
25 :name="iconStart"
26 :category="iconStartCategory"
27 :type="iconStartType"
28 class="ivyforms-input__icon-start"
29 size="l"
30 color="var(--map-base-dusk-symbol-2)"
31 />
32
33 <!-- TODO Add the avatar component-->
34 <IvyIcon v-if="props.avatar" class="ivyforms-input__avatar" name="user" size="l" />
35 <!-- <IvyAvatar-->
36 <!-- v-if="props.avatar"-->
37 <!-- class="ivyforms-input__avatar"-->
38 <!-- />-->
39 </slot>
40 </template>
41 <slot />
42 </ElSelect>
43 </template>
44
45 <script setup lang="ts">
46 import { useSlots, inject, computed } from 'vue'
47 import type { IconCategory } from '@/types/icons/icon-category'
48 import type { IconType } from '@/types/icons/icon-type'
49
50 interface Props {
51 modelValue: string | string[] | null | undefined
52 label?: string
53 placeholder?: string
54 iconStart?: string
55 iconEnd?: string
56 iconStartCategory?: IconCategory
57 iconEndCategory?: IconCategory
58 avatar?: string
59 iconStartType?: IconType
60 iconEndType?: IconType
61 filled?: boolean
62 prefix?: string
63 suffix?: string
64 clearable?: boolean
65 disabled?: boolean
66 multiple?: boolean
67 maxTags?: number
68 }
69
70 const props = withDefaults(defineProps<Props>(), {
71 placeholder: '',
72 iconStartCategory: 'global',
73 iconEndCategory: 'global',
74 iconStartType: 'outline',
75 iconEndType: 'outline',
76 label: '',
77 iconStart: '',
78 iconEnd: '',
79 avatar: '',
80 prefix: '',
81 suffix: '',
82 maxTags: 3,
83 })
84
85 const isSecondary = inject('isSecondary', false)
86
87 const slots = useSlots()
88
89 const emit = defineEmits(['update:modelValue'])
90
91 const model = computed({
92 get: () => props.modelValue,
93 set: (value) => emit('update:modelValue', value),
94 })
95 </script>
96
97 <style lang="scss">
98 .ivyforms-form-item-select {
99 .el-select__wrapper {
100 border: 1px solid var(--map-base-dusk-stroke--2);
101 background: var(--map-base-dusk-o05);
102 border-radius: var(--Radius-radius-md, 8px);
103 display: flex;
104 align-items: center;
105 gap: var(--Spacing-sm, 8px);
106 padding: var(--Spacing-sm, 8px) var(--Spacing-lg, 12px);
107 height: 40px;
108 box-shadow: none !important;
109
110 &:hover,
111 &.is-hovering:not(.is-focused) {
112 border: 1px solid var(--map-base-dusk-stroke-0);
113 }
114
115 &:focus,
116 &:active,
117 &.is-active,
118 &.is-focused {
119 border: 1px solid var(--map-base-brand-stroke-0);
120
121 .el-tag {
122 background: var(--map-base-brand-o10);
123 color: var(--map-base-brand-symbol-0);
124
125 .el-tag__close svg {
126 color: var(--map-base-brand-symbol-0);
127 width: 14px;
128 height: 14px;
129 }
130 }
131 }
132
133 .el-select__selection {
134 padding: 0;
135 font-size: 16px;
136 font-weight: 400;
137 line-height: 22px;
138 color: var(--map-base-text-0);
139 background-color: transparent;
140 display: flex;
141 align-items: center;
142 gap: 4px;
143 flex: 1 0 0;
144 }
145
146 .el-select__suffix .el-icon.el-select__caret.el-select__icon {
147 background: url('../../../assets/icons/arrows/line/chevron-down.svg') no-repeat center;
148 background-size: contain;
149 width: 16px;
150 height: 16px;
151 cursor: pointer;
152 opacity: 1 !important;
153
154 &.el-select__clear {
155 background: url('../../../assets/icons/global/fill-duo/close-circle.svg') no-repeat center;
156 }
157 }
158 }
159
160 &.is-secondary .el-select__wrapper {
161 &:active,
162 &:focus,
163 &.is-focused,
164 &.is-active {
165 border: 1px solid var(--map-base-purple-stroke-0);
166
167 .el-tag {
168 background: var(--map-base-purple-o10);
169 color: var(--map-base-purple-symbol-0);
170
171 .el-tag__close svg {
172 color: var(--map-base-purple-symbol-0);
173 width: 14px;
174 height: 14px;
175 }
176 }
177 }
178
179 .el-select__wrapper {
180 // Active & Focus
181 &:active,
182 &:focus,
183 &.is-focused,
184 &.is-active {
185 border: 1px solid var(--map-base-purple-stroke-0);
186 }
187 }
188 }
189
190 // Filled
191 &.is-filled {
192 .el-select__wrapper {
193 border: 1px solid var(--map-base-dusk-stroke--2);
194 background: var(--map-base-dusk-o05);
195
196 &:hover,
197 &.is-hovering {
198 border: 1px solid var(--map-base-dusk-stroke-0);
199 }
200
201 &:active,
202 &.is-active,
203 &:focus,
204 &.is-focused {
205 border: 1px solid var(--map-base-brand-stroke-0);
206
207 .el-tag {
208 background: var(--map-base-brand-o10);
209 color: var(--map-base-brand-symbol-0);
210
211 .el-tag__close svg {
212 color: var(--map-base-brand-symbol-0);
213 width: 14px;
214 height: 14px;
215 }
216 }
217 }
218
219 .el-tag {
220 background: var(--map-base-dusk-o20);
221 color: var(--map-base-text-0);
222
223 .el-tag__close svg {
224 color: var(--map-base-text-0);
225 width: 14px;
226 height: 14px;
227 }
228 }
229 }
230
231 &.is-error .el-select__wrapper {
232 border: 1px solid var(--map-status-error-symbol-0);
233 }
234
235 &.is-warning .el-select__wrapper {
236 border: 1px solid var(--map-status-warning-stroke-0);
237 }
238
239 .el-tag {
240 font-size: 14px;
241 font-weight: 400;
242 line-height: 20px;
243 display: flex;
244 padding: 2px 4px 2px 8px;
245 align-items: center;
246 gap: 4px;
247 cursor: pointer;
248 background: var(--map-base-dusk-o20);
249 color: var(--map-base-text-0);
250
251 .el-tag__close {
252 background: url('../../../assets/icons/global/outline/close.svg') no-repeat center;
253 background-size: contain;
254 width: 16px;
255 height: 16px;
256 cursor: pointer;
257 margin: 0;
258
259 svg {
260 color: var(--map-base-text-0);
261 width: 14px;
262 height: 14px;
263 }
264
265 &:hover {
266 background: url('../../../assets/icons/global/outline/close.svg') no-repeat center;
267 width: 16px;
268 height: 16px;
269 }
270 }
271 }
272 }
273 }
274 </style>
275