添加全局字号,动态调整大小
This commit is contained in:
@@ -15,7 +15,12 @@
|
||||
<slot name="prepend"></slot>
|
||||
|
||||
<view class="cl-action-sheet__description" v-if="config.description != ''">
|
||||
<text class="text-surface-400 text-md">{{ config.description }}</text>
|
||||
<cl-text
|
||||
:pt="{
|
||||
className: '!text-surface-400 !text-md text-center'
|
||||
}"
|
||||
>{{ config.description }}</cl-text
|
||||
>
|
||||
</view>
|
||||
|
||||
<view class="cl-action-sheet__list" :class="[pt.list?.className]">
|
||||
|
||||
@@ -13,10 +13,16 @@
|
||||
},
|
||||
pt.className
|
||||
]"
|
||||
:style="badgeStyle"
|
||||
>
|
||||
<text class="cl-badge__text" v-if="!dot">
|
||||
<cl-text
|
||||
:pt="{
|
||||
className: parseClass(['cl-badge__text', pt.text?.className])
|
||||
}"
|
||||
v-if="!dot"
|
||||
>
|
||||
{{ value }}
|
||||
</text>
|
||||
</cl-text>
|
||||
|
||||
<slot></slot>
|
||||
</view>
|
||||
@@ -25,8 +31,9 @@
|
||||
<script setup lang="ts">
|
||||
import { computed } from "vue";
|
||||
import type { PropType } from "vue";
|
||||
import type { Type } from "../../types";
|
||||
import { parsePt } from "@/cool";
|
||||
import type { PassThroughProps, Type } from "../../types";
|
||||
import { parseClass, parsePt } from "@/cool";
|
||||
import { useSize } from "../../hooks";
|
||||
|
||||
defineOptions({
|
||||
name: "cl-badge"
|
||||
@@ -55,11 +62,39 @@ const props = defineProps({
|
||||
}
|
||||
});
|
||||
|
||||
const { getRpx } = useSize();
|
||||
|
||||
type PassThrough = {
|
||||
className?: string;
|
||||
text?: PassThroughProps;
|
||||
};
|
||||
|
||||
const pt = computed(() => parsePt<PassThrough>(props.pt));
|
||||
|
||||
const badgeStyle = computed(() => {
|
||||
const style = {};
|
||||
|
||||
if (props.dot) {
|
||||
style["height"] = getRpx(10);
|
||||
style["width"] = getRpx(10);
|
||||
style["minWidth"] = getRpx(10);
|
||||
style["padding"] = 0;
|
||||
} else {
|
||||
style["height"] = getRpx(30);
|
||||
style["minWidth"] = getRpx(30);
|
||||
style["padding"] = `0 ${getRpx(6)}`;
|
||||
}
|
||||
|
||||
if (props.position) {
|
||||
style["transform"] = "translate(50%, -50%)";
|
||||
|
||||
if (props.dot) {
|
||||
style["transform"] = `translate(-${getRpx(5)}, ${getRpx(5)})`;
|
||||
}
|
||||
}
|
||||
|
||||
return style;
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@@ -67,29 +102,12 @@ const pt = computed(() => parsePt<PassThrough>(props.pt));
|
||||
@apply flex flex-row items-center justify-center;
|
||||
@apply rounded-full;
|
||||
|
||||
height: 30rpx;
|
||||
min-width: 30rpx;
|
||||
padding: 0 6rpx;
|
||||
|
||||
&__text {
|
||||
@apply text-white;
|
||||
font-size: 18rpx;
|
||||
}
|
||||
|
||||
&--dot {
|
||||
height: 10rpx;
|
||||
width: 10rpx;
|
||||
min-width: 10rpx;
|
||||
padding: 0;
|
||||
@apply text-white text-sm;
|
||||
}
|
||||
|
||||
&--position {
|
||||
@apply absolute z-10 right-0 top-0;
|
||||
transform: translate(50%, -50%);
|
||||
|
||||
&.cl-badge--dot {
|
||||
transform: translate(-5rpx, 5rpx);
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -18,13 +18,24 @@
|
||||
v-if="showIcon"
|
||||
></image>
|
||||
|
||||
<text class="cl-empty__text dark:!text-surface-100" v-if="text">{{ text }}</text>
|
||||
<cl-text
|
||||
:pt="{
|
||||
className: parseClass([
|
||||
'cl-empty__text',
|
||||
{
|
||||
'!text-surface-100': isDark
|
||||
}
|
||||
])
|
||||
}"
|
||||
v-if="text"
|
||||
>{{ text }}</cl-text
|
||||
>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { t } from "@/locale";
|
||||
import { parsePt, parseRpx } from "@/cool";
|
||||
import { isDark, parseClass, parsePt, parseRpx } from "@/cool";
|
||||
import { computed } from "vue";
|
||||
|
||||
// 组件属性定义
|
||||
|
||||
@@ -24,8 +24,9 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed, type PropType } from "vue";
|
||||
import { forInObject, get, has, parseRpx, parsePt, useCache, isDark } from "@/cool";
|
||||
import { forInObject, get, has, parsePt, useCache, isDark } from "@/cool";
|
||||
import { icons } from "@/icons";
|
||||
import { useSize } from "../../hooks";
|
||||
|
||||
defineOptions({
|
||||
name: "cl-icon"
|
||||
@@ -68,6 +69,9 @@ const props = defineProps({
|
||||
// 缓存
|
||||
const { cache } = useCache(() => [props.color]);
|
||||
|
||||
// 字号
|
||||
const { getRpx } = useSize();
|
||||
|
||||
// 透传样式类型定义
|
||||
type PassThrough = {
|
||||
className?: string;
|
||||
@@ -126,11 +130,14 @@ const iconStyle = computed(() => {
|
||||
style["color"] = props.color;
|
||||
}
|
||||
|
||||
style["fontFamily"] = icon.value.font;
|
||||
style["fontSize"] = parseRpx(props.size!);
|
||||
style["height"] = parseRpx(props.height ?? props.size!);
|
||||
style["width"] = parseRpx(props.width ?? props.size!);
|
||||
style["lineHeight"] = parseRpx(props.size!);
|
||||
if (icon.value.font != "") {
|
||||
style["fontFamily"] = icon.value.font;
|
||||
}
|
||||
|
||||
style["fontSize"] = getRpx(props.size!);
|
||||
style["height"] = getRpx(props.height ?? props.size!);
|
||||
style["width"] = getRpx(props.width ?? props.size!);
|
||||
style["lineHeight"] = getRpx(props.size!);
|
||||
|
||||
return style;
|
||||
});
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
<template>
|
||||
<view class="cl-input-otp" :class="[pt.className]">
|
||||
<view
|
||||
class="cl-input-otp"
|
||||
:class="[
|
||||
{
|
||||
'cl-input-otp--disabled': disabled
|
||||
},
|
||||
pt.className
|
||||
]"
|
||||
>
|
||||
<view class="cl-input-otp__inner">
|
||||
<cl-input
|
||||
v-model="value"
|
||||
@@ -33,16 +41,11 @@
|
||||
pt.item?.className
|
||||
]"
|
||||
>
|
||||
<text
|
||||
class="cl-input-otp__value"
|
||||
:class="[
|
||||
{
|
||||
'is-disabled': disabled,
|
||||
'is-dark': isDark
|
||||
},
|
||||
pt.value?.className
|
||||
]"
|
||||
>{{ item }}</text
|
||||
<cl-text
|
||||
:pt="{
|
||||
className: pt.value?.className
|
||||
}"
|
||||
>{{ item }}</cl-text
|
||||
>
|
||||
<view
|
||||
class="cl-input-otp__cursor"
|
||||
@@ -268,14 +271,6 @@ function animateCursor(isIncreasing: boolean) {
|
||||
}
|
||||
}
|
||||
|
||||
&__value {
|
||||
@apply text-surface-700 text-md;
|
||||
|
||||
&.is-dark {
|
||||
@apply text-white;
|
||||
}
|
||||
}
|
||||
|
||||
&__cursor {
|
||||
@apply absolute;
|
||||
@apply bg-primary-500;
|
||||
@@ -302,5 +297,9 @@ function animateCursor(isIncreasing: boolean) {
|
||||
}
|
||||
}
|
||||
// #endif
|
||||
|
||||
&--disabled {
|
||||
@apply opacity-50;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -30,8 +30,9 @@
|
||||
'is-disabled': isDisabled,
|
||||
'is-dark': isDark
|
||||
},
|
||||
pt.inner?.className
|
||||
ptClassName
|
||||
]"
|
||||
:style="inputStyle"
|
||||
:value="value"
|
||||
:disabled="readonly ?? isDisabled"
|
||||
:type="type"
|
||||
@@ -86,7 +87,7 @@ import type { ClInputType, PassThroughProps } from "../../types";
|
||||
import { isDark, parseClass, parsePt } from "@/cool";
|
||||
import type { ClIconProps } from "../cl-icon/props";
|
||||
import { t } from "@/locale";
|
||||
import { useForm, useFormItem } from "../../hooks";
|
||||
import { useForm, useFormItem, useSize } from "../../hooks";
|
||||
|
||||
defineOptions({
|
||||
name: "cl-input"
|
||||
@@ -225,6 +226,22 @@ type PassThrough = {
|
||||
// 解析透传样式
|
||||
const pt = computed(() => parsePt<PassThrough>(props.pt));
|
||||
|
||||
// 字号
|
||||
const { ptClassName, getSize } = useSize(() => pt.value.inner?.className ?? "");
|
||||
|
||||
// 输入框样式
|
||||
const inputStyle = computed(() => {
|
||||
const style = {};
|
||||
|
||||
// 字号
|
||||
const fontSize = getSize(null);
|
||||
if (fontSize != null) {
|
||||
style["fontSize"] = fontSize;
|
||||
}
|
||||
|
||||
return style;
|
||||
});
|
||||
|
||||
// 绑定值
|
||||
const value = ref<string>("");
|
||||
|
||||
|
||||
@@ -22,10 +22,21 @@
|
||||
class="cl-keyboard-car__value"
|
||||
:class="[pt.value?.className]"
|
||||
>
|
||||
<text class="cl-keyboard-car__value-text dark:!text-white" v-if="value != ''">{{
|
||||
valueText
|
||||
}}</text>
|
||||
<text class="cl-keyboard-car__value-placeholder" v-else>{{ placeholder }}</text>
|
||||
<cl-text
|
||||
v-if="value != ''"
|
||||
:pt="{
|
||||
className: '!text-2xl'
|
||||
}"
|
||||
>{{ valueText }}</cl-text
|
||||
>
|
||||
|
||||
<cl-text
|
||||
v-else
|
||||
:pt="{
|
||||
className: '!text-md !text-surface-400'
|
||||
}"
|
||||
>{{ placeholder }}</cl-text
|
||||
>
|
||||
</view>
|
||||
</slot>
|
||||
|
||||
@@ -70,9 +81,7 @@
|
||||
color="white"
|
||||
></cl-icon>
|
||||
|
||||
<text v-else class="cl-keyboard-car__item-text dark:!text-white">{{
|
||||
item
|
||||
}}</text>
|
||||
<cl-text v-else>{{ item }}</cl-text>
|
||||
</slot>
|
||||
</view>
|
||||
</view>
|
||||
@@ -289,16 +298,8 @@ defineExpose({
|
||||
|
||||
&__value {
|
||||
@apply flex flex-row items-center justify-center;
|
||||
height: 60rpx;
|
||||
margin-bottom: 28rpx;
|
||||
|
||||
&-text {
|
||||
@apply text-2xl text-surface-700;
|
||||
}
|
||||
|
||||
&-placeholder {
|
||||
@apply text-md text-surface-400;
|
||||
}
|
||||
height: 80rpx;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
&__list {
|
||||
@@ -327,10 +328,6 @@ defineExpose({
|
||||
@apply bg-surface-800;
|
||||
}
|
||||
|
||||
&-text {
|
||||
@apply text-lg;
|
||||
}
|
||||
|
||||
&.is-fill {
|
||||
flex: 1;
|
||||
}
|
||||
@@ -347,10 +344,6 @@ defineExpose({
|
||||
&.is-keycode-confirm {
|
||||
@apply bg-primary-500;
|
||||
flex: 1;
|
||||
|
||||
.cl-keyboard-car__item-text {
|
||||
@apply text-white;
|
||||
}
|
||||
}
|
||||
|
||||
&.is-empty {
|
||||
|
||||
@@ -22,14 +22,21 @@
|
||||
class="cl-keyboard-number__value"
|
||||
:class="[pt.value?.className]"
|
||||
>
|
||||
<text
|
||||
class="cl-keyboard-number__value-text dark:!text-white"
|
||||
<cl-text
|
||||
v-if="value != ''"
|
||||
>{{ value }}</text
|
||||
:pt="{
|
||||
className: '!text-2xl'
|
||||
}"
|
||||
>{{ value }}</cl-text
|
||||
>
|
||||
|
||||
<cl-text
|
||||
v-else
|
||||
:pt="{
|
||||
className: '!text-md !text-surface-400'
|
||||
}"
|
||||
>{{ placeholder }}</cl-text
|
||||
>
|
||||
<text class="cl-keyboard-number__value-placeholder" v-else>{{
|
||||
placeholder
|
||||
}}</text>
|
||||
</view>
|
||||
</slot>
|
||||
|
||||
@@ -61,15 +68,21 @@
|
||||
v-else-if="item == 'confirm'"
|
||||
class="cl-keyboard-number__item-confirm"
|
||||
>
|
||||
<text class="cl-keyboard-number__item-text">{{
|
||||
confirmText
|
||||
}}</text>
|
||||
<cl-text
|
||||
color="white"
|
||||
:pt="{
|
||||
className: '!text-lg'
|
||||
}"
|
||||
>{{ confirmText }}</cl-text
|
||||
>
|
||||
</view>
|
||||
|
||||
<text
|
||||
<cl-text
|
||||
v-else
|
||||
class="cl-keyboard-number__item-text dark:!text-white"
|
||||
>{{ item }}</text
|
||||
:pt="{
|
||||
className: '!text-lg'
|
||||
}"
|
||||
>{{ item }}</cl-text
|
||||
>
|
||||
</slot>
|
||||
</view>
|
||||
@@ -346,16 +359,8 @@ defineExpose({
|
||||
|
||||
&__value {
|
||||
@apply flex flex-row items-center justify-center;
|
||||
height: 60rpx;
|
||||
margin-bottom: 28rpx;
|
||||
|
||||
&-text {
|
||||
@apply text-2xl text-surface-700;
|
||||
}
|
||||
|
||||
&-placeholder {
|
||||
@apply text-md text-surface-400;
|
||||
}
|
||||
height: 80rpx;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
&__list {
|
||||
@@ -372,10 +377,6 @@ defineExpose({
|
||||
@apply bg-surface-800;
|
||||
}
|
||||
|
||||
&-text {
|
||||
@apply text-lg;
|
||||
}
|
||||
|
||||
&.is-keycode-delete {
|
||||
@apply bg-surface-200;
|
||||
|
||||
@@ -386,10 +387,6 @@ defineExpose({
|
||||
|
||||
&.is-keycode-confirm {
|
||||
@apply bg-transparent relative;
|
||||
|
||||
.cl-keyboard-number__item-text {
|
||||
@apply text-white;
|
||||
}
|
||||
}
|
||||
|
||||
&-confirm {
|
||||
|
||||
@@ -22,14 +22,21 @@
|
||||
class="cl-keyboard-password__value"
|
||||
:class="[pt.value?.className]"
|
||||
>
|
||||
<text
|
||||
class="cl-keyboard-password__value-text dark:!text-white"
|
||||
<cl-text
|
||||
v-if="value != ''"
|
||||
>{{ valueText }}</text
|
||||
:pt="{
|
||||
className: '!text-2xl'
|
||||
}"
|
||||
>{{ valueText }}</cl-text
|
||||
>
|
||||
|
||||
<cl-text
|
||||
v-else
|
||||
:pt="{
|
||||
className: '!text-md !text-surface-400'
|
||||
}"
|
||||
>{{ placeholder }}</cl-text
|
||||
>
|
||||
<text class="cl-keyboard-password__value-placeholder" v-else>{{
|
||||
placeholder
|
||||
}}</text>
|
||||
</view>
|
||||
</slot>
|
||||
|
||||
@@ -66,22 +73,29 @@
|
||||
:size="36"
|
||||
></cl-icon>
|
||||
|
||||
<text
|
||||
<cl-text
|
||||
v-else-if="item == 'confirm'"
|
||||
class="cl-keyboard-password__item-text"
|
||||
>{{ confirmText }}</text
|
||||
color="white"
|
||||
:pt="{
|
||||
className: '!text-lg'
|
||||
}"
|
||||
>{{ confirmText }}</cl-text
|
||||
>
|
||||
|
||||
<text
|
||||
<cl-text
|
||||
v-else-if="item == 'letter'"
|
||||
class="cl-keyboard-password__item-text dark:!text-white"
|
||||
>ABC</text
|
||||
:pt="{
|
||||
className: '!text-lg'
|
||||
}"
|
||||
>ABC</cl-text
|
||||
>
|
||||
|
||||
<text
|
||||
<cl-text
|
||||
v-else-if="item == 'number'"
|
||||
class="cl-keyboard-password__item-text dark:!text-white"
|
||||
>123</text
|
||||
:pt="{
|
||||
className: '!text-lg'
|
||||
}"
|
||||
>123</cl-text
|
||||
>
|
||||
|
||||
<template v-else-if="item == 'caps'">
|
||||
@@ -97,9 +111,13 @@
|
||||
></cl-badge>
|
||||
</template>
|
||||
|
||||
<text v-else class="cl-keyboard-password__item-text dark:!text-white">{{
|
||||
item
|
||||
}}</text>
|
||||
<cl-text
|
||||
v-else
|
||||
:pt="{
|
||||
className: '!text-lg'
|
||||
}"
|
||||
>{{ item }}</cl-text
|
||||
>
|
||||
</slot>
|
||||
</view>
|
||||
</view>
|
||||
@@ -364,16 +382,8 @@ defineExpose({
|
||||
|
||||
&__value {
|
||||
@apply flex flex-row items-center justify-center;
|
||||
height: 60rpx;
|
||||
margin-bottom: 28rpx;
|
||||
|
||||
&-text {
|
||||
@apply text-2xl text-surface-700;
|
||||
}
|
||||
|
||||
&-placeholder {
|
||||
@apply text-md text-surface-400;
|
||||
}
|
||||
height: 80rpx;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
&__list {
|
||||
@@ -403,10 +413,6 @@ defineExpose({
|
||||
@apply bg-surface-800;
|
||||
}
|
||||
|
||||
&-text {
|
||||
@apply text-lg bg-transparent;
|
||||
}
|
||||
|
||||
&.is-keycode-number,
|
||||
&.is-keycode-letter {
|
||||
width: 150rpx;
|
||||
@@ -434,10 +440,6 @@ defineExpose({
|
||||
@apply bg-primary-500;
|
||||
width: 150rpx !important;
|
||||
flex: none;
|
||||
|
||||
.cl-keyboard-password__item-text {
|
||||
@apply text-white;
|
||||
}
|
||||
}
|
||||
|
||||
&.is-empty {
|
||||
|
||||
@@ -21,8 +21,9 @@
|
||||
// #ifdef APP
|
||||
transform: `rotate(${rotate}deg)`,
|
||||
// #endif
|
||||
height: parseRpx(size!),
|
||||
width: parseRpx(size!),
|
||||
height: getRpx(size!),
|
||||
width: getRpx(size!),
|
||||
borderWidth: getRpx(2),
|
||||
borderTopColor: color,
|
||||
borderRightColor: 'transparent',
|
||||
borderBottomColor: color,
|
||||
@@ -35,8 +36,9 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed, onMounted, ref, watch } from "vue";
|
||||
import { isDark, parsePt, parseRpx } from "@/cool";
|
||||
import { isDark, parsePt } from "@/cool";
|
||||
import type { ClIconProps } from "../cl-icon/props";
|
||||
import { useSize } from "../../hooks";
|
||||
|
||||
defineOptions({
|
||||
name: "cl-loading"
|
||||
@@ -66,6 +68,8 @@ const props = defineProps({
|
||||
}
|
||||
});
|
||||
|
||||
const { getRpx } = useSize();
|
||||
|
||||
// 透传样式类型定义
|
||||
type PassThrough = {
|
||||
className?: string;
|
||||
@@ -114,7 +118,6 @@ onMounted(() => {
|
||||
.cl-loading {
|
||||
@apply flex flex-row items-center justify-center rounded-full;
|
||||
@apply border-surface-700 border-solid;
|
||||
border-width: 2rpx;
|
||||
|
||||
&--dark {
|
||||
border-color: white !important;
|
||||
|
||||
@@ -16,10 +16,11 @@
|
||||
}"
|
||||
>
|
||||
<slot name="text" :item="item">
|
||||
<text
|
||||
class="cl-noticebar__text dark:!text-white"
|
||||
:class="[pt.text?.className]"
|
||||
>{{ item }}</text
|
||||
<cl-text
|
||||
:pt="{
|
||||
className: parseClass(['cl-noticebar__text', pt.text?.className])
|
||||
}"
|
||||
>{{ item }}</cl-text
|
||||
>
|
||||
</slot>
|
||||
</view>
|
||||
@@ -37,7 +38,7 @@ import {
|
||||
type PropType,
|
||||
watch
|
||||
} from "vue";
|
||||
import { parseRpx, parsePt } from "@/cool";
|
||||
import { parseRpx, parsePt, parseClass } from "@/cool";
|
||||
import type { PassThroughProps } from "../../types";
|
||||
|
||||
defineOptions({
|
||||
@@ -248,7 +249,6 @@ onUnmounted(() => {
|
||||
}
|
||||
|
||||
&__text {
|
||||
@apply text-md text-surface-700;
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,13 +30,17 @@
|
||||
]"
|
||||
@tap="toPage(item)"
|
||||
>
|
||||
<text
|
||||
class="cl-pagination__item-text"
|
||||
:class="{
|
||||
'is-active': item == value,
|
||||
'is-dark': isDark
|
||||
<cl-text
|
||||
:pt="{
|
||||
className: parseClass([
|
||||
'cl-pagination__item-text',
|
||||
{
|
||||
'is-active': item == value,
|
||||
'is-dark': isDark
|
||||
}
|
||||
])
|
||||
}"
|
||||
>{{ item }}</text
|
||||
>{{ item }}</cl-text
|
||||
>
|
||||
</view>
|
||||
|
||||
@@ -61,7 +65,7 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import type { PassThroughProps } from "../../types";
|
||||
import { isDark, parsePt } from "@/cool";
|
||||
import { isDark, parseClass, parsePt } from "@/cool";
|
||||
import { computed, ref, watch } from "vue";
|
||||
|
||||
defineOptions({
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
<template>
|
||||
<view class="cl-picker-view">
|
||||
<view class="cl-picker-view__header" v-if="headers.length > 0">
|
||||
<text
|
||||
class="cl-picker-view__header-item dark:!text-white"
|
||||
<cl-text
|
||||
:pt="{
|
||||
className: 'flex-1 !text-sm text-center'
|
||||
}"
|
||||
v-for="(label, index) in headers"
|
||||
:key="index"
|
||||
>{{ label }}</text
|
||||
>{{ label }}</cl-text
|
||||
>
|
||||
</view>
|
||||
|
||||
@@ -168,11 +170,6 @@ function onChange(e: UniPickerViewChangeEvent) {
|
||||
|
||||
&__header {
|
||||
@apply flex flex-row items-center py-4;
|
||||
|
||||
&-item {
|
||||
@apply text-center text-sm text-surface-700;
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
|
||||
&__item {
|
||||
|
||||
@@ -252,7 +252,7 @@ const paddingBottom = computed(() => {
|
||||
let h = 0;
|
||||
|
||||
if (props.direction == "bottom") {
|
||||
h += hasCustomTabBar() ? getTabBarHeight() : getSafeAreaHeight("bottom");
|
||||
h += getSafeAreaHeight("bottom");
|
||||
}
|
||||
|
||||
return h + "px";
|
||||
|
||||
@@ -28,13 +28,14 @@
|
||||
{{ text }}
|
||||
</cl-text>
|
||||
|
||||
<text
|
||||
class="cl-select-trigger__placeholder"
|
||||
:class="[pt.placeholder?.className]"
|
||||
<cl-text
|
||||
:pt="{
|
||||
className: parseClass(['!text-surface-400', pt.placeholder?.className])
|
||||
}"
|
||||
v-else
|
||||
>
|
||||
{{ placeholder }}
|
||||
</text>
|
||||
</cl-text>
|
||||
</view>
|
||||
|
||||
<view v-if="showText && !isDisabled" class="cl-select-trigger__icon" @tap.stop="clear">
|
||||
@@ -152,10 +153,6 @@ function open() {
|
||||
height: 66rpx;
|
||||
padding: 0 20rpx;
|
||||
|
||||
&__placeholder {
|
||||
@apply text-surface-400 text-md;
|
||||
}
|
||||
|
||||
&__content {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
@@ -26,6 +26,8 @@
|
||||
}"
|
||||
>
|
||||
<view class="cl-select-popup" @touchmove.stop>
|
||||
<slot name="prepend"></slot>
|
||||
|
||||
<view class="cl-select-popup__picker">
|
||||
<cl-picker-view
|
||||
:value="indexes"
|
||||
@@ -34,6 +36,8 @@
|
||||
></cl-picker-view>
|
||||
</view>
|
||||
|
||||
<slot name="append"></slot>
|
||||
|
||||
<view class="cl-select-popup__op">
|
||||
<cl-button
|
||||
v-if="showCancel"
|
||||
@@ -73,6 +77,11 @@ defineOptions({
|
||||
name: "cl-select"
|
||||
});
|
||||
|
||||
defineSlots<{
|
||||
prepend(): any;
|
||||
append(): any;
|
||||
}>();
|
||||
|
||||
// 值类型
|
||||
type Value = string[] | number[] | number | string | null;
|
||||
|
||||
@@ -146,7 +155,7 @@ const props = defineProps({
|
||||
});
|
||||
|
||||
// 定义事件
|
||||
const emit = defineEmits(["update:modelValue", "change"]);
|
||||
const emit = defineEmits(["update:modelValue", "change", "changing"]);
|
||||
|
||||
// 弹出层引用
|
||||
const popupRef = ref<ClPopupComponentPublicInstance | null>(null);
|
||||
@@ -230,6 +239,11 @@ const text = computed(() => {
|
||||
.join(props.splitor);
|
||||
});
|
||||
|
||||
// 获取当前选中值
|
||||
function getValue() {
|
||||
return props.columnCount == 1 ? value.value[0] : value.value;
|
||||
}
|
||||
|
||||
// 选择器值改变事件
|
||||
function onChange(a: number[]) {
|
||||
// 复制当前组件内部维护的索引数组
|
||||
@@ -258,6 +272,9 @@ function onChange(a: number[]) {
|
||||
indexes.value = b;
|
||||
// 根据最新的索引数组,更新选中的值数组
|
||||
value.value = b.map((e, i) => columns.value[i][e].value);
|
||||
|
||||
// 触发changing事件
|
||||
emit("changing", getValue());
|
||||
}
|
||||
|
||||
// 选择器显示状态
|
||||
@@ -291,7 +308,7 @@ function clear() {
|
||||
// 确认选择
|
||||
function confirm() {
|
||||
// 根据列数返回单个值或数组
|
||||
const val = props.columnCount == 1 ? value.value[0] : value.value;
|
||||
const val = getValue();
|
||||
|
||||
// 触发更新事件
|
||||
emit("update:modelValue", val);
|
||||
|
||||
@@ -35,19 +35,21 @@
|
||||
@tap="change(index)"
|
||||
>
|
||||
<slot name="item" :item="item" :active="item.isActive">
|
||||
<text
|
||||
class="cl-tabs__item-label"
|
||||
:class="[
|
||||
{
|
||||
'is-active': item.isActive,
|
||||
'is-disabled': item.disabled,
|
||||
'is-dark': isDark,
|
||||
'is-fill': fill
|
||||
},
|
||||
pt.text?.className
|
||||
]"
|
||||
<cl-text
|
||||
:pt="{
|
||||
className: parseClass([
|
||||
'cl-tabs__item-label',
|
||||
{
|
||||
'is-active': item.isActive,
|
||||
'is-disabled': item.disabled,
|
||||
'is-dark': isDark,
|
||||
'is-fill': fill
|
||||
},
|
||||
pt.text?.className
|
||||
])
|
||||
}"
|
||||
:style="getTextStyle(item)"
|
||||
>{{ item.label }}</text
|
||||
>{{ item.label }}</cl-text
|
||||
>
|
||||
</slot>
|
||||
</view>
|
||||
@@ -73,7 +75,7 @@
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { type PropType, computed, getCurrentInstance, nextTick, onMounted, ref, watch } from "vue";
|
||||
import { isDark, isEmpty, isHarmony, isNull, parsePt, parseRpx, rpx2px } from "@/cool";
|
||||
import { isDark, isEmpty, isHarmony, isNull, parseClass, parsePt, parseRpx, rpx2px } from "@/cool";
|
||||
import type { ClTabsItem, PassThroughProps } from "../../types";
|
||||
|
||||
// 定义标签类型
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
'!text-surface-50': color == 'light',
|
||||
'!text-surface-400': color == 'disabled'
|
||||
},
|
||||
pt.className
|
||||
ptClassName
|
||||
]"
|
||||
:style="textStyle"
|
||||
:selectable="selectable"
|
||||
@@ -49,7 +49,7 @@
|
||||
'!text-surface-50': color == 'light',
|
||||
'!text-surface-400': color == 'disabled'
|
||||
},
|
||||
pt.className
|
||||
ptClassName
|
||||
]"
|
||||
:style="textStyle"
|
||||
:selectable="selectable"
|
||||
@@ -66,6 +66,7 @@
|
||||
import { computed, type PropType } from "vue";
|
||||
import { isDark, parsePt, useCache } from "@/cool";
|
||||
import type { ClTextType } from "../../types";
|
||||
import { useSize } from "../../hooks";
|
||||
|
||||
defineOptions({
|
||||
name: "cl-text"
|
||||
@@ -88,6 +89,11 @@ const props = defineProps({
|
||||
type: String,
|
||||
default: ""
|
||||
},
|
||||
// 字体大小
|
||||
size: {
|
||||
type: [Number, String] as PropType<number | string | null>,
|
||||
default: null
|
||||
},
|
||||
// 文本类型
|
||||
type: {
|
||||
type: String as PropType<ClTextType>,
|
||||
@@ -161,6 +167,9 @@ type PassThrough = {
|
||||
// 解析透传样式
|
||||
const pt = computed(() => parsePt<PassThrough>(props.pt));
|
||||
|
||||
// 文本大小
|
||||
const { getSize, getLineHeight, ptClassName } = useSize(() => pt.value.className ?? "");
|
||||
|
||||
// 文本样式
|
||||
const textStyle = computed(() => {
|
||||
const style = {};
|
||||
@@ -169,6 +178,18 @@ const textStyle = computed(() => {
|
||||
style["color"] = props.color;
|
||||
}
|
||||
|
||||
// 字号
|
||||
const fontSize = getSize(props.size);
|
||||
if (fontSize != null) {
|
||||
style["fontSize"] = fontSize;
|
||||
}
|
||||
|
||||
// 行高
|
||||
const lineHeight = getLineHeight();
|
||||
if (lineHeight != null) {
|
||||
style["lineHeight"] = lineHeight;
|
||||
}
|
||||
|
||||
return style;
|
||||
});
|
||||
|
||||
|
||||
@@ -20,11 +20,9 @@
|
||||
'is-disabled': isDisabled,
|
||||
'is-dark': isDark
|
||||
},
|
||||
pt.inner?.className
|
||||
ptClassName
|
||||
]"
|
||||
:style="{
|
||||
height: parseRpx(height)
|
||||
}"
|
||||
:style="textareaStyle"
|
||||
:value="value"
|
||||
:name="name"
|
||||
:disabled="readonly ?? isDisabled"
|
||||
@@ -48,12 +46,14 @@
|
||||
@input="onInput"
|
||||
@linechange="onLineChange"
|
||||
@blur="onBlur"
|
||||
@keyboardheightchange="onKeyboardheightchange"
|
||||
@focus="onFocus"
|
||||
@keyboardheightchange="onKeyboardheightchange"
|
||||
/>
|
||||
|
||||
<text class="cl-textarea__count" v-if="showWordLimit"
|
||||
>{{ value.length }}/{{ maxlength }}</text
|
||||
<cl-text
|
||||
:pt="{ className: 'absolute right-2 bottom-2 !text-xs !text-surface-400' }"
|
||||
v-if="showWordLimit"
|
||||
>{{ value.length }} / {{ maxlength }}</cl-text
|
||||
>
|
||||
</view>
|
||||
</template>
|
||||
@@ -64,7 +64,7 @@ import { parsePt, parseRpx } from "@/cool";
|
||||
import type { PassThroughProps } from "../../types";
|
||||
import { isDark } from "@/cool";
|
||||
import { t } from "@/locale";
|
||||
import { useForm, useFormItem } from "../../hooks";
|
||||
import { useForm, useFormItem, useSize } from "../../hooks";
|
||||
|
||||
defineOptions({
|
||||
name: "cl-textarea"
|
||||
@@ -243,6 +243,24 @@ type PassThrough = {
|
||||
// 解析透传样式
|
||||
const pt = computed(() => parsePt<PassThrough>(props.pt));
|
||||
|
||||
// 字号
|
||||
const { ptClassName, getSize } = useSize(() => pt.value.inner?.className ?? "");
|
||||
|
||||
// 文本框样式
|
||||
const textareaStyle = computed(() => {
|
||||
const style = {
|
||||
height: parseRpx(props.height)
|
||||
};
|
||||
|
||||
// 字号
|
||||
const fontSize = getSize(null);
|
||||
if (fontSize != null) {
|
||||
style["fontSize"] = fontSize;
|
||||
}
|
||||
|
||||
return style;
|
||||
});
|
||||
|
||||
// 绑定值
|
||||
const value = ref(props.modelValue);
|
||||
|
||||
@@ -348,10 +366,6 @@ defineExpose({
|
||||
padding-left: 20rpx;
|
||||
}
|
||||
|
||||
&__count {
|
||||
@apply text-surface-400 text-sm absolute right-2 bottom-2;
|
||||
}
|
||||
|
||||
&--border {
|
||||
@apply border border-solid border-surface-200;
|
||||
}
|
||||
|
||||
@@ -37,7 +37,13 @@
|
||||
></cl-icon>
|
||||
</view>
|
||||
|
||||
<text class="cl-toast__text">{{ item.message }}</text>
|
||||
<cl-text
|
||||
color="white"
|
||||
:pt="{
|
||||
className: 'text-center'
|
||||
}"
|
||||
>{{ item.message }}</cl-text
|
||||
>
|
||||
</view>
|
||||
</view>
|
||||
</cl-popup>
|
||||
@@ -157,10 +163,6 @@ defineExpose({
|
||||
max-width: 600rpx;
|
||||
opacity: 0;
|
||||
|
||||
&__text {
|
||||
@apply text-md text-center font-bold text-white;
|
||||
}
|
||||
|
||||
&.is-open {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
<cl-text
|
||||
:color="color"
|
||||
:pt="{
|
||||
className: parseClass(['!text-[16px]', pt.title?.className])
|
||||
className: parseClass(['!text-md', pt.title?.className])
|
||||
}"
|
||||
>
|
||||
{{ title }}
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
|
||||
<view
|
||||
v-if="isAdd"
|
||||
class="cl-upload"
|
||||
class="cl-upload is-add"
|
||||
:class="[
|
||||
{
|
||||
'is-dark': isDark,
|
||||
@@ -109,7 +109,7 @@ const props = defineProps({
|
||||
// 上传按钮显示的文本
|
||||
text: {
|
||||
type: String,
|
||||
default: () => t("上传/拍摄")
|
||||
default: () => t("上传 / 拍摄")
|
||||
},
|
||||
// 图片压缩方式:original原图,compressed压缩图
|
||||
sizeType: {
|
||||
@@ -421,6 +421,10 @@ watch(
|
||||
@apply opacity-50;
|
||||
}
|
||||
|
||||
&.is-add {
|
||||
@apply p-1;
|
||||
}
|
||||
|
||||
&__image {
|
||||
@apply w-full h-full absolute top-0 left-0;
|
||||
transition-property: opacity;
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
import { reactive } from "vue";
|
||||
|
||||
type Config = {
|
||||
fontSize: number | null;
|
||||
zIndex: number;
|
||||
startDate: string;
|
||||
endDate: string;
|
||||
};
|
||||
|
||||
export const config: Config = {
|
||||
export const config = reactive<Config>({
|
||||
fontSize: null,
|
||||
zIndex: 600,
|
||||
startDate: "2000-01-01 00:00:00",
|
||||
endDate: "2050-12-31 23:59:59"
|
||||
};
|
||||
});
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
export * from "./component";
|
||||
export * from "./form";
|
||||
export * from "./page";
|
||||
export * from "./size";
|
||||
export * from "./ui";
|
||||
|
||||
130
uni_modules/cool-ui/hooks/size.ts
Normal file
130
uni_modules/cool-ui/hooks/size.ts
Normal file
@@ -0,0 +1,130 @@
|
||||
import { computed, type ComputedRef } from "vue";
|
||||
import { config } from "../config";
|
||||
import { px2rpx } from "@/cool";
|
||||
|
||||
/**
|
||||
* 字号管理类
|
||||
* 用于处理文本大小的缩放和样式
|
||||
*/
|
||||
class Size {
|
||||
// 预设的字号类名
|
||||
public names = [
|
||||
"text-xs",
|
||||
"text-sm",
|
||||
"text-md",
|
||||
"text-lg",
|
||||
"text-xl",
|
||||
"text-2xl",
|
||||
"text-3xl",
|
||||
"text-4xl",
|
||||
"text-5xl",
|
||||
"text-6xl",
|
||||
"text-7xl",
|
||||
"text-8xl",
|
||||
"text-9xl"
|
||||
];
|
||||
|
||||
// 对应的字号大小(px)
|
||||
public sizes = [10, 12, 14, 16, 18, 22, 28, 34, 46, 58, 70, 94, 126];
|
||||
|
||||
// 对应的行高(px)
|
||||
public lineHeights = [14, 18, 22, 26, 26, 1, 1, 1, 1, 1, 1, 1, 1];
|
||||
|
||||
// 原始类名
|
||||
public className: ComputedRef<string> = computed(() => "");
|
||||
|
||||
// 计算后的类名
|
||||
public ptClassName: ComputedRef<string>;
|
||||
|
||||
constructor(cb: (() => string) | null) {
|
||||
this.className = computed(cb ?? (() => ""));
|
||||
|
||||
// 根据全局字号配置动态计算类名
|
||||
this.ptClassName = computed(() => {
|
||||
if (config.fontSize == null) {
|
||||
return this.className.value;
|
||||
}
|
||||
|
||||
const name = this.names[this.getIndex()];
|
||||
return this.className.value.replace(`-important-${name}`, "").replace(name, "");
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取全局字号缩放比例
|
||||
*/
|
||||
getScale = () => {
|
||||
return config.fontSize ?? 1;
|
||||
};
|
||||
|
||||
/**
|
||||
* 根据缩放比例计算rpx值
|
||||
* @param val - 需要转换的值
|
||||
*/
|
||||
getRpx = (val: number | string) => {
|
||||
const scale = this.getScale();
|
||||
|
||||
if (typeof val == "number") {
|
||||
return val * scale + "rpx";
|
||||
} else {
|
||||
const num = parseFloat(val);
|
||||
const unit = val.replace(`${num}`, "");
|
||||
|
||||
return num * scale + unit;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取当前字号在预设中的索引
|
||||
*/
|
||||
getIndex = () => {
|
||||
let index = this.names.findIndex((name) => {
|
||||
if (this.className.value.includes(name)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
// 默认使用 text-md (14px)
|
||||
if (index < 0) {
|
||||
index = 2;
|
||||
}
|
||||
|
||||
return index;
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取最终的字号大小
|
||||
* @param size - 指定字号大小,为空则使用预设值
|
||||
*/
|
||||
getSize = (size: number | string | null): null | string => {
|
||||
// 未设置全局字号时返回null
|
||||
if (config.fontSize == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return this.getRpx(size ?? px2rpx(this.sizes[this.getIndex()]));
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取当前行高
|
||||
*/
|
||||
getLineHeight = (): null | string => {
|
||||
// 未设置全局字号时返回null
|
||||
if (config.fontSize == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const lineHeight = this.lineHeights[this.getIndex()];
|
||||
return lineHeight == 1 ? `1` : this.getRpx(px2rpx(lineHeight));
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 字号管理Hook
|
||||
* @param className - 类名
|
||||
*/
|
||||
export function useSize(cb: (() => string) | null = null): Size {
|
||||
return new Size(cb);
|
||||
}
|
||||
@@ -6,9 +6,9 @@ import Build from "android.os.Build";
|
||||
|
||||
/**
|
||||
* 震动
|
||||
* @param {number} duriation 震动时间单位ms
|
||||
* @param {number} duration 震动时间单位ms
|
||||
*/
|
||||
export function vibrate(duriation: number) {
|
||||
export function vibrate(duration: number) {
|
||||
try {
|
||||
const context = UTSAndroid.getAppContext() as Context;
|
||||
let vb: Vibrator | null = null;
|
||||
@@ -25,7 +25,7 @@ export function vibrate(duriation: number) {
|
||||
// Android 8.0 (API 26) 及以上使用 VibrationEffect
|
||||
if (Build.VERSION.SDK_INT >= 26) {
|
||||
const effect = VibrationEffect.createOneShot(
|
||||
duriation.toLong(),
|
||||
duration.toLong(),
|
||||
VibrationEffect.DEFAULT_AMPLITUDE
|
||||
);
|
||||
vb.vibrate(effect);
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/**
|
||||
* 震动
|
||||
* @param {number} duriation 震动时间单位ms,ios微信失效
|
||||
* @param {number} duration 震动时间单位ms,ios微信失效
|
||||
*/
|
||||
export function vibrate(duriation: number) {
|
||||
export function vibrate(duration: number) {
|
||||
wx.vibrateShort({
|
||||
type: "medium",
|
||||
success() {},
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
/**
|
||||
* 震动
|
||||
* @param {number} duriation 震动时间单位ms,ios微信失效
|
||||
* @param {number} duration 震动时间单位ms,ios微信失效
|
||||
*/
|
||||
export function vibrate(duriation: number) {
|
||||
export function vibrate(duration: number) {
|
||||
try {
|
||||
navigator.vibrate(duriation);
|
||||
navigator.vibrate(duration);
|
||||
} catch (error) {
|
||||
console.error("WEB震动失败:", error);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user