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.
Files changed (55) hide show
  1. package/common/index.ts +2 -1
  2. package/common/shakeService.ts +60 -0
  3. package/components/hy-action-sheet/hy-action-sheet.vue +184 -0
  4. package/components/hy-action-sheet/index.scss +123 -0
  5. package/components/hy-action-sheet/props.ts +18 -0
  6. package/components/hy-action-sheet/typing.d.ts +96 -0
  7. package/components/hy-address-picker/hy-address-picker.vue +75 -91
  8. package/components/hy-avatar/hy-avatar.vue +64 -73
  9. package/components/hy-button/hy-button.vue +3 -3
  10. package/components/hy-button/typing.d.ts +35 -31
  11. package/components/hy-cell/typing.d.ts +27 -24
  12. package/components/hy-empty/hy-empty.vue +30 -37
  13. package/components/hy-empty/icon.ts +78 -0
  14. package/components/hy-empty/index.scss +2 -1
  15. package/components/hy-empty/props.ts +10 -9
  16. package/components/hy-empty/typing.d.ts +39 -14
  17. package/components/hy-float-button/hy-float-button.vue +183 -17
  18. package/components/hy-float-button/props.ts +17 -15
  19. package/components/hy-float-button/typing.d.ts +51 -27
  20. package/components/hy-icon/hy-icon.vue +39 -41
  21. package/components/hy-icon/props.ts +17 -16
  22. package/components/hy-icon/typing.d.ts +24 -20
  23. package/components/hy-image/hy-image.vue +69 -104
  24. package/components/hy-image/index.scss +21 -5
  25. package/components/hy-image/props.ts +11 -10
  26. package/components/hy-image/typing.d.ts +23 -19
  27. package/components/hy-modal/hy-modal.vue +42 -54
  28. package/components/hy-modal/index.scss +56 -32
  29. package/components/hy-modal/props.ts +15 -14
  30. package/components/hy-modal/typing.d.ts +23 -17
  31. package/components/hy-popover/hy-popover.vue +200 -0
  32. package/components/hy-popover/index.scss +83 -0
  33. package/components/hy-popover/props.ts +13 -0
  34. package/components/hy-popover/typing.d.ts +56 -0
  35. package/components/hy-popup/index.scss +2 -2
  36. package/components/hy-popup/props.ts +7 -7
  37. package/components/hy-popup/typing.d.ts +17 -17
  38. package/components/hy-qrcode/hy-qrcode.vue +44 -45
  39. package/components/hy-rate/props.ts +6 -6
  40. package/components/hy-signature/props.ts +14 -14
  41. package/components/hy-tooltip/index.scss +2 -2
  42. package/components/hy-transition/hy-transition.vue +64 -72
  43. package/components/hy-transition/typing.d.ts +10 -6
  44. package/composables/index.ts +4 -2
  45. package/composables/usePopover.ts +221 -0
  46. package/composables/useQueue.ts +52 -0
  47. package/libs/css/_config.scss +5 -0
  48. package/libs/css/_function.scss +89 -0
  49. package/libs/css/mixin.scss +146 -21
  50. package/libs/css/vars.css +3 -1
  51. package/package.json +2 -2
  52. package/theme.scss +2 -1
  53. package/utils/inside.ts +96 -108
  54. package/utils/inspect.ts +48 -40
  55. package/utils/utils.ts +170 -187
