Files
astra-frontend/src/components/base/BaseSelect.vue
2023-09-25 21:12:05 +03:00

259 lines
7.0 KiB
Vue

<template lang="pug">
.flex.flex-col.gap-y-2
base-input-container(:label="label", :style="{width: widthInternal, ...sizeVariable}")
q-select.select(
ref="selectRef"
v-model="value",
:options="items",
:readonly="readonly"
:disable="disabled",
:hide-dropdown-icon="hideDropdownIcon || disabled || readonly"
outlined,
:behavior="behavior",
emit-value,
map-options,
:clearable="clearable",
dropdown-icon="app:down-arrow",
:menu-offset="[0, 8]",
:use-input="useInput",
:input-debounce="inputDebounce",
:placeholder="useInput && placeholder ? placeholder : ''",
@filter="filterFn",
:popup-content-style="popupContentStyle"
@blur="$emit('blur')"
)
template(#selected)
slot(name="selected")
template(v-slot:option="scope", v-if="!customOption")
q-item(v-bind="scope.itemProps", style="justify-content: center", v-if="value?.icon")
q-item-section(avatar, style="padding: 0px; min-width: 0px")
q-icon.icon(:name="scope.opt.icon", size="24px")
q-item.item.px-4.py-2(v-bind="scope.itemProps", style="justify-content: center", v-else)
q-item-section
q-item-label.text-dark.text-base.font-medium {{ scope.opt.label }}
template(v-slot:option="{itemProps, opt}", v-else)
slot(
name="customOption",
:props="itemProps",
:data="opt"
)
template(v-slot:prepend, v-if="iconLeft")
slot(name="iconLeft")
template(v-slot:append, v-if="iconRight")
slot(name="iconRight")
template(v-slot:before-options)
slot(name="beforeOptions")
template(v-slot:no-option)
slot(name="noOption")
</template>
<script>
import BaseMenu from "@/components/base/BaseMenu";
import BaseInputContainer from "@/components/base/BaseInputContainer";
export default {
name: "VSelect",
components: { BaseMenu, BaseInputContainer },
props: {
placeholder: String,
hideDropdownIcon: Boolean,
modelValue: [Object, String],
items: {
type: Array,
default: () => [],
},
behavior: {
type: String,
default: "menu",
},
disabled: Boolean,
label: String,
readonly: Boolean,
width: String,
clearable: Boolean,
size: String,
useInput: Boolean,
inputDebounce: Number,
iconLeft: Boolean,
iconRight: Boolean,
customOption: Boolean,
filterFn: Function,
popupContentStyle: Object,
},
emits: ["update:modelValue", "blur"],
computed: {
value: {
get() {
return this.modelValue;
},
set(value) {
this.$emit("update:modelValue", value);
},
},
textSelect() {
if (typeof this.modelValue === "string") return this.value;
return this.value?.label
? this.value.label
: !this.useInput
? this.placeholder
: "";
},
iconSelect() {
return this.value?.icon ? this.value.icon : this.placeholder;
},
sizeVariable() {
if (this.size === "XS")
return {
"--input-height": "28px",
"--text-size": "12px",
"--line-height": "135%",
"--px": "0 8px",
"--py": "10px 0",
};
if (this.size === "S")
return {
"--input-height": "32px",
"--text-size": "12px",
"--line-height": "135%",
"--px": "0 8px",
"--py": "10px 0",
};
if (this.size === "M")
return {
"--input-height": "40px",
"--text-size": "16px",
"--line-height": "normal",
"--px": "0 16px",
"--py": "8px 0",
};
if (this.size === "L")
return {
"--input-height": "48px",
"--text-size": "16px",
"--line-height": "normal",
"--px": "0 16px",
"--py": "8px 0",
};
if (this.size)
return {
"--input-height": this.size,
"--text-size": "16px",
"--line-height": "normal",
"--px": "0 16px",
"--py": "8px 0",
};
return {
"--input-height": "56px",
"--text-size": "16px",
"--line-height": "normal",
"--px": "0 16px",
"--py": "8px 0",
};
},
placeholderColor() {
return {
placeholder: !this.useInput && this.placeholder,
selected:
typeof this.modelValue === "string"
? !!this.value
: !!this.value?.label,
};
},
widthInternal() {
if (typeof this.width === "number") return this.width + "px";
return this.width;
},
},
methods: {
updateInputValue(value, noFilter) {
this.$refs?.selectRef?.updateInputValue(value, noFilter);
},
hidePopup() {
this.$refs?.selectRef?.hidePopup();
},
},
};
</script>
<style lang="sass">
.placeholder
color: var(--font-grey-color)
.selected
color: var(--font-dark-blue-color)
.q-placeholder
font-weight: 500 !important
&::placeholder
opacity: 1 !important
color: var(--font-grey-color) !important
.q-field--auto-height .q-field__native
min-height: var(--input-height) !important
font-weight: 500
font-size: var(--text-size)
line-height: var(--line-height)
color: var(--font-dark-blue-color)
padding: var(--py)
.q-field--auto-height .q-field__control
min-height: var(--input-height) !important
height: var(--input-height) !important
color: var(--font-dark-blue-color)
padding: var(--px) !important
&:before
border-color: var(--border-light-grey-color) !important
transition: none
&:hover:before
border-color: var(--font-grey-color) !important
&:after
border-width: 1px !important
transition: none
transform: none !important
.q-field--disabled .q-field__control > div
opacity: 1 !important
.q-field--outlined.q-field--disabled .q-field__native
color: var(--font-grey-color)
.q-field--outlined.q-field--disabled .q-field__control
background: var(--bg-light-grey) !important
.q-field--outlined.q-field--readonly .q-field__control
background: var(--bg-light-grey) !important
&:before
border-color: var(--bg-light-grey) !important
transition: none
&:hover:before
border-color: var(--bg-light-grey) !important
.q-field--outlined.q-field--readonly .q-field__native
cursor: default
.q-field--error :deep(.q-field__bottom)
padding: 4px 0 0 0
font-weight: 500
font-size: 12px
line-height: 135% !important
.q-field__marginal
height: var(--input-height) !important
.q-select__dropdown-icon path
fill: var(--font-dark-blue-color)
.q-select__dropdown-icon
width: 20px
height: 20px
.item
border-bottom: 1px solid var(--gray-secondary)
&:last-child
border-bottom: none
&:hover
background-color: var(--gray-thirdly)
.q-menu
box-shadow: 1px 1px 8px 0px rgba(37, 40, 80, 0.15) !important
font-feature-settings: 'pnum' on, 'lnum' on !important
//max-height: var(--input-height) !important
</style>