cl-select-trigger.uvue 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. <template>
  2. <view
  3. class="cl-select-trigger"
  4. :class="[
  5. {
  6. 'is-dark': isDark,
  7. 'cl-select-trigger--disabled': isDisabled,
  8. 'cl-select-trigger--focus': focus
  9. },
  10. pt.className
  11. ]"
  12. @tap="open"
  13. >
  14. <view class="cl-select-trigger__content">
  15. <cl-text
  16. v-if="showText"
  17. :pt="{
  18. className: parseClass([
  19. {
  20. '!text-surface-400': isDisabled
  21. },
  22. pt.text?.className
  23. ])
  24. }"
  25. ellipsis
  26. >
  27. {{ text }}
  28. </cl-text>
  29. <text
  30. class="cl-select-trigger__placeholder"
  31. :class="[pt.placeholder?.className]"
  32. v-else
  33. >
  34. {{ placeholder }}
  35. </text>
  36. </view>
  37. <view v-if="showText && !isDisabled" class="cl-select-trigger__icon" @tap.stop="clear">
  38. <cl-icon
  39. name="close-circle-fill"
  40. :size="32"
  41. :pt="{ className: '!text-surface-400' }"
  42. ></cl-icon>
  43. </view>
  44. <view v-if="!isDisabled && !showText" class="cl-select-trigger__icon">
  45. <cl-icon
  46. :name="pt.icon?.name ?? arrowIcon"
  47. :size="pt.icon?.size ?? 32"
  48. :pt="{
  49. className: `!text-surface-400 ${pt.icon?.className}`
  50. }"
  51. ></cl-icon>
  52. </view>
  53. </view>
  54. </template>
  55. <script setup lang="ts">
  56. import { computed } from "vue";
  57. import type { ClIconProps } from "../cl-icon/props";
  58. import { isDark, parseClass, parsePt } from "@/cool";
  59. import { t } from "@/locale";
  60. import type { PassThroughProps } from "../../types";
  61. import { useForm } from "../../hooks";
  62. defineOptions({
  63. name: "cl-select-trigger"
  64. });
  65. // 组件属性定义
  66. const props = defineProps({
  67. // 透传样式配置
  68. pt: {
  69. type: Object,
  70. default: () => ({})
  71. },
  72. // 显示文本
  73. text: {
  74. type: String,
  75. default: ""
  76. },
  77. // 占位符文本
  78. placeholder: {
  79. type: String,
  80. default: () => t("请选择")
  81. },
  82. // 箭头图标名称
  83. arrowIcon: {
  84. type: String,
  85. default: "arrow-down-s-line"
  86. },
  87. // 是否禁用选择器
  88. disabled: {
  89. type: Boolean,
  90. default: false
  91. },
  92. // 是否聚焦
  93. focus: {
  94. type: Boolean,
  95. default: false
  96. }
  97. });
  98. const emit = defineEmits(["open", "clear"]);
  99. const { disabled } = useForm();
  100. // 是否禁用
  101. const isDisabled = computed(() => {
  102. return disabled.value || props.disabled;
  103. });
  104. // 透传样式类型定义
  105. type PassThrough = {
  106. className?: string; // 根元素类名
  107. icon?: ClIconProps; // 图标样式
  108. placeholder?: PassThroughProps; // 占位符样式
  109. text?: PassThroughProps; // 文本样式
  110. };
  111. // 解析透传样式配置
  112. const pt = computed(() => parsePt<PassThrough>(props.pt));
  113. // 是否显示文本
  114. const showText = computed(() => props.text != "");
  115. // 清空文本
  116. function clear() {
  117. emit("clear");
  118. }
  119. // 打开选择器
  120. function open() {
  121. if (isDisabled.value) {
  122. return;
  123. }
  124. emit("open");
  125. }
  126. </script>
  127. <style lang="scss" scoped>
  128. .cl-select-trigger {
  129. @apply flex flex-row items-center w-full;
  130. @apply border border-solid border-surface-200 rounded-lg bg-white;
  131. height: 66rpx;
  132. padding: 0 20rpx;
  133. &__placeholder {
  134. @apply text-surface-400 text-md;
  135. }
  136. &__content {
  137. flex: 1;
  138. }
  139. &__icon {
  140. @apply flex flex-row items-center justify-center;
  141. padding-left: 20rpx;
  142. }
  143. &--disabled {
  144. @apply bg-surface-100 opacity-70;
  145. }
  146. &--focus {
  147. @apply border-primary-500;
  148. &.is-dark {
  149. @apply border-primary-500;
  150. }
  151. }
  152. &.is-dark {
  153. @apply border-surface-700 bg-surface-800;
  154. &.cl-select-trigger--disabled {
  155. @apply bg-surface-700;
  156. }
  157. }
  158. }
  159. </style>