hy-app 0.2.5 → 0.2.7
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/common/index.ts +2 -1
- package/common/shakeService.ts +60 -0
- package/components/hy-action-sheet/hy-action-sheet.vue +184 -0
- package/components/hy-action-sheet/index.scss +123 -0
- package/components/hy-action-sheet/props.ts +18 -0
- package/components/hy-action-sheet/typing.d.ts +96 -0
- package/components/hy-address-picker/hy-address-picker.vue +75 -91
- package/components/hy-avatar/hy-avatar.vue +64 -73
- package/components/hy-button/hy-button.vue +3 -3
- package/components/hy-button/typing.d.ts +35 -31
- package/components/hy-cell/typing.d.ts +27 -24
- package/components/hy-empty/hy-empty.vue +30 -37
- package/components/hy-empty/icon.ts +78 -0
- package/components/hy-empty/index.scss +2 -1
- package/components/hy-empty/props.ts +10 -9
- package/components/hy-empty/typing.d.ts +39 -14
- package/components/hy-float-button/hy-float-button.vue +183 -17
- package/components/hy-float-button/props.ts +17 -15
- package/components/hy-float-button/typing.d.ts +51 -27
- package/components/hy-icon/hy-icon.vue +39 -41
- package/components/hy-icon/props.ts +17 -16
- package/components/hy-icon/typing.d.ts +24 -20
- package/components/hy-image/hy-image.vue +69 -104
- package/components/hy-image/index.scss +21 -5
- package/components/hy-image/props.ts +11 -10
- package/components/hy-image/typing.d.ts +23 -19
- package/components/hy-modal/hy-modal.vue +42 -54
- package/components/hy-modal/index.scss +56 -32
- package/components/hy-modal/props.ts +15 -14
- package/components/hy-modal/typing.d.ts +23 -17
- package/components/hy-popover/hy-popover.vue +200 -0
- package/components/hy-popover/index.scss +83 -0
- package/components/hy-popover/props.ts +13 -0
- package/components/hy-popover/typing.d.ts +56 -0
- package/components/hy-popup/index.scss +2 -2
- package/components/hy-popup/props.ts +7 -7
- package/components/hy-popup/typing.d.ts +17 -17
- package/components/hy-qrcode/hy-qrcode.vue +44 -45
- package/components/hy-rate/props.ts +6 -6
- package/components/hy-signature/props.ts +14 -14
- package/components/hy-tooltip/index.scss +2 -2
- package/components/hy-transition/hy-transition.vue +64 -72
- package/components/hy-transition/typing.d.ts +10 -6
- package/composables/index.ts +4 -2
- package/composables/usePopover.ts +221 -0
- package/composables/useQueue.ts +52 -0
- package/libs/css/_config.scss +5 -0
- package/libs/css/_function.scss +89 -0
- package/libs/css/mixin.scss +146 -21
- package/libs/css/vars.css +3 -1
- package/package.json +2 -2
- package/theme.scss +2 -1
- package/utils/inside.ts +96 -108
- package/utils/inspect.ts +48 -40
- package/utils/utils.ts +170 -187
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
<HyPopup
|
|
3
3
|
mode="center"
|
|
4
4
|
:zoom="zoom"
|
|
5
|
-
:show="
|
|
5
|
+
:show="modelValue"
|
|
6
|
+
:round="round"
|
|
6
7
|
:customStyle="{
|
|
7
|
-
borderRadius: '6px',
|
|
8
8
|
overflow: 'hidden',
|
|
9
9
|
marginTop: `-${addUnit(negativeTop)}`,
|
|
10
10
|
}"
|
|
@@ -32,53 +32,41 @@
|
|
|
32
32
|
</text>
|
|
33
33
|
</slot>
|
|
34
34
|
</view>
|
|
35
|
-
<view
|
|
36
|
-
class="hy-modal__button-group--confirm-button"
|
|
37
|
-
v-if="$slots.confirmButton"
|
|
38
|
-
>
|
|
35
|
+
<view class="hy-modal__button-group--confirm-button" v-if="$slots.confirmButton">
|
|
39
36
|
<slot name="confirmButton"></slot>
|
|
40
37
|
</view>
|
|
41
38
|
<template v-else>
|
|
42
39
|
<view
|
|
43
|
-
class="
|
|
40
|
+
:class="[
|
|
41
|
+
'hy-modal__button-group',
|
|
42
|
+
showCancelButton &&
|
|
43
|
+
showConfirmButton &&
|
|
44
|
+
(!buttonReverse ? 'hy-modal__button-exact' : 'hy-modal__button-exact--reverse'),
|
|
45
|
+
]"
|
|
44
46
|
:style="{
|
|
45
47
|
flexDirection: buttonReverse ? 'row-reverse' : 'row',
|
|
46
48
|
}"
|
|
47
49
|
>
|
|
48
50
|
<view
|
|
49
|
-
class="hy-modal__button-group__wrapper
|
|
51
|
+
class="hy-modal__button-group__wrapper hy-modal__button-group__wrapper--cancel"
|
|
50
52
|
:hover-stay-time="150"
|
|
51
53
|
hover-class="hy-modal__button-group__wrapper--hover"
|
|
52
|
-
:class="[
|
|
53
|
-
showCancelButton &&
|
|
54
|
-
!showConfirmButton &&
|
|
55
|
-
'hy-modal__button-group__wrapper--only-cancel',
|
|
56
|
-
]"
|
|
57
54
|
v-if="showCancelButton"
|
|
58
55
|
@tap.stop="cancelHandler"
|
|
59
56
|
>
|
|
60
57
|
<text
|
|
61
|
-
class="hy-modal__button-group__wrapper__text"
|
|
58
|
+
class="hy-modal__button-group__wrapper__text hy-modal__button-group__wrapper--cancel-text"
|
|
62
59
|
:style="{
|
|
63
60
|
color: cancelColor,
|
|
64
61
|
}"
|
|
65
|
-
>{{ cancelText }}</text
|
|
66
62
|
>
|
|
63
|
+
{{ cancelText }}
|
|
64
|
+
</text>
|
|
67
65
|
</view>
|
|
68
|
-
<hy-line
|
|
69
|
-
v-if="showConfirmButton && showCancelButton"
|
|
70
|
-
length="48px"
|
|
71
|
-
direction="column"
|
|
72
|
-
></hy-line>
|
|
73
66
|
<view
|
|
74
67
|
class="hy-modal__button-group__wrapper hy-modal__button-group__wrapper--confirm"
|
|
75
68
|
:hover-stay-time="150"
|
|
76
69
|
hover-class="hy-modal__button-group__wrapper--hover"
|
|
77
|
-
:class="[
|
|
78
|
-
!showCancelButton &&
|
|
79
|
-
showConfirmButton &&
|
|
80
|
-
'hy-modal__button-group__wrapper--only-confirm',
|
|
81
|
-
]"
|
|
82
70
|
v-if="showConfirmButton"
|
|
83
71
|
@tap="confirmHandler"
|
|
84
72
|
>
|
|
@@ -89,8 +77,9 @@
|
|
|
89
77
|
:style="{
|
|
90
78
|
color: confirmColor,
|
|
91
79
|
}"
|
|
92
|
-
>{{ confirmText }}</text
|
|
93
80
|
>
|
|
81
|
+
{{ confirmText }}
|
|
82
|
+
</text>
|
|
94
83
|
</view>
|
|
95
84
|
</view>
|
|
96
85
|
</template>
|
|
@@ -100,38 +89,37 @@
|
|
|
100
89
|
|
|
101
90
|
<script lang="ts">
|
|
102
91
|
export default {
|
|
103
|
-
name:
|
|
92
|
+
name: 'hy-modal',
|
|
104
93
|
options: {
|
|
105
94
|
addGlobalClass: true,
|
|
106
95
|
virtualHost: true,
|
|
107
|
-
styleIsolation:
|
|
96
|
+
styleIsolation: 'shared',
|
|
108
97
|
},
|
|
109
|
-
}
|
|
98
|
+
}
|
|
110
99
|
</script>
|
|
111
100
|
|
|
112
101
|
<script setup lang="ts">
|
|
113
|
-
import { ref, toRefs, watch } from
|
|
114
|
-
import defaultProps from
|
|
115
|
-
import type IProps from
|
|
116
|
-
import { addUnit } from
|
|
102
|
+
import { ref, toRefs, watch } from 'vue'
|
|
103
|
+
import defaultProps from './props'
|
|
104
|
+
import type IProps from './typing'
|
|
105
|
+
import { addUnit } from '../../utils'
|
|
117
106
|
|
|
118
107
|
// 组件
|
|
119
|
-
import
|
|
120
|
-
import
|
|
121
|
-
import HyLoading from "../hy-loading/hy-loading.vue";
|
|
108
|
+
import HyPopup from '../hy-popup/hy-popup.vue'
|
|
109
|
+
import HyLoading from '../hy-loading/hy-loading.vue'
|
|
122
110
|
|
|
123
|
-
const props = withDefaults(defineProps<IProps>(), defaultProps)
|
|
124
|
-
const {
|
|
125
|
-
const emit = defineEmits([
|
|
111
|
+
const props = withDefaults(defineProps<IProps>(), defaultProps)
|
|
112
|
+
const { modelValue, asyncClose, closeOnClickOverlay } = toRefs(props)
|
|
113
|
+
const emit = defineEmits(['confirm', 'cancel', 'close', 'update:modelValue'])
|
|
126
114
|
|
|
127
|
-
const loading = ref<boolean>(false)
|
|
115
|
+
const loading = ref<boolean>(false)
|
|
128
116
|
|
|
129
117
|
watch(
|
|
130
|
-
() =>
|
|
118
|
+
() => modelValue.value,
|
|
131
119
|
(newValue) => {
|
|
132
|
-
if (newValue && loading.value) loading.value = false
|
|
120
|
+
if (newValue && loading.value) loading.value = false
|
|
133
121
|
},
|
|
134
|
-
)
|
|
122
|
+
)
|
|
135
123
|
|
|
136
124
|
/**
|
|
137
125
|
* @description 点击确定按钮
|
|
@@ -139,34 +127,34 @@ watch(
|
|
|
139
127
|
const confirmHandler = () => {
|
|
140
128
|
// 如果配置了异步关闭,将按钮值为loading状态
|
|
141
129
|
if (asyncClose.value) {
|
|
142
|
-
loading.value = true
|
|
130
|
+
loading.value = true
|
|
143
131
|
} else {
|
|
144
|
-
emit(
|
|
132
|
+
emit('update:modelValue', false)
|
|
145
133
|
}
|
|
146
|
-
emit(
|
|
147
|
-
}
|
|
134
|
+
emit('confirm')
|
|
135
|
+
}
|
|
148
136
|
|
|
149
137
|
/**
|
|
150
138
|
* @description 点击取消按钮
|
|
151
139
|
* */
|
|
152
140
|
const cancelHandler = () => {
|
|
153
|
-
emit(
|
|
154
|
-
emit(
|
|
155
|
-
}
|
|
141
|
+
emit('update:modelValue', false)
|
|
142
|
+
emit('cancel')
|
|
143
|
+
}
|
|
156
144
|
|
|
157
145
|
/**
|
|
158
146
|
* @description 点击遮罩
|
|
159
147
|
* */
|
|
160
148
|
const clickHandler = () => {
|
|
161
149
|
if (closeOnClickOverlay.value) {
|
|
162
|
-
emit(
|
|
163
|
-
emit(
|
|
150
|
+
emit('update:modelValue', false)
|
|
151
|
+
emit('close')
|
|
164
152
|
}
|
|
165
|
-
}
|
|
153
|
+
}
|
|
166
154
|
</script>
|
|
167
155
|
|
|
168
156
|
<style lang="scss" scoped>
|
|
169
|
-
@import
|
|
157
|
+
@import './index.scss';
|
|
170
158
|
.modal__content__text {
|
|
171
159
|
text-align: v-bind(contentTextAlign);
|
|
172
160
|
}
|
|
@@ -6,70 +6,94 @@
|
|
|
6
6
|
border-radius: $hy-border-radius-base;
|
|
7
7
|
overflow: hidden;
|
|
8
8
|
|
|
9
|
+
/* 标题 */
|
|
9
10
|
&__title {
|
|
10
11
|
display: flex;
|
|
11
12
|
flex-direction: column;
|
|
12
13
|
justify-content: center;
|
|
13
14
|
align-items: center;
|
|
14
|
-
font-size:
|
|
15
|
+
font-size: $hy-font-size-base;
|
|
15
16
|
font-weight: bold;
|
|
16
17
|
color: $hy-text-color;
|
|
17
18
|
text-align: center;
|
|
18
19
|
padding-top: 25px;
|
|
19
20
|
}
|
|
20
21
|
|
|
22
|
+
/* 内容 */
|
|
21
23
|
&__content {
|
|
22
24
|
padding: 20px;
|
|
23
25
|
@include flex;
|
|
24
26
|
justify-content: center;
|
|
25
27
|
|
|
26
28
|
&__text {
|
|
27
|
-
font-size:
|
|
29
|
+
font-size: $hy-font-size-sm;
|
|
28
30
|
color: $hy-text-color--grey;
|
|
29
31
|
flex: 1;
|
|
30
32
|
text-align: center;
|
|
31
33
|
}
|
|
32
34
|
}
|
|
33
35
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
36
|
+
/* 底部按钮 */
|
|
37
|
+
&__button {
|
|
38
|
+
/* 两个按钮的样式 */
|
|
39
|
+
&-exact {
|
|
40
|
+
view:first-child {
|
|
41
|
+
margin-right: $hy-border-margin-padding-lg;
|
|
42
|
+
}
|
|
43
|
+
&--reverse {
|
|
44
|
+
view:last-child {
|
|
45
|
+
margin-right: $hy-border-margin-padding-lg;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
41
48
|
}
|
|
42
49
|
|
|
43
|
-
|
|
44
|
-
|
|
50
|
+
|
|
51
|
+
&-group {
|
|
45
52
|
@include flex;
|
|
46
|
-
|
|
47
|
-
align-items: center;
|
|
48
|
-
height: 48px;
|
|
53
|
+
padding: 20px;
|
|
49
54
|
|
|
50
|
-
|
|
51
|
-
&--
|
|
52
|
-
|
|
55
|
+
/* 自定义底部按钮 */
|
|
56
|
+
&--confirm-button {
|
|
57
|
+
flex-direction: column;
|
|
58
|
+
padding: 0 25px 15px;
|
|
53
59
|
}
|
|
54
60
|
|
|
55
|
-
&--cancel,
|
|
56
|
-
&--only-confirm {
|
|
57
|
-
border-bottom-left-radius: $hy-border-radius-base;
|
|
58
|
-
}
|
|
59
61
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
62
|
+
&__wrapper {
|
|
63
|
+
flex: 1;
|
|
64
|
+
@include flex;
|
|
65
|
+
justify-content: center;
|
|
66
|
+
align-items: center;
|
|
67
|
+
height: 43px;
|
|
68
|
+
border-radius: $hy-border-radius-semicircle;
|
|
63
69
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
70
|
+
/* 确认 */
|
|
71
|
+
&--confirm {
|
|
72
|
+
background-color: $hy-primary;
|
|
73
|
+
&-text {
|
|
74
|
+
color: #FFFFFF;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/* 取消 */
|
|
79
|
+
&--cancel {
|
|
80
|
+
//background-color: $hy-background--empty;
|
|
81
|
+
background-color: #323233;
|
|
82
|
+
|
|
83
|
+
&-text {
|
|
84
|
+
color: $hy-text-color;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
&--hover {
|
|
89
|
+
opacity: 0.7;
|
|
90
|
+
}
|
|
69
91
|
|
|
70
|
-
|
|
71
|
-
|
|
92
|
+
&__text {
|
|
93
|
+
font-size: 16px;
|
|
94
|
+
text-align: center;
|
|
95
|
+
}
|
|
72
96
|
}
|
|
73
97
|
}
|
|
74
98
|
}
|
|
75
|
-
}
|
|
99
|
+
}
|
|
@@ -1,24 +1,25 @@
|
|
|
1
|
-
import type IProps from
|
|
2
|
-
import { ColorConfig } from
|
|
1
|
+
import type IProps from './typing'
|
|
2
|
+
import { ColorConfig } from '../../config'
|
|
3
3
|
|
|
4
4
|
const defaultProps: IProps = {
|
|
5
|
-
|
|
6
|
-
title:
|
|
7
|
-
content:
|
|
8
|
-
confirmText:
|
|
9
|
-
cancelText:
|
|
5
|
+
modelValue: false,
|
|
6
|
+
title: '',
|
|
7
|
+
content: '',
|
|
8
|
+
confirmText: '确认',
|
|
9
|
+
cancelText: '取消',
|
|
10
10
|
showConfirmButton: true,
|
|
11
11
|
showCancelButton: false,
|
|
12
|
-
confirmColor:
|
|
13
|
-
cancelColor:
|
|
12
|
+
confirmColor: '',
|
|
13
|
+
cancelColor: '',
|
|
14
14
|
buttonReverse: false,
|
|
15
15
|
zoom: true,
|
|
16
|
+
round: 16,
|
|
16
17
|
asyncClose: false,
|
|
17
18
|
closeOnClickOverlay: false,
|
|
18
19
|
negativeTop: 0,
|
|
19
|
-
width:
|
|
20
|
-
confirmButtonShape:
|
|
21
|
-
contentTextAlign:
|
|
22
|
-
}
|
|
20
|
+
width: '550rpx',
|
|
21
|
+
confirmButtonShape: '',
|
|
22
|
+
contentTextAlign: 'left',
|
|
23
|
+
}
|
|
23
24
|
|
|
24
|
-
export default defaultProps
|
|
25
|
+
export default defaultProps
|
|
@@ -1,70 +1,76 @@
|
|
|
1
|
+
import { RowCenterType } from 'hy-app/typing/modules/common'
|
|
2
|
+
|
|
1
3
|
export default interface HyModalProps {
|
|
2
4
|
/**
|
|
3
5
|
* @description 是否显示模态框,请赋值给show (默认 false )
|
|
4
6
|
* */
|
|
5
|
-
|
|
7
|
+
modelValue: boolean
|
|
6
8
|
/**
|
|
7
9
|
* @description 标题内容
|
|
8
10
|
* */
|
|
9
|
-
title?: string
|
|
11
|
+
title?: string
|
|
10
12
|
/**
|
|
11
13
|
* @description 模态框内容,如传入slot内容,则此参数无效
|
|
12
14
|
* */
|
|
13
|
-
content?: string
|
|
15
|
+
content?: string
|
|
14
16
|
/**
|
|
15
17
|
* @description 确认按钮的文字 (默认 '确认' )
|
|
16
18
|
* */
|
|
17
|
-
confirmText?: string
|
|
19
|
+
confirmText?: string
|
|
18
20
|
/**
|
|
19
21
|
* @description 取消按钮的文字 (默认 '取消' )
|
|
20
22
|
* */
|
|
21
|
-
cancelText?: string
|
|
23
|
+
cancelText?: string
|
|
22
24
|
/**
|
|
23
25
|
* @description 是否显示确认按钮 (默认 true )
|
|
24
26
|
* */
|
|
25
|
-
showConfirmButton?: boolean
|
|
27
|
+
showConfirmButton?: boolean
|
|
26
28
|
/**
|
|
27
29
|
* @description 是否显示取消按钮 (默认 false )
|
|
28
30
|
* */
|
|
29
|
-
showCancelButton?: boolean
|
|
31
|
+
showCancelButton?: boolean
|
|
30
32
|
/**
|
|
31
33
|
* @description 确认按钮的颜色 (默认 '#2979ff' )
|
|
32
34
|
* */
|
|
33
|
-
confirmColor?: string
|
|
35
|
+
confirmColor?: string
|
|
34
36
|
/**
|
|
35
37
|
* @description 取消按钮的颜色 (默认 '#606266' )
|
|
36
38
|
* */
|
|
37
|
-
cancelColor?: string
|
|
39
|
+
cancelColor?: string
|
|
38
40
|
/**
|
|
39
41
|
* @description 对调确认和取消的位置 (默认 false )
|
|
40
42
|
* */
|
|
41
|
-
buttonReverse?: boolean
|
|
43
|
+
buttonReverse?: boolean
|
|
42
44
|
/**
|
|
43
45
|
* @description 是否开启缩放模式 (默认 true )
|
|
44
46
|
* */
|
|
45
|
-
zoom?: boolean
|
|
47
|
+
zoom?: boolean
|
|
48
|
+
/**
|
|
49
|
+
* @description 弹窗的圆角 (默认 16 )
|
|
50
|
+
* */
|
|
51
|
+
round?: string | number
|
|
46
52
|
/**
|
|
47
53
|
* @description 是否异步关闭,只对确定按钮有效,见上方说明 (默认 false )
|
|
48
54
|
* */
|
|
49
|
-
asyncClose?: boolean
|
|
55
|
+
asyncClose?: boolean
|
|
50
56
|
/**
|
|
51
57
|
* @description 是否允许点击遮罩关闭Modal (默认 false )
|
|
52
58
|
* */
|
|
53
|
-
closeOnClickOverlay?: boolean
|
|
59
|
+
closeOnClickOverlay?: boolean
|
|
54
60
|
/**
|
|
55
61
|
* @description 往上偏移的值,给一个负的margin-top,往上偏移,避免和键盘重合的情况,单位任意,数值则默认为px单位 (默认 0 )
|
|
56
62
|
* */
|
|
57
|
-
negativeTop?: number
|
|
63
|
+
negativeTop?: number
|
|
58
64
|
/**
|
|
59
65
|
* @description modal宽度,不支持百分比,可以数值,px,rpx单位 (默认 '650rpx' )
|
|
60
66
|
* */
|
|
61
|
-
width?: string | number
|
|
67
|
+
width?: string | number
|
|
62
68
|
/**
|
|
63
69
|
* @description 确认按钮的样式,如设置,将不会显示取消按钮
|
|
64
70
|
* */
|
|
65
|
-
confirmButtonShape?: HyApp.ShapeType |
|
|
71
|
+
confirmButtonShape?: HyApp.ShapeType | ''
|
|
66
72
|
/**
|
|
67
73
|
* @description 文案对齐方式
|
|
68
74
|
* */
|
|
69
|
-
contentTextAlign?: HyApp.
|
|
75
|
+
contentTextAlign?: HyApp.RowCenterType
|
|
70
76
|
}
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<view class="hy-popover" :style="customStyle" id="popover" @click.stop="popover.noop">
|
|
3
|
+
<!-- 使用插槽时无法获取正确宽高 -->
|
|
4
|
+
<view class="hy-popover__pos hy-popover__hidden" id="pos">
|
|
5
|
+
<view class="hy-popover__container">
|
|
6
|
+
<view v-if="mode === 'normal'" class="hy-popover__inner">
|
|
7
|
+
{{ content }}
|
|
8
|
+
</view>
|
|
9
|
+
<view v-if="mode === 'menu' && typeof content === 'object'" class="hy-popover__menu">
|
|
10
|
+
<view
|
|
11
|
+
v-for="(item, index) in content"
|
|
12
|
+
:key="index"
|
|
13
|
+
class="hy-popover__menu-inner"
|
|
14
|
+
@click="menuClick(index)"
|
|
15
|
+
>
|
|
16
|
+
<hy-icon v-if="item.iconClass" :name="item.iconClass" custom-class="hy-popover__icon" />
|
|
17
|
+
<text>{{ item.content }}</text>
|
|
18
|
+
</view>
|
|
19
|
+
</view>
|
|
20
|
+
</view>
|
|
21
|
+
</view>
|
|
22
|
+
<hy-transition
|
|
23
|
+
class="hy-popover__pos"
|
|
24
|
+
:custom-style="popover.popStyle.value"
|
|
25
|
+
:show="showPopover"
|
|
26
|
+
name="fade"
|
|
27
|
+
:duration="200"
|
|
28
|
+
>
|
|
29
|
+
<view class="hy-popover__container">
|
|
30
|
+
<!-- 三角形 -->
|
|
31
|
+
<view
|
|
32
|
+
:class="`hy-popover__arrow ${popover.arrowClass.value}`"
|
|
33
|
+
:style="popover.arrowStyle.value"
|
|
34
|
+
></view>
|
|
35
|
+
<!-- 三角形 -->
|
|
36
|
+
|
|
37
|
+
<!-- 普通模式 -->
|
|
38
|
+
<view v-if="mode === 'normal'" class="hy-popover__inner">
|
|
39
|
+
{{ content }}
|
|
40
|
+
</view>
|
|
41
|
+
<!-- 普通模式 -->
|
|
42
|
+
|
|
43
|
+
<!-- 列表模式 -->
|
|
44
|
+
<view v-if="mode === 'menu'" class="hy-popover__menu">
|
|
45
|
+
<view
|
|
46
|
+
v-for="(item, index) in content"
|
|
47
|
+
:key="index"
|
|
48
|
+
class="hy-popover__menu-inner"
|
|
49
|
+
@click="menuClick(index)"
|
|
50
|
+
:style="index === 0 ? 'border-top: none' : ''"
|
|
51
|
+
>
|
|
52
|
+
<hy-icon
|
|
53
|
+
v-if="typeof item === 'object' && item.iconClass"
|
|
54
|
+
:name="item.iconClass"
|
|
55
|
+
custom-class="hy-popover__icon"
|
|
56
|
+
/>
|
|
57
|
+
<view style="display: inline-block">
|
|
58
|
+
{{ typeof item === 'object' && item.content ? item.content : item }}
|
|
59
|
+
</view>
|
|
60
|
+
</view>
|
|
61
|
+
</view>
|
|
62
|
+
<!-- 列表模式 -->
|
|
63
|
+
|
|
64
|
+
<!-- 用户自定义样式 -->
|
|
65
|
+
<slot name="content" v-else />
|
|
66
|
+
<!-- 用户自定义样式 -->
|
|
67
|
+
</view>
|
|
68
|
+
<hy-icon
|
|
69
|
+
v-if="showClose"
|
|
70
|
+
name="close"
|
|
71
|
+
custom-class="hy-popover__close-icon"
|
|
72
|
+
@click="toggle"
|
|
73
|
+
></hy-icon>
|
|
74
|
+
</hy-transition>
|
|
75
|
+
<view @click="toggle" class="hy-popover__target" id="target">
|
|
76
|
+
<slot />
|
|
77
|
+
</view>
|
|
78
|
+
</view>
|
|
79
|
+
</template>
|
|
80
|
+
|
|
81
|
+
<script lang="ts">
|
|
82
|
+
export default {
|
|
83
|
+
name: 'hy-popover',
|
|
84
|
+
options: {
|
|
85
|
+
virtualHost: true,
|
|
86
|
+
addGlobalClass: true,
|
|
87
|
+
styleIsolation: 'shared',
|
|
88
|
+
},
|
|
89
|
+
}
|
|
90
|
+
</script>
|
|
91
|
+
|
|
92
|
+
<script lang="ts" setup>
|
|
93
|
+
import { getCurrentInstance, onMounted, ref, toRefs, watch } from 'vue'
|
|
94
|
+
import defaultProps from './props'
|
|
95
|
+
import IProps, { type PopoverExpose } from './typing'
|
|
96
|
+
import { isArray } from '../../utils'
|
|
97
|
+
import { type Queue, queueKey, usePopover } from '../../composables'
|
|
98
|
+
|
|
99
|
+
// 组件
|
|
100
|
+
import HyIcon from '../hy-icon/hy-icon.vue'
|
|
101
|
+
import HyTransition from '../hy-transition/hy-transition.vue'
|
|
102
|
+
|
|
103
|
+
const props = withDefaults(defineProps<IProps>(), defaultProps)
|
|
104
|
+
const { modelValue, content, mode, placement } = toRefs(props)
|
|
105
|
+
const emit = defineEmits(['update:modelValue', 'menuClick', 'change', 'open', 'close'])
|
|
106
|
+
|
|
107
|
+
const queue = inject<Queue | null>(queueKey, null)
|
|
108
|
+
const selector: string = 'popover'
|
|
109
|
+
const { proxy } = getCurrentInstance() as any
|
|
110
|
+
const popover = usePopover()
|
|
111
|
+
const showPopover = ref<boolean>(false) // 控制popover显隐
|
|
112
|
+
|
|
113
|
+
watch(
|
|
114
|
+
() => content.value,
|
|
115
|
+
(newVal) => {
|
|
116
|
+
if (mode.value === 'normal' && typeof newVal !== 'string') {
|
|
117
|
+
console.error('在“normal”模式下,值类型必须为字符串类型。')
|
|
118
|
+
} else if (mode.value === 'menu' && !isArray(newVal)) {
|
|
119
|
+
console.error('在“menu”模式下,值类型必须是数组类型。')
|
|
120
|
+
}
|
|
121
|
+
},
|
|
122
|
+
)
|
|
123
|
+
|
|
124
|
+
watch(
|
|
125
|
+
() => props.placement,
|
|
126
|
+
() => {
|
|
127
|
+
popover.init(placement.value, true, selector)
|
|
128
|
+
},
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
watch(
|
|
132
|
+
() => modelValue.value,
|
|
133
|
+
(newValue: boolean) => {
|
|
134
|
+
showPopover.value = newValue
|
|
135
|
+
},
|
|
136
|
+
)
|
|
137
|
+
|
|
138
|
+
watch(
|
|
139
|
+
() => showPopover.value,
|
|
140
|
+
(newValue) => {
|
|
141
|
+
if (newValue) {
|
|
142
|
+
popover.control(placement.value, props.offset)
|
|
143
|
+
// if (queue && queue.closeOther) {
|
|
144
|
+
// queue.closeOther(proxy)
|
|
145
|
+
// }
|
|
146
|
+
queue.closeOther(proxy)
|
|
147
|
+
}
|
|
148
|
+
popover.showStyle.value = newValue ? 'display: inline-block;' : 'display: none;'
|
|
149
|
+
emit('change', { show: newValue })
|
|
150
|
+
emit(`${newValue ? 'open' : 'close'}`)
|
|
151
|
+
},
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
onMounted(() => {
|
|
155
|
+
popover.init(placement.value, true, selector)
|
|
156
|
+
})
|
|
157
|
+
|
|
158
|
+
onBeforeMount(() => {
|
|
159
|
+
queue.pushToQueue(proxy)
|
|
160
|
+
popover.showStyle.value = showPopover.value ? 'opacity: 1;' : 'opacity: 0;'
|
|
161
|
+
})
|
|
162
|
+
|
|
163
|
+
onBeforeUnmount(() => {
|
|
164
|
+
queue.removeFromQueue(proxy)
|
|
165
|
+
})
|
|
166
|
+
|
|
167
|
+
const menuClick = (index: number) => {
|
|
168
|
+
updateModelValue(false)
|
|
169
|
+
emit('menuClick', {
|
|
170
|
+
item: (props.content as Array<Record<string, any>>)[index],
|
|
171
|
+
index,
|
|
172
|
+
})
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
const toggle = () => {
|
|
176
|
+
if (props.disabled) return
|
|
177
|
+
updateModelValue(!showPopover.value)
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
const open = () => {
|
|
181
|
+
updateModelValue(true)
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
const close = () => {
|
|
185
|
+
updateModelValue(false)
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
function updateModelValue(value: boolean) {
|
|
189
|
+
showPopover.value = value
|
|
190
|
+
emit('update:modelValue', value)
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
defineExpose<PopoverExpose>({
|
|
194
|
+
open,
|
|
195
|
+
close,
|
|
196
|
+
})
|
|
197
|
+
</script>
|
|
198
|
+
<style lang="scss" scoped>
|
|
199
|
+
@import './index.scss';
|
|
200
|
+
</style>
|