papayaui 0.0.53 → 0.1.0
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/.DS_Store +0 -0
- package/components/badge/badge.vue +9 -14
- package/components/badge/demo.vue +11 -6
- package/components/bottom-popup/bottom-popup.vue +30 -16
- package/components/button/button.vue +81 -30
- package/components/button/demo.vue +2 -4
- package/components/calendar/calendar-wrapper.vue +52 -37
- package/components/calendar/calendar.vue +9 -5
- package/components/cascader/cascader.vue +105 -54
- package/components/cascader/search-view.vue +28 -14
- package/components/cell/cell.vue +26 -23
- package/components/cell-group/cell-group.vue +4 -2
- package/components/checkbox/checkbox.vue +12 -11
- package/components/checkbox-btns/checkbox-btns.vue +8 -5
- package/components/checkbox-group/checkbox-group.vue +4 -2
- package/components/container/container.vue +14 -7
- package/components/count-to/count-to.vue +4 -6
- package/components/date-picker/date-picker.vue +42 -22
- package/components/empty/empty.vue +6 -4
- package/components/env-view/env-view.vue +3 -1
- package/components/field/field.vue +15 -12
- package/components/form/demo.vue +10 -10
- package/components/form/form.vue +5 -3
- package/components/form-item/form-item.vue +5 -8
- package/components/icon/icon.vue +5 -3
- package/components/image/demo.vue +1 -2
- package/components/image/image.vue +8 -6
- package/components/input-number/input-number.vue +25 -33
- package/components/list/list.vue +10 -3
- package/components/list-item/list-item.vue +71 -0
- package/components/loading-icon/loading-icon.vue +7 -5
- package/components/loadmore/loadmore.vue +6 -4
- package/components/menu/menu.vue +18 -19
- package/components/menu-item/menu-item.vue +42 -38
- package/components/nav-bar/demo.vue +1 -1
- package/components/nav-bar/nav-bar.vue +12 -7
- package/components/number-input/number-input.vue +5 -3
- package/components/overlay/overlay.vue +4 -2
- package/components/picker-popup/picker-popup.vue +38 -27
- package/components/picker-view/picker-view.vue +12 -15
- package/components/popover/popover.vue +13 -18
- package/components/popup/popup.vue +8 -6
- package/components/radio/radio.vue +12 -11
- package/components/radio-group/radio-group.vue +4 -2
- package/components/safe-bottom/safe-bottom.vue +4 -2
- package/components/search/search.vue +7 -5
- package/components/section/section.vue +7 -5
- package/components/sidebar/sidebar.vue +4 -2
- package/components/sidebar-item/sidebar-item.vue +7 -6
- package/components/sort-label/sort-label.vue +9 -7
- package/components/steps/steps.vue +13 -18
- package/components/sticky/demo.vue +1 -1
- package/components/sticky/sticky.vue +148 -255
- package/components/swipe-cell/swipe-cell.vue +12 -10
- package/components/switch/switch.vue +6 -12
- package/components/tabs/tabs.vue +12 -10
- package/components/tag/tag.vue +5 -5
- package/components/textarea/textarea.vue +7 -11
- package/components/tooltip/tooltip.vue +11 -16
- package/components/transition/transition.vue +5 -3
- package/components/watermark/watermark.vue +7 -5
- package/core/{useCalendar.ts → useCalendar/index.ts} +1 -1
- package/core/useCascader/index.ts +51 -0
- package/core/{tests/useCountTo.test.ts → useCountTo/index.test.ts} +1 -1
- package/core/{useCountTo.ts → useCountTo/index.ts} +1 -1
- package/core/{tests/useDatePicker.test.ts → useDatePicker/index.test.ts} +1 -1
- package/core/{useDatePicker.ts → useDatePicker/index.ts} +2 -2
- package/{hooks/form → core/useForm}/useFormValidate.ts +4 -2
- package/core/{useInputNumber.ts → useInputNumber/index.ts} +1 -1
- package/core/useNamespace/index.ts +106 -0
- package/core/{useSelect.ts → useSelect/index.ts} +1 -1
- package/core/{useSwitch.ts → useSwitch/index.ts} +1 -1
- package/core/useTree/index.test.ts +38 -0
- package/core/useTree/index.ts +160 -0
- package/core/useVirtualList/demo.vue +48 -0
- package/core/useVirtualList/index.ts +374 -0
- package/fonts/.DS_Store +0 -0
- package/hooks/index.ts +1 -3
- package/hooks/useRect.ts +17 -0
- package/images/.DS_Store +0 -0
- package/images/demo.jpeg +0 -0
- package/package.json +1 -1
- package/request/utils.ts +1 -12
- package/styles/color.scss +3 -0
- package/styles/index.scss +1 -0
- package/types/index.ts +5 -2
- package/utils/common.ts +2 -2
- package/utils/lang.ts +12 -0
- package/components/cascader/list-item.vue +0 -51
- package/components/popup/popup.bak.vue +0 -224
- package/core/useTree.ts +0 -156
- package/utils/style.ts +0 -30
- /package/{hooks/form → core/useForm}/index.ts +0 -0
- /package/{hooks/form → core/useForm}/message.ts +0 -0
- /package/core/{demo/useList.vue → useList/demo.vue} +0 -0
- /package/core/{useList.ts → useList/index.ts} +0 -0
- /package/core/{tests/useSwitch.test.ts → useSwitch/index.test.ts} +0 -0
package/.DS_Store
CHANGED
|
Binary file
|
|
@@ -1,16 +1,9 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<view
|
|
3
|
-
:class="
|
|
4
|
-
computedClass('badge', {
|
|
5
|
-
'badge--dot': dot,
|
|
6
|
-
'badge--fixed': !!$slots.default,
|
|
7
|
-
})
|
|
8
|
-
"
|
|
9
|
-
>
|
|
2
|
+
<view :class="[ns.b(), ns.is('dot', dot), ns.is('fixed', !!$slots.default)]">
|
|
10
3
|
<slot></slot>
|
|
11
4
|
<view
|
|
12
5
|
v-if="visible"
|
|
13
|
-
:class="
|
|
6
|
+
:class="ns.e('content')"
|
|
14
7
|
:style="{
|
|
15
8
|
backgroundColor: color,
|
|
16
9
|
top: getUnitValue(offset[1].toString()),
|
|
@@ -25,8 +18,8 @@
|
|
|
25
18
|
|
|
26
19
|
<script lang="ts" setup>
|
|
27
20
|
import { computed, CSSProperties } from 'vue'
|
|
21
|
+
import useNamespace, { defaultNamespace } from '../../core/useNamespace'
|
|
28
22
|
import { getUnitValue } from '../../utils'
|
|
29
|
-
import { computedClass, PREFIX } from '../../utils/style'
|
|
30
23
|
|
|
31
24
|
export interface BadgeProps {
|
|
32
25
|
/** 徽标内容 */
|
|
@@ -45,9 +38,11 @@ export interface BadgeProps {
|
|
|
45
38
|
show?: boolean
|
|
46
39
|
}
|
|
47
40
|
|
|
41
|
+
const ns = useNamespace('badge')
|
|
42
|
+
|
|
48
43
|
const props = withDefaults(defineProps<BadgeProps>(), {
|
|
49
44
|
content: undefined,
|
|
50
|
-
color: `var(--${
|
|
45
|
+
color: `var(--${defaultNamespace}-color-danger)`,
|
|
51
46
|
max: undefined,
|
|
52
47
|
offset: () => [0, 0],
|
|
53
48
|
showZero: false,
|
|
@@ -75,7 +70,7 @@ const value = computed(() => {
|
|
|
75
70
|
.#{$prefix}-badge {
|
|
76
71
|
position: relative;
|
|
77
72
|
display: inline-block;
|
|
78
|
-
|
|
73
|
+
&__content {
|
|
79
74
|
position: relative;
|
|
80
75
|
display: flex;
|
|
81
76
|
flex-direction: row;
|
|
@@ -86,12 +81,12 @@ const value = computed(() => {
|
|
|
86
81
|
padding: 2px 5px;
|
|
87
82
|
border-radius: 100px;
|
|
88
83
|
}
|
|
89
|
-
&--dot
|
|
84
|
+
&--dot &__content {
|
|
90
85
|
padding: 0;
|
|
91
86
|
width: 8px;
|
|
92
87
|
height: 8px;
|
|
93
88
|
}
|
|
94
|
-
&--fixed
|
|
89
|
+
&--fixed &__content {
|
|
95
90
|
position: absolute;
|
|
96
91
|
transform: translate(50%, -50%);
|
|
97
92
|
transform-origin: 100%;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<DocDemoBlock title="基础用法" card>
|
|
3
|
-
<view class="
|
|
3
|
+
<view class="demo-badge">
|
|
4
4
|
<pa-badge content="5">
|
|
5
5
|
<view class="demo-block"></view>
|
|
6
6
|
</pa-badge>
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
</view>
|
|
17
17
|
</DocDemoBlock>
|
|
18
18
|
<DocDemoBlock title="最大值" card>
|
|
19
|
-
<view class="
|
|
19
|
+
<view class="demo-badge">
|
|
20
20
|
<pa-badge content="999" :max="9">
|
|
21
21
|
<view class="demo-block"></view>
|
|
22
22
|
</pa-badge>
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
</view>
|
|
30
30
|
</DocDemoBlock>
|
|
31
31
|
<DocDemoBlock title="自定义颜色" card>
|
|
32
|
-
<view class="
|
|
32
|
+
<view class="demo-badge">
|
|
33
33
|
<pa-badge content="5" color="#1989fa">
|
|
34
34
|
<view class="demo-block"></view>
|
|
35
35
|
</pa-badge>
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
</view>
|
|
46
46
|
</DocDemoBlock>
|
|
47
47
|
<DocDemoBlock title="自定义内容" card>
|
|
48
|
-
<view class="
|
|
48
|
+
<view class="demo-badge">
|
|
49
49
|
<pa-badge>
|
|
50
50
|
<view class="demo-block"></view>
|
|
51
51
|
<template #content>
|
|
@@ -61,7 +61,7 @@
|
|
|
61
61
|
</view>
|
|
62
62
|
</DocDemoBlock>
|
|
63
63
|
<DocDemoBlock title="自定义位置" card>
|
|
64
|
-
<view class="
|
|
64
|
+
<view class="demo-badge">
|
|
65
65
|
<pa-badge content="99" :offset="[-10, -10]">
|
|
66
66
|
<view class="demo-block"></view>
|
|
67
67
|
</pa-badge>
|
|
@@ -71,7 +71,7 @@
|
|
|
71
71
|
</view>
|
|
72
72
|
</DocDemoBlock>
|
|
73
73
|
<DocDemoBlock title="独立展示" card>
|
|
74
|
-
<view class="
|
|
74
|
+
<view class="demo-badge">
|
|
75
75
|
<pa-badge content="9" />
|
|
76
76
|
<pa-badge content="99" />
|
|
77
77
|
</view>
|
|
@@ -84,6 +84,11 @@ import DocDemoBlock from '../../doc/doc-demo-block.vue'
|
|
|
84
84
|
</script>
|
|
85
85
|
|
|
86
86
|
<style lang="scss" scoped>
|
|
87
|
+
.demo-badge {
|
|
88
|
+
:deep(.pa-badge) {
|
|
89
|
+
margin-right: 42px;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
87
92
|
.demo-block {
|
|
88
93
|
width: 40px;
|
|
89
94
|
height: 40px;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<Popup
|
|
3
|
-
:custom-class="
|
|
3
|
+
:custom-class="ns.b()"
|
|
4
4
|
:show="show"
|
|
5
5
|
position="bottom"
|
|
6
6
|
:height="height"
|
|
@@ -13,28 +13,19 @@
|
|
|
13
13
|
:safe-area-inset-bottom="false"
|
|
14
14
|
@update:show="emit('update:show', !!$event)"
|
|
15
15
|
>
|
|
16
|
-
<view
|
|
17
|
-
class="
|
|
18
|
-
:class="[
|
|
19
|
-
computedClass('bottom-popup__wrapper'),
|
|
20
|
-
{ 'safe-bottom-padding': safeAreaInsetBottom },
|
|
21
|
-
]"
|
|
22
|
-
>
|
|
23
|
-
<view
|
|
24
|
-
:class="computedClass('bottom-popup__header')"
|
|
25
|
-
class="width-full flex items-center justify-center flex-shrink-0"
|
|
26
|
-
>
|
|
16
|
+
<view :class="[ns.e('wrapper'), { 'safe-bottom-padding': safeAreaInsetBottom }]">
|
|
17
|
+
<view :class="ns.e('header')">
|
|
27
18
|
<slot name="before-title"></slot>
|
|
28
|
-
<text class="
|
|
19
|
+
<text :class="ns.e('title')">{{ title }}</text>
|
|
29
20
|
<slot name="after-title"></slot>
|
|
30
21
|
</view>
|
|
31
22
|
|
|
32
|
-
<view class="
|
|
23
|
+
<view :class="ns.e('body')">
|
|
33
24
|
<view class="flex-1" style="overflow: hidden">
|
|
34
25
|
<slot></slot>
|
|
35
26
|
</view>
|
|
36
27
|
|
|
37
|
-
<view v-if="$slots.footer" :class="
|
|
28
|
+
<view v-if="$slots.footer" :class="ns.e('footer')">
|
|
38
29
|
<slot name="footer"></slot>
|
|
39
30
|
</view>
|
|
40
31
|
</view>
|
|
@@ -44,7 +35,7 @@
|
|
|
44
35
|
|
|
45
36
|
<script lang="ts" setup>
|
|
46
37
|
import { CSSProperties, toRefs } from 'vue'
|
|
47
|
-
import
|
|
38
|
+
import useNamespace from '../../core/useNamespace'
|
|
48
39
|
import Popup from '../popup/popup.vue'
|
|
49
40
|
|
|
50
41
|
export interface BottomPopupProps {
|
|
@@ -70,6 +61,8 @@ export interface BottomPopupProps {
|
|
|
70
61
|
safeAreaInsetBottom?: boolean
|
|
71
62
|
}
|
|
72
63
|
|
|
64
|
+
const ns = useNamespace('bottom-popup')
|
|
65
|
+
|
|
73
66
|
const props = withDefaults(defineProps<BottomPopupProps>(), {
|
|
74
67
|
show: false,
|
|
75
68
|
title: undefined,
|
|
@@ -95,14 +88,35 @@ const emit = defineEmits<{
|
|
|
95
88
|
.#{$prefix}-bottom-popup {
|
|
96
89
|
&__wrapper {
|
|
97
90
|
position: relative;
|
|
91
|
+
display: flex;
|
|
92
|
+
flex-direction: column;
|
|
98
93
|
height: 100%;
|
|
99
94
|
border-radius: 24rpx 24rpx 0 0;
|
|
100
95
|
}
|
|
101
96
|
|
|
102
97
|
&__header {
|
|
103
98
|
position: relative;
|
|
99
|
+
display: flex;
|
|
100
|
+
align-items: center;
|
|
101
|
+
justify-content: center;
|
|
102
|
+
flex-shrink: 0;
|
|
103
|
+
width: 100%;
|
|
104
104
|
height: 88rpx;
|
|
105
105
|
}
|
|
106
|
+
&__title {
|
|
107
|
+
font-size: 32rpx;
|
|
108
|
+
line-height: 40rpx;
|
|
109
|
+
color: _var(color-black);
|
|
110
|
+
font-weight: 500;
|
|
111
|
+
margin-right: 8rpx;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
&__body {
|
|
115
|
+
display: flex;
|
|
116
|
+
flex-direction: column;
|
|
117
|
+
flex: 1;
|
|
118
|
+
overflow: hidden;
|
|
119
|
+
}
|
|
106
120
|
|
|
107
121
|
&__footer {
|
|
108
122
|
width: 100%;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<button
|
|
3
|
-
:class="[
|
|
3
|
+
:class="[ns.b(), ns.m(type), ns.m(size), ns.is('block', block), ns.is('plain', plain)]"
|
|
4
4
|
:style="customStyle"
|
|
5
|
-
:hover-class="
|
|
5
|
+
:hover-class="ns.m('hover')"
|
|
6
6
|
:disabled="disabled"
|
|
7
7
|
:plain="plain"
|
|
8
8
|
:open-type="openType"
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
@chooseavatar="emit('chooseavatar', $event)"
|
|
16
16
|
@tap="onClick"
|
|
17
17
|
>
|
|
18
|
-
<view class="
|
|
18
|
+
<view :class="ns.e('content')">
|
|
19
19
|
<Loadmore
|
|
20
20
|
v-if="localLoading"
|
|
21
21
|
class="mr-4"
|
|
@@ -40,9 +40,9 @@
|
|
|
40
40
|
<script lang="ts" setup>
|
|
41
41
|
import { getUnitValue } from '../../utils/common'
|
|
42
42
|
import { computed, CSSProperties, ref, StyleValue } from 'vue'
|
|
43
|
-
import { computedClass } from '../../utils/style'
|
|
44
43
|
import Icon from '../icon/icon.vue'
|
|
45
44
|
import Loadmore from '../loadmore/loadmore.vue'
|
|
45
|
+
import useNamespace from '../../core/useNamespace'
|
|
46
46
|
|
|
47
47
|
export interface ButtonProps {
|
|
48
48
|
/** 按钮类型 */
|
|
@@ -51,6 +51,8 @@ export interface ButtonProps {
|
|
|
51
51
|
width?: string
|
|
52
52
|
/** 按钮高度 */
|
|
53
53
|
height?: string
|
|
54
|
+
/**尺寸 */
|
|
55
|
+
size?: 'large' | 'normal' | 'small' | 'mini'
|
|
54
56
|
/** 字体大小 */
|
|
55
57
|
fontSize?: string
|
|
56
58
|
/** 是否为块级元素 */
|
|
@@ -101,12 +103,15 @@ export interface ButtonProps {
|
|
|
101
103
|
showMessageCard?: boolean
|
|
102
104
|
}
|
|
103
105
|
|
|
106
|
+
const ns = useNamespace('button')
|
|
107
|
+
|
|
104
108
|
const props = withDefaults(defineProps<ButtonProps>(), {
|
|
105
109
|
type: 'primary',
|
|
106
|
-
width:
|
|
107
|
-
height:
|
|
108
|
-
|
|
109
|
-
|
|
110
|
+
width: undefined,
|
|
111
|
+
height: undefined,
|
|
112
|
+
size: 'normal',
|
|
113
|
+
fontSize: undefined,
|
|
114
|
+
round: undefined,
|
|
110
115
|
icon: undefined,
|
|
111
116
|
syncClick: undefined,
|
|
112
117
|
customStyle: undefined,
|
|
@@ -136,16 +141,24 @@ const clickLoading = ref<boolean>()
|
|
|
136
141
|
const localLoading = computed(() => props.loading || clickLoading.value)
|
|
137
142
|
|
|
138
143
|
const customStyle = computed<StyleValue>(() => {
|
|
139
|
-
|
|
144
|
+
const style: CSSProperties = {
|
|
140
145
|
...props.customStyle,
|
|
141
|
-
|
|
142
|
-
|
|
146
|
+
}
|
|
147
|
+
if (props.width) {
|
|
148
|
+
style.width = props.block
|
|
143
149
|
? getUnitValue(props.width === 'auto' ? '100%' : props.width)
|
|
144
|
-
: getUnitValue(props.width)
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
150
|
+
: getUnitValue(props.width)
|
|
151
|
+
}
|
|
152
|
+
if (props.height) {
|
|
153
|
+
style.height = getUnitValue(props.height)
|
|
154
|
+
}
|
|
155
|
+
if (props.fontSize) {
|
|
156
|
+
style.fontSize = getUnitValue(props.fontSize)
|
|
157
|
+
}
|
|
158
|
+
if (props.round) {
|
|
159
|
+
style.borderRadius = props.round === true ? '100px' : getUnitValue(props.round)
|
|
148
160
|
}
|
|
161
|
+
return style
|
|
149
162
|
})
|
|
150
163
|
|
|
151
164
|
const onClick = async (event: MouseEvent) => {
|
|
@@ -167,9 +180,20 @@ const onClick = async (event: MouseEvent) => {
|
|
|
167
180
|
<style lang="scss" scoped>
|
|
168
181
|
@import '../../styles/vars.scss';
|
|
169
182
|
.#{$prefix}-button {
|
|
170
|
-
|
|
183
|
+
display: inline-block;
|
|
184
|
+
height: 44px;
|
|
185
|
+
line-height: 1.2;
|
|
186
|
+
margin: _var(button-margin, 0);
|
|
171
187
|
border: 1px solid transparent;
|
|
172
188
|
box-sizing: border-box;
|
|
189
|
+
|
|
190
|
+
&__content {
|
|
191
|
+
display: flex;
|
|
192
|
+
align-items: center;
|
|
193
|
+
justify-content: center;
|
|
194
|
+
height: 100%;
|
|
195
|
+
}
|
|
196
|
+
|
|
173
197
|
&::before {
|
|
174
198
|
position: absolute;
|
|
175
199
|
top: 50%;
|
|
@@ -187,42 +211,69 @@ const onClick = async (event: MouseEvent) => {
|
|
|
187
211
|
&::after {
|
|
188
212
|
border: none;
|
|
189
213
|
}
|
|
214
|
+
|
|
190
215
|
&--hover {
|
|
191
216
|
&::before {
|
|
192
217
|
opacity: 0.1;
|
|
193
218
|
}
|
|
194
219
|
}
|
|
195
|
-
|
|
220
|
+
|
|
221
|
+
&--default {
|
|
196
222
|
color: _var(color-black);
|
|
197
223
|
background-color: #fff;
|
|
198
224
|
border-color: #ebedf0;
|
|
199
225
|
}
|
|
200
|
-
|
|
226
|
+
&--primary {
|
|
201
227
|
color: #fff;
|
|
202
228
|
background-color: _var(color-primary);
|
|
203
229
|
border-color: _var(color-primary);
|
|
204
|
-
&.button--plain {
|
|
205
|
-
color: _var(color-primary);
|
|
206
|
-
}
|
|
207
230
|
}
|
|
208
|
-
|
|
231
|
+
&--warning {
|
|
209
232
|
color: #fff;
|
|
210
233
|
background-color: _var(color-warning);
|
|
211
234
|
border-color: _var(color-warning);
|
|
212
|
-
&.button--plain {
|
|
213
|
-
color: _var(color-warning);
|
|
214
|
-
}
|
|
215
235
|
}
|
|
216
|
-
|
|
236
|
+
&--danger {
|
|
217
237
|
color: #fff;
|
|
218
238
|
background-color: _var(color-danger);
|
|
219
239
|
border-color: _var(color-danger);
|
|
220
|
-
&.button--plain {
|
|
221
|
-
color: _var(color-danger);
|
|
222
|
-
}
|
|
223
240
|
}
|
|
224
|
-
|
|
241
|
+
|
|
242
|
+
&--large {
|
|
243
|
+
width: 100%;
|
|
244
|
+
height: 50px;
|
|
245
|
+
}
|
|
246
|
+
&--normal {
|
|
247
|
+
font-size: 14px;
|
|
248
|
+
padding: _var(button-padding, 0 15px);
|
|
249
|
+
}
|
|
250
|
+
&--small {
|
|
251
|
+
height: 32px;
|
|
252
|
+
font-size: 12px;
|
|
253
|
+
padding: _var(button-padding, 0 8px);
|
|
254
|
+
}
|
|
255
|
+
&--mini {
|
|
256
|
+
height: 24px;
|
|
257
|
+
font-size: 10px;
|
|
258
|
+
padding: _var(button-padding, 0 4px);
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
&--block {
|
|
262
|
+
display: block;
|
|
263
|
+
width: 100%;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
&--plain {
|
|
225
267
|
background-color: transparent;
|
|
268
|
+
&.#{$prefix}-button--primary {
|
|
269
|
+
color: _var(color-primary);
|
|
270
|
+
}
|
|
271
|
+
&.#{$prefix}-button--warning {
|
|
272
|
+
color: _var(color-warning);
|
|
273
|
+
}
|
|
274
|
+
&.#{$prefix}-button--danger {
|
|
275
|
+
color: _var(color-danger);
|
|
276
|
+
}
|
|
226
277
|
}
|
|
227
278
|
&[disabled]:not([type]) {
|
|
228
279
|
color: _var(color-black);
|
|
@@ -1,52 +1,55 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<view :class="
|
|
3
|
-
<view :class="
|
|
4
|
-
<view v-if="showTitle" :class="
|
|
5
|
-
<view v-if="showSubtitle" :class="
|
|
2
|
+
<view :class="ns.b('wrapper')">
|
|
3
|
+
<view :class="ns.b('header')">
|
|
4
|
+
<view v-if="showTitle" :class="ns.be('header', 'title')">{{ title }}</view>
|
|
5
|
+
<view v-if="showSubtitle" :class="ns.be('header', 'subtitle')">
|
|
6
6
|
{{ months[monthCurrent]?.date.format('YYYY年M月') || '' }}
|
|
7
7
|
</view>
|
|
8
|
-
<view :class="
|
|
9
|
-
<view v-for="item in weekdays" :key="item" :class="
|
|
8
|
+
<view :class="ns.e('weekdays')">
|
|
9
|
+
<view v-for="item in weekdays" :key="item" :class="ns.e('weekday')">
|
|
10
10
|
{{ item }}
|
|
11
11
|
</view>
|
|
12
12
|
</view>
|
|
13
13
|
</view>
|
|
14
|
-
<scroll-view
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
:class="computedClass('calendar-body')"
|
|
18
|
-
@scroll="onScroll"
|
|
19
|
-
>
|
|
20
|
-
<view
|
|
21
|
-
v-for="(monthItem, monthIndex) in months"
|
|
22
|
-
:key="monthIndex"
|
|
23
|
-
:class="computedClass('calendar__month')"
|
|
24
|
-
>
|
|
25
|
-
<view v-if="monthIndex !== 0" :class="computedClass('calendar__month-title')">
|
|
14
|
+
<scroll-view scroll-y :scroll-top="scrollTop" :class="ns.b('body')" @scroll="onThrottleScroll">
|
|
15
|
+
<view v-for="(monthItem, monthIndex) in months" :key="monthIndex" :class="ns.e('month')">
|
|
16
|
+
<view v-if="monthIndex !== 0" :class="ns.e('month-title')">
|
|
26
17
|
{{ monthItem.date.format('YYYY年M月') }}
|
|
27
18
|
</view>
|
|
28
|
-
<view
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
<view :class="
|
|
41
|
-
{{
|
|
19
|
+
<view
|
|
20
|
+
:class="ns.e('days')"
|
|
21
|
+
:style="{
|
|
22
|
+
height: isVisualRange(monthIndex)
|
|
23
|
+
? 'auto'
|
|
24
|
+
: getUnitValue(
|
|
25
|
+
Math.ceil((monthItem.dayOfWeekStart + monthItem.dayLength) / 7) * 64,
|
|
26
|
+
'px',
|
|
27
|
+
),
|
|
28
|
+
}"
|
|
29
|
+
>
|
|
30
|
+
<template v-if="isVisualRange(monthIndex)">
|
|
31
|
+
<view v-if="showMark" :class="ns.e('month-mark')">
|
|
32
|
+
{{ monthItem.date.month() + 1 }}
|
|
42
33
|
</view>
|
|
43
|
-
<view
|
|
44
|
-
|
|
34
|
+
<view
|
|
35
|
+
v-for="(dayItem, dayIndex) in getDays(monthItem.date)"
|
|
36
|
+
:key="dayItem.text"
|
|
37
|
+
:class="[ns.e('day'), ns.em('day', dayItem.type)]"
|
|
38
|
+
:style="{ gridColumnStart: dayIndex === 0 ? monthItem.dayOfWeekStart + 1 : 'auto' }"
|
|
39
|
+
@tap="onSelect(dayItem)"
|
|
40
|
+
>
|
|
41
|
+
<view :class="ns.e('top-info')">{{ dayItem.topInfo }}</view>
|
|
42
|
+
<view :class="ns.e('day__select')">
|
|
43
|
+
{{ dayItem.text }}
|
|
44
|
+
</view>
|
|
45
|
+
<view :class="ns.e('bottom-info')">{{ dayItem.bottomInfo }}</view>
|
|
46
|
+
</view>
|
|
47
|
+
</template>
|
|
45
48
|
</view>
|
|
46
49
|
</view>
|
|
47
50
|
<SafeBottom v-if="!showConfirm && safeAreaInsetBottom" />
|
|
48
51
|
</scroll-view>
|
|
49
|
-
<view v-if="showConfirm" :class="
|
|
52
|
+
<view v-if="showConfirm" :class="ns.b('footer')" class="px-26 py-15">
|
|
50
53
|
<ButtonComponent type="primary" block :disabled="!confirmEnabled" @click="onConfirm">
|
|
51
54
|
{{ confirmEnabled ? confirmText : confirmDisabledText }}
|
|
52
55
|
</ButtonComponent>
|
|
@@ -61,9 +64,10 @@ import { computed, getCurrentInstance, nextTick, ref, toRefs } from 'vue'
|
|
|
61
64
|
import useCalendar, { DayItem, FirstDayOfWeekType } from '../../core/useCalendar'
|
|
62
65
|
import { useRect } from '../../hooks'
|
|
63
66
|
import { EventDetail } from '../../types'
|
|
64
|
-
import { computedClass } from '../../utils/style'
|
|
65
67
|
import ButtonComponent from '../button/button.vue'
|
|
66
68
|
import SafeBottom from '../safe-bottom/safe-bottom.vue'
|
|
69
|
+
import { getUnitValue, throttle } from '../../utils'
|
|
70
|
+
import useNamespace from '../../core/useNamespace'
|
|
67
71
|
|
|
68
72
|
export interface CalendarWrapperProps {
|
|
69
73
|
/** 选择类型: single表示选择单个日期,multiple表示选择多个日期,range表示选择日期区间 */
|
|
@@ -103,6 +107,8 @@ export interface CalendarWrapperProps {
|
|
|
103
107
|
maxRange?: number
|
|
104
108
|
}
|
|
105
109
|
|
|
110
|
+
const ns = useNamespace('calendar')
|
|
111
|
+
|
|
106
112
|
const props = withDefaults(defineProps<CalendarWrapperProps>(), {
|
|
107
113
|
type: 'single',
|
|
108
114
|
title: '日期选择',
|
|
@@ -155,6 +161,14 @@ const confirmEnabled = computed<boolean>(() => {
|
|
|
155
161
|
return selectedItems.value.length > 0
|
|
156
162
|
})
|
|
157
163
|
|
|
164
|
+
/**
|
|
165
|
+
* 月份是否在显示范围
|
|
166
|
+
*/
|
|
167
|
+
const isVisualRange = (monthIndex: number) => {
|
|
168
|
+
const diff = monthIndex - monthCurrent.value
|
|
169
|
+
return diff >= -1 && diff <= 1
|
|
170
|
+
}
|
|
171
|
+
|
|
158
172
|
const onScroll = (e: EventDetail<{ scrollTop: number }>) => {
|
|
159
173
|
let current = 0
|
|
160
174
|
const scrollTop = e.detail.scrollTop
|
|
@@ -165,10 +179,11 @@ const onScroll = (e: EventDetail<{ scrollTop: number }>) => {
|
|
|
165
179
|
}
|
|
166
180
|
monthCurrent.value = current
|
|
167
181
|
}
|
|
182
|
+
const onThrottleScroll = throttle(onScroll, 100, { trailing: true })
|
|
168
183
|
|
|
169
184
|
const updateMonthTop = () => {
|
|
170
185
|
if (!instance) return
|
|
171
|
-
useRect(instance,
|
|
186
|
+
useRect(instance, `.${ns.e('month')}`, true).then((nodes) => {
|
|
172
187
|
const tops = (nodes ?? []).reduce((result, node) => {
|
|
173
188
|
result.push((result[result.length - 1] || 0) + node.height)
|
|
174
189
|
return result
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<Popup
|
|
3
3
|
v-if="poppable"
|
|
4
|
-
:custom-class="
|
|
4
|
+
:custom-class="ns.b()"
|
|
5
5
|
:show="show"
|
|
6
6
|
:height="getUnitValue(height)"
|
|
7
7
|
:closeable="showTitle || showSubtitle"
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
</Popup>
|
|
21
21
|
<view
|
|
22
22
|
v-else
|
|
23
|
-
:class="
|
|
23
|
+
:class="ns.b()"
|
|
24
24
|
:style="{ height: getUnitValue(height), borderRadius: getUnitValue($attrs.round as string ?? '0') }"
|
|
25
25
|
>
|
|
26
26
|
<CalendarWrapper
|
|
@@ -36,10 +36,10 @@
|
|
|
36
36
|
|
|
37
37
|
<script lang="ts" setup>
|
|
38
38
|
import { Dayjs } from 'dayjs'
|
|
39
|
-
import { onMounted, ref, watch } from 'vue'
|
|
39
|
+
import { onMounted, ref, watch, nextTick } from 'vue'
|
|
40
40
|
import { DayItem } from '../../core/useCalendar'
|
|
41
|
+
import useNamespace from '../../core/useNamespace'
|
|
41
42
|
import { getUnitValue } from '../../utils'
|
|
42
|
-
import { computedClass } from '../../utils/style'
|
|
43
43
|
import CalendarWrapper, { CalendarWrapperProps } from '../calendar/calendar-wrapper.vue'
|
|
44
44
|
import Popup, { PopupProps } from '../popup/popup.vue'
|
|
45
45
|
|
|
@@ -62,6 +62,8 @@ export interface CalendarProps
|
|
|
62
62
|
showSubtitle?: boolean
|
|
63
63
|
}
|
|
64
64
|
|
|
65
|
+
const ns = useNamespace('calendar')
|
|
66
|
+
|
|
65
67
|
const props = withDefaults(defineProps<CalendarProps>(), {
|
|
66
68
|
poppable: true,
|
|
67
69
|
show: false,
|
|
@@ -85,7 +87,9 @@ watch(
|
|
|
85
87
|
() => props.show,
|
|
86
88
|
(newVal, oldVal) => {
|
|
87
89
|
if (newVal !== oldVal && newVal && props.poppable) {
|
|
88
|
-
|
|
90
|
+
nextTick(() => {
|
|
91
|
+
wrapperRef.value?.updateMonthTop()
|
|
92
|
+
})
|
|
89
93
|
}
|
|
90
94
|
},
|
|
91
95
|
)
|