uview-pro 0.5.16 → 0.5.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/changelog.md +73 -29
- package/components/u-alert-tips/u-alert-tips.vue +1 -1
- package/components/u-calendar/types.ts +44 -2
- package/components/u-calendar/u-calendar.vue +553 -162
- package/components/u-popup/u-popup.vue +48 -2
- package/components/u-tabbar/u-tabbar.vue +66 -35
- package/components/u-th/u-th.vue +1 -1
- package/locale/lang/en-US.ts +3 -1
- package/locale/lang/zh-CN.ts +3 -1
- package/package.json +4 -4
- package/readme.md +239 -239
- package/types/global.d.ts +3 -1
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
<template>
|
|
2
|
+
<!-- inline 模式:直接渲染内容,不显示为弹窗 -->
|
|
3
|
+
<view v-if="props.mode === 'inline'" class="u-popup-inline" :class="customClass" :style="inlineStyle">
|
|
4
|
+
<slot />
|
|
5
|
+
</view>
|
|
6
|
+
<!-- 弹窗模式 -->
|
|
2
7
|
<view
|
|
3
|
-
v-if="visibleSync"
|
|
8
|
+
v-else-if="visibleSync"
|
|
4
9
|
class="u-drawer"
|
|
5
10
|
:style="$u.toStyle({ zIndex: Number(uZIndex) - 1 }, customStyle)"
|
|
6
11
|
:class="customClass"
|
|
@@ -78,7 +83,7 @@ import { PopupProps } from './types';
|
|
|
78
83
|
* popup 弹窗
|
|
79
84
|
* @description 弹出层容器,用于展示弹窗、信息提示等内容,支持上、下、左、右和中部弹出。组件只提供容器,内部内容由用户自定义
|
|
80
85
|
* @tutorial https://uviewpro.cn/zh/components/popup.html
|
|
81
|
-
* @property {String} mode 弹出方向(默认left
|
|
86
|
+
* @property {String} mode 弹出方向(默认left),新增 inline 模式可直接插入页面
|
|
82
87
|
* @property {Boolean} mask 是否显示遮罩(默认true)
|
|
83
88
|
* @property {Stringr | Number} length mode=left | 见官网说明(默认auto)
|
|
84
89
|
* @property {Boolean} zoom 是否开启缩放动画,只在mode为center时有效(默认true)
|
|
@@ -96,6 +101,7 @@ import { PopupProps } from './types';
|
|
|
96
101
|
* @event {Function} open 弹出层打开
|
|
97
102
|
* @event {Function} close 弹出层收起
|
|
98
103
|
* @example <u-popup v-model="show"><view>出淤泥而不染,濯清涟而不妖</view></u-popup>
|
|
104
|
+
* @example <u-popup mode="inline"><view>直接插入页面内容</view></u-popup>
|
|
99
105
|
*/
|
|
100
106
|
|
|
101
107
|
const props = defineProps(PopupProps);
|
|
@@ -106,6 +112,25 @@ const visibleSync = ref(false);
|
|
|
106
112
|
const showDrawer = ref(false);
|
|
107
113
|
const timer = ref<ReturnType<typeof setTimeout> | null>(null);
|
|
108
114
|
const closeFromInner = ref(false); // value的值改变,是发生在内部还是外部
|
|
115
|
+
|
|
116
|
+
// inline 模式的样式
|
|
117
|
+
const inlineStyle = computed(() => {
|
|
118
|
+
let style: Record<string, any> = {};
|
|
119
|
+
if (props.width) style.width = getUnitValue(props.width);
|
|
120
|
+
if (props.height) style.height = getUnitValue(props.height);
|
|
121
|
+
if (props.borderRadius) style.borderRadius = `${props.borderRadius}rpx`;
|
|
122
|
+
// 合并用户自定义样式
|
|
123
|
+
if (props.customStyle) {
|
|
124
|
+
if (typeof props.customStyle === 'string') {
|
|
125
|
+
// 简单处理字符串样式
|
|
126
|
+
style = { ...style };
|
|
127
|
+
} else {
|
|
128
|
+
Object.assign(style, props.customStyle);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
return style;
|
|
132
|
+
});
|
|
133
|
+
|
|
109
134
|
// 根据mode的位置,设定其弹窗的宽度(mode = left|right),或者高度(mode = top|bottom)
|
|
110
135
|
const style = computed(() => {
|
|
111
136
|
let style: Record<string, any> = {};
|
|
@@ -171,6 +196,8 @@ const uZIndex = computed(() => (props.zIndex ? props.zIndex : $u.zIndex.popup));
|
|
|
171
196
|
watch(
|
|
172
197
|
() => props.modelValue,
|
|
173
198
|
val => {
|
|
199
|
+
// inline 模式下不响应 modelValue 变化
|
|
200
|
+
if (props.mode === 'inline') return;
|
|
174
201
|
if (val) {
|
|
175
202
|
open();
|
|
176
203
|
} else if (!closeFromInner.value) {
|
|
@@ -181,6 +208,8 @@ watch(
|
|
|
181
208
|
);
|
|
182
209
|
|
|
183
210
|
onMounted(() => {
|
|
211
|
+
// inline 模式下不执行弹窗逻辑
|
|
212
|
+
if (props.mode === 'inline') return;
|
|
184
213
|
if (props.modelValue) open();
|
|
185
214
|
});
|
|
186
215
|
|
|
@@ -203,6 +232,8 @@ function maskClick() {
|
|
|
203
232
|
* 关闭弹窗
|
|
204
233
|
*/
|
|
205
234
|
function close() {
|
|
235
|
+
// inline 模式下不执行关闭逻辑
|
|
236
|
+
if (props.mode === 'inline') return;
|
|
206
237
|
// 标记关闭是内部发生的,否则修改了value值,导致watch中对value检测,导致再执行一遍close
|
|
207
238
|
// 造成@close事件触发两次
|
|
208
239
|
closeFromInner.value = true;
|
|
@@ -213,6 +244,8 @@ function close() {
|
|
|
213
244
|
* 中部弹出时,点击内容区域关闭弹窗
|
|
214
245
|
*/
|
|
215
246
|
function modeCenterClose(mode: string) {
|
|
247
|
+
// inline 模式下不执行关闭逻辑
|
|
248
|
+
if (props.mode === 'inline') return;
|
|
216
249
|
// 中部弹出时,需要.u-drawer-content将居中内容,此元素会铺满屏幕,点击需要关闭弹窗
|
|
217
250
|
// 让其只在mode=center时起作用
|
|
218
251
|
if (mode != 'center' || !props.maskCloseAble) return;
|
|
@@ -223,6 +256,8 @@ function modeCenterClose(mode: string) {
|
|
|
223
256
|
* 打开弹窗
|
|
224
257
|
*/
|
|
225
258
|
function open() {
|
|
259
|
+
// inline 模式下不执行打开逻辑
|
|
260
|
+
if (props.mode === 'inline') return;
|
|
226
261
|
change('visibleSync', 'showDrawer', true);
|
|
227
262
|
}
|
|
228
263
|
|
|
@@ -232,6 +267,8 @@ function open() {
|
|
|
232
267
|
* 打开时,先渲染组件,延时一定时间再让遮罩和弹窗的动画起作用
|
|
233
268
|
*/
|
|
234
269
|
function change(param1: 'showDrawer' | 'visibleSync', param2: 'visibleSync' | 'showDrawer', status: boolean) {
|
|
270
|
+
// inline 模式下不执行状态变更
|
|
271
|
+
if (props.mode === 'inline') return;
|
|
235
272
|
// 如果this.popup为false,意味着为picker,actionsheet等组件调用了popup组件
|
|
236
273
|
if (props.popup === true) {
|
|
237
274
|
emit('update:modelValue', status);
|
|
@@ -262,6 +299,15 @@ function change(param1: 'showDrawer' | 'visibleSync', param2: 'visibleSync' | 's
|
|
|
262
299
|
<style scoped lang="scss">
|
|
263
300
|
@import '../../libs/css/style.components.scss';
|
|
264
301
|
|
|
302
|
+
// inline 模式样式
|
|
303
|
+
.u-popup-inline {
|
|
304
|
+
/* #ifndef APP-NVUE */
|
|
305
|
+
display: block;
|
|
306
|
+
/* #endif */
|
|
307
|
+
position: relative;
|
|
308
|
+
background-color: var(--u-bg-white);
|
|
309
|
+
}
|
|
310
|
+
|
|
265
311
|
.u-drawer {
|
|
266
312
|
/* #ifndef APP-NVUE */
|
|
267
313
|
display: block;
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
:key="index"
|
|
18
18
|
:class="{ 'u-tabbar__content__circle': props.midButton && item.midButton }"
|
|
19
19
|
@tap.stop="clickHandler(index)"
|
|
20
|
-
:style="
|
|
20
|
+
:style="$u.toStyle(getItemStyle(item))"
|
|
21
21
|
>
|
|
22
22
|
<view
|
|
23
23
|
class="u-tabbar__content__item__container"
|
|
@@ -32,6 +32,12 @@
|
|
|
32
32
|
: 'u-tabbar__content__item__icon'
|
|
33
33
|
]"
|
|
34
34
|
>
|
|
35
|
+
<!-- 凸起按钮边框 -->
|
|
36
|
+
<view
|
|
37
|
+
v-if="props.midButton && item.midButton && props.borderTop"
|
|
38
|
+
class="u-tabbar__content__circle__border"
|
|
39
|
+
:style="{ backgroundColor: props.bgColor }"
|
|
40
|
+
></view>
|
|
35
41
|
<u-icon
|
|
36
42
|
:size="getIconSize(index)"
|
|
37
43
|
:name="elIconPath(index)"
|
|
@@ -69,12 +75,6 @@
|
|
|
69
75
|
</view>
|
|
70
76
|
</view>
|
|
71
77
|
</view>
|
|
72
|
-
<view
|
|
73
|
-
v-if="props.midButton"
|
|
74
|
-
class="u-tabbar__content__circle__border"
|
|
75
|
-
:class="{ 'u-border': props.borderTop }"
|
|
76
|
-
:style="{ backgroundColor: props.bgColor, left: midButtonLeft }"
|
|
77
|
-
></view>
|
|
78
78
|
</view>
|
|
79
79
|
<!-- 这里加上一个48rpx的高度,是为了增高有凸起按钮时的防塌陷高度(也即按钮凸出来部分的高度) -->
|
|
80
80
|
<!-- calc 计算0时单位不一致会计算失败,这里+1px -->
|
|
@@ -102,6 +102,7 @@ export default {
|
|
|
102
102
|
import { ref, computed, onMounted } from 'vue';
|
|
103
103
|
import { $u } from '../..';
|
|
104
104
|
import { TabbarProps } from './types';
|
|
105
|
+
import type { TabbarItem } from '../../types/global';
|
|
105
106
|
|
|
106
107
|
/**
|
|
107
108
|
* u-tabbar 底部导航栏
|
|
@@ -128,8 +129,51 @@ const emit = defineEmits<{ (e: 'change', index: number): void; (e: 'update:model
|
|
|
128
129
|
// 计算z-index值
|
|
129
130
|
const uZIndex = computed(() => props?.zIndex ?? $u.zIndex.tabbar);
|
|
130
131
|
|
|
131
|
-
|
|
132
|
-
|
|
132
|
+
/**
|
|
133
|
+
* 检查是否有任意item设置了width
|
|
134
|
+
*/
|
|
135
|
+
const hasCustomWidth = computed(() => {
|
|
136
|
+
return props.list?.some(item => item.width !== undefined && item.width !== null && item.width !== '') || false;
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* 计算每个item的宽度,根据list数量平分
|
|
141
|
+
* 如果任意item设置了width,则不自动计算,返回auto
|
|
142
|
+
*/
|
|
143
|
+
const autoItemWidth = computed(() => {
|
|
144
|
+
// 如果用户设置了任意一个width,就不自动计算
|
|
145
|
+
if (hasCustomWidth.value) return 'auto';
|
|
146
|
+
|
|
147
|
+
const count = props.list?.length || 0;
|
|
148
|
+
if (count === 0) return 'auto';
|
|
149
|
+
return `${100 / count}%`;
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* 获取单个item的样式
|
|
154
|
+
* 使用 flex 简写属性设置宽度,与原有样式保持一致
|
|
155
|
+
*/
|
|
156
|
+
function getItemStyle(item: TabbarItem): Record<string, any> {
|
|
157
|
+
const style: Record<string, any> = {};
|
|
158
|
+
// 背景色
|
|
159
|
+
style.backgroundColor = props.bgColor;
|
|
160
|
+
// flex宽度设置
|
|
161
|
+
if (item.width !== undefined && item.width !== null && item.width !== '') {
|
|
162
|
+
// 固定宽度:不伸缩
|
|
163
|
+
style.flex = `0 0 ${$u.addUnit(item.width)}`;
|
|
164
|
+
style.width = $u.addUnit(item.width);
|
|
165
|
+
} else if (hasCustomWidth.value) {
|
|
166
|
+
// 如果其他item设置了width,未设置的自动填充剩余空间
|
|
167
|
+
style.flex = '1 1 auto';
|
|
168
|
+
style.width = 'auto';
|
|
169
|
+
} else {
|
|
170
|
+
// 自动平分:不伸缩,按百分比分配
|
|
171
|
+
style.flex = `0 0 ${autoItemWidth.value}`;
|
|
172
|
+
style.width = autoItemWidth.value;
|
|
173
|
+
}
|
|
174
|
+
return style;
|
|
175
|
+
}
|
|
176
|
+
|
|
133
177
|
const pageUrl = ref(''); // 当前页面URL
|
|
134
178
|
|
|
135
179
|
onMounted(() => {
|
|
@@ -140,7 +184,6 @@ onMounted(() => {
|
|
|
140
184
|
const pages = getCurrentPages();
|
|
141
185
|
// 页面栈中的最后一个即为项为当前页面,route属性为页面路径
|
|
142
186
|
pageUrl.value = pages[pages.length - 1].route as string;
|
|
143
|
-
if (props.midButton) getMidButtonLeft();
|
|
144
187
|
});
|
|
145
188
|
|
|
146
189
|
/**
|
|
@@ -303,15 +346,6 @@ function getTextSize(index: number) {
|
|
|
303
346
|
return props.textSize;
|
|
304
347
|
}
|
|
305
348
|
|
|
306
|
-
/**
|
|
307
|
-
* 获取凸起按钮外层元素的left值,让其水平居中
|
|
308
|
-
*/
|
|
309
|
-
function getMidButtonLeft() {
|
|
310
|
-
const windowWidth = $u.sys().windowWidth;
|
|
311
|
-
// 由于安卓中css计算left: 50%的结果不准确,故用js计算
|
|
312
|
-
midButtonLeft.value = windowWidth / 2 + 'px';
|
|
313
|
-
}
|
|
314
|
-
|
|
315
349
|
/**
|
|
316
350
|
* 图标和文字间距
|
|
317
351
|
*/
|
|
@@ -358,22 +392,7 @@ function containerStyle(index: number) {
|
|
|
358
392
|
/* #ifndef APP-NVUE */
|
|
359
393
|
box-sizing: content-box;
|
|
360
394
|
/* #endif */
|
|
361
|
-
|
|
362
|
-
border-radius: 100%;
|
|
363
|
-
width: 130rpx;
|
|
364
|
-
height: 130rpx;
|
|
365
|
-
top: -58rpx;
|
|
366
|
-
position: absolute;
|
|
367
|
-
z-index: 4;
|
|
368
|
-
background-color: var(--u-bg-white);
|
|
369
|
-
// 由于安卓的无能,导致只有3个tabbar item时,此css计算方式有误差
|
|
370
|
-
// 故使用js计算的形式来定位,此处不注释,是因为js计算有延后,避免出现位置闪动
|
|
371
|
-
left: 50%;
|
|
372
|
-
transform: translateX(-50%);
|
|
373
|
-
&:after {
|
|
374
|
-
border-radius: 100px;
|
|
375
|
-
}
|
|
376
|
-
}
|
|
395
|
+
|
|
377
396
|
&__item {
|
|
378
397
|
flex: 1;
|
|
379
398
|
justify-content: center;
|
|
@@ -404,6 +423,7 @@ function containerStyle(index: number) {
|
|
|
404
423
|
line-height: 28rpx;
|
|
405
424
|
text-align: center;
|
|
406
425
|
width: 100%;
|
|
426
|
+
z-index: 6;
|
|
407
427
|
}
|
|
408
428
|
}
|
|
409
429
|
&__circle {
|
|
@@ -440,6 +460,17 @@ function containerStyle(index: number) {
|
|
|
440
460
|
z-index: 6;
|
|
441
461
|
transform: translateX(-50%);
|
|
442
462
|
}
|
|
463
|
+
&__border {
|
|
464
|
+
position: absolute;
|
|
465
|
+
top: -18rpx;
|
|
466
|
+
width: 130rpx;
|
|
467
|
+
height: 130rpx;
|
|
468
|
+
border-radius: 100%;
|
|
469
|
+
border-top: 1px solid var(--u-border-color);
|
|
470
|
+
background-color: var(--u-bg-white);
|
|
471
|
+
z-index: 0;
|
|
472
|
+
pointer-events: none;
|
|
473
|
+
}
|
|
443
474
|
}
|
|
444
475
|
}
|
|
445
476
|
}
|
package/components/u-th/u-th.vue
CHANGED
package/locale/lang/en-US.ts
CHANGED
package/locale/lang/zh-CN.ts
CHANGED
package/package.json
CHANGED
|
@@ -2,17 +2,17 @@
|
|
|
2
2
|
"id": "uview-pro",
|
|
3
3
|
"name": "uview-pro",
|
|
4
4
|
"displayName": "【支持鸿蒙】uView Pro|基于Vue3+TS的高质量UI组件库,支持多主题、暗黑模式、多语言",
|
|
5
|
-
"version": "0.5.
|
|
5
|
+
"version": "0.5.18",
|
|
6
6
|
"description": "uView Pro是基于Vue3+TS的多平台UI框架,提供80+高质量组件、便捷工具和常用模板,支持多主题、暗黑模式、多语言,支持H5/APP/鸿蒙/小程序多端开发。已在鸿蒙应用商店上架,欢迎体验!",
|
|
7
7
|
"main": "index.ts",
|
|
8
8
|
"module": "index.ts",
|
|
9
9
|
"browser": "index.ts",
|
|
10
10
|
"keywords": [
|
|
11
|
-
"ui",
|
|
12
|
-
"uview",
|
|
13
11
|
"uview-pro",
|
|
14
12
|
"vue3",
|
|
15
|
-
"
|
|
13
|
+
"多主题",
|
|
14
|
+
"暗黑模式",
|
|
15
|
+
"多语言"
|
|
16
16
|
],
|
|
17
17
|
"author": "anyup",
|
|
18
18
|
"license": "MIT",
|