@gm-mobile/mp 3.9.3-beta.3 → 3.9.3-beta.33

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gm-mobile/mp",
3
- "version": "3.9.3-beta.3",
3
+ "version": "3.9.3-beta.33",
4
4
  "description": "",
5
5
  "author": "liyatang <liyatang@qq.com>",
6
6
  "homepage": "https://github.com/gmfe/gm-mobile#readme",
@@ -21,9 +21,9 @@
21
21
  "url": "https://github.com/gmfe/gm-mobile/issues"
22
22
  },
23
23
  "dependencies": {
24
- "@gm-mobile/c-react": "^3.9.3-beta.3",
25
- "@gm-mobile/c-tool": "^3.9.3-beta.3",
26
- "@gm-mobile/locales": "^3.9.3-beta.3"
24
+ "@gm-mobile/c-react": "^3.9.3-beta.33",
25
+ "@gm-mobile/c-tool": "^3.9.3-beta.33",
26
+ "@gm-mobile/locales": "^3.9.3-beta.33"
27
27
  },
28
28
  "peerDependencies": {
29
29
  "@tarojs/components": "3.0.18",
@@ -33,5 +33,5 @@
33
33
  "prop-types": "^15.7.2",
34
34
  "react": "^16.13.1"
35
35
  },
36
- "gitHead": "9f44aa37c49971d60bc29358ce64aaf0c0d15ed8"
36
+ "gitHead": "038d343fd258aaa0c64146a958e6ed17baf3212d"
37
37
  }
@@ -1,6 +1,21 @@
1
1
  @supports (bottom: constant(safe-area-inset-bottom)) or
