antd-mobile 5.41.1 → 5.42.0-alpha.0
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/2x/bundle/antd-mobile.cjs.development.js +65 -51
- package/2x/bundle/antd-mobile.cjs.js +6 -6
- package/2x/bundle/antd-mobile.es.development.js +65 -51
- package/2x/bundle/antd-mobile.es.js +1534 -1524
- package/2x/bundle/antd-mobile.umd.development.js +65 -51
- package/2x/bundle/antd-mobile.umd.js +6 -6
- package/2x/bundle/style.css +9 -2
- package/2x/cjs/components/dialog/dialog.d.ts +2 -2
- package/2x/cjs/components/dialog/dialog.js +3 -3
- package/2x/cjs/components/modal/modal.d.ts +2 -2
- package/2x/cjs/components/modal/modal.js +4 -4
- package/2x/cjs/components/number-keyboard/number-keyboard.js +18 -21
- package/2x/cjs/components/virtual-input/use-click-outside.d.ts +2 -0
- package/2x/cjs/components/virtual-input/use-click-outside.js +25 -0
- package/2x/cjs/components/virtual-input/virtual-input.css +9 -2
- package/2x/cjs/components/virtual-input/virtual-input.js +32 -30
- package/2x/es/components/dialog/dialog.d.ts +2 -2
- package/2x/es/components/dialog/dialog.js +3 -3
- package/2x/es/components/modal/modal.d.ts +2 -2
- package/2x/es/components/modal/modal.js +4 -4
- package/2x/es/components/number-keyboard/number-keyboard.js +18 -21
- package/2x/es/components/virtual-input/use-click-outside.d.ts +2 -0
- package/2x/es/components/virtual-input/use-click-outside.js +18 -0
- package/2x/es/components/virtual-input/virtual-input.css +9 -2
- package/2x/es/components/virtual-input/virtual-input.js +32 -30
- package/2x/package.json +1 -1
- package/bundle/antd-mobile.cjs.development.js +65 -51
- package/bundle/antd-mobile.cjs.js +6 -6
- package/bundle/antd-mobile.compatible.umd.js +1 -1
- package/bundle/antd-mobile.es.development.js +65 -51
- package/bundle/antd-mobile.es.js +1534 -1524
- package/bundle/antd-mobile.umd.development.js +65 -51
- package/bundle/antd-mobile.umd.js +6 -6
- package/bundle/style.css +1 -1
- package/cjs/components/dialog/dialog.d.ts +2 -2
- package/cjs/components/dialog/dialog.js +3 -3
- package/cjs/components/modal/modal.d.ts +2 -2
- package/cjs/components/modal/modal.js +4 -4
- package/cjs/components/number-keyboard/number-keyboard.js +18 -21
- package/cjs/components/virtual-input/use-click-outside.d.ts +2 -0
- package/cjs/components/virtual-input/use-click-outside.js +25 -0
- package/cjs/components/virtual-input/virtual-input.css +8 -2
- package/cjs/components/virtual-input/virtual-input.js +32 -30
- package/es/components/dialog/dialog.d.ts +2 -2
- package/es/components/dialog/dialog.js +3 -3
- package/es/components/modal/modal.d.ts +2 -2
- package/es/components/modal/modal.js +4 -4
- package/es/components/number-keyboard/number-keyboard.js +18 -21
- package/es/components/virtual-input/use-click-outside.d.ts +2 -0
- package/es/components/virtual-input/use-click-outside.js +18 -0
- package/es/components/virtual-input/virtual-input.css +8 -2
- package/es/components/virtual-input/virtual-input.js +32 -30
- package/package.json +1 -1
- package/umd/antd-mobile.js +1 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { FC, ReactNode } from 'react';
|
|
2
|
-
import { Action } from './dialog-action-button';
|
|
3
2
|
import { NativeProps } from '../../utils/native-props';
|
|
4
3
|
import { CenterPopupProps } from '../center-popup';
|
|
4
|
+
import { Action } from './dialog-action-button';
|
|
5
5
|
export declare type DialogProps = Pick<CenterPopupProps, 'afterClose' | 'afterShow' | 'bodyClassName' | 'bodyStyle' | 'destroyOnClose' | 'disableBodyScroll' | 'forceRender' | 'getContainer' | 'maskClassName' | 'maskStyle' | 'stopPropagation' | 'visible'> & {
|
|
6
6
|
image?: string;
|
|
7
7
|
header?: ReactNode;
|
|
@@ -12,5 +12,5 @@ export declare type DialogProps = Pick<CenterPopupProps, 'afterClose' | 'afterSh
|
|
|
12
12
|
onClose?: () => void;
|
|
13
13
|
closeOnAction?: boolean;
|
|
14
14
|
closeOnMaskClick?: boolean;
|
|
15
|
-
} & NativeProps
|
|
15
|
+
} & NativeProps<'--background-color' | '--border-radius' | '--max-width' | '--min-width' | '--z-index'>;
|
|
16
16
|
export declare const Dialog: FC<DialogProps>;
|
|
@@ -5,13 +5,13 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
exports.Dialog = void 0;
|
|
7
7
|
var _tslib = require("tslib");
|
|
8
|
+
var _classnames = _interopRequireDefault(require("classnames"));
|
|
8
9
|
var _react = _interopRequireDefault(require("react"));
|
|
9
10
|
var _withDefaultProps = require("../../utils/with-default-props");
|
|
10
|
-
var _classnames = _interopRequireDefault(require("classnames"));
|
|
11
|
-
var _dialogActionButton = require("./dialog-action-button");
|
|
12
|
-
var _image = _interopRequireDefault(require("../image"));
|
|
13
11
|
var _autoCenter = _interopRequireDefault(require("../auto-center"));
|
|
14
12
|
var _centerPopup = _interopRequireDefault(require("../center-popup"));
|
|
13
|
+
var _image = _interopRequireDefault(require("../image"));
|
|
14
|
+
var _dialogActionButton = require("./dialog-action-button");
|
|
15
15
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
16
16
|
const defaultProps = {
|
|
17
17
|
actions: [],
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { FC, ReactNode } from 'react';
|
|
2
|
-
import { Action } from './modal-action-button';
|
|
3
2
|
import { NativeProps } from '../../utils/native-props';
|
|
4
3
|
import { CenterPopupProps } from '../center-popup';
|
|
4
|
+
import { Action } from './modal-action-button';
|
|
5
5
|
export declare type ModalProps = Pick<CenterPopupProps, 'afterClose' | 'afterShow' | 'bodyClassName' | 'bodyStyle' | 'destroyOnClose' | 'disableBodyScroll' | 'forceRender' | 'getContainer' | 'maskClassName' | 'maskStyle' | 'stopPropagation' | 'visible'> & {
|
|
6
6
|
image?: string;
|
|
7
7
|
header?: ReactNode;
|
|
@@ -13,5 +13,5 @@ export declare type ModalProps = Pick<CenterPopupProps, 'afterClose' | 'afterSho
|
|
|
13
13
|
closeOnAction?: boolean;
|
|
14
14
|
closeOnMaskClick?: boolean;
|
|
15
15
|
showCloseButton?: boolean;
|
|
16
|
-
} & NativeProps
|
|
16
|
+
} & NativeProps<'--background-color' | '--border-radius' | '--max-width' | '--min-width' | '--z-index'>;
|
|
17
17
|
export declare const Modal: FC<ModalProps>;
|
|
@@ -5,14 +5,14 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
exports.Modal = void 0;
|
|
7
7
|
var _tslib = require("tslib");
|
|
8
|
+
var _classnames = _interopRequireDefault(require("classnames"));
|
|
8
9
|
var _react = _interopRequireDefault(require("react"));
|
|
9
10
|
var _withDefaultProps = require("../../utils/with-default-props");
|
|
10
|
-
var _classnames = _interopRequireDefault(require("classnames"));
|
|
11
|
-
var _modalActionButton = require("./modal-action-button");
|
|
12
|
-
var _image = _interopRequireDefault(require("../image"));
|
|
13
|
-
var _space = _interopRequireDefault(require("../space"));
|
|
14
11
|
var _autoCenter = _interopRequireDefault(require("../auto-center"));
|
|
15
12
|
var _centerPopup = _interopRequireDefault(require("../center-popup"));
|
|
13
|
+
var _image = _interopRequireDefault(require("../image"));
|
|
14
|
+
var _space = _interopRequireDefault(require("../space"));
|
|
15
|
+
var _modalActionButton = require("./modal-action-button");
|
|
16
16
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
17
17
|
const defaultProps = {
|
|
18
18
|
actions: [],
|
|
@@ -78,7 +78,6 @@ const NumberKeyboard = p => {
|
|
|
78
78
|
};
|
|
79
79
|
const onKeyPress = (e, key) => {
|
|
80
80
|
var _a, _b;
|
|
81
|
-
e.preventDefault();
|
|
82
81
|
switch (key) {
|
|
83
82
|
case 'BACKSPACE':
|
|
84
83
|
onDelete === null || onDelete === void 0 ? void 0 : onDelete();
|
|
@@ -115,6 +114,15 @@ const NumberKeyboard = p => {
|
|
|
115
114
|
tabIndex: -1
|
|
116
115
|
}, _react.default.createElement(_antdMobileIcons.DownOutline, null)));
|
|
117
116
|
};
|
|
117
|
+
const onBackspaceTouchStart = () => {
|
|
118
|
+
stopContinueClear();
|
|
119
|
+
startContinueClear();
|
|
120
|
+
};
|
|
121
|
+
const onBackspaceTouchEnd = e => {
|
|
122
|
+
e.preventDefault(); // 短按时,touchend 会阻止后续 click 事件触发,防止删除两次
|
|
123
|
+
stopContinueClear();
|
|
124
|
+
onKeyPress(e, 'BACKSPACE');
|
|
125
|
+
};
|
|
118
126
|
const renderKey = (key, index) => {
|
|
119
127
|
const isNumberKey = /^\d$/.test(key);
|
|
120
128
|
const isBackspace = key === 'BACKSPACE';
|
|
@@ -132,17 +140,13 @@ const NumberKeyboard = p => {
|
|
|
132
140
|
key: key,
|
|
133
141
|
className: className,
|
|
134
142
|
// 仅为 backspace 绑定,支持长按快速删除
|
|
135
|
-
onTouchStart: isBackspace ?
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
} : undefined,
|
|
139
|
-
onTouchEnd: isBackspace ? e => {
|
|
140
|
-
stopContinueClear();
|
|
141
|
-
onKeyPress(e, key);
|
|
142
|
-
} : undefined,
|
|
143
|
+
onTouchStart: isBackspace ? onBackspaceTouchStart : undefined,
|
|
144
|
+
onTouchEnd: isBackspace ? onBackspaceTouchEnd : undefined,
|
|
145
|
+
onTouchCancel: isBackspace ? stopContinueClear : undefined,
|
|
143
146
|
// <div role="button" title="1" onTouchEnd={e => {}}>1</div> 安卓上 talback 可读不可点
|
|
144
147
|
// see https://ua-gilded-eef7f9.netlify.app/grid-button-bug.html
|
|
145
|
-
//
|
|
148
|
+
// 所以普通按钮绑定 click 事件,而 backspace 仍然额外绑定 touch 事件支持长按删除
|
|
149
|
+
// backspace touchend 时会 preventDefault 阻止其后续 click 事件
|
|
146
150
|
onClick: e => {
|
|
147
151
|
stopContinueClear();
|
|
148
152
|
onKeyPress(e, key);
|
|
@@ -161,10 +165,7 @@ const NumberKeyboard = p => {
|
|
|
161
165
|
forceRender: props.forceRender
|
|
162
166
|
}, (0, _nativeProps.withNativeProps)(props, _react.default.createElement("div", {
|
|
163
167
|
ref: keyboardRef,
|
|
164
|
-
className: classPrefix
|
|
165
|
-
onMouseDown: e => {
|
|
166
|
-
e.preventDefault();
|
|
167
|
-
}
|
|
168
|
+
className: classPrefix
|
|
168
169
|
}, renderHeader(), _react.default.createElement("div", {
|
|
169
170
|
className: `${classPrefix}-wrapper`
|
|
170
171
|
}, _react.default.createElement("div", {
|
|
@@ -175,13 +176,9 @@ const NumberKeyboard = p => {
|
|
|
175
176
|
className: `${classPrefix}-confirm`
|
|
176
177
|
}, _react.default.createElement("div", {
|
|
177
178
|
className: `${classPrefix}-key ${classPrefix}-key-extra ${classPrefix}-key-bs`,
|
|
178
|
-
onTouchStart:
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
onTouchEnd: e => {
|
|
182
|
-
stopContinueClear();
|
|
183
|
-
onKeyPress(e, 'BACKSPACE');
|
|
184
|
-
},
|
|
179
|
+
onTouchStart: onBackspaceTouchStart,
|
|
180
|
+
onTouchEnd: onBackspaceTouchEnd,
|
|
181
|
+
onTouchCancel: stopContinueClear,
|
|
185
182
|
onClick: e => {
|
|
186
183
|
stopContinueClear();
|
|
187
184
|
onKeyPress(e, 'BACKSPACE');
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = void 0;
|
|
7
|
+
var _react = require("react");
|
|
8
|
+
// 监听点击组件外部的事件
|
|
9
|
+
function useClickOutside(handler, ref) {
|
|
10
|
+
(0, _react.useEffect)(() => {
|
|
11
|
+
function handleClick(event) {
|
|
12
|
+
if (!ref.current || ref.current.contains(event.target)) {
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
handler(event);
|
|
16
|
+
}
|
|
17
|
+
// 在捕获阶段监听,以确保在事件被阻止传播之前触发
|
|
18
|
+
document.addEventListener('click', handleClick, true);
|
|
19
|
+
return () => {
|
|
20
|
+
document.removeEventListener('click', handleClick, true);
|
|
21
|
+
};
|
|
22
|
+
}, [handler, ref]);
|
|
23
|
+
}
|
|
24
|
+
var _default = useClickOutside;
|
|
25
|
+
exports.default = _default;
|
|
@@ -36,6 +36,12 @@
|
|
|
36
36
|
.adm-virtual-input-content::-webkit-scrollbar {
|
|
37
37
|
display: none;
|
|
38
38
|
}
|
|
39
|
+
.adm-virtual-input-trap {
|
|
40
|
+
width: 10px;
|
|
41
|
+
height: 10px;
|
|
42
|
+
position: absolute;
|
|
43
|
+
opacity: 0;
|
|
44
|
+
}
|
|
39
45
|
.adm-virtual-input-placeholder {
|
|
40
46
|
display: block;
|
|
41
47
|
position: absolute;
|
|
@@ -66,10 +72,10 @@
|
|
|
66
72
|
left: 0;
|
|
67
73
|
z-index: 1;
|
|
68
74
|
}
|
|
69
|
-
.adm-virtual-input
|
|
75
|
+
.adm-virtual-input-focused {
|
|
70
76
|
outline: none;
|
|
71
77
|
}
|
|
72
|
-
.adm-virtual-input
|
|
78
|
+
.adm-virtual-input-focused .adm-virtual-input-caret {
|
|
73
79
|
animation-name: adm-caret-blink;
|
|
74
80
|
animation-duration: 1s;
|
|
75
81
|
animation-timing-function: linear;
|
|
@@ -12,6 +12,7 @@ var _nativeProps = require("../../utils/native-props");
|
|
|
12
12
|
var _usePropsValue = require("../../utils/use-props-value");
|
|
13
13
|
var _withDefaultProps = require("../../utils/with-default-props");
|
|
14
14
|
var _configProvider = require("../config-provider");
|
|
15
|
+
var _useClickOutside = _interopRequireDefault(require("./use-click-outside"));
|
|
15
16
|
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
|
|
16
17
|
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
|
|
17
18
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
@@ -42,13 +43,10 @@ const VirtualInput = (0, _react.forwardRef)((props, ref) => {
|
|
|
42
43
|
const touchMoveTimeoutRef = (0, _react.useRef)();
|
|
43
44
|
const clearIcon = (0, _withDefaultProps.mergeProp)(_react.default.createElement(_antdMobileIcons.CloseCircleFill, null), componentConfig.clearIcon, props.clearIcon);
|
|
44
45
|
function scrollToEnd() {
|
|
45
|
-
const
|
|
46
|
-
if (!
|
|
47
|
-
if (document.activeElement !== root) {
|
|
46
|
+
const content = contentRef.current;
|
|
47
|
+
if (!content) {
|
|
48
48
|
return;
|
|
49
49
|
}
|
|
50
|
-
const content = contentRef.current;
|
|
51
|
-
if (!content) return;
|
|
52
50
|
content.scrollLeft = content.clientWidth;
|
|
53
51
|
}
|
|
54
52
|
(0, _react.useEffect)(() => {
|
|
@@ -80,23 +78,29 @@ const VirtualInput = (0, _react.forwardRef)((props, ref) => {
|
|
|
80
78
|
(0, _react.useImperativeHandle)(ref, () => ({
|
|
81
79
|
focus: () => {
|
|
82
80
|
var _a;
|
|
83
|
-
(_a =
|
|
81
|
+
(_a = contentRef.current) === null || _a === void 0 ? void 0 : _a.focus();
|
|
84
82
|
},
|
|
85
83
|
blur: () => {
|
|
86
84
|
var _a;
|
|
87
|
-
(_a =
|
|
85
|
+
(_a = contentRef.current) === null || _a === void 0 ? void 0 : _a.blur();
|
|
86
|
+
setBlur();
|
|
88
87
|
}
|
|
89
88
|
}));
|
|
90
|
-
function
|
|
89
|
+
function setFocus() {
|
|
91
90
|
var _a;
|
|
91
|
+
if (hasFocus) return;
|
|
92
92
|
setHasFocus(true);
|
|
93
93
|
(_a = mergedProps.onFocus) === null || _a === void 0 ? void 0 : _a.call(mergedProps);
|
|
94
94
|
}
|
|
95
|
-
function
|
|
95
|
+
function setBlur() {
|
|
96
96
|
var _a;
|
|
97
|
+
if (!hasFocus) return;
|
|
97
98
|
setHasFocus(false);
|
|
98
99
|
(_a = mergedProps.onBlur) === null || _a === void 0 ? void 0 : _a.call(mergedProps);
|
|
99
100
|
}
|
|
101
|
+
(0, _useClickOutside.default)(() => {
|
|
102
|
+
setBlur();
|
|
103
|
+
}, rootRef);
|
|
100
104
|
const keyboard = mergedProps.keyboard;
|
|
101
105
|
const keyboardElement = keyboard && _react.default.cloneElement(keyboard, {
|
|
102
106
|
onInput: v => {
|
|
@@ -124,26 +128,20 @@ const VirtualInput = (0, _react.forwardRef)((props, ref) => {
|
|
|
124
128
|
},
|
|
125
129
|
visible: hasFocus,
|
|
126
130
|
onClose: () => {
|
|
127
|
-
var _a, _b
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
// We will trigger blur on the child element instead
|
|
131
|
-
if (activeElement && ((_a = rootRef.current) === null || _a === void 0 ? void 0 : _a.contains(activeElement))) {
|
|
132
|
-
activeElement.blur();
|
|
133
|
-
} else {
|
|
134
|
-
(_b = rootRef.current) === null || _b === void 0 ? void 0 : _b.blur();
|
|
135
|
-
}
|
|
136
|
-
(_d = (_c = keyboard.props).onClose) === null || _d === void 0 ? void 0 : _d.call(_c);
|
|
131
|
+
var _a, _b;
|
|
132
|
+
setBlur();
|
|
133
|
+
(_b = (_a = keyboard.props).onClose) === null || _b === void 0 ? void 0 : _b.call(_a);
|
|
137
134
|
},
|
|
138
135
|
getContainer: null
|
|
139
136
|
});
|
|
140
137
|
// 点击输入框时,将光标置于最后
|
|
141
|
-
const setCaretPositionToEnd =
|
|
142
|
-
var _a, _b;
|
|
138
|
+
const setCaretPositionToEnd = e => {
|
|
139
|
+
var _a, _b, _c;
|
|
143
140
|
if (caretPosition !== value.length) {
|
|
144
141
|
setCaretPosition(value.length);
|
|
145
142
|
(_b = (_a = mergedProps.cursor) === null || _a === void 0 ? void 0 : _a.onMove) === null || _b === void 0 ? void 0 : _b.call(_a, value.length);
|
|
146
143
|
}
|
|
144
|
+
(_c = mergedProps.onClick) === null || _c === void 0 ? void 0 : _c.call(mergedProps, e);
|
|
147
145
|
};
|
|
148
146
|
// 点击单个字符时,根据点击位置置于字符前或后
|
|
149
147
|
const changeCaretPosition = index => e => {
|
|
@@ -212,23 +210,27 @@ const VirtualInput = (0, _react.forwardRef)((props, ref) => {
|
|
|
212
210
|
ref: rootRef,
|
|
213
211
|
className: (0, _classnames.default)(classPrefix, {
|
|
214
212
|
[`${classPrefix}-disabled`]: mergedProps.disabled,
|
|
215
|
-
[`${classPrefix}-caret-dragging`]: isCaretDragging
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
role: 'textbox',
|
|
219
|
-
onFocus: onFocus,
|
|
220
|
-
onBlur: onBlur,
|
|
221
|
-
onClick: mergedProps.onClick
|
|
213
|
+
[`${classPrefix}-caret-dragging`]: isCaretDragging,
|
|
214
|
+
[`${classPrefix}-focused`]: hasFocus
|
|
215
|
+
})
|
|
222
216
|
}, _react.default.createElement("div", {
|
|
223
217
|
className: `${classPrefix}-content`,
|
|
224
218
|
ref: contentRef,
|
|
225
219
|
"aria-disabled": mergedProps.disabled,
|
|
226
|
-
"aria-label": mergedProps.placeholder,
|
|
220
|
+
"aria-label": value || mergedProps.placeholder,
|
|
221
|
+
role: 'textbox',
|
|
222
|
+
tabIndex: mergedProps.disabled ? undefined : 0,
|
|
223
|
+
// note: 这里增加 onFocus 有两个目的:
|
|
224
|
+
// 1. 在安卓 talkback 模式下,role=textbox 的元素双击后只会触发 focus 而非 click
|
|
225
|
+
// 2. 处理 content 框点击、单个字符点击时,不用再额外处理 focus 逻辑,因为 focus 事件会先触发
|
|
226
|
+
onFocus: setFocus,
|
|
227
227
|
onClick: setCaretPositionToEnd,
|
|
228
228
|
onTouchStart: handleTouchStart,
|
|
229
229
|
onTouchMove: handleTouchMove,
|
|
230
230
|
onTouchEnd: handleTouchEnd
|
|
231
|
-
},
|
|
231
|
+
}, _react.default.createElement("span", {
|
|
232
|
+
className: `${classPrefix}-trap`
|
|
233
|
+
}), chars.slice(0, caretPosition).map((i, index) => _react.default.createElement("span", {
|
|
232
234
|
ref: index === 0 ? charRef : undefined,
|
|
233
235
|
key: index,
|
|
234
236
|
onClick: changeCaretPosition(index)
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { FC, ReactNode } from 'react';
|
|
2
|
-
import { Action } from './dialog-action-button';
|
|
3
2
|
import { NativeProps } from '../../utils/native-props';
|
|
4
3
|
import { CenterPopupProps } from '../center-popup';
|
|
4
|
+
import { Action } from './dialog-action-button';
|
|
5
5
|
export declare type DialogProps = Pick<CenterPopupProps, 'afterClose' | 'afterShow' | 'bodyClassName' | 'bodyStyle' | 'destroyOnClose' | 'disableBodyScroll' | 'forceRender' | 'getContainer' | 'maskClassName' | 'maskStyle' | 'stopPropagation' | 'visible'> & {
|
|
6
6
|
image?: string;
|
|
7
7
|
header?: ReactNode;
|
|
@@ -12,5 +12,5 @@ export declare type DialogProps = Pick<CenterPopupProps, 'afterClose' | 'afterSh
|
|
|
12
12
|
onClose?: () => void;
|
|
13
13
|
closeOnAction?: boolean;
|
|
14
14
|
closeOnMaskClick?: boolean;
|
|
15
|
-
} & NativeProps
|
|
15
|
+
} & NativeProps<'--background-color' | '--border-radius' | '--max-width' | '--min-width' | '--z-index'>;
|
|
16
16
|
export declare const Dialog: FC<DialogProps>;
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { __awaiter } from "tslib";
|
|
2
|
+
import classNames from 'classnames';
|
|
2
3
|
import React from 'react';
|
|
3
4
|
import { mergeProps } from '../../utils/with-default-props';
|
|
4
|
-
import classNames from 'classnames';
|
|
5
|
-
import { DialogActionButton } from './dialog-action-button';
|
|
6
|
-
import Image from '../image';
|
|
7
5
|
import AutoCenter from '../auto-center';
|
|
8
6
|
import CenterPopup from '../center-popup';
|
|
7
|
+
import Image from '../image';
|
|
8
|
+
import { DialogActionButton } from './dialog-action-button';
|
|
9
9
|
const defaultProps = {
|
|
10
10
|
actions: [],
|
|
11
11
|
closeOnAction: false,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { FC, ReactNode } from 'react';
|
|
2
|
-
import { Action } from './modal-action-button';
|
|
3
2
|
import { NativeProps } from '../../utils/native-props';
|
|
4
3
|
import { CenterPopupProps } from '../center-popup';
|
|
4
|
+
import { Action } from './modal-action-button';
|
|
5
5
|
export declare type ModalProps = Pick<CenterPopupProps, 'afterClose' | 'afterShow' | 'bodyClassName' | 'bodyStyle' | 'destroyOnClose' | 'disableBodyScroll' | 'forceRender' | 'getContainer' | 'maskClassName' | 'maskStyle' | 'stopPropagation' | 'visible'> & {
|
|
6
6
|
image?: string;
|
|
7
7
|
header?: ReactNode;
|
|
@@ -13,5 +13,5 @@ export declare type ModalProps = Pick<CenterPopupProps, 'afterClose' | 'afterSho
|
|
|
13
13
|
closeOnAction?: boolean;
|
|
14
14
|
closeOnMaskClick?: boolean;
|
|
15
15
|
showCloseButton?: boolean;
|
|
16
|
-
} & NativeProps
|
|
16
|
+
} & NativeProps<'--background-color' | '--border-radius' | '--max-width' | '--min-width' | '--z-index'>;
|
|
17
17
|
export declare const Modal: FC<ModalProps>;
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { __awaiter } from "tslib";
|
|
2
|
+
import classNames from 'classnames';
|
|
2
3
|
import React from 'react';
|
|
3
4
|
import { mergeProps } from '../../utils/with-default-props';
|
|
4
|
-
import classNames from 'classnames';
|
|
5
|
-
import { ModalActionButton } from './modal-action-button';
|
|
6
|
-
import Image from '../image';
|
|
7
|
-
import Space from '../space';
|
|
8
5
|
import AutoCenter from '../auto-center';
|
|
9
6
|
import CenterPopup from '../center-popup';
|
|
7
|
+
import Image from '../image';
|
|
8
|
+
import Space from '../space';
|
|
9
|
+
import { ModalActionButton } from './modal-action-button';
|
|
10
10
|
const defaultProps = {
|
|
11
11
|
actions: [],
|
|
12
12
|
closeOnAction: false,
|
|
@@ -69,7 +69,6 @@ export const NumberKeyboard = p => {
|
|
|
69
69
|
};
|
|
70
70
|
const onKeyPress = (e, key) => {
|
|
71
71
|
var _a, _b;
|
|
72
|
-
e.preventDefault();
|
|
73
72
|
switch (key) {
|
|
74
73
|
case 'BACKSPACE':
|
|
75
74
|
onDelete === null || onDelete === void 0 ? void 0 : onDelete();
|
|
@@ -106,6 +105,15 @@ export const NumberKeyboard = p => {
|
|
|
106
105
|
tabIndex: -1
|
|
107
106
|
}, React.createElement(DownOutline, null)));
|
|
108
107
|
};
|
|
108
|
+
const onBackspaceTouchStart = () => {
|
|
109
|
+
stopContinueClear();
|
|
110
|
+
startContinueClear();
|
|
111
|
+
};
|
|
112
|
+
const onBackspaceTouchEnd = e => {
|
|
113
|
+
e.preventDefault(); // 短按时,touchend 会阻止后续 click 事件触发,防止删除两次
|
|
114
|
+
stopContinueClear();
|
|
115
|
+
onKeyPress(e, 'BACKSPACE');
|
|
116
|
+
};
|
|
109
117
|
const renderKey = (key, index) => {
|
|
110
118
|
const isNumberKey = /^\d$/.test(key);
|
|
111
119
|
const isBackspace = key === 'BACKSPACE';
|
|
@@ -123,17 +131,13 @@ export const NumberKeyboard = p => {
|
|
|
123
131
|
key: key,
|
|
124
132
|
className: className,
|
|
125
133
|
// 仅为 backspace 绑定,支持长按快速删除
|
|
126
|
-
onTouchStart: isBackspace ?
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
} : undefined,
|
|
130
|
-
onTouchEnd: isBackspace ? e => {
|
|
131
|
-
stopContinueClear();
|
|
132
|
-
onKeyPress(e, key);
|
|
133
|
-
} : undefined,
|
|
134
|
+
onTouchStart: isBackspace ? onBackspaceTouchStart : undefined,
|
|
135
|
+
onTouchEnd: isBackspace ? onBackspaceTouchEnd : undefined,
|
|
136
|
+
onTouchCancel: isBackspace ? stopContinueClear : undefined,
|
|
134
137
|
// <div role="button" title="1" onTouchEnd={e => {}}>1</div> 安卓上 talback 可读不可点
|
|
135
138
|
// see https://ua-gilded-eef7f9.netlify.app/grid-button-bug.html
|
|
136
|
-
//
|
|
139
|
+
// 所以普通按钮绑定 click 事件,而 backspace 仍然额外绑定 touch 事件支持长按删除
|
|
140
|
+
// backspace touchend 时会 preventDefault 阻止其后续 click 事件
|
|
137
141
|
onClick: e => {
|
|
138
142
|
stopContinueClear();
|
|
139
143
|
onKeyPress(e, key);
|
|
@@ -152,10 +156,7 @@ export const NumberKeyboard = p => {
|
|
|
152
156
|
forceRender: props.forceRender
|
|
153
157
|
}, withNativeProps(props, React.createElement("div", {
|
|
154
158
|
ref: keyboardRef,
|
|
155
|
-
className: classPrefix
|
|
156
|
-
onMouseDown: e => {
|
|
157
|
-
e.preventDefault();
|
|
158
|
-
}
|
|
159
|
+
className: classPrefix
|
|
159
160
|
}, renderHeader(), React.createElement("div", {
|
|
160
161
|
className: `${classPrefix}-wrapper`
|
|
161
162
|
}, React.createElement("div", {
|
|
@@ -166,13 +167,9 @@ export const NumberKeyboard = p => {
|
|
|
166
167
|
className: `${classPrefix}-confirm`
|
|
167
168
|
}, React.createElement("div", {
|
|
168
169
|
className: `${classPrefix}-key ${classPrefix}-key-extra ${classPrefix}-key-bs`,
|
|
169
|
-
onTouchStart:
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
onTouchEnd: e => {
|
|
173
|
-
stopContinueClear();
|
|
174
|
-
onKeyPress(e, 'BACKSPACE');
|
|
175
|
-
},
|
|
170
|
+
onTouchStart: onBackspaceTouchStart,
|
|
171
|
+
onTouchEnd: onBackspaceTouchEnd,
|
|
172
|
+
onTouchCancel: stopContinueClear,
|
|
176
173
|
onClick: e => {
|
|
177
174
|
stopContinueClear();
|
|
178
175
|
onKeyPress(e, 'BACKSPACE');
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { useEffect } from 'react';
|
|
2
|
+
// 监听点击组件外部的事件
|
|
3
|
+
function useClickOutside(handler, ref) {
|
|
4
|
+
useEffect(() => {
|
|
5
|
+
function handleClick(event) {
|
|
6
|
+
if (!ref.current || ref.current.contains(event.target)) {
|
|
7
|
+
return;
|
|
8
|
+
}
|
|
9
|
+
handler(event);
|
|
10
|
+
}
|
|
11
|
+
// 在捕获阶段监听,以确保在事件被阻止传播之前触发
|
|
12
|
+
document.addEventListener('click', handleClick, true);
|
|
13
|
+
return () => {
|
|
14
|
+
document.removeEventListener('click', handleClick, true);
|
|
15
|
+
};
|
|
16
|
+
}, [handler, ref]);
|
|
17
|
+
}
|
|
18
|
+
export default useClickOutside;
|
|
@@ -36,6 +36,12 @@
|
|
|
36
36
|
.adm-virtual-input-content::-webkit-scrollbar {
|
|
37
37
|
display: none;
|
|
38
38
|
}
|
|
39
|
+
.adm-virtual-input-trap {
|
|
40
|
+
width: 10px;
|
|
41
|
+
height: 10px;
|
|
42
|
+
position: absolute;
|
|
43
|
+
opacity: 0;
|
|
44
|
+
}
|
|
39
45
|
.adm-virtual-input-placeholder {
|
|
40
46
|
display: block;
|
|
41
47
|
position: absolute;
|
|
@@ -66,10 +72,10 @@
|
|
|
66
72
|
left: 0;
|
|
67
73
|
z-index: 1;
|
|
68
74
|
}
|
|
69
|
-
.adm-virtual-input
|
|
75
|
+
.adm-virtual-input-focused {
|
|
70
76
|
outline: none;
|
|
71
77
|
}
|
|
72
|
-
.adm-virtual-input
|
|
78
|
+
.adm-virtual-input-focused .adm-virtual-input-caret {
|
|
73
79
|
animation-name: adm-caret-blink;
|
|
74
80
|
animation-duration: 1s;
|
|
75
81
|
animation-timing-function: linear;
|
|
@@ -6,6 +6,7 @@ import { withNativeProps } from '../../utils/native-props';
|
|
|
6
6
|
import { usePropsValue } from '../../utils/use-props-value';
|
|
7
7
|
import { mergeProp, mergeProps } from '../../utils/with-default-props';
|
|
8
8
|
import { useConfig } from '../config-provider';
|
|
9
|
+
import useClickOutside from './use-click-outside';
|
|
9
10
|
const classPrefix = 'adm-virtual-input';
|
|
10
11
|
const defaultProps = {
|
|
11
12
|
defaultValue: '',
|
|
@@ -33,13 +34,10 @@ export const VirtualInput = forwardRef((props, ref) => {
|
|
|
33
34
|
const touchMoveTimeoutRef = useRef();
|
|
34
35
|
const clearIcon = mergeProp(React.createElement(CloseCircleFill, null), componentConfig.clearIcon, props.clearIcon);
|
|
35
36
|
function scrollToEnd() {
|
|
36
|
-
const
|
|
37
|
-
if (!
|
|
38
|
-
if (document.activeElement !== root) {
|
|
37
|
+
const content = contentRef.current;
|
|
38
|
+
if (!content) {
|
|
39
39
|
return;
|
|
40
40
|
}
|
|
41
|
-
const content = contentRef.current;
|
|
42
|
-
if (!content) return;
|
|
43
41
|
content.scrollLeft = content.clientWidth;
|
|
44
42
|
}
|
|
45
43
|
useEffect(() => {
|
|
@@ -71,23 +69,29 @@ export const VirtualInput = forwardRef((props, ref) => {
|
|
|
71
69
|
useImperativeHandle(ref, () => ({
|
|
72
70
|
focus: () => {
|
|
73
71
|
var _a;
|
|
74
|
-
(_a =
|
|
72
|
+
(_a = contentRef.current) === null || _a === void 0 ? void 0 : _a.focus();
|
|
75
73
|
},
|
|
76
74
|
blur: () => {
|
|
77
75
|
var _a;
|
|
78
|
-
(_a =
|
|
76
|
+
(_a = contentRef.current) === null || _a === void 0 ? void 0 : _a.blur();
|
|
77
|
+
setBlur();
|
|
79
78
|
}
|
|
80
79
|
}));
|
|
81
|
-
function
|
|
80
|
+
function setFocus() {
|
|
82
81
|
var _a;
|
|
82
|
+
if (hasFocus) return;
|
|
83
83
|
setHasFocus(true);
|
|
84
84
|
(_a = mergedProps.onFocus) === null || _a === void 0 ? void 0 : _a.call(mergedProps);
|
|
85
85
|
}
|
|
86
|
-
function
|
|
86
|
+
function setBlur() {
|
|
87
87
|
var _a;
|
|
88
|
+
if (!hasFocus) return;
|
|
88
89
|
setHasFocus(false);
|
|
89
90
|
(_a = mergedProps.onBlur) === null || _a === void 0 ? void 0 : _a.call(mergedProps);
|
|
90
91
|
}
|
|
92
|
+
useClickOutside(() => {
|
|
93
|
+
setBlur();
|
|
94
|
+
}, rootRef);
|
|
91
95
|
const keyboard = mergedProps.keyboard;
|
|
92
96
|
const keyboardElement = keyboard && React.cloneElement(keyboard, {
|
|
93
97
|
onInput: v => {
|
|
@@ -115,26 +119,20 @@ export const VirtualInput = forwardRef((props, ref) => {
|
|
|
115
119
|
},
|
|
116
120
|
visible: hasFocus,
|
|
117
121
|
onClose: () => {
|
|
118
|
-
var _a, _b
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
// We will trigger blur on the child element instead
|
|
122
|
-
if (activeElement && ((_a = rootRef.current) === null || _a === void 0 ? void 0 : _a.contains(activeElement))) {
|
|
123
|
-
activeElement.blur();
|
|
124
|
-
} else {
|
|
125
|
-
(_b = rootRef.current) === null || _b === void 0 ? void 0 : _b.blur();
|
|
126
|
-
}
|
|
127
|
-
(_d = (_c = keyboard.props).onClose) === null || _d === void 0 ? void 0 : _d.call(_c);
|
|
122
|
+
var _a, _b;
|
|
123
|
+
setBlur();
|
|
124
|
+
(_b = (_a = keyboard.props).onClose) === null || _b === void 0 ? void 0 : _b.call(_a);
|
|
128
125
|
},
|
|
129
126
|
getContainer: null
|
|
130
127
|
});
|
|
131
128
|
// 点击输入框时,将光标置于最后
|
|
132
|
-
const setCaretPositionToEnd =
|
|
133
|
-
var _a, _b;
|
|
129
|
+
const setCaretPositionToEnd = e => {
|
|
130
|
+
var _a, _b, _c;
|
|
134
131
|
if (caretPosition !== value.length) {
|
|
135
132
|
setCaretPosition(value.length);
|
|
136
133
|
(_b = (_a = mergedProps.cursor) === null || _a === void 0 ? void 0 : _a.onMove) === null || _b === void 0 ? void 0 : _b.call(_a, value.length);
|
|
137
134
|
}
|
|
135
|
+
(_c = mergedProps.onClick) === null || _c === void 0 ? void 0 : _c.call(mergedProps, e);
|
|
138
136
|
};
|
|
139
137
|
// 点击单个字符时,根据点击位置置于字符前或后
|
|
140
138
|
const changeCaretPosition = index => e => {
|
|
@@ -203,23 +201,27 @@ export const VirtualInput = forwardRef((props, ref) => {
|
|
|
203
201
|
ref: rootRef,
|
|
204
202
|
className: classNames(classPrefix, {
|
|
205
203
|
[`${classPrefix}-disabled`]: mergedProps.disabled,
|
|
206
|
-
[`${classPrefix}-caret-dragging`]: isCaretDragging
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
role: 'textbox',
|
|
210
|
-
onFocus: onFocus,
|
|
211
|
-
onBlur: onBlur,
|
|
212
|
-
onClick: mergedProps.onClick
|
|
204
|
+
[`${classPrefix}-caret-dragging`]: isCaretDragging,
|
|
205
|
+
[`${classPrefix}-focused`]: hasFocus
|
|
206
|
+
})
|
|
213
207
|
}, React.createElement("div", {
|
|
214
208
|
className: `${classPrefix}-content`,
|
|
215
209
|
ref: contentRef,
|
|
216
210
|
"aria-disabled": mergedProps.disabled,
|
|
217
|
-
"aria-label": mergedProps.placeholder,
|
|
211
|
+
"aria-label": value || mergedProps.placeholder,
|
|
212
|
+
role: 'textbox',
|
|
213
|
+
tabIndex: mergedProps.disabled ? undefined : 0,
|
|
214
|
+
// note: 这里增加 onFocus 有两个目的:
|
|
215
|
+
// 1. 在安卓 talkback 模式下,role=textbox 的元素双击后只会触发 focus 而非 click
|
|
216
|
+
// 2. 处理 content 框点击、单个字符点击时,不用再额外处理 focus 逻辑,因为 focus 事件会先触发
|
|
217
|
+
onFocus: setFocus,
|
|
218
218
|
onClick: setCaretPositionToEnd,
|
|
219
219
|
onTouchStart: handleTouchStart,
|
|
220
220
|
onTouchMove: handleTouchMove,
|
|
221
221
|
onTouchEnd: handleTouchEnd
|
|
222
|
-
},
|
|
222
|
+
}, React.createElement("span", {
|
|
223
|
+
className: `${classPrefix}-trap`
|
|
224
|
+
}), chars.slice(0, caretPosition).map((i, index) => React.createElement("span", {
|
|
223
225
|
ref: index === 0 ? charRef : undefined,
|
|
224
226
|
key: index,
|
|
225
227
|
onClick: changeCaretPosition(index)
|