package/common/index.ts CHANGED
@@ -1 +1,2 @@
1
- export * from "./versionControl";
1
+ export * from './versionControl'
2
+ export * from './shakeService'
@@ -0,0 +1,60 @@
1
+ // src/composables/useShakeService.ts
2
+ import { ref, Ref } from 'vue'
3
+ import { debounce } from '../utils'
4
+
5
+ interface Acceleration {
6
+ x: number
7
+ y: number
8
+ z: number
9
+ }
10
+
11
+ export function useShakeService(shakeThreshold: number = 30) {
12
+ const lastAcceleration: Ref<Acceleration> = ref({ x: 0, y: 0, z: 0 })
13
+ const lastTime: Ref<number> = ref(Date.now())
14
+ const shakeCallback: Ref<null | (() => void)> = ref(null)
15
+
16
+ const startShakeListener = (callback: () => void): void => {
17
+ shakeCallback.value = callback
18
+ uni.startAccelerometer({
19
+ success: () => {
20
+ uni.onAccelerometerChange(handleShake)
21
+ },
22
+ fail: (err: any) => {
23
+ console.error('加速度传感器启动失败', err.errMsg)
24
+ },
25
+ })
26
+ }
27
+
28
+ const stopShakeListener = (): void => {
29
+ uni.stopAccelerometer().then(
30
+ (res) => {
31
+ uni.offAccelerometerChange(handleShake)
32
+ },
33
+ (err) => console.error('加速度传感器关闭失败', err.errMsg),
34
+ )
35
+ }
36
+
37
+ const handleShake = (res: Acceleration): void => {
38
+ const acceleration = res
39
+ const currentTime = Date.now()
40
+ const timeDiff = (currentTime - lastTime.value) / 1000 // 转换为秒
41
+
42
+ // 计算加速度的欧几里得距离
43
+ const deltaX = acceleration.x - lastAcceleration.value.x
44
+ const deltaY = acceleration.y - lastAcceleration.value.y
45
+ const deltaZ = acceleration.z - lastAcceleration.value.z
46
+ const speed = Math.sqrt(deltaX * deltaX + deltaY * deltaY + deltaZ * deltaZ) / timeDiff
47
+
48
+ if (speed > shakeThreshold && shakeCallback.value) {
49
+ debounce(shakeCallback.value, 500)
50
+ }
51
+
52
+ lastAcceleration.value = acceleration
53
+ lastTime.value = currentTime
54
+ }
55
+
56
+ return {
57
+ startShakeListener,
58
+ stopShakeListener,
59
+ }
60
+ }
@@ -0,0 +1,184 @@
1
+ <template>
2
+ <view>
3
+ <HyPopup
4
+ :show="showPopup"
5
+ :duration="duration"
6
+ mode="bottom"
7
+ :close-on-click-overlay="closeOnClickOverlay"
8
+ :safe-area-inset-bottom="safeAreaInsetBottom"
9
+ @open="onOpen"
10
+ @close="onClose"
11
+ :z-index="zIndex"
12
+ :round="round"
13
+ >
14
+ <view
15
+ :class="`hy-action-sheet ${customClass}`"
16
+ :style="`${
17
+ (actions && actions.length) || (panels && panels.length)
18
+ ? 'margin: 0 10px calc(var(--window-bottom) + 10px) 10px; border-radius: 16px;'
19
+ : 'margin-bottom: var(--window-bottom);'
20
+ } ${customStyle}`"
21
+ >
22
+ <!-- 标题 -->
23
+ <view v-if="title" :class="`hy-action-sheet__header ${customHeaderClass}`">
24
+ {{ title }}
25
+ <HyIcon
26
+ customClass="hy-action-sheet__close"
27
+ class="hy-action-sheet__close"
28
+ name="close"
29
+ @click="onClose"
30
+ />
31
+ </view>
32
+ <!-- 标题 -->
33
+
34
+ <!-- 选项卡 -->
35
+ <view class="hy-action-sheet__actions" v-if="actions && actions.length">
36
+ <button
37
+ v-for="(action, rowIndex) in actions"
38
+ :key="rowIndex"
39
+ :class="`hy-action-sheet__action ${action?.disabled ? 'hy-action-sheet__action--disabled' : ''} ${
40
+ action?.loading ? 'hy-action-sheet__action--loading' : ''
41
+ }`"
42
+ :style="`color: ${action?.color}`"
43
+ @click="onSelect(rowIndex, 'action')"
44
+ >
45
+ <HyLoading :show="!!action?.loading" mode="circle" />
46
+ <view v-if="!action?.loading" class="hy-action-sheet__name">{{ action?.name }}</view>
47
+ <view v-if="!action?.loading && action?.sub" class="hy-action-sheet__subname">
48
+ {{ action?.sub }}
49
+ </view>
50
+ </button>
51
+ </view>
52
+ <!-- 选项卡 -->
53
+
54
+ <!-- 自定义面板 -->
55
+ <view v-if="formatPanels && formatPanels.length">
56
+ <view
57
+ v-for="(panel, rowIndex) in formatPanels"
58
+ :key="rowIndex"
59
+ class="hy-action-sheet__panels"
60
+ >
61
+ <view class="hy-action-sheet__panels-content">
62
+ <view
63
+ v-for="(col, colIndex) in panel"
64
+ :key="colIndex"
65
+ class="hy-action-sheet__panel"
66
+ @click="onSelect(rowIndex, 'panels', colIndex)"
67
+ >
68
+ <image class="hy-action-sheet__panel-img" :src="(col as any).iconUrl" />
69
+ <view class="hy-action-sheet__panel-title">{{ (col as any).name }}</view>
70
+ </view>
71
+ </view>
72
+ </view>
73
+ </view>
74
+ <!-- 自定义面板 -->
75
+
76
+ <!-- 面板插槽 -->
77
+ <slot />
78
+ <!-- 自定义面板 -->
79
+
80
+ <!-- 取消按钮 -->
81
+ <HyButton
82
+ v-if="cancelText"
83
+ :text="cancelText"
84
+ shape="circle"
85
+ custom-class="hy-action-sheet__cancel"
86
+ @click="handleCancel"
87
+ ></HyButton>
88
+ <!-- 取消按钮 -->
89
+ </view>
90
+ </HyPopup>
91
+ </view>
92
+ </template>
93
+ <script lang="ts">
94
+ export default {
95
+ name: 'hy-action-sheet',
96
+ options: {
97
+ addGlobalClass: true,
98
+ virtualHost: true,
99
+ styleIsolation: 'shared',
100
+ },
101
+ }
102
+ </script>
103
+
104
+ <script lang="ts" setup>
105
+ import { watch, ref } from 'vue'
106
+ import { isArray } from '../../utils'
107
+ import defaultProps from './props'
108
+ import IProps, { IActionSheetPanel } from './typing'
109
+
110
+ // 组件
111
+ import HyIcon from '../hy-icon/hy-icon.vue'
112
+ import HyPopup from '../hy-popup/hy-popup.vue'
113
+ import HyLoading from '../hy-loading/hy-loading.vue'
114
+ import HyButton from '../hy-button/hy-button.vue'
115
+
116
+ const props = withDefaults(defineProps<IProps>(), defaultProps)
117
+ const emit = defineEmits(['select', 'cancel', 'close', 'open', 'update:modelValue'])
118
+
119
+ const formatPanels = ref<Array<IActionSheetPanel> | Array<IActionSheetPanel[]>>([])
120
+ const showPopup = ref<boolean>(false)
121
+
122
+ watch(() => props.panels, computedValue, { deep: true, immediate: true })
123
+
124
+ watch(
125
+ () => props.modelValue,
126
+ (newValue) => {
127
+ showPopup.value = newValue
128
+ },
129
+ { deep: true, immediate: true },
130
+ )
131
+
132
+ function isPanelArray() {
133
+ return props.panels.length && !isArray(props.panels[0])
134
+ }
135
+ function computedValue() {
136
+ formatPanels.value = isPanelArray()
137
+ ? [props.panels as IActionSheetPanel[]]
138
+ : (props.panels as IActionSheetPanel[][])
139
+ }
140
+
141
+ function onSelect(rowIndex: number, type: 'action' | 'panels', colIndex?: number) {
142
+ if (type === 'action') {
143
+ if (props.actions[rowIndex].disabled || props.actions[rowIndex].loading) {
144
+ return
145
+ }
146
+ emit('select', {
147
+ item: props.actions[rowIndex],
148
+ index: rowIndex,
149
+ })
150
+ } else if (isPanelArray()) {
151
+ emit('select', {
152
+ item: props.panels[Number(colIndex)],
153
+ index: colIndex,
154
+ })
155
+ } else {
156
+ emit('select', {
157
+ item: (props.panels as IActionSheetPanel[][])[rowIndex][Number(colIndex)],
158
+ rowIndex,
159
+ colIndex,
160
+ })
161
+ }
162
+ if (props.closeOnClickAction) {
163
+ onClose()
164
+ }
165
+ }
166
+ function handleCancel() {
167
+ emit('cancel')
168
+ onClose()
169
+ }
170
+ function onClose() {
171
+ emit('update:modelValue', false)
172
+ emit('close')
173
+ }
174
+ function onOpen() {
175
+ emit('open')
176
+ }
177
+ </script>
178
+
179
+ <style lang="scss" scoped>
180
+ @import './index.scss';
181
+ .hy-action-sheet__header {
182
+ text-align: v-bind(titleAlign);
183
+ }
184
+ </style>
@@ -0,0 +1,123 @@
1
+ @use "../../libs/css/mixin.scss" as *;
2
+ @use "../../theme.scss" as *;
3
+
4
+
5
+ @include b(action-sheet) {
6
+ padding-bottom: 1px;
7
+ font-size: $hy-font-size-base;
8
+ width: calc(100vw - 20px);
9
+
10
+
11
+ @include e(actions) {
12
+ padding: $hy-border-margin-padding-base 0;
13
+ max-height: 50vh;
14
+ overflow-y: auto;
15
+ -webkit-overflow-scrolling: touch;
16
+ }
17
+
18
+ @include e(action) {
19
+ position: relative;
20
+ display: block;
21
+ width: 100%;
22
+ height: 48px;
23
+ line-height: 48px;
24
+ color: $hy-text-color;
25
+ font-size: $hy-font-size-base;
26
+ text-align: center;
27
+ border: none;
28
+ background: transparent;
29
+ outline: none;
30
+ padding: 0;
31
+
32
+ @include m(disabled) {
33
+ color: $hy-text-color--disabled;
34
+ cursor: not-allowed;
35
+ }
36
+
37
+ @include m(loading) {
38
+ display: flex;
39
+ align-items: center;
40
+ justify-content: center;
41
+ line-height: initial;
42
+ }
43
+ }
44
+
45
+ @include e(name) {
46
+ display: inline-block;
47
+ }
48
+
49
+ @include e(subname) {
50
+ display: inline-block;
51
+ margin-left: 4px;
52
+ font-size: $hy-font-size-sm;
53
+ color: $hy-text-color--grey;
54
+ }
55
+
56
+ /* 取消按钮 */
57
+ @include edeep(cancel) {
58
+ color: $hy-text-color;
59
+ width: calc(100% - 48px);
60
+ background: $hy-background--track;
61
+ margin: 0 auto 24px;
62
+ border: none;
63
+ }
64
+
65
+ /* 头部 */
66
+ @include e(header) {
67
+ position: relative;
68
+ line-height: 44px;
69
+ font-weight: 700;
70
+ padding: $hy-border-margin-padding-base $hy-border-margin-padding-base 0;
71
+ }
72
+
73
+ @include edeep(close) {
74
+ position: absolute;
75
+ top: 20px;
76
+ right: 15px;
77
+ background-color: rgba(128, 128, 128, 0.25);
78
+ border-radius: $hy-border-radius-circle;
79
+ padding: $hy-border-margin-padding-sm;
80
+ }
81
+
82
+ /* 面板样式 */
83
+ @include e(panels) {
84
+ height: 160rpx;
85
+ width: 100%;
86
+ overflow-y: hidden;
87
+
88
+ &:first-of-type {
89
+ margin-top: 10px;
90
+ }
91
+
92
+ &:last-of-type {
93
+ margin-bottom: 12px;
94
+ }
95
+ }
96
+
97
+ @include e(panels-content) {
98
+ display: flex;
99
+ overflow-x: auto;
100
+ -webkit-overflow-scrolling: touch;
101
+ }
102
+
103
+ @include e(panel) {
104
+ width: 140rpx;
105
+ flex: 0 0 auto;
106
+ display: inline-block;
107
+ padding: $hy-border-margin-padding-sm $hy-border-margin-padding-base;
108
+ }
109
+
110
+ @include e(panel-img) {
111
+ display: block;
112
+ width: $hy-img-size-base;
113
+ height: $hy-img-size-base;
114
+ margin: 0 auto 7px;
115
+ border-radius: $hy-border-radius-base;
116
+ }
117
+
118
+ @include e(panel-title) {
119
+ font-size: $hy-font-size-sm;
120
+ text-align: center;
121
+ @include lineEllipsis;
122
+ }
123
+ }
@@ -0,0 +1,18 @@
1
+ import type IProps from './typing'
2
+
3
+ const defaultProps: IProps = {
4
+ modelValue: false,
5
+ actions: [],
6
+ panels: [],
7
+ round: '20px',
8
+ title: '',
9
+ titleAlign: 'center',
10
+ cancelText: '',
11
+ closeOnClickAction: true,
12
+ closeOnClickOverlay: true,
13
+ duration: 200,
14
+ zIndex: 100,
15
+ safeAreaInsetBottom: true,
16
+ }
17
+
18
+ export default defaultProps
@@ -0,0 +1,96 @@
1
+ import type { CSSProperties } from 'vue'
2
+ import { HyApp } from 'hy-app/typing/modules/common'
3
+ export interface IActionSheetAction {
4
+ /**
5
+ * 选项名称
6
+ */
7
+ name: string
8
+ /**
9
+ * 描述信息
10
+ */
11
+ sub?: string
12
+ /**
13
+ * 颜色
14
+ */
15
+ color?: string
16
+ /**
17
+ * 禁用
18
+ */
19
+ disabled?: boolean
20
+ /**
21
+ * 加载中状态
22
+ */
23
+ loading?: boolean
24
+ }
25
+ export interface IActionSheetPanel {
26
+ /**
27
+ * 图片地址
28
+ */
29
+ iconUrl: string
30
+ /**
31
+ * 标题内容
32
+ */
33
+ name: string
34
+ }
35
+ export default interface HyActionSheetProps {
36
+ /**
37
+ * @description 操作菜单是否展示 ( 默认 false )
38
+ * */
39
+ modelValue?: boolean
40
+ /**
41
+ * @description 菜单选项
42
+ * */
43
+ actions?: IActionSheetAction[]
44
+ /**
45
+ * @description 自定义面板项,可以为字符串数组,也可以为对象数组,如果为二维数组,则为多行展示
46
+ * */
47
+ panels?: Array<IActionSheetPanel | IActionSheetPanel[]>
48
+ /**
49
+ * @description 圆角值 (默认 20 )
50
+ * */
51
+ round?: string | number
52
+ /**
53
+ * @description 标题
54
+ * */
55
+ title?: string
56
+ /**
57
+ * @description 标题文字位置
58
+ * */
59
+ titleAlign?: HyApp.RowCenterType
60
+ /**
61
+ * @description 取消按钮的提示文字,不为空时显示按钮
62
+ * */
63
+ cancelText?: string
64
+ /**
65
+ * @description 点击某个菜单项时是否关闭弹窗 (默认 true )
66
+ * */
67
+ closeOnClickAction?: boolean
68
+ /**
69
+ * @description 点击遮罩是否允许关闭 (默认 true )
70
+ * */
71
+ closeOnClickOverlay?: boolean
72
+ /**
73
+ * @description 弹框动画持续时间 ( 默认 200 )
74
+ * */
75
+ duration?: number
76
+ /**
77
+ * @description 菜单层级 ( 默认 100 )
78
+ * */
79
+ zIndex?: number
80
+ /**
81
+ * @description 处理底部安全区 (默认 true )
82
+ * */
83
+ safeAreaInsetBottom?: boolean
84
+ /**
85
+ * @description 自定义外部样式
86
+ * */
87
+ customStyle?: CSSProperties
88
+ /**
89
+ * @description 自定义外部类名
90
+ * */
91
+ customClass?: string
92
+ /**
93
+ * @description 自定义标题类名
94
+ * */
95
+ customHeaderClass?: string
96
+ }