2
2
  (bottom: env(safe-area-inset-bottom)) {
3
- .m-page.without-safe-bottom {
4
- padding-bottom: 0 !important;
3
+ .m-page {
4
+ padding-bottom: 0;
5
+ }
6
+ .m-page.safe-bottom {
7
+ padding-bottom: constant(safe-area-inset-bottom); /* 兼容 iOS < 11.2 */
8
+ padding-bottom: env(safe-area-inset-bottom); /* 兼容 iOS >= 11.2 */
9
+ }
10
+ }
11
+
12
+ .transformer {
13
+ background-color: rgba(0, 0, 0, 0.9);
14
+ width: 100vw;
15
+ height: 100vh;
16
+ .transformed-page {
17
+ .m-page {
18
+ position: absolute;
19
+ }
5
20
  }
6
21
  }
@@ -2,6 +2,7 @@ import React, { CSSProperties, FC, HtmlHTMLAttributes, ReactNode } from 'react'
2
2
  import classNames from 'classnames'
3
3
  import { Flex, Status, View } from '@gm-mobile/c-react/src'
4
4
  import './base.less'
5
+ import SafeBottomMP from '../safe_bottom/safe_bottom'
5
6
 
6
7
  interface PageProps extends HtmlHTMLAttributes<HTMLDivElement> {
7
8
  loading?: boolean
@@ -11,11 +12,17 @@ interface PageProps extends HtmlHTMLAttributes<HTMLDivElement> {
11
12
  header?: ReactNode
12
13
  tabbar?: ReactNode
13
14
  top?: ReactNode
15
+ /** bottom位置自带底部安全边距,不需要和safeBottom同时使用 */
14
16
  bottom?: ReactNode
17
+ /** 左侧内容 */
18
+ left?: ReactNode
15
19
  pageClassName?: string
16
20
  pageStyle?: CSSProperties
17
- /** 去掉底部安全区域 */
18
- withoutSafeBottom?: boolean
21
+ /** 底部安全区域 */
22
+ safeBottom?: boolean
23
+ /** 用于放置绝对定位组件 */
24
+ extra?: ReactNode
25
+ onRefresh?: () => Promise<any>
19
26
  }
20
27
 
21
28
  const Page: FC<PageProps> = ({
@@ -27,15 +34,15 @@ const Page: FC<PageProps> = ({
27
34
  tabbar,
28
35
  top,
29
36
  bottom,
37
+ left,
30
38
  children,
31
39
  className,
32
40
  pageClassName,
33
41
  pageStyle,
34
- withoutSafeBottom,
42
+ safeBottom,
43
+ extra,
35
44
  ...rest
36
45
  }) => {
37
- const { safeArea, screenHeight } = wx.getSystemInfoSync()
38
- const paddingBottom = screenHeight - safeArea.bottom
39
46
  return (
40
47
  <Flex
41
48
  {...rest}
@@ -44,7 +51,7 @@ const Page: FC<PageProps> = ({
44
51
  'm-page',
45
52
  {
46
53
  'm-page-white': white,
47
- 'without-safe-bottom': withoutSafeBottom,
54
+ 'safe-bottom': safeBottom,
48
55
  },
49
56
  className
50
57
  )}
@@ -72,26 +79,23 @@ const Page: FC<PageProps> = ({
72
79
  </Flex>
73
80
  )}
74
81
  {top && <View className='m-top m-flex-none'>{top}</View>}
75
- <View
76
- className={classNames('m-page-content', pageClassName)}
77
- style={pageStyle}
78
- >
79
- {children}
80
- </View>
81
- {bottom && (
82
- <View className='m-bottom m-flex-none'>
83
- {React.cloneElement(bottom as React.ReactElement, {
84
- style: {
85
- paddingBottom:
86
- paddingBottom > 0
87
- ? `${paddingBottom}px!important`
88
- : undefined,
89
- },
90
- })}
82
+ <Flex auto className='m-page-wrapper'>
83
+ <View className='m-page-side'>{left}</View>
84
+ <View
85
+ className={classNames('m-page-content', pageClassName)}
86
+ style={pageStyle}
87
+ >
88
+ {children}
91
89
  </View>
90
+ </Flex>
91
+ {bottom && (
92
+ <SafeBottomMP className='m-bottom m-flex-none'>
93
+ {bottom}
94
+ </SafeBottomMP>
92
95
  )}
93
96
  </>
94
97
  )}
98
+ {extra}
95
99
  {tabbar && <View className='m-page-tabbar m-flex-none'>{tabbar}</View>}
96
100
  </Flex>
97
101
  )
@@ -1,19 +1,37 @@
1
- import React, { useEffect, useRef, FC, useState } from 'react'
2
- import { LayoutRoot, LayoutRootV1 } from '@gm-mobile/c-react'
3
- import { ScrollView } from '@tarojs/components'
4
- import PageBase, { PageProps as PageMPProps } from './base'
1
+ import React, { useEffect, useRef, FC, useState, CSSProperties } from 'react'
2
+ import { Flex, LayoutRoot, LayoutRootV1, Loading } from '@gm-mobile/c-react'
3
+ import { ScrollView, View } from '@tarojs/components'
4
+ import PageBase, { PageProps } from './base'
5
+ import { pxTransform } from '@tarojs/taro'
6
+
7
+ interface PageMPProps extends PageProps {
8
+ /** 最大宽度,对超过最大宽度的页面做做居中变窄处理 */
9
+ maxWidth?: number
10
+ onRefresh?: () => Promise<any>
11
+ /** 上滑加载更多事件。如果promise返回一个空数组,表示没有更多了 */
12
+ onLoadMore?: () => Promise<Array<any> | undefined>
13
+ }
14
+
15
+ const PageMP: FC<PageMPProps> = ({
16
+ children,
17
+ maxWidth = 2048,
18
+ onRefresh,
19
+ onLoadMore,
20
+ style,
21
+ ...props
22
+ }) => {
23
+ const { screenWidth } = wx.getSystemInfoSync()
24
+ const transformRatio = maxWidth / screenWidth
25
+ const transform = screenWidth > maxWidth
5
26
 
6
- const PageMP: FC<
7
- PageMPProps & {
8
- onRefresh?: () => Promise<any>
9
- }
10
- > = ({ children, onRefresh, ...props }) => {
11
27
  const [state, setState] = useState({
12
28
  refreshing: false,
29
+ loadingMore: false,
13
30
  })
31
+
32
+ // Page加载状态
14
33
  const refLoading = useRef<boolean | undefined>(false)
15
34
  useEffect(() => {
16
- // 和之前的不一样
17
35
  if (props.loading !== refLoading.current) {
18
36
  if (props.loading) {
19
37
  wx.showNavigationBarLoading()
@@ -24,51 +42,125 @@ const PageMP: FC<
24
42
  refLoading.current = props.loading
25
43
  }
26
44
  }, [props.loading])
27
- const methods = {
28
- async refresh() {
29
- setState((state) => {
30
- return {
31
- ...state,
32
- refreshing: true,
33
- }
34
- })
35
- try {
36
- onRefresh && (await onRefresh())
37
- } catch (err) {
38
- console.error(err)
45
+
46
+ const refresh = async () => {
47
+ setState((state) => {
48
+ return {
49
+ ...state,
50
+ refreshing: true,
39
51
  }
40
- setState((state) => {
41
- return {
42
- ...state,
43
- refreshing: false,
44
- }
45
- })
46
- },
52
+ })
53
+ try {
54
+ onRefresh && (await onRefresh())
55
+ } catch (err) {
56
+ console.error(err)
57
+ }
58
+ setState((state) => {
59
+ return {
60
+ ...state,
61
+ refreshing: false,
62
+ }
63
+ })
47
64
  }
48
65
 
49
- return (
66
+ const loadMore = async () => {
67
+ console.log('load more')
68
+ setState((state) => {
69
+ return {
70
+ ...state,
71
+ loadingMore: true,
72
+ }
73
+ })
74
+ try {
75
+ onLoadMore && (await onLoadMore())
76
+ } catch (err) {
77
+ console.error(err)
78
+ }
79
+ setState((state) => {
80
+ return {
81
+ ...state,
82
+ loadingMore: false,
83
+ }
84
+ })
85
+ }
86
+ const withScrollView = !!onRefresh || !!onLoadMore
87
+
88
+ const layoutStyle: CSSProperties = transform
89
+ ? {
90
+ position: 'absolute',
91
+ width: '100%',
92
+ height: `calc(100vh / ${transformRatio})`,
93
+ }
94
+ : {}
95
+
96
+ const page = (
50
97
  <>
51
- <PageBase {...props}>
52
- {onRefresh && (
98
+ <PageBase
99
+ {...props}
100
+ style={{
101
+ ...style,
102
+ height: transform ? `calc(100vh / ${transformRatio})` : undefined,
103
+ }}
104
+ >
105
+ {withScrollView && (
53
106
  <ScrollView
54
107
  className='m-flex'
55
108
  style={{ height: '100%' }}
109
+ enableBackToTop
56
110
  scrollY
57
- refresherEnabled
111
+ refresherEnabled={!!onRefresh}
112
+ scrollWithAnimation
113
+ scrollAnchoring
58
114
  refresherBackground='transparent'
59
115
  refresherTriggered={state.refreshing}
60
- onRefresherRefresh={methods.refresh}
116
+ lowerThreshold={50}
117
+ onRefresherRefresh={onRefresh ? () => refresh() : undefined}
118
+ onScrollToLower={onLoadMore ? () => loadMore() : undefined}
61
119
  >
62
120
  {children}
121
+ {state.loadingMore && (
122
+ <Flex height={pxTransform(60)} alignCenter justifyCenter>
123
+ <Loading style={{ opacity: 0.5 }} />
124
+ </Flex>
125
+ )}
63
126
  </ScrollView>
64
127
  )}
65
- {!onRefresh && children}
128
+ {!withScrollView && children}
66
129
  </PageBase>
67
- <LayoutRoot />
68
- <LayoutRootV1 />
130
+ <LayoutRoot style={layoutStyle} />
131
+ <LayoutRootV1 style={layoutStyle} />
69
132
  </>
70
133
  )
134
+
135
+ if (transform) {
136
+ return (
137
+ <View className='transformer'>
138
+ <View
139
+ className='transformed-page'
140
+ style={{
141
+ transform: `scale(${transformRatio})`,
142
+ }}
143
+ >
144
+ {page}
145
+ </View>
146
+ </View>
147
+ )
148
+ }
149
+ return page
71
150
  }
72
151
 
73
152
  export default PageMP
74
153
  export type { PageMPProps }
154
+
155
+ /** 适配后的高度,考虑ipad 大屏裁剪宽度后的比例 */
156
+ export function calcPageHeightWithMaxWidth(maxWidth = 480) {
157
+ const { screenWidth } = wx.getSystemInfoSync()
158
+ const transformRatio = maxWidth / screenWidth
159
+ return `calc(100vh / ${transformRatio})`
160
+ }
161
+
162
+ export function calcPageWidthWithMaxWidth(maxWidth = 800) {
163
+ const { screenWidth } = wx.getSystemInfoSync()
164
+ const transformRatio = maxWidth / screenWidth
165
+ return `calc(100vw / ${transformRatio})`
166
+ }
@@ -0,0 +1 @@
1
+ export { default as SafeBottom } from './safe_bottom'
@@ -0,0 +1,27 @@
1
+ import React, { memo, FC } from 'react'
2
+ import { View } from '@tarojs/components'
3
+ import classNames from 'classnames'
4
+ import { ViewProps } from '@tarojs/components/types/View'
5
+
6
+ type SafeBottomMPProps = ViewProps
7
+
8
+ const SafeBottomMP: FC<SafeBottomMPProps> = memo(
9
+ ({ className, children, ...rest }) => {
10
+ const { safeArea, screenHeight } = wx.getSystemInfoSync()
11
+ const paddingBottom = screenHeight - safeArea.bottom
12
+
13
+ return (
14
+ <View className={classNames(className)} {...rest}>
15
+ {React.cloneElement((children as React.ReactElement) || <View />, {
16
+ style: {
17
+ paddingBottom:
18
+ paddingBottom > 0 ? `${paddingBottom}px!important` : undefined,
19
+ },
20
+ })}
21
+ </View>
22
+ )
23
+ }
24
+ )
25
+
26
+ export default SafeBottomMP
27
+ export type { SafeBottomMPProps }
@@ -5,10 +5,9 @@ import UtilMP from '../../util'
5
5
  export type StatusBarMPProps = HTMLAttributes<HTMLDivElement>
6
6
 
7
7
  const StatusBarMP: FC<StatusBarMPProps> = memo((style, ...rest) => {
8
- const [height, setHeight] = useState(20)
8
+ const [height, setHeight] = useState(wx.getSystemInfoSync().statusBarHeight)
9
9
  useEffect(() => {
10
10
  const rect = UtilMP.getMenuButtonBoundingClientRect()
11
-
12
11
  UtilMP.getSystemInfo().then((res) => {
13
12
  // 不一定能读到胶囊,或者胶囊占据整个宽, 此时不需要设置statusBar
14
13
  return setHeight(rect?.left ? res.statusBarHeight : 0)
package/src/index.ts CHANGED
@@ -12,5 +12,6 @@ export * from './component/counter'
12
12
  export * from './component/status_bar'
13
13
  export * from './component/swiper'
14
14
  export * from './component/safe_header'
15
+ export * from './component/safe_bottom'
15
16
 
16
17
  export { LocalStorage, useFirstDidShow, Router, upload }
@@ -54,7 +54,7 @@ export default class Router {
54
54
  } = {}
55
55
 
56
56
  /** navigateTo传入的{data:值} */
57
- private _data?: any
57
+ private _data: { [key: string]: any } = {}
58
58
 
59
59
  /** 最近一次的路由跳转动作是 */
60
60
  currentAction?:
@@ -67,6 +67,7 @@ export default class Router {
67
67
  /** 当前路由信息 */
68
68
  get route() {
69
69
  const page = getCurrentPages().reverse()[0]
70
+ const data = this._data['/' + this._urlToPath(page.route)]
70
71
  return {
71
72
  /** 页面config而配置的标题 */
72
73
  title: page.config.navigationBarTitleText as string,
@@ -75,7 +76,7 @@ export default class Router {
75
76
  /** url参数 */
76
77
  options: page.options,
77
78
  /** navigateTo传入的{data:值} */
78
- data: this._data,
79
+ data,
79
80
  }
80
81
  }
81
82
 
@@ -122,7 +123,9 @@ export default class Router {
122
123
  const data = typeof option === 'object' ? option.data : undefined
123
124
  // @ts-ignore
124
125
  data && delete parsed.data
125
- this._data = data
126
+ this._data[to] = data
127
+ } else {
128
+ this._data[to] = undefined
126
129
  }
127
130
  this._beforeChange(option, () => Taro.navigateTo(parsed))
128
131
  })
@@ -16,8 +16,6 @@ Normal.parameters = {
16
16
  code: `
17
17
  import { Router } from '@gm-mobile/mp'
18
18
  const router = new Router({
19
- /** 开发模式,会在代码变化界面刷新后,自动恢复刷新前的页面 */
20
- dev: true,
21
19
  /** 路由变化前调用,返回false停止路由跳转 */
22
20
  auth(from, to) {
23
21
  if (!globalStore) {