@gm-mobile/c-react 3.9.3-beta.8 → 3.9.3
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 +5 -5
- package/src/component/cell/cell.tsx +29 -27
- package/src/component/custom_tabbar/custom_tabbar.weapp.tsx +6 -1
- package/src/component/dialog/common/base.less +3 -0
- package/src/component/dialog/common/base.tsx +8 -4
- package/src/component/dialog/common/choose.tsx +3 -0
- package/src/component/dialog/dialog.tsx +6 -1
- package/src/component/digital_keyboard/index.tsx +9 -2
- package/src/component/digital_keyboard/stories.tsx +1 -1
- package/src/component/error/error.tsx +23 -0
- package/src/component/error/index.ts +1 -0
- package/src/component/error/style.less +42 -0
- package/src/component/error/types.ts +5 -0
- package/src/component/layout_root/layout_root.tsx +20 -3
- package/src/component/layout_root/layout_root_v1.tsx +18 -3
- package/src/component/page/style.less +8 -0
- package/src/component/popup/popup.tsx +4 -1
- package/src/component/popup/popup_v1.tsx +2 -1
- package/src/component/popup/style.less +1 -1
- package/src/component/popup/types.ts +4 -0
- package/src/component/text_field/TextField.tsx +20 -2
- package/src/component/text_field/stories.tsx +0 -1
- package/src/component/text_field/style.less +3 -0
- package/src/component/text_field/types.ts +3 -1
- package/src/index.less +2 -1
- package/src/index.ts +1 -0
- package/src/less/animation.less +9 -4
- package/src/less/border.less +12 -3
- package/src/less/distance.less +41 -45
- package/src/less/text.less +16 -6
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gm-mobile/c-react",
|
|
3
|
-
"version": "3.9.3
|
|
3
|
+
"version": "3.9.3",
|
|
4
4
|
"description": "> TODO: 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-font": "^3.9.3
|
|
25
|
-
"@gm-mobile/c-tool": "^3.9.3
|
|
26
|
-
"@gm-mobile/locales": "^3.9.3
|
|
24
|
+
"@gm-mobile/c-font": "^3.9.3",
|
|
25
|
+
"@gm-mobile/c-tool": "^3.9.3",
|
|
26
|
+
"@gm-mobile/locales": "^3.9.3"
|
|
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": "
|
|
36
|
+
"gitHead": "1f1d2b656046efe6479f05f9fde2e34cb99df4de"
|
|
37
37
|
}
|
|
@@ -19,35 +19,37 @@ export const Cell: FC<CellProps> = ({
|
|
|
19
19
|
...rest
|
|
20
20
|
}) => {
|
|
21
21
|
return (
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
onClick={onClick}
|
|
35
|
-
>
|
|
36
|
-
{icon && <View className='m-cell-icon'>{icon}</View>}
|
|
37
|
-
{left && <View className='m-cell-left'>{left}</View>}
|
|
38
|
-
<View className='m-cell-body'>{children}</View>
|
|
39
|
-
<Flex alignCenter>
|
|
40
|
-
{right &&
|
|
41
|
-
(_.isString(right) ? (
|
|
42
|
-
<View className='m-cell-right'>{right}</View>
|
|
43
|
-
) : (
|
|
44
|
-
right
|
|
45
|
-
))}
|
|
46
|
-
{access && (
|
|
47
|
-
<Text className='m-font m-font-angle-right m-cell-access-icon' />
|
|
22
|
+
<>
|
|
23
|
+
<Flex
|
|
24
|
+
{...rest}
|
|
25
|
+
alignCenter
|
|
26
|
+
className={classNames(
|
|
27
|
+
'm-cell',
|
|
28
|
+
{
|
|
29
|
+
'm-cell-access': access,
|
|
30
|
+
'm-cell-with-icon': icon,
|
|
31
|
+
'm-cell-no-active': noActive,
|
|
32
|
+
},
|
|
33
|
+
className
|
|
48
34
|
)}
|
|
35
|
+
onClick={onClick}
|
|
36
|
+
>
|
|
37
|
+
{icon && <View className='m-cell-icon'>{icon}</View>}
|
|
38
|
+
{left && <View className='m-cell-left'>{left}</View>}
|
|
39
|
+
<View className='m-cell-body'>{children}</View>
|
|
40
|
+
<Flex alignCenter>
|
|
41
|
+
{right &&
|
|
42
|
+
(_.isString(right) ? (
|
|
43
|
+
<View className='m-cell-right'>{right}</View>
|
|
44
|
+
) : (
|
|
45
|
+
right
|
|
46
|
+
))}
|
|
47
|
+
{access && (
|
|
48
|
+
<Text className='m-font m-font-angle-right m-cell-access-icon' />
|
|
49
|
+
)}
|
|
50
|
+
</Flex>
|
|
49
51
|
</Flex>
|
|
50
|
-
|
|
52
|
+
</>
|
|
51
53
|
)
|
|
52
54
|
}
|
|
53
55
|
|
|
@@ -24,7 +24,12 @@ const CustomTabbar = () => {
|
|
|
24
24
|
return null
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
-
return
|
|
27
|
+
return (
|
|
28
|
+
<View
|
|
29
|
+
className='custom-tabbar-placeholder'
|
|
30
|
+
style={{ height: `${height}px` }}
|
|
31
|
+
/>
|
|
32
|
+
)
|
|
28
33
|
}
|
|
29
34
|
|
|
30
35
|
CustomTabbar.getCustomTabbarHeight = getCustomTabbarHeight
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import React, { ReactNode } from 'react'
|
|
2
2
|
import { Flex, Popup, View, Button } from '../../..'
|
|
3
3
|
import { noop } from 'lodash'
|
|
4
|
+
import './base.less'
|
|
4
5
|
|
|
5
6
|
interface Option<T> {
|
|
6
7
|
title: ReactNode
|
|
@@ -54,7 +55,11 @@ export function showDialog<T>({
|
|
|
54
55
|
const Template = () => {
|
|
55
56
|
return (
|
|
56
57
|
<Flex column className='m-border-radius m-overflow-hidden m-bg-white'>
|
|
57
|
-
<Flex
|
|
58
|
+
<Flex
|
|
59
|
+
justifyBetween
|
|
60
|
+
alignCenter
|
|
61
|
+
className='m-customer-dialog-header m-padding-10'
|
|
62
|
+
>
|
|
58
63
|
<Flex flex>{left}</Flex>
|
|
59
64
|
<Flex
|
|
60
65
|
flex
|
|
@@ -68,7 +73,6 @@ export function showDialog<T>({
|
|
|
68
73
|
<Button
|
|
69
74
|
mini
|
|
70
75
|
plain
|
|
71
|
-
noRound
|
|
72
76
|
type='link'
|
|
73
77
|
className='m-text-desc m-margin-lr-0'
|
|
74
78
|
onClick={cancel}
|
|
@@ -81,7 +85,7 @@ export function showDialog<T>({
|
|
|
81
85
|
{children}
|
|
82
86
|
{bottom || (
|
|
83
87
|
<Flex className='m-padding-lr-10'>
|
|
84
|
-
<Button block
|
|
88
|
+
<Button block type='primary' onClick={() => ok()}>
|
|
85
89
|
{okText}
|
|
86
90
|
</Button>
|
|
87
91
|
</Flex>
|
|
@@ -94,7 +98,7 @@ export function showDialog<T>({
|
|
|
94
98
|
disabledHeader: true,
|
|
95
99
|
[direction]: true,
|
|
96
100
|
disabledAnimate: false,
|
|
97
|
-
onHide:
|
|
101
|
+
onHide: cancel,
|
|
98
102
|
children: <Template />,
|
|
99
103
|
})
|
|
100
104
|
})
|
|
@@ -24,6 +24,7 @@ export interface ChooseProps {
|
|
|
24
24
|
/** 搜索功能 */
|
|
25
25
|
// search?: boolean
|
|
26
26
|
maxHeight?: string
|
|
27
|
+
onCancel?: () => void
|
|
27
28
|
}
|
|
28
29
|
|
|
29
30
|
/** 底部弹出的选择界面 */
|
|
@@ -34,6 +35,7 @@ export default function ({
|
|
|
34
35
|
multiSelect = false,
|
|
35
36
|
defaultSelected = [],
|
|
36
37
|
maxHeight = '50vh',
|
|
38
|
+
onCancel,
|
|
37
39
|
}: ChooseProps) {
|
|
38
40
|
if (multiSelect) needConfirm = true
|
|
39
41
|
const selected = [...defaultSelected] as Item[]
|
|
@@ -93,6 +95,7 @@ export default function ({
|
|
|
93
95
|
title,
|
|
94
96
|
children: <Children />,
|
|
95
97
|
onOk: () => selected,
|
|
98
|
+
onCancel: onCancel,
|
|
96
99
|
bottom: needConfirm ? undefined : <View />,
|
|
97
100
|
})
|
|
98
101
|
return promise
|
|
@@ -44,6 +44,11 @@ const ErrorInput: FC<ErrorInputProps> = ({
|
|
|
44
44
|
|
|
45
45
|
const DialogStatics: DialogStaticsTypes<string | RenderOptions> = {
|
|
46
46
|
render(options, type) {
|
|
47
|
+
const autoHide = !(
|
|
48
|
+
typeof options === 'object' &&
|
|
49
|
+
options.onConfirm &&
|
|
50
|
+
typeof options.children === 'object'
|
|
51
|
+
)
|
|
47
52
|
if (typeof options === 'string') {
|
|
48
53
|
options = {
|
|
49
54
|
children: options as string,
|
|
@@ -92,7 +97,7 @@ const DialogStatics: DialogStaticsTypes<string | RenderOptions> = {
|
|
|
92
97
|
}
|
|
93
98
|
|
|
94
99
|
Promise.resolve(result).then(() => {
|
|
95
|
-
DialogStatics.hide()
|
|
100
|
+
if (autoHide) DialogStatics.hide()
|
|
96
101
|
|
|
97
102
|
return setTimeout(() => {
|
|
98
103
|
resolve(type === 'prompt' ? inputValue : undefined)
|
|
@@ -30,6 +30,7 @@ export type DigitalKeyboardProps = Omit<KeyboardProps, 'value' | 'int'> & {
|
|
|
30
30
|
min?: number
|
|
31
31
|
/** 最大值 */
|
|
32
32
|
max?: number
|
|
33
|
+
withUseRef?: boolean
|
|
33
34
|
}
|
|
34
35
|
|
|
35
36
|
export class DigitalKeyboard {
|
|
@@ -45,6 +46,7 @@ export class DigitalKeyboard {
|
|
|
45
46
|
min,
|
|
46
47
|
max,
|
|
47
48
|
style,
|
|
49
|
+
withUseRef = true,
|
|
48
50
|
...rest
|
|
49
51
|
}: DigitalKeyboardProps) {
|
|
50
52
|
this.form = form
|
|
@@ -100,7 +102,12 @@ export class DigitalKeyboard {
|
|
|
100
102
|
|
|
101
103
|
if (btn.type === 'digit' && value && !value.endsWith('.')) {
|
|
102
104
|
const num = parseFloat(value)
|
|
103
|
-
if (
|
|
105
|
+
if (value.endsWith('.0')) {
|
|
106
|
+
// 处理特殊情况
|
|
107
|
+
if (fractionDigits === 0) {
|
|
108
|
+
value = value.replace(/\.0$/, '')
|
|
109
|
+
}
|
|
110
|
+
} else if (!isNaN(num as number)) {
|
|
104
111
|
value = clamp(
|
|
105
112
|
num,
|
|
106
113
|
min === undefined ? num : min,
|
|
@@ -136,7 +143,7 @@ export class DigitalKeyboard {
|
|
|
136
143
|
setInt: true,
|
|
137
144
|
})
|
|
138
145
|
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
139
|
-
return useRef(this).current
|
|
146
|
+
return withUseRef ? useRef(this).current : this
|
|
140
147
|
}
|
|
141
148
|
|
|
142
149
|
active: string
|
|
@@ -58,7 +58,7 @@ const Template: Story<DigitalKeyboardProps> = (args) => {
|
|
|
58
58
|
export const Usage = Template.bind({})
|
|
59
59
|
Usage.argTypes = {
|
|
60
60
|
form: {
|
|
61
|
-
description: '`Object`
|
|
61
|
+
description: '`Object` 表单的字段键值对,可以通过.set增改,通过.get读取',
|
|
62
62
|
type: {
|
|
63
63
|
required: true,
|
|
64
64
|
},
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import React, { FC } from 'react'
|
|
2
|
+
import classNames from 'classnames'
|
|
3
|
+
import _ from 'lodash'
|
|
4
|
+
import { View } from '../view'
|
|
5
|
+
import { ErrorProps } from './types'
|
|
6
|
+
import { Text } from '../text'
|
|
7
|
+
|
|
8
|
+
export const Error: FC<ErrorProps> = ({ className, topLine, children }) => {
|
|
9
|
+
return children ? (
|
|
10
|
+
<View
|
|
11
|
+
className={classNames('error', className, {
|
|
12
|
+
'm-border-1px-top-before': topLine,
|
|
13
|
+
'has-error': !!children,
|
|
14
|
+
})}
|
|
15
|
+
>
|
|
16
|
+
<View className='error-message'>{children}</View>
|
|
17
|
+
</View>
|
|
18
|
+
) : (
|
|
19
|
+
<></>
|
|
20
|
+
)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export default Error
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as Error } from './error'
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
.error {
|
|
2
|
+
@red: fade(red, 50);
|
|
3
|
+
color: @red;
|
|
4
|
+
font-size: 10px;
|
|
5
|
+
width: 100%;
|
|
6
|
+
padding: 5px 0;
|
|
7
|
+
&.m-border-1px-top-before::before {
|
|
8
|
+
border-color: @red;
|
|
9
|
+
}
|
|
10
|
+
.error-message {
|
|
11
|
+
display: inline-block;
|
|
12
|
+
animation-name: headShake;
|
|
13
|
+
animation-timing-function: ease;
|
|
14
|
+
animation-duration: 0.75s;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
@keyframes headShake {
|
|
19
|
+
0% {
|
|
20
|
+
transform: translateX(0);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
6.5% {
|
|
24
|
+
transform: translateX(-6px) rotateY(-9deg);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
18.5% {
|
|
28
|
+
transform: translateX(5px) rotateY(7deg);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
31.5% {
|
|
32
|
+
transform: translateX(-3px) rotateY(-5deg);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
43.5% {
|
|
36
|
+
transform: translateX(2px) rotateY(3deg);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
50% {
|
|
40
|
+
transform: translateX(0);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
@@ -1,4 +1,10 @@
|
|
|
1
|
-
import React, {
|
|
1
|
+
import React, {
|
|
2
|
+
FC,
|
|
3
|
+
useState,
|
|
4
|
+
ReactNode,
|
|
5
|
+
useEffect,
|
|
6
|
+
HTMLAttributes,
|
|
7
|
+
} from 'react'
|
|
2
8
|
import _ from 'lodash'
|
|
3
9
|
import { is } from '@gm-mobile/c-tool'
|
|
4
10
|
|
|
@@ -13,7 +19,10 @@ import {
|
|
|
13
19
|
|
|
14
20
|
const cbMap: CBMapType = {}
|
|
15
21
|
|
|
16
|
-
const LayoutRoot: FC & LayoutRootStatic = (
|
|
22
|
+
const LayoutRoot: FC<HTMLAttributes<HTMLDivElement>> & LayoutRootStatic = ({
|
|
23
|
+
style,
|
|
24
|
+
...rest
|
|
25
|
+
}) => {
|
|
17
26
|
const [state, setState] = useState<LayoutRootState>({})
|
|
18
27
|
const path: string = getPath()
|
|
19
28
|
|
|
@@ -31,7 +40,15 @@ const LayoutRoot: FC & LayoutRootStatic = () => {
|
|
|
31
40
|
|
|
32
41
|
// 有层级关系
|
|
33
42
|
return (
|
|
34
|
-
<View
|
|
43
|
+
<View
|
|
44
|
+
style={{
|
|
45
|
+
...style,
|
|
46
|
+
display: Object.keys(state).find((k) => !!state[k as 'popup'])
|
|
47
|
+
? 'block'
|
|
48
|
+
: 'none',
|
|
49
|
+
}}
|
|
50
|
+
{...rest}
|
|
51
|
+
>
|
|
35
52
|
{state.innerLayer}
|
|
36
53
|
{state.popup}
|
|
37
54
|
{state.picker}
|
|
@@ -1,4 +1,10 @@
|
|
|
1
|
-
import React, {
|
|
1
|
+
import React, {
|
|
2
|
+
FC,
|
|
3
|
+
useState,
|
|
4
|
+
ReactNode,
|
|
5
|
+
useEffect,
|
|
6
|
+
HTMLAttributes,
|
|
7
|
+
} from 'react'
|
|
2
8
|
import _ from 'lodash'
|
|
3
9
|
import { is } from '@gm-mobile/c-tool'
|
|
4
10
|
|
|
@@ -16,7 +22,10 @@ const cbMap: CBMapV1Type = {}
|
|
|
16
22
|
/**
|
|
17
23
|
* @description: 目前仅用于Popup的多层弹窗
|
|
18
24
|
*/
|
|
19
|
-
const LayoutRootV1: FC & LayoutV1RootStatic = (
|
|
25
|
+
const LayoutRootV1: FC<HTMLAttributes<HTMLDivElement>> & LayoutV1RootStatic = ({
|
|
26
|
+
style,
|
|
27
|
+
...rest
|
|
28
|
+
}) => {
|
|
20
29
|
const path = getPath()
|
|
21
30
|
const [state, setState] = useState<LayoutRootState>({})
|
|
22
31
|
|
|
@@ -52,7 +61,13 @@ const LayoutRootV1: FC & LayoutV1RootStatic = () => {
|
|
|
52
61
|
|
|
53
62
|
// 有层级关系
|
|
54
63
|
return (
|
|
55
|
-
<View
|
|
64
|
+
<View
|
|
65
|
+
style={{
|
|
66
|
+
...style,
|
|
67
|
+
display: state.popup && state.popup.length > 0 ? 'block' : 'none',
|
|
68
|
+
}}
|
|
69
|
+
{...rest}
|
|
70
|
+
>
|
|
56
71
|
{/* {state.innerLayer} */}
|
|
57
72
|
{state.popup}
|
|
58
73
|
{/* {state.modal}
|
|
@@ -38,6 +38,8 @@ const PopupBase: FC<PopupProps> = ({
|
|
|
38
38
|
/** 动画有卡顿现象,先禁用 */
|
|
39
39
|
disabledAnimate = true,
|
|
40
40
|
children,
|
|
41
|
+
hasCustomTab = true,
|
|
42
|
+
disableBottomSafeArea,
|
|
41
43
|
...rest
|
|
42
44
|
}) => {
|
|
43
45
|
devWarnForHook(() => {
|
|
@@ -57,6 +59,7 @@ const PopupBase: FC<PopupProps> = ({
|
|
|
57
59
|
'm-animated-slide-in-left': left,
|
|
58
60
|
'm-animated-slide-in-right': right,
|
|
59
61
|
'm-animated-slide-in-bottom': bottom,
|
|
62
|
+
'm-bottom-safe-area': !disableBottomSafeArea,
|
|
60
63
|
},
|
|
61
64
|
className
|
|
62
65
|
)
|
|
@@ -90,7 +93,7 @@ const PopupBase: FC<PopupProps> = ({
|
|
|
90
93
|
</Flex>
|
|
91
94
|
)}
|
|
92
95
|
<View className='m-popup-content'>{children}</View>
|
|
93
|
-
<CustomTabbar />
|
|
96
|
+
{hasCustomTab && <CustomTabbar />}
|
|
94
97
|
</View>
|
|
95
98
|
</View>
|
|
96
99
|
)
|
|
@@ -51,6 +51,7 @@ const PopupBase: FC<PopupV1Props> = ({
|
|
|
51
51
|
titleClassName,
|
|
52
52
|
titleCenter,
|
|
53
53
|
clickMaskClose = true,
|
|
54
|
+
disableBottomSafeArea,
|
|
54
55
|
...rest
|
|
55
56
|
}) => {
|
|
56
57
|
devWarnForHook(() => {
|
|
@@ -128,7 +129,7 @@ const PopupBase: FC<PopupV1Props> = ({
|
|
|
128
129
|
</Flex>
|
|
129
130
|
)}
|
|
130
131
|
<View className='m-popup-content'>{children}</View>
|
|
131
|
-
<CustomTabbar />
|
|
132
|
+
{!disableBottomSafeArea && <CustomTabbar />}
|
|
132
133
|
</View>
|
|
133
134
|
</View>
|
|
134
135
|
)
|
|
@@ -65,7 +65,7 @@
|
|
|
65
65
|
|
|
66
66
|
@supports (bottom: constant(safe-area-inset-bottom)) or
|
|
67
67
|
(bottom: env(safe-area-inset-bottom)) {
|
|
68
|
-
.m-popup {
|
|
68
|
+
.m-popup.m-bottom-safe-area {
|
|
69
69
|
padding-bottom: constant(safe-area-inset-bottom); /* 兼容 iOS < 11.2 */
|
|
70
70
|
padding-bottom: env(safe-area-inset-bottom); /* 兼容 iOS >= 11.2 */
|
|
71
71
|
}
|
|
@@ -19,6 +19,10 @@ interface PopupProps extends HTMLAttributes<HTMLDivElement> {
|
|
|
19
19
|
disabledAnimate?: boolean
|
|
20
20
|
/** 内部用 */
|
|
21
21
|
isPickPopup?: boolean
|
|
22
|
+
/** 禁用下方安全边距,默认为false */
|
|
23
|
+
disableBottomSafeArea?: boolean
|
|
24
|
+
/** 预留底部自定义导航高度,默认为true */
|
|
25
|
+
hasCustomTab?: boolean
|
|
22
26
|
}
|
|
23
27
|
|
|
24
28
|
interface PopupStaticsTypes {
|
|
@@ -17,6 +17,8 @@ const ios = mp && wx.getSystemInfoSync().platform === 'ios'
|
|
|
17
17
|
interface TextFieldState {
|
|
18
18
|
/** 是否输入状态 */
|
|
19
19
|
active: boolean
|
|
20
|
+
/** 是否需要清空 */
|
|
21
|
+
needClear: boolean
|
|
20
22
|
}
|
|
21
23
|
|
|
22
24
|
const store = observable({ active: '' })
|
|
@@ -43,6 +45,7 @@ export class TextField extends Component<TextFieldProps, TextFieldState> {
|
|
|
43
45
|
|
|
44
46
|
state = {
|
|
45
47
|
active: false,
|
|
48
|
+
needClear: false,
|
|
46
49
|
}
|
|
47
50
|
|
|
48
51
|
id = uniqueId('textField-')
|
|
@@ -82,12 +85,17 @@ export class TextField extends Component<TextFieldProps, TextFieldState> {
|
|
|
82
85
|
})
|
|
83
86
|
}
|
|
84
87
|
this.props.onClick && this.props.onClick(e)
|
|
88
|
+
this.setState({ ...this.state, needClear: !!this.props.rewriteMode })
|
|
85
89
|
}
|
|
86
90
|
|
|
87
91
|
onInput(e: any) {
|
|
88
92
|
if (this.props.disabled) return
|
|
89
93
|
if (!mp) e.persist()
|
|
90
94
|
let value = mp ? e.detail.value : e.target.value
|
|
95
|
+
if (this.state.needClear) {
|
|
96
|
+
value = value.slice(-1)
|
|
97
|
+
this.setState({ ...this.state, needClear: false })
|
|
98
|
+
}
|
|
91
99
|
const { min, max } = this.props
|
|
92
100
|
if (
|
|
93
101
|
value &&
|
|
@@ -97,6 +105,11 @@ export class TextField extends Component<TextFieldProps, TextFieldState> {
|
|
|
97
105
|
const float = parseFloat(value.replace(/\D\./g, ''))
|
|
98
106
|
if (isNaN(float)) {
|
|
99
107
|
value = ''
|
|
108
|
+
} else if (value.endsWith('.0')) {
|
|
109
|
+
// 处理特殊情况
|
|
110
|
+
if (this.props.fractionDigits === 0) {
|
|
111
|
+
value = value.replace(/\.0$/, '')
|
|
112
|
+
}
|
|
100
113
|
} else {
|
|
101
114
|
value = clamp(
|
|
102
115
|
float,
|
|
@@ -159,7 +172,7 @@ export class TextField extends Component<TextFieldProps, TextFieldState> {
|
|
|
159
172
|
disabled,
|
|
160
173
|
highlight,
|
|
161
174
|
cursorSpacing = 30,
|
|
162
|
-
maxLength,
|
|
175
|
+
maxLength = -1,
|
|
163
176
|
confirmType,
|
|
164
177
|
adjustPosition,
|
|
165
178
|
block,
|
|
@@ -180,7 +193,7 @@ export class TextField extends Component<TextFieldProps, TextFieldState> {
|
|
|
180
193
|
|
|
181
194
|
const common = {
|
|
182
195
|
disabled: disabled,
|
|
183
|
-
onInput: this.onInput.bind(this),
|
|
196
|
+
// onInput: this.onInput.bind(this),
|
|
184
197
|
onChange: this.onInput.bind(this),
|
|
185
198
|
onClick: this.onClick.bind(this),
|
|
186
199
|
onBlur: () => {
|
|
@@ -226,6 +239,7 @@ export class TextField extends Component<TextFieldProps, TextFieldState> {
|
|
|
226
239
|
active: highlight || active,
|
|
227
240
|
highlight,
|
|
228
241
|
disabled,
|
|
242
|
+
block,
|
|
229
243
|
})}
|
|
230
244
|
width={width}
|
|
231
245
|
style={style}
|
|
@@ -315,3 +329,7 @@ export class TextField extends Component<TextFieldProps, TextFieldState> {
|
|
|
315
329
|
}
|
|
316
330
|
|
|
317
331
|
export default TextField
|
|
332
|
+
|
|
333
|
+
export function AutoPreview_TextField() {
|
|
334
|
+
return <TextField value='test' onChange={() => {}} />
|
|
335
|
+
}
|
|
@@ -7,7 +7,7 @@ interface TextFieldProps
|
|
|
7
7
|
'style' | 'onBlur' | 'onFocus' | 'onClick' | 'onChange' | 'type'
|
|
8
8
|
> {
|
|
9
9
|
value: string
|
|
10
|
-
/** 输入事件, e在web中为ChangeEvent,在小程序中为onInputEventDetail */
|
|
10
|
+
/** 输入事件, e在web中为ChangeEvent(value为e.target.value),在小程序中为onInputEventDetail(value为e.detail.value) */
|
|
11
11
|
onChange?: (e: any) => void
|
|
12
12
|
/** 输入框类型, web端和小程序端取值有差异 */
|
|
13
13
|
type?: InputProps['type']
|
|
@@ -63,6 +63,8 @@ interface TextFieldProps
|
|
|
63
63
|
errClassName?: string
|
|
64
64
|
/** 键盘和输入框距离,小程序特有 */
|
|
65
65
|
cursorSpacing?: number
|
|
66
|
+
/** 重新获得焦点后,输入前清空现有内容 */
|
|
67
|
+
rewriteMode?: boolean
|
|
66
68
|
onBlur?: () => void
|
|
67
69
|
onFocus?: () => void
|
|
68
70
|
/** e在web中和小程序中不一样 */
|
package/src/index.less
CHANGED
|
@@ -37,7 +37,8 @@
|
|
|
37
37
|
@import './component/picker/style.less';
|
|
38
38
|
@import './component/nav/style.less';
|
|
39
39
|
@import './component/date_selector/style.less';
|
|
40
|
-
@import './component
|
|
40
|
+
@import './component/text_field/style.less';
|
|
41
|
+
@import './component/error/style.less';
|
|
41
42
|
|
|
42
43
|
// 公共
|
|
43
44
|
@import './less/mixin';
|
package/src/index.ts
CHANGED
package/src/less/animation.less
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
.m-animated {
|
|
2
|
-
animation-duration: 0.2s;
|
|
3
|
-
animation-fill-mode: none;
|
|
2
|
+
// animation-duration: 0.2s;
|
|
3
|
+
// animation-fill-mode: none;
|
|
4
|
+
transition: all 0.2s;
|
|
4
5
|
}
|
|
5
6
|
|
|
6
7
|
.m-animated-fade-in {
|
|
@@ -153,10 +154,14 @@
|
|
|
153
154
|
|
|
154
155
|
@keyframes slide-in-bottom {
|
|
155
156
|
from {
|
|
156
|
-
transform: translate3d(0, 100%, 0);
|
|
157
|
+
// transform: translate3d(0, 100%, 0);
|
|
158
|
+
max-height: 0%;
|
|
159
|
+
overflow: hidden;
|
|
157
160
|
}
|
|
158
161
|
|
|
159
162
|
to {
|
|
160
|
-
transform: translate3d(0, 0, 0);
|
|
163
|
+
// transform: translate3d(0, 0, 0);
|
|
164
|
+
max-height: 100%;
|
|
165
|
+
overflow: hidden;
|
|
161
166
|
}
|
|
162
167
|
}
|
package/src/less/border.less
CHANGED
|
@@ -98,13 +98,22 @@
|
|
|
98
98
|
}
|
|
99
99
|
|
|
100
100
|
.m-border-radius-circle {
|
|
101
|
-
border-radius: 50
|
|
101
|
+
border-radius: 50% !important;
|
|
102
102
|
}
|
|
103
103
|
|
|
104
104
|
.m-border-radius-chip {
|
|
105
|
-
border-radius: 100px;
|
|
105
|
+
border-radius: 100px !important;
|
|
106
106
|
}
|
|
107
107
|
|
|
108
108
|
.m-border-radius-5 {
|
|
109
|
-
border-radius: 5px;
|
|
109
|
+
border-radius: 5px !important;
|
|
110
110
|
}
|
|
111
|
+
|
|
112
|
+
// 生成圆角, .m-border-radius-{1-10}
|
|
113
|
+
.generate-size(@size) when (@size<=10) {
|
|
114
|
+
.m-border-radius-@{size} {
|
|
115
|
+
border-radius: @size * 1px !important;
|
|
116
|
+
}
|
|
117
|
+
.generate-size(@size + 1);
|
|
118
|
+
}
|
|
119
|
+
.generate-size(0);
|
package/src/less/distance.less
CHANGED
|
@@ -17,76 +17,72 @@
|
|
|
17
17
|
.generate-gap-more-direction(@num, @name, @direction1, @direction2, (@i + 4));
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
-
@
|
|
21
|
-
|
|
22
|
-
5: 5px;
|
|
23
|
-
10: 10px;
|
|
24
|
-
15: 15px;
|
|
25
|
-
20: 20px;
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
each(@size, {
|
|
29
|
-
.m-gap-@{key} {
|
|
20
|
+
.generate-distances(@value) when (@value<=30) {
|
|
21
|
+
.m-gap-@{value} {
|
|
30
22
|
display: inline-block !important;
|
|
31
|
-
height: @value !important;
|
|
32
|
-
width: @value !important;
|
|
23
|
+
height: @value * 1px !important;
|
|
24
|
+
width: @value * 1px !important;
|
|
33
25
|
}
|
|
34
26
|
|
|
35
|
-
.m-padding-@{
|
|
36
|
-
padding: @value !important;
|
|
27
|
+
.m-padding-@{value} {
|
|
28
|
+
padding: @value * 1px !important;
|
|
37
29
|
}
|
|
38
30
|
|
|
39
|
-
.m-padding-top-@{
|
|
40
|
-
padding-top: @value !important;
|
|
31
|
+
.m-padding-top-@{value} {
|
|
32
|
+
padding-top: @value * 1px !important;
|
|
41
33
|
}
|
|
42
34
|
|
|
43
|
-
.m-padding-bottom-@{
|
|
44
|
-
padding-bottom: @value !important;
|
|
35
|
+
.m-padding-bottom-@{value} {
|
|
36
|
+
padding-bottom: @value * 1px !important;
|
|
45
37
|
}
|
|
46
|
-
.m-padding-left-@{
|
|
47
|
-
padding-left: @value !important;
|
|
38
|
+
.m-padding-left-@{value} {
|
|
39
|
+
padding-left: @value * 1px !important;
|
|
48
40
|
}
|
|
49
41
|
|
|
50
|
-
.m-padding-right-@{
|
|
51
|
-
padding-right: @value !important;
|
|
42
|
+
.m-padding-right-@{value} {
|
|
43
|
+
padding-right: @value * 1px !important;
|
|
52
44
|
}
|
|
53
45
|
|
|
54
|
-
.m-padding-lr-@{
|
|
55
|
-
padding-left: @value !important;
|
|
56
|
-
padding-right: @value !important;
|
|
46
|
+
.m-padding-lr-@{value} {
|
|
47
|
+
padding-left: @value * 1px !important;
|
|
48
|
+
padding-right: @value * 1px !important;
|
|
57
49
|
}
|
|
58
50
|
|
|
59
|
-
.m-padding-tb-@{
|
|
60
|
-
padding-top: @value !important;
|
|
61
|
-
padding-bottom: @value !important;
|
|
51
|
+
.m-padding-tb-@{value} {
|
|
52
|
+
padding-top: @value * 1px !important;
|
|
53
|
+
padding-bottom: @value * 1px !important;
|
|
62
54
|
}
|
|
63
55
|
|
|
64
|
-
.m-margin-@{
|
|
65
|
-
margin: @value !important;
|
|
56
|
+
.m-margin-@{value} {
|
|
57
|
+
margin: @value * 1px !important;
|
|
66
58
|
}
|
|
67
59
|
|
|
68
|
-
.m-margin-top-@{
|
|
69
|
-
margin-top: @value !important;
|
|
60
|
+
.m-margin-top-@{value} {
|
|
61
|
+
margin-top: @value * 1px !important;
|
|
70
62
|
}
|
|
71
63
|
|
|
72
|
-
.m-margin-bottom-@{
|
|
73
|
-
margin-bottom: @value !important;
|
|
64
|
+
.m-margin-bottom-@{value} {
|
|
65
|
+
margin-bottom: @value * 1px !important;
|
|
74
66
|
}
|
|
75
|
-
.m-margin-left-@{
|
|
76
|
-
margin-left: @value !important;
|
|
67
|
+
.m-margin-left-@{value} {
|
|
68
|
+
margin-left: @value * 1px !important;
|
|
77
69
|
}
|
|
78
70
|
|
|
79
|
-
.m-margin-right-@{
|
|
80
|
-
margin-right: @value !important;
|
|
71
|
+
.m-margin-right-@{value} {
|
|
72
|
+
margin-right: @value * 1px !important;
|
|
81
73
|
}
|
|
82
74
|
|
|
83
|
-
.m-margin-lr-@{
|
|
84
|
-
margin-left: @value !important;
|
|
85
|
-
margin-right: @value !important;
|
|
75
|
+
.m-margin-lr-@{value} {
|
|
76
|
+
margin-left: @value * 1px !important;
|
|
77
|
+
margin-right: @value * 1px !important;
|
|
86
78
|
}
|
|
87
79
|
|
|
88
|
-
.m-margin-tb-@{
|
|
89
|
-
margin-top: @value !important;
|
|
90
|
-
margin-bottom: @value !important;
|
|
80
|
+
.m-margin-tb-@{value} {
|
|
81
|
+
margin-top: @value * 1px !important;
|
|
82
|
+
margin-bottom: @value * 1px !important;
|
|
91
83
|
}
|
|
92
|
-
|
|
84
|
+
|
|
85
|
+
.generate-distances(@value + 1);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
.generate-distances(0);
|
package/src/less/text.less
CHANGED
|
@@ -66,6 +66,10 @@
|
|
|
66
66
|
text-decoration: line-through;
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
+
.m-text-normal {
|
|
70
|
+
font-weight: normal;
|
|
71
|
+
}
|
|
72
|
+
|
|
69
73
|
.m-text-bold {
|
|
70
74
|
font-weight: bold;
|
|
71
75
|
}
|
|
@@ -105,14 +109,20 @@ each(@colors,.(@color,@colorKey,@index){
|
|
|
105
109
|
});
|
|
106
110
|
|
|
107
111
|
// 生成size, .m-text-{8-32}, --m-size-text-{8-32}
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
112
|
+
:root,
|
|
113
|
+
page {
|
|
114
|
+
.generate-text-variables(@size) when (@size<=32) {
|
|
115
|
+
.generate-text-variables(@size + 1);
|
|
111
116
|
--m-size-text-@{size}: ~'@{size}px';
|
|
112
117
|
}
|
|
118
|
+
.generate-text-variables(8);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
.generate-text-size(@size) when (@size<=32) {
|
|
113
122
|
.m-text-@{size} {
|
|
114
|
-
font-size: e(%('var(--m-size-text-%s)!important', @size));
|
|
123
|
+
// font-size: e(%('var(--m-size-text-%s)!important', @size));
|
|
124
|
+
font-size: @size * 1px;
|
|
115
125
|
}
|
|
116
|
-
.generate-size(@size +
|
|
126
|
+
.generate-text-size(@size + 1);
|
|
117
127
|
}
|
|
118
|
-
.generate-size(8);
|
|
128
|
+
.generate-text-size(8);
|