ipanel-rnapp-ajb-base 1.0.13 → 1.0.15
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/app/App.js +3 -0
- package/app/components/common/PickerV1/index.js +93 -0
- package/app/components/common/PickerV2/index.js +96 -0
- package/app/components/common/PickerV2Base/_util/devWarning.tsx +5 -0
- package/app/components/common/PickerV2Base/_util/getLocale.tsx +42 -0
- package/app/components/common/PickerV2Base/_util/hooks/useAnimations.tsx +57 -0
- package/app/components/common/PickerV2Base/_util/hooks/useClickAway.ts +30 -0
- package/app/components/common/PickerV2Base/_util/isPromise.ts +5 -0
- package/app/components/common/PickerV2Base/_util/reactNode.ts +27 -0
- package/app/components/common/PickerV2Base/_util/version.json +1 -0
- package/app/components/common/PickerV2Base/_util/with-default-props.tsx +15 -0
- package/app/components/common/PickerV2Base/config-provider/DisabledContext.tsx +24 -0
- package/app/components/common/PickerV2Base/config-provider/index.tsx +7 -0
- package/app/components/common/PickerV2Base/locale-provider/en_US.tsx +22 -0
- package/app/components/common/PickerV2Base/locale-provider/es_ES.tsx +22 -0
- package/app/components/common/PickerV2Base/locale-provider/fa_IR.tsx +22 -0
- package/app/components/common/PickerV2Base/locale-provider/index.en-US.md +37 -0
- package/app/components/common/PickerV2Base/locale-provider/index.tsx +126 -0
- package/app/components/common/PickerV2Base/locale-provider/index.zh-CN.md +38 -0
- package/app/components/common/PickerV2Base/locale-provider/ko_KR.tsx +22 -0
- package/app/components/common/PickerV2Base/locale-provider/pt_BR.tsx +22 -0
- package/app/components/common/PickerV2Base/locale-provider/ru_RU.tsx +22 -0
- package/app/components/common/PickerV2Base/locale-provider/sv_SE.tsx +22 -0
- package/app/components/common/PickerV2Base/locale-provider/useLocale.tsx +36 -0
- package/app/components/common/PickerV2Base/locale-provider/zh_CN.tsx +22 -0
- package/app/components/common/PickerV2Base/picker/Picker.tsx +216 -0
- package/app/components/common/PickerV2Base/picker/Popup.tsx +77 -0
- package/app/components/common/PickerV2Base/picker/PopupPickerTypes.tsx +16 -0
- package/app/components/common/PickerV2Base/picker/PropsType.tsx +26 -0
- package/app/components/common/PickerV2Base/picker/index.en-US.md +98 -0
- package/app/components/common/PickerV2Base/picker/index.tsx +85 -0
- package/app/components/common/PickerV2Base/picker/index.zh-CN.md +97 -0
- package/app/components/common/PickerV2Base/picker/locale/en_US.tsx +5 -0
- package/app/components/common/PickerV2Base/picker/locale/es_ES.tsx +5 -0
- package/app/components/common/PickerV2Base/picker/locale/fa_IR.tsx +5 -0
- package/app/components/common/PickerV2Base/picker/locale/id_ID.tsx +5 -0
- package/app/components/common/PickerV2Base/picker/locale/ko_KR.tsx +5 -0
- package/app/components/common/PickerV2Base/picker/locale/pt_BR.tsx +5 -0
- package/app/components/common/PickerV2Base/picker/locale/ru_RU.tsx +5 -0
- package/app/components/common/PickerV2Base/picker/locale/sv_SE.tsx +5 -0
- package/app/components/common/PickerV2Base/picker/locale/zh_CN.tsx +5 -0
- package/app/components/common/PickerV2Base/picker/style/index.tsx +57 -0
- package/app/components/common/PickerV2Base/picker-view/PropsType.tsx +37 -0
- package/app/components/common/PickerV2Base/picker-view/Wheel.tsx +200 -0
- package/app/components/common/PickerV2Base/picker-view/columns-extend.tsx +86 -0
- package/app/components/common/PickerV2Base/picker-view/index.en-US.md +71 -0
- package/app/components/common/PickerV2Base/picker-view/index.tsx +69 -0
- package/app/components/common/PickerV2Base/picker-view/index.zh-CN.md +72 -0
- package/app/components/common/PickerV2Base/picker-view/picker-view.tsx +166 -0
- package/app/components/common/PickerV2Base/picker-view/style/index.tsx +51 -0
- package/app/components/common/PickerV2Base/style/index.tsx +96 -0
- package/app/components/common/PickerV2Base/style/themes/default.tsx +203 -0
- package/app/components/index.js +2 -0
- package/app/eventBus/index.js +1 -0
- package/app/hooks/shopMessageManager.js +5 -3
- package/app/screens/LoginScreen/OpenLogSheet.js +6 -1
- package/app/utils/common.js +0 -1
- package/package.json +19 -19
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import useMergedState from 'rc-util/lib/hooks/useMergedState'
|
|
2
|
+
import React, {
|
|
3
|
+
forwardRef,
|
|
4
|
+
useCallback,
|
|
5
|
+
useImperativeHandle,
|
|
6
|
+
useMemo,
|
|
7
|
+
} from 'react'
|
|
8
|
+
import { mergeProps } from '../_util/with-default-props'
|
|
9
|
+
import { WithThemeStyles } from '../style'
|
|
10
|
+
import { PickerValue, PickerViewPropsType } from './PropsType'
|
|
11
|
+
import { getColumns, getValueExtend } from './columns-extend'
|
|
12
|
+
import RMCPickerView from './picker-view'
|
|
13
|
+
import { PickerViewStyle } from './style'
|
|
14
|
+
|
|
15
|
+
export interface PickerViewProps
|
|
16
|
+
extends PickerViewPropsType,
|
|
17
|
+
WithThemeStyles<PickerViewStyle> {}
|
|
18
|
+
|
|
19
|
+
const defaultProps = {
|
|
20
|
+
cols: 3,
|
|
21
|
+
cascade: true,
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const PickerView = forwardRef<any, PickerViewProps>((props, ref) => {
|
|
25
|
+
const p = mergeProps(defaultProps, props)
|
|
26
|
+
|
|
27
|
+
const [innerValue, setInnerValue] = useMergedState<PickerValue[]>([], {
|
|
28
|
+
value: p.value,
|
|
29
|
+
defaultValue: p.defaultValue,
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
useImperativeHandle(ref, () => ({
|
|
33
|
+
value: innerValue,
|
|
34
|
+
}))
|
|
35
|
+
|
|
36
|
+
const columns = useMemo(
|
|
37
|
+
() => getColumns(p.data, innerValue, p.cols, p.cascade),
|
|
38
|
+
[p.data, innerValue, p.cols, p.cascade],
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
const handleSelect = useCallback(
|
|
42
|
+
(val: PickerValue, index: number) => {
|
|
43
|
+
const value = innerValue?.slice?.(0) || []
|
|
44
|
+
value[index] = val
|
|
45
|
+
const { nextValue, extend } = getValueExtend(
|
|
46
|
+
p.data,
|
|
47
|
+
value,
|
|
48
|
+
p.cols,
|
|
49
|
+
p.cascade,
|
|
50
|
+
)
|
|
51
|
+
setInnerValue(nextValue)
|
|
52
|
+
p.onChange?.(nextValue, { items: extend, columns })
|
|
53
|
+
},
|
|
54
|
+
[p, columns, innerValue, setInnerValue],
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
return (
|
|
58
|
+
<RMCPickerView
|
|
59
|
+
{...p}
|
|
60
|
+
value={innerValue}
|
|
61
|
+
columns={columns}
|
|
62
|
+
handleSelect={handleSelect}
|
|
63
|
+
/>
|
|
64
|
+
)
|
|
65
|
+
})
|
|
66
|
+
|
|
67
|
+
PickerView.displayName = 'AntmPickerView'
|
|
68
|
+
|
|
69
|
+
export default PickerView
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
---
|
|
2
|
+
category: Components
|
|
3
|
+
type: Data Entry
|
|
4
|
+
title: PickerView
|
|
5
|
+
subtitle: 选择器
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
PickerView 的功能类似于 Picker ,但它是直接渲染在区域中,而不是弹出窗口。
|
|
9
|
+
|
|
10
|
+
## API
|
|
11
|
+
|
|
12
|
+
### 属性
|
|
13
|
+
|
|
14
|
+
属性 | 说明 | 类型 | 默认值
|
|
15
|
+
----|-----|------|------
|
|
16
|
+
| data | 数据源 | `PickerColumn` / `PickerColumn[]` | - |
|
|
17
|
+
| value | 选中项 | `PickerValue[]` | - |
|
|
18
|
+
| defaultValue | 默认选中项 | `PickerValue[]` | - |
|
|
19
|
+
| cascade | 是否级联。<br/>子级来自`data`参数内的`children`属性 | Boolean | `true` |
|
|
20
|
+
| cols | 列数 | Number | `3` |
|
|
21
|
+
| onChange | 选中后的回调,可使用[rc-form](https://github.com/react-component/form) | `(value: PickerValue[], extend: PickerValueExtend) => void` | - |
|
|
22
|
+
| renderLabel | 自定义渲染每列展示的内容 | `(item: PickerColumnItem, index: number) => ReactNode` | `(item) => item.label` |
|
|
23
|
+
| loading | 是否处于加载状态 | Boolean | - |
|
|
24
|
+
| loadingContent | 加载状态下展示的内容 | ReactNode | `<ActivityIndicator/>` |
|
|
25
|
+
| indicatorStyle | 默认Indicator的样式 | Object | - |
|
|
26
|
+
|
|
27
|
+
关于 `PickerColumnItem` `PickerColumn` `PickerValue` `PickerValueExtend` 的类型定义,请参考 [Picker](/components/picker-cn/) 的文档。
|
|
28
|
+
|
|
29
|
+
### 自定义样式
|
|
30
|
+
|
|
31
|
+
属性 | 说明 | 类型 | 默认值
|
|
32
|
+
----|-----|------|------
|
|
33
|
+
| style | 外部样式 | `StyleProp<ViewStyle>` | - |
|
|
34
|
+
| styles | 语义化结构 style | [PickerViewStyle](#pickerviewstyle-语义化样式) | - |
|
|
35
|
+
| itemStyle| 每列样式 | `StyleProp<TextStyle>` | - |
|
|
36
|
+
| itemHeight | 每列固定高度,未设值时会根据`numberOfLines`动态计算;`itemStyle`属性设置`{height}`值是无效的 | Number | - |
|
|
37
|
+
| numberOfLines | 允许每列显示行数 | Number | `1` |
|
|
38
|
+
|
|
39
|
+
#### PickerViewStyle 语义化样式
|
|
40
|
+
|
|
41
|
+
```jsx
|
|
42
|
+
interface PickerViewStyle {
|
|
43
|
+
wrappper: ViewStyle
|
|
44
|
+
wheelWrapper: ViewStyle
|
|
45
|
+
mask: ViewStyle
|
|
46
|
+
maskTop: ViewStyle
|
|
47
|
+
maskMiddle: ViewStyle
|
|
48
|
+
maskBottom: ViewStyle
|
|
49
|
+
}
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
#### 遮罩层
|
|
53
|
+
|
|
54
|
+
还支持自定义遮罩样式,如使用渐变组件`<LinearGradient />`。当前默认为白色半透明。
|
|
55
|
+
|
|
56
|
+
属性 | 说明 | 类型 | 默认值
|
|
57
|
+
----|-----|------|------
|
|
58
|
+
| renderMaskTop | 自定义渲染上半部分遮罩层 | `()=> ReactNode` | `<View style={{ flex: 1, backgroundColor: 'rgba(255,255,255,0.8)' }} />` |
|
|
59
|
+
| renderMaskBottom | 自定义渲染下半部分遮罩层 | `()=> ReactNode` | `<View style={{ flex: 1, backgroundColor: 'rgba(255,255,255,0.8)' }} />` |
|
|
60
|
+
|
|
61
|
+
## FAQ
|
|
62
|
+
|
|
63
|
+
### 在Android平台,ScrollView中嵌套使用PickerView,会发生Picker Item不能滑动的情况,怎么办?
|
|
64
|
+
|
|
65
|
+
`5.1.3`新增支持。 设置`ScrollView`的`nestedScrollEnabled`属性为`true`即可。
|
|
66
|
+
|
|
67
|
+
```jsx
|
|
68
|
+
<ScrollView nestedScrollEnabled={true}>
|
|
69
|
+
...
|
|
70
|
+
<PickerView />
|
|
71
|
+
</ScrollView>
|
|
72
|
+
```
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import { ActivityIndicator, LayoutChangeEvent, Text, View } from 'react-native'
|
|
3
|
+
import { WithTheme, WithThemeStyles } from '../style'
|
|
4
|
+
import {
|
|
5
|
+
PickerColumn,
|
|
6
|
+
PickerColumnItem,
|
|
7
|
+
PickerValue,
|
|
8
|
+
PickerViewPropsType,
|
|
9
|
+
} from './PropsType'
|
|
10
|
+
import Wheel from './Wheel'
|
|
11
|
+
import pickerViewStyles, { PickerViewStyle } from './style/index'
|
|
12
|
+
|
|
13
|
+
export type RMCPickerViewProps = Omit<
|
|
14
|
+
PickerViewPropsType,
|
|
15
|
+
'data' | 'cols' | 'cascade' | 'onChange'
|
|
16
|
+
> &
|
|
17
|
+
WithThemeStyles<PickerViewStyle> & {
|
|
18
|
+
columns: PickerColumn[]
|
|
19
|
+
handleSelect: (value: PickerValue, index: number) => void
|
|
20
|
+
}
|
|
21
|
+
export default class RMCPickerView extends React.Component<
|
|
22
|
+
RMCPickerViewProps,
|
|
23
|
+
any
|
|
24
|
+
> {
|
|
25
|
+
static defaultProps = {
|
|
26
|
+
value: [],
|
|
27
|
+
itemHeight: 0,
|
|
28
|
+
numberOfLines: 1,
|
|
29
|
+
renderMaskTop: () => (
|
|
30
|
+
<View style={{ flex: 1, backgroundColor: 'rgba(255,255,255,0.8)' }} />
|
|
31
|
+
),
|
|
32
|
+
renderMaskBottom: () => (
|
|
33
|
+
<View style={{ flex: 1, backgroundColor: 'rgba(255,255,255,0.8)' }} />
|
|
34
|
+
),
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
constructor(props: RMCPickerViewProps) {
|
|
38
|
+
super(props)
|
|
39
|
+
this.state = {
|
|
40
|
+
itemHeight: 0,
|
|
41
|
+
wheelHeight: 0,
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
wrapperMeasure = (e: LayoutChangeEvent) => {
|
|
46
|
+
const { height } = e.nativeEvent.layout
|
|
47
|
+
this.setState({ wheelHeight: height })
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
itemHeightMeasure = (e: LayoutChangeEvent) => {
|
|
51
|
+
const { height } = e.nativeEvent.layout
|
|
52
|
+
this.setState({ itemHeight: height })
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
renderLabel = (item: PickerColumnItem, index: number) => {
|
|
56
|
+
return (
|
|
57
|
+
<View
|
|
58
|
+
key={item.key || item.value}
|
|
59
|
+
style={[
|
|
60
|
+
{
|
|
61
|
+
height: this.props.itemHeight || this.state.itemHeight || 'auto',
|
|
62
|
+
overflow: 'hidden',
|
|
63
|
+
justifyContent: 'center',
|
|
64
|
+
},
|
|
65
|
+
]}>
|
|
66
|
+
{this.props.renderLabel?.(item, index) || (
|
|
67
|
+
<Text
|
|
68
|
+
style={[
|
|
69
|
+
{
|
|
70
|
+
fontSize: 16,
|
|
71
|
+
color: '#333',
|
|
72
|
+
textAlign: 'center',
|
|
73
|
+
includeFontPadding: false,
|
|
74
|
+
padding: 8,
|
|
75
|
+
},
|
|
76
|
+
this.props.itemStyle,
|
|
77
|
+
// itemStyle was not allowed to set height
|
|
78
|
+
{ height: 'auto' },
|
|
79
|
+
]}
|
|
80
|
+
numberOfLines={this.props.numberOfLines}>
|
|
81
|
+
{item.label}
|
|
82
|
+
</Text>
|
|
83
|
+
)}
|
|
84
|
+
</View>
|
|
85
|
+
)
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
renderMask = (s: PickerViewStyle) => (
|
|
89
|
+
<View style={s.mask} pointerEvents="none">
|
|
90
|
+
<View style={s.maskTop}>{this.props.renderMaskTop?.()}</View>
|
|
91
|
+
<View
|
|
92
|
+
style={[
|
|
93
|
+
s.maskMiddle,
|
|
94
|
+
{ height: this.props.itemHeight || this.state.itemHeight },
|
|
95
|
+
]}
|
|
96
|
+
/>
|
|
97
|
+
<View style={s.maskBottom}>{this.props.renderMaskBottom?.()}</View>
|
|
98
|
+
</View>
|
|
99
|
+
)
|
|
100
|
+
|
|
101
|
+
render() {
|
|
102
|
+
const { wheelHeight } = this.state
|
|
103
|
+
const {
|
|
104
|
+
style,
|
|
105
|
+
styles,
|
|
106
|
+
columns,
|
|
107
|
+
value,
|
|
108
|
+
loading,
|
|
109
|
+
indicatorStyle,
|
|
110
|
+
numberOfLines,
|
|
111
|
+
handleSelect,
|
|
112
|
+
loadingContent,
|
|
113
|
+
} = this.props
|
|
114
|
+
const itemHeight = this.props.itemHeight || this.state.itemHeight
|
|
115
|
+
return (
|
|
116
|
+
<WithTheme themeStyles={pickerViewStyles} styles={styles}>
|
|
117
|
+
{(s) =>
|
|
118
|
+
// {/* 计算中文占位符换行的高度后,items统一这个高度 */}
|
|
119
|
+
itemHeight === 0 ? (
|
|
120
|
+
<View onLayout={this.itemHeightMeasure}>
|
|
121
|
+
{this.renderLabel(
|
|
122
|
+
{
|
|
123
|
+
value: 'layout',
|
|
124
|
+
label: <>{Array(numberOfLines).join('\n')} </>,
|
|
125
|
+
},
|
|
126
|
+
0,
|
|
127
|
+
)}
|
|
128
|
+
</View>
|
|
129
|
+
) : (
|
|
130
|
+
<View
|
|
131
|
+
style={[{ height: 7 * itemHeight }, s.wrappper, style]}
|
|
132
|
+
onLayout={this.wrapperMeasure}>
|
|
133
|
+
<View style={[s.wheelWrapper, { height: wheelHeight }]}>
|
|
134
|
+
{(loading || columns?.length === 0) && loading !== false
|
|
135
|
+
? loadingContent || (
|
|
136
|
+
<View style={{ flex: 1, alignSelf: 'center' }}>
|
|
137
|
+
<ActivityIndicator
|
|
138
|
+
animating
|
|
139
|
+
style={indicatorStyle || {}}
|
|
140
|
+
/>
|
|
141
|
+
</View>
|
|
142
|
+
)
|
|
143
|
+
: itemHeight > 0 &&
|
|
144
|
+
wheelHeight > 0 &&
|
|
145
|
+
columns.map((column, index) => (
|
|
146
|
+
<Wheel
|
|
147
|
+
key={index}
|
|
148
|
+
index={index}
|
|
149
|
+
column={column}
|
|
150
|
+
value={value?.[index]}
|
|
151
|
+
onSelect={handleSelect}
|
|
152
|
+
itemHeight={itemHeight}
|
|
153
|
+
wheelHeight={wheelHeight}
|
|
154
|
+
renderLabel={this.renderLabel}
|
|
155
|
+
/>
|
|
156
|
+
))}
|
|
157
|
+
</View>
|
|
158
|
+
{/* mask */}
|
|
159
|
+
{this.renderMask(s)}
|
|
160
|
+
</View>
|
|
161
|
+
)
|
|
162
|
+
}
|
|
163
|
+
</WithTheme>
|
|
164
|
+
)
|
|
165
|
+
}
|
|
166
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { StyleSheet, ViewStyle } from 'react-native'
|
|
2
|
+
|
|
3
|
+
export interface PickerViewStyle {
|
|
4
|
+
wrappper: ViewStyle
|
|
5
|
+
wheelWrapper: ViewStyle
|
|
6
|
+
mask: ViewStyle
|
|
7
|
+
maskTop: ViewStyle
|
|
8
|
+
maskMiddle: ViewStyle
|
|
9
|
+
maskBottom: ViewStyle
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export default () =>
|
|
13
|
+
StyleSheet.create<PickerViewStyle>({
|
|
14
|
+
wrappper: {
|
|
15
|
+
display: 'flex',
|
|
16
|
+
flexDirection: 'column',
|
|
17
|
+
justifyContent: 'center',
|
|
18
|
+
overflow: 'hidden',
|
|
19
|
+
backgroundColor: '#fff',
|
|
20
|
+
},
|
|
21
|
+
wheelWrapper: {
|
|
22
|
+
display: 'flex',
|
|
23
|
+
flexDirection: 'row',
|
|
24
|
+
},
|
|
25
|
+
mask: {
|
|
26
|
+
position: 'absolute',
|
|
27
|
+
zIndex: 10000,
|
|
28
|
+
left: 0,
|
|
29
|
+
top: 0,
|
|
30
|
+
width: '100%',
|
|
31
|
+
height: '100%',
|
|
32
|
+
display: 'flex',
|
|
33
|
+
flexDirection: 'column',
|
|
34
|
+
},
|
|
35
|
+
|
|
36
|
+
maskTop: {
|
|
37
|
+
flex: 1,
|
|
38
|
+
overflow: 'hidden',
|
|
39
|
+
},
|
|
40
|
+
|
|
41
|
+
maskMiddle: {
|
|
42
|
+
borderColor: '#eee',
|
|
43
|
+
borderTopWidth: 1,
|
|
44
|
+
borderBottomWidth: 1,
|
|
45
|
+
},
|
|
46
|
+
|
|
47
|
+
maskBottom: {
|
|
48
|
+
flex: 1,
|
|
49
|
+
overflow: 'hidden',
|
|
50
|
+
},
|
|
51
|
+
})
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import shallowequal from 'shallowequal'
|
|
3
|
+
import defaultTheme from './themes/default'
|
|
4
|
+
|
|
5
|
+
export const ThemeContext = React.createContext(defaultTheme)
|
|
6
|
+
export type Theme = typeof defaultTheme & { [key: string]: any }
|
|
7
|
+
export type PartialTheme = Partial<Theme>
|
|
8
|
+
export interface ThemeProviderProps {
|
|
9
|
+
value?: PartialTheme
|
|
10
|
+
children?: React.ReactNode
|
|
11
|
+
}
|
|
12
|
+
export const ThemeProvider = (props: ThemeProviderProps) => {
|
|
13
|
+
const { value, children } = props
|
|
14
|
+
const theme = React.useMemo(() => ({ ...defaultTheme, ...value }), [value])
|
|
15
|
+
return <ThemeContext.Provider value={theme}>{children}</ThemeContext.Provider>
|
|
16
|
+
}
|
|
17
|
+
export interface UseThemeContextProps {
|
|
18
|
+
theme?: PartialTheme
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// useTheme hook
|
|
22
|
+
export function useTheme<T>(props: {
|
|
23
|
+
themeStyles: (theme: Theme) => T
|
|
24
|
+
styles?: Partial<T>
|
|
25
|
+
}): T {
|
|
26
|
+
const theme = React.useContext(ThemeContext)
|
|
27
|
+
const { themeStyles, styles } = props
|
|
28
|
+
|
|
29
|
+
const stylesRef = React.useRef<Partial<T>>({})
|
|
30
|
+
const cache = React.useRef<T | any>(themeStyles(theme))
|
|
31
|
+
|
|
32
|
+
return React.useMemo(() => {
|
|
33
|
+
if (styles && !shallowequal(stylesRef.current, styles)) {
|
|
34
|
+
stylesRef.current = styles
|
|
35
|
+
const themeStyle = themeStyles(theme)
|
|
36
|
+
// merge styles from user defined
|
|
37
|
+
for (let key in styles) {
|
|
38
|
+
if (cache.current[key]) {
|
|
39
|
+
cache.current[key] = [themeStyle[key], styles[key]]
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return cache.current
|
|
45
|
+
}, [styles, theme, themeStyles])
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export interface WithThemeProps<T, S> {
|
|
49
|
+
themeStyles?: (theme: Theme) => T
|
|
50
|
+
styles?: S & { [key: string]: any }
|
|
51
|
+
children: (
|
|
52
|
+
// fix: styles[`${size}RawText`]
|
|
53
|
+
styles: T & { [key: string]: any },
|
|
54
|
+
theme: Theme,
|
|
55
|
+
) => React.ReactNode
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Component can extends this props
|
|
60
|
+
*/
|
|
61
|
+
export type WithThemeStyles<T> = { styles?: Partial<T> }
|
|
62
|
+
|
|
63
|
+
export function WithTheme<T, S>(props: WithThemeProps<T, S>) {
|
|
64
|
+
const { children, themeStyles, styles } = props
|
|
65
|
+
|
|
66
|
+
const stylesRef = React.useRef<S | undefined>(undefined)
|
|
67
|
+
const cache = React.useRef<T | any>(undefined)
|
|
68
|
+
|
|
69
|
+
const getStyles = React.useCallback(
|
|
70
|
+
(theme: Theme) => {
|
|
71
|
+
if (!cache.current) {
|
|
72
|
+
cache.current = themeStyles?.(theme) as typeof styles
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if (styles && !shallowequal(stylesRef.current, styles)) {
|
|
76
|
+
stylesRef.current = styles
|
|
77
|
+
const themeStyle = themeStyles?.(theme) as typeof styles
|
|
78
|
+
// merge styles from user defined
|
|
79
|
+
for (let key in styles) {
|
|
80
|
+
if (cache.current[key]) {
|
|
81
|
+
cache.current[key] = [themeStyle[key], styles[key]]
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
return cache.current
|
|
87
|
+
},
|
|
88
|
+
[themeStyles, styles],
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
return (
|
|
92
|
+
<ThemeContext.Consumer>
|
|
93
|
+
{(theme) => children(getStyles(theme), theme)}
|
|
94
|
+
</ThemeContext.Consumer>
|
|
95
|
+
)
|
|
96
|
+
}
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
const brandPrimary = '#108ee9'
|
|
2
|
+
const brandPrimaryTap = '#1284d6'
|
|
3
|
+
|
|
4
|
+
export default {
|
|
5
|
+
// 支付宝钱包默认主题
|
|
6
|
+
// https://github.com/ant-design/ant-design-mobile/wiki/设计变量表及命名规范
|
|
7
|
+
|
|
8
|
+
// 色彩, NOTE: must use `#000000` instead of `#000`
|
|
9
|
+
// https://facebook.github.io/react-native/docs/colors.html
|
|
10
|
+
// 8-digit-hex to 4-digit hex https://css-tricks.com/8-digit-hex-codes/
|
|
11
|
+
// https://www.chromestatus.com/feature/5685348285808640 chrome will support `#RGBA`
|
|
12
|
+
// 文字色
|
|
13
|
+
color_text_base: '#000000', // 基本
|
|
14
|
+
color_text_base_inverse: '#ffffff', // 基本 _ 反色
|
|
15
|
+
color_text_secondary: '#a4a9b0', // 辅助色
|
|
16
|
+
color_text_placeholder: '#bbbbbb', // 文本框提示
|
|
17
|
+
color_text_disabled: '#bbbbbb', // 失效
|
|
18
|
+
color_text_caption: '#888888', // 辅助描述
|
|
19
|
+
color_text_paragraph: '#333333', // 段落
|
|
20
|
+
color_link: brandPrimary, // 链接
|
|
21
|
+
color_error: '#ff4d4f', // 错误(form validate)
|
|
22
|
+
color_warning: '#faad14', // 警告
|
|
23
|
+
color_success: '#52c41a',
|
|
24
|
+
color_primary: '#1677ff',
|
|
25
|
+
|
|
26
|
+
// 背景色
|
|
27
|
+
fill_base: '#ffffff', // 组件默认背景
|
|
28
|
+
fill_body: '#f5f5f9', // 页面背景
|
|
29
|
+
fill_tap: '#dddddd', // 组件默认背景 _ 按下
|
|
30
|
+
fill_disabled: '#dddddd', // 通用失效背景
|
|
31
|
+
fill_mask: 'rgba(0, 0, 0, .4)', // 遮罩背景
|
|
32
|
+
color_icon_base: '#cccccc', // 许多小图标的背景,比如一些小圆点,加减号
|
|
33
|
+
fill_grey: '#f7f7f7',
|
|
34
|
+
|
|
35
|
+
// 透明度
|
|
36
|
+
opacity_disabled: '0.3', // switch checkbox radio 等组件禁用的透明度
|
|
37
|
+
|
|
38
|
+
// 全局/品牌色
|
|
39
|
+
brand_primary: brandPrimary,
|
|
40
|
+
brand_primary_tap: brandPrimaryTap,
|
|
41
|
+
brand_success: '#6abf47',
|
|
42
|
+
brand_warning: '#f4333c',
|
|
43
|
+
brand_error: '#f4333c',
|
|
44
|
+
brand_important: '#ff5b05', // 用于小红点
|
|
45
|
+
brand_wait: '#108ee9',
|
|
46
|
+
|
|
47
|
+
// 边框色
|
|
48
|
+
border_color_base: '#dddddd',
|
|
49
|
+
|
|
50
|
+
// 字体尺寸
|
|
51
|
+
// ---
|
|
52
|
+
font_size_icontext: 10,
|
|
53
|
+
font_size_caption_sm: 12,
|
|
54
|
+
font_size_base: 14,
|
|
55
|
+
font_size_subhead: 15,
|
|
56
|
+
font_size_caption: 16,
|
|
57
|
+
font_size_heading: 17,
|
|
58
|
+
|
|
59
|
+
// 圆角
|
|
60
|
+
// ---
|
|
61
|
+
radius_xs: 2,
|
|
62
|
+
radius_sm: 3,
|
|
63
|
+
radius_md: 5,
|
|
64
|
+
radius_lg: 7,
|
|
65
|
+
|
|
66
|
+
// 边框尺寸
|
|
67
|
+
// ---
|
|
68
|
+
border_width_sm: 0.5,
|
|
69
|
+
border_width_md: 1,
|
|
70
|
+
border_width_lg: 2,
|
|
71
|
+
|
|
72
|
+
// 间距
|
|
73
|
+
// ---
|
|
74
|
+
// 水平间距
|
|
75
|
+
h_spacing_sm: 5,
|
|
76
|
+
h_spacing_md: 8,
|
|
77
|
+
h_spacing_lg: 15,
|
|
78
|
+
|
|
79
|
+
// 垂直间距
|
|
80
|
+
v_spacing_xs: 3,
|
|
81
|
+
v_spacing_sm: 6,
|
|
82
|
+
v_spacing_md: 9,
|
|
83
|
+
v_spacing_lg: 15,
|
|
84
|
+
v_spacing_xl: 21,
|
|
85
|
+
|
|
86
|
+
// 高度
|
|
87
|
+
// ---
|
|
88
|
+
line_height_base: 1, // 单行行高
|
|
89
|
+
line_height_paragraph: 1.5, // 多行行高
|
|
90
|
+
|
|
91
|
+
// 图标尺寸
|
|
92
|
+
// ---
|
|
93
|
+
icon_size_xxs: 15,
|
|
94
|
+
icon_size_xs: 18,
|
|
95
|
+
icon_size_sm: 21,
|
|
96
|
+
icon_size_md: 22, // 导航条上的图标
|
|
97
|
+
icon_size_lg: 36,
|
|
98
|
+
|
|
99
|
+
// 动画缓动
|
|
100
|
+
// ---
|
|
101
|
+
ease_in_out_quint: 'cubic_bezier(0.86, 0, 0.07, 1)',
|
|
102
|
+
|
|
103
|
+
// 组件变量
|
|
104
|
+
// ---
|
|
105
|
+
|
|
106
|
+
actionsheet_item_height: 50,
|
|
107
|
+
actionsheet_item_font_size: 18,
|
|
108
|
+
|
|
109
|
+
// button
|
|
110
|
+
button_height: 47,
|
|
111
|
+
button_font_size: 18,
|
|
112
|
+
|
|
113
|
+
button_height_sm: 23,
|
|
114
|
+
button_font_size_sm: 12,
|
|
115
|
+
|
|
116
|
+
primary_button_fill: brandPrimary,
|
|
117
|
+
primary_button_fill_tap: '#0e80d2',
|
|
118
|
+
|
|
119
|
+
ghost_button_color: brandPrimary, // 同时应用于背景、文字颜色、边框色
|
|
120
|
+
ghost_button_fill_tap: `${brandPrimary}99`, // alpha 60% https://codepen.io/chriscoyier/pen/XjbzAW
|
|
121
|
+
|
|
122
|
+
warning_button_fill: '#e94f4f',
|
|
123
|
+
warning_button_fill_tap: '#d24747',
|
|
124
|
+
|
|
125
|
+
link_button_fill_tap: '#dddddd',
|
|
126
|
+
link_button_font_size: 16,
|
|
127
|
+
|
|
128
|
+
// modal
|
|
129
|
+
modal_font_size_heading: 18,
|
|
130
|
+
modal_button_font_size: 18, // 按钮字号
|
|
131
|
+
modal_button_height: 50, // 按钮高度
|
|
132
|
+
|
|
133
|
+
// list
|
|
134
|
+
list_title_height: 30,
|
|
135
|
+
list_item_height_sm: 35,
|
|
136
|
+
list_item_height: 44,
|
|
137
|
+
|
|
138
|
+
// input
|
|
139
|
+
input_label_width: 17, // InputItem、TextareaItem 文字长度基础值
|
|
140
|
+
input_font_size: 17,
|
|
141
|
+
input_color_icon: '#cccccc',
|
|
142
|
+
input_color_icon_tap: brandPrimary,
|
|
143
|
+
|
|
144
|
+
// tabs
|
|
145
|
+
tabs_color: brandPrimary,
|
|
146
|
+
tabs_height: 42,
|
|
147
|
+
tabs_font_size_heading: 15,
|
|
148
|
+
|
|
149
|
+
// segmented_control
|
|
150
|
+
segmented_control_color: brandPrimary, // 同时应用于背景、文字颜色、边框色
|
|
151
|
+
segmented_control_height: 27,
|
|
152
|
+
segmented_control_fill_tap: `${brandPrimary}10`,
|
|
153
|
+
|
|
154
|
+
// tab_bar
|
|
155
|
+
tab_bar_fill: '#ebeeef',
|
|
156
|
+
tab_bar_height: 50,
|
|
157
|
+
|
|
158
|
+
// toast
|
|
159
|
+
toast_fill: 'rgba(0, 0, 0, .8)',
|
|
160
|
+
|
|
161
|
+
// search_bar
|
|
162
|
+
search_bar_fill: '#efeff4',
|
|
163
|
+
search_bar_height: 44,
|
|
164
|
+
search_bar_input_height: 28,
|
|
165
|
+
search_bar_font_size: 15,
|
|
166
|
+
search_color_icon: '#bbbbbb', // input search icon 的背景色
|
|
167
|
+
|
|
168
|
+
// notice_bar
|
|
169
|
+
notice_bar_fill: '#fffada',
|
|
170
|
+
notice_bar_height: 36,
|
|
171
|
+
|
|
172
|
+
// checkbox
|
|
173
|
+
checkbox_fill: '#1890ff',
|
|
174
|
+
checkbox_fill_disabled: '#f5f5f5',
|
|
175
|
+
checkbox_border: '#d9d9d9',
|
|
176
|
+
checkbox_border_disabled: '#b9b9b9',
|
|
177
|
+
|
|
178
|
+
// switch
|
|
179
|
+
switch_fill: '#1890ff',
|
|
180
|
+
switch_unchecked: '#cccccc',
|
|
181
|
+
switch_unchecked_disabled: '#cccccc66', // switch_fill的40%透明度
|
|
182
|
+
switch_checked_disabled: '#1890ff66', // switch_unchecked的40%透明度
|
|
183
|
+
|
|
184
|
+
// tag
|
|
185
|
+
tag_height: 25,
|
|
186
|
+
tag_small_height: 15,
|
|
187
|
+
|
|
188
|
+
// picker
|
|
189
|
+
option_height: 42, // picker 标题的高度
|
|
190
|
+
|
|
191
|
+
// form
|
|
192
|
+
prefix_width: 65, // 水平布局时,表单项的标签宽度
|
|
193
|
+
prefix_padding: 6, // form item 上下内边距
|
|
194
|
+
extra_max_width: '50%',
|
|
195
|
+
|
|
196
|
+
toast_zindex: 1999,
|
|
197
|
+
action_sheet_zindex: 1000,
|
|
198
|
+
popup_zindex: 999,
|
|
199
|
+
modal_zindex: 999,
|
|
200
|
+
tooltip_zindex: 999,
|
|
201
|
+
tooltip_dark: 'rgba(0, 0, 0, 0.75)',
|
|
202
|
+
arrow_size: 8,
|
|
203
|
+
}
|
package/app/components/index.js
CHANGED
|
@@ -6,3 +6,5 @@ export ActionPicker from './common/ActionPicker';
|
|
|
6
6
|
export ScreenBackHeader from './common/ScreenBackHeader';
|
|
7
7
|
export CustomDialog from './common/CustomDialog';
|
|
8
8
|
export OnceTouchable from './common/OnceTouchable';
|
|
9
|
+
export PickerV2 from './common/PickerV2';
|
|
10
|
+
export PickerV1 from "./common/PickerV1";
|
package/app/eventBus/index.js
CHANGED
|
@@ -50,5 +50,6 @@ export const EVENTS = {
|
|
|
50
50
|
RECONNECT: 'shop.message.reconnect', // 触发websocket重连事件
|
|
51
51
|
ONLINE_LIST: 'shop.message.online', // 商城在线用户
|
|
52
52
|
CUSTOM_SERVICE_CONNECT_CHANGE: 'shop.message.customServiceConnectChange', // 智能客服转人工的进入和退出事件
|
|
53
|
+
HISTORY_MESSAGE_LIST: 'shop.message.history', // 获取历史消息
|
|
53
54
|
},
|
|
54
55
|
};
|
|
@@ -107,7 +107,7 @@ const ShopMessageManager = () => {
|
|
|
107
107
|
`user_id=${accountData?.user?.user_id}`,
|
|
108
108
|
'platform=web',
|
|
109
109
|
'api=ipanel_test',
|
|
110
|
-
`source=${
|
|
110
|
+
`source=${config.IPANEL_CLOUD_DOMAIN}`,
|
|
111
111
|
];
|
|
112
112
|
|
|
113
113
|
// 缓存全局商城客服websocket连接
|
|
@@ -153,9 +153,11 @@ const ShopMessageManager = () => {
|
|
|
153
153
|
msgData.route === 'message_list_new')
|
|
154
154
|
) {
|
|
155
155
|
if (msgData?.data) {
|
|
156
|
-
console.log(msgData, 'message_list_new');
|
|
157
156
|
const msgList = JSON.parse(msgData?.data);
|
|
158
|
-
global.base.shopMessageManager.messages =
|
|
157
|
+
global.base.shopMessageManager.messages =
|
|
158
|
+
msgList?.list || msgList || [];
|
|
159
|
+
let list = msgList?.list || msgList || [];
|
|
160
|
+
eventBus.emit(EVENTS.SHOPMESSAGE.HISTORY_MESSAGE_LIST, list);
|
|
159
161
|
}
|
|
160
162
|
}
|
|
161
163
|
};
|