Files
WAI_Project_UNIX/uni_modules/cool-ui/components/cl-select-trigger/cl-select-trigger.uvue

190 lines
3.4 KiB
Plaintext

<template>
<view
class="cl-select-trigger"
:class="[
{
'is-dark': isDark,
'cl-select-trigger--disabled': isDisabled,
'cl-select-trigger--focus': focus,
'cl-select-trigger--error': isError
},
pt.className
]"
@tap="open"
>
<view class="cl-select-trigger__content">
<cl-text
v-if="showText"
:pt="{
className: parseClass([
{
'text-surface-400': isDisabled
},
pt.text?.className
])
}"
ellipsis
>
{{ text }}
</cl-text>
<cl-text
:pt="{
className: parseClass(['text-surface-400', pt.placeholder?.className])
}"
v-else
>
{{ placeholder }}
</cl-text>
</view>
<view v-if="showText && !isDisabled" class="cl-select-trigger__icon" @tap.stop="clear">
<cl-icon
name="close-circle-fill"
:size="32"
:pt="{ className: 'text-surface-400' }"
></cl-icon>
</view>
<view v-if="!isDisabled && !showText" class="cl-select-trigger__icon">
<cl-icon
:name="pt.icon?.name ?? arrowIcon"
:size="pt.icon?.size ?? 32"
:pt="{
className: `text-surface-400 ${pt.icon?.className}`
}"
></cl-icon>
</view>
</view>
</template>
<script setup lang="ts">
import { computed } from "vue";
import type { ClIconProps } from "../cl-icon/props";
import { isDark, parseClass, parsePt } from "@/cool";
import { t } from "@/locale";
import type { PassThroughProps } from "../../types";
import { useForm, useFormItem } from "../../hooks";
defineOptions({
name: "cl-select-trigger"
});
// 组件属性定义
const props = defineProps({
// 透传样式配置
pt: {
type: Object,
default: () => ({})
},
// 显示文本
text: {
type: String,
default: ""
},
// 占位符文本
placeholder: {
type: String,
default: () => t("请选择")
},
// 箭头图标名称
arrowIcon: {
type: String,
default: "arrow-down-s-line"
},
// 是否禁用选择器
disabled: {
type: Boolean,
default: false
},
// 是否聚焦
focus: {
type: Boolean,
default: false
}
});
const emit = defineEmits(["open", "clear"]);
// cl-form 上下文
const { disabled } = useForm();
// cl-form-item 上下文
const { isError } = useFormItem();
// 是否禁用
const isDisabled = computed(() => {
return disabled.value || props.disabled;
});
// 透传样式类型定义
type PassThrough = {
className?: string; // 根元素类名
icon?: ClIconProps; // 图标样式
placeholder?: PassThroughProps; // 占位符样式
text?: PassThroughProps; // 文本样式
};
// 解析透传样式配置
const pt = computed(() => parsePt<PassThrough>(props.pt));
// 是否显示文本
const showText = computed(() => props.text != "");
// 清空文本
function clear() {
emit("clear");
}
// 打开选择器
function open() {
if (isDisabled.value) {
return;
}
emit("open");
}
</script>
<style lang="scss" scoped>
.cl-select-trigger {
@apply flex flex-row items-center w-full box-border;
@apply border border-solid border-surface-200 rounded-lg bg-white;
height: 66rpx;
padding: 0 20rpx;
&__content {
flex: 1;
}
&__icon {
@apply flex flex-row items-center justify-center;
padding-left: 20rpx;
}
&--disabled {
@apply bg-surface-100 opacity-70;
}
&--focus {
@apply border-primary-500;
&.is-dark {
@apply border-primary-500;
}
}
&--error {
@apply border-red-500;
}
&.is-dark {
@apply border-surface-700 bg-surface-800;
&.cl-select-trigger--disabled {
@apply bg-surface-700;
}
}
}
</style>