cl-select-trigger.uvue 2.7 KB

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