antd-mobile 5.40.0 → 5.41.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 +150 -16
- package/2x/bundle/antd-mobile.cjs.js +6 -6
- package/2x/bundle/antd-mobile.es.development.js +150 -16
- package/2x/bundle/antd-mobile.es.js +3983 -3914
- package/2x/bundle/antd-mobile.umd.development.js +150 -16
- package/2x/bundle/antd-mobile.umd.js +7 -7
- package/2x/bundle/style.css +4 -1
- package/2x/cjs/components/date-picker/date-picker-week-utils.js +2 -1
- package/2x/cjs/components/ellipsis/ellipsis.d.ts +3 -0
- package/2x/cjs/components/ellipsis/ellipsis.js +10 -2
- package/2x/cjs/components/swiper/swiper.js +1 -1
- package/2x/cjs/components/tabs/tabs.js +45 -13
- package/2x/cjs/components/virtual-input/virtual-input.css +4 -1
- package/2x/cjs/components/virtual-input/virtual-input.d.ts +6 -0
- package/2x/cjs/components/virtual-input/virtual-input.js +105 -8
- package/2x/es/components/date-picker/date-picker-week-utils.js +2 -1
- package/2x/es/components/ellipsis/ellipsis.d.ts +3 -0
- package/2x/es/components/ellipsis/ellipsis.js +10 -2
- package/2x/es/components/swiper/swiper.js +1 -1
- package/2x/es/components/tabs/tabs.js +44 -12
- package/2x/es/components/virtual-input/virtual-input.css +4 -1
- package/2x/es/components/virtual-input/virtual-input.d.ts +6 -0
- package/2x/es/components/virtual-input/virtual-input.js +105 -8
- package/2x/package.json +3 -3
- package/bundle/antd-mobile.cjs.development.js +150 -16
- package/bundle/antd-mobile.cjs.js +6 -6
- package/bundle/antd-mobile.compatible.umd.js +1 -1
- package/bundle/antd-mobile.es.development.js +150 -16
- package/bundle/antd-mobile.es.js +3983 -3914
- package/bundle/antd-mobile.umd.development.js +150 -16
- package/bundle/antd-mobile.umd.js +7 -7
- package/bundle/style.css +1 -1
- package/cjs/components/date-picker/date-picker-week-utils.js +2 -1
- package/cjs/components/ellipsis/ellipsis.d.ts +3 -0
- package/cjs/components/ellipsis/ellipsis.js +10 -2
- package/cjs/components/swiper/swiper.js +1 -1
- package/cjs/components/tabs/tabs.js +45 -13
- package/cjs/components/virtual-input/virtual-input.css +3 -1
- package/cjs/components/virtual-input/virtual-input.d.ts +6 -0
- package/cjs/components/virtual-input/virtual-input.js +105 -8
- package/es/components/date-picker/date-picker-week-utils.js +2 -1
- package/es/components/ellipsis/ellipsis.d.ts +3 -0
- package/es/components/ellipsis/ellipsis.js +10 -2
- package/es/components/swiper/swiper.js +1 -1
- package/es/components/tabs/tabs.js +44 -12
- package/es/components/virtual-input/virtual-input.css +3 -1
- package/es/components/virtual-input/virtual-input.d.ts +6 -0
- package/es/components/virtual-input/virtual-input.js +105 -8
- package/package.json +3 -3
- package/umd/antd-mobile.js +1 -1
- package/2x/cjs/components/ellipsis/~ellipsis.d.ts +0 -15
- package/2x/cjs/components/ellipsis/~ellipsis.js +0 -161
- package/2x/es/components/ellipsis/~ellipsis.d.ts +0 -15
- package/2x/es/components/ellipsis/~ellipsis.js +0 -151
- package/cjs/components/ellipsis/~ellipsis.d.ts +0 -15
- package/cjs/components/ellipsis/~ellipsis.js +0 -161
- package/es/components/ellipsis/~ellipsis.d.ts +0 -15
- package/es/components/ellipsis/~ellipsis.js +0 -151
package/2x/bundle/style.css
CHANGED
|
@@ -5751,7 +5751,6 @@ a.adm-list-item:active:not(.adm-list-item-disabled):after {
|
|
|
5751
5751
|
}
|
|
5752
5752
|
|
|
5753
5753
|
.adm-virtual-input:focus .adm-virtual-input-caret {
|
|
5754
|
-
display: block;
|
|
5755
5754
|
animation-name: adm-caret-blink;
|
|
5756
5755
|
animation-duration: 1s;
|
|
5757
5756
|
animation-timing-function: linear;
|
|
@@ -5762,6 +5761,10 @@ a.adm-list-item:active:not(.adm-list-item-disabled):after {
|
|
|
5762
5761
|
color: var(--disabled-color);
|
|
5763
5762
|
}
|
|
5764
5763
|
|
|
5764
|
+
.adm-virtual-input-caret-dragging .adm-virtual-input-caret {
|
|
5765
|
+
animation: none!important;
|
|
5766
|
+
}
|
|
5767
|
+
|
|
5765
5768
|
@keyframes adm-caret-blink {
|
|
5766
5769
|
0% {
|
|
5767
5770
|
opacity: 1;
|
|
@@ -100,6 +100,7 @@ function convertStringArrayToDate(value) {
|
|
|
100
100
|
const yearString = (_a = value[0]) !== null && _a !== void 0 ? _a : '1900';
|
|
101
101
|
const weekString = (_b = value[1]) !== null && _b !== void 0 ? _b : '1';
|
|
102
102
|
const weekdayString = (_c = value[2]) !== null && _c !== void 0 ? _c : '1';
|
|
103
|
-
|
|
103
|
+
// See https://github.com/ant-design/ant-design-mobile/issues/6905
|
|
104
|
+
const day = (0, _dayjs.default)(`${parseInt(yearString)}-01-04`).isoWeek(parseInt(weekString)).isoWeekday(parseInt(weekdayString)).hour(0).minute(0).second(0);
|
|
104
105
|
return day.toDate();
|
|
105
106
|
}
|
|
@@ -11,5 +11,8 @@ export declare type EllipsisProps = {
|
|
|
11
11
|
stopPropagationForActionButtons?: PropagationEvent[];
|
|
12
12
|
onContentClick?: (e: React.MouseEvent<HTMLDivElement, MouseEvent>) => void;
|
|
13
13
|
defaultExpanded?: boolean;
|
|
14
|
+
onExpand?: (expanded: boolean, info: {
|
|
15
|
+
event: React.MouseEvent<HTMLAnchorElement, MouseEvent>;
|
|
16
|
+
}) => void;
|
|
14
17
|
} & NativeProps;
|
|
15
18
|
export declare const Ellipsis: FC<EllipsisProps>;
|
|
@@ -39,13 +39,21 @@ const Ellipsis = p => {
|
|
|
39
39
|
// ========================== Expanded ==========================
|
|
40
40
|
const [expanded, setExpanded] = _react.default.useState(defaultExpanded);
|
|
41
41
|
const expandNode = expandText ? (0, _withStopPropagation.withStopPropagation)(stopPropagationForActionButtons, _react.default.createElement("a", {
|
|
42
|
-
onClick:
|
|
42
|
+
onClick: e => {
|
|
43
|
+
var _a;
|
|
43
44
|
setExpanded(true);
|
|
45
|
+
(_a = props.onExpand) === null || _a === void 0 ? void 0 : _a.call(props, true, {
|
|
46
|
+
event: e
|
|
47
|
+
});
|
|
44
48
|
}
|
|
45
49
|
}, expandText)) : null;
|
|
46
50
|
const collapseNode = collapseText ? (0, _withStopPropagation.withStopPropagation)(stopPropagationForActionButtons, _react.default.createElement("a", {
|
|
47
|
-
onClick:
|
|
51
|
+
onClick: e => {
|
|
52
|
+
var _a;
|
|
48
53
|
setExpanded(false);
|
|
54
|
+
(_a = props.onExpand) === null || _a === void 0 ? void 0 : _a.call(props, false, {
|
|
55
|
+
event: e
|
|
56
|
+
});
|
|
49
57
|
}
|
|
50
58
|
}, collapseText)) : null;
|
|
51
59
|
// ========================== Ellipsis ==========================
|
|
@@ -279,7 +279,7 @@ const Swiper = (0, _react.forwardRef)((0, _stagedComponents.staged)((p, ref) =>
|
|
|
279
279
|
return _react.default.createElement(_react.default.Fragment, null, _react.default.createElement("div", {
|
|
280
280
|
className: `${classPrefix}-slide-placeholder`,
|
|
281
281
|
style: {
|
|
282
|
-
width: `${startIndex * 100}%`
|
|
282
|
+
[isVertical ? 'height' : 'width']: `${startIndex * 100}%`
|
|
283
283
|
}
|
|
284
284
|
}), items);
|
|
285
285
|
}
|
|
@@ -4,22 +4,22 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.Tabs = exports.Tab = void 0;
|
|
7
|
-
var _react = _interopRequireWildcard(require("react"));
|
|
8
|
-
var _classnames = _interopRequireDefault(require("classnames"));
|
|
9
7
|
var _web = require("@react-spring/web");
|
|
10
|
-
var _nativeProps = require("../../utils/native-props");
|
|
11
|
-
var _usePropsValue = require("../../utils/use-props-value");
|
|
12
|
-
var _bound = require("../../utils/bound");
|
|
13
8
|
var _ahooks = require("ahooks");
|
|
9
|
+
var _classnames = _interopRequireDefault(require("classnames"));
|
|
10
|
+
var _react = _interopRequireWildcard(require("react"));
|
|
11
|
+
var _bound = require("../../utils/bound");
|
|
12
|
+
var _nativeProps = require("../../utils/native-props");
|
|
13
|
+
var _shouldRender = require("../../utils/should-render");
|
|
14
|
+
var _traverseReactNode = require("../../utils/traverse-react-node");
|
|
15
|
+
var _useIsomorphicUpdateLayoutEffect = require("../../utils/use-isomorphic-update-layout-effect");
|
|
14
16
|
var _useMutationEffect = require("../../utils/use-mutation-effect");
|
|
17
|
+
var _usePropsValue = require("../../utils/use-props-value");
|
|
15
18
|
var _useResizeEffect = require("../../utils/use-resize-effect");
|
|
16
19
|
var _withDefaultProps = require("../../utils/with-default-props");
|
|
17
|
-
var _useIsomorphicUpdateLayoutEffect = require("../../utils/use-isomorphic-update-layout-effect");
|
|
18
|
-
var _shouldRender = require("../../utils/should-render");
|
|
19
|
-
var _traverseReactNode = require("../../utils/traverse-react-node");
|
|
20
|
-
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
21
20
|
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); }
|
|
22
21
|
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; }
|
|
22
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
23
23
|
const classPrefix = `adm-tabs`;
|
|
24
24
|
const Tab = () => {
|
|
25
25
|
return null;
|
|
@@ -35,6 +35,7 @@ const Tabs = p => {
|
|
|
35
35
|
const props = (0, _withDefaultProps.mergeProps)(defaultProps, p);
|
|
36
36
|
const tabListContainerRef = (0, _react.useRef)(null);
|
|
37
37
|
const activeLineRef = (0, _react.useRef)(null);
|
|
38
|
+
const tabRefs = (0, _react.useRef)({});
|
|
38
39
|
const keyToIndexRecord = {};
|
|
39
40
|
let firstActiveKey = null;
|
|
40
41
|
const panes = [];
|
|
@@ -176,7 +177,7 @@ const Tabs = p => {
|
|
|
176
177
|
});
|
|
177
178
|
const {
|
|
178
179
|
run: updateMask
|
|
179
|
-
} = (0, _ahooks.useThrottleFn)(
|
|
180
|
+
} = (0, _ahooks.useThrottleFn)(immediate => {
|
|
180
181
|
const container = tabListContainerRef.current;
|
|
181
182
|
if (!container) return;
|
|
182
183
|
const scrollLeft = container.scrollLeft;
|
|
@@ -207,6 +208,34 @@ const Tabs = p => {
|
|
|
207
208
|
(0, _ahooks.useIsomorphicLayoutEffect)(() => {
|
|
208
209
|
updateMask(true);
|
|
209
210
|
}, []);
|
|
211
|
+
const handleKeyDown = e => {
|
|
212
|
+
const keys = Object.keys(keyToIndexRecord);
|
|
213
|
+
const currentIndex = keyToIndexRecord[activeKey];
|
|
214
|
+
const isNext = isRTL ? e.key === 'ArrowLeft' : e.key === 'ArrowRight';
|
|
215
|
+
const isPrev = isRTL ? e.key === 'ArrowRight' : e.key === 'ArrowLeft';
|
|
216
|
+
const offsetDirection = isNext ? 1 : -1;
|
|
217
|
+
const findNextEnabledTab = (startIndex, direction) => {
|
|
218
|
+
const length = keys.length;
|
|
219
|
+
for (let i = 0; i < length; i++) {
|
|
220
|
+
const index = (startIndex + direction * (i + 1) + length) % length;
|
|
221
|
+
const key = keys[index];
|
|
222
|
+
const pane = panes.find(p => p.key === key);
|
|
223
|
+
if (!(pane === null || pane === void 0 ? void 0 : pane.props.disabled)) return key;
|
|
224
|
+
}
|
|
225
|
+
return keys[startIndex];
|
|
226
|
+
};
|
|
227
|
+
const currentKey = findNextEnabledTab(currentIndex, offsetDirection);
|
|
228
|
+
if (isNext || isPrev) {
|
|
229
|
+
e.preventDefault();
|
|
230
|
+
setActiveKey(currentKey);
|
|
231
|
+
}
|
|
232
|
+
};
|
|
233
|
+
(0, _react.useEffect)(() => {
|
|
234
|
+
var _a;
|
|
235
|
+
if (activeKey && tabRefs.current[activeKey]) {
|
|
236
|
+
(_a = tabRefs.current[activeKey]) === null || _a === void 0 ? void 0 : _a.focus();
|
|
237
|
+
}
|
|
238
|
+
}, [activeKey]);
|
|
210
239
|
return (0, _nativeProps.withNativeProps)(props, _react.default.createElement("div", {
|
|
211
240
|
className: classPrefix,
|
|
212
241
|
style: {
|
|
@@ -229,6 +258,7 @@ const Tabs = p => {
|
|
|
229
258
|
ref: tabListContainerRef,
|
|
230
259
|
scrollLeft: scrollLeft,
|
|
231
260
|
onScroll: updateMask,
|
|
261
|
+
onKeyDown: handleKeyDown,
|
|
232
262
|
role: 'tablist'
|
|
233
263
|
}, _react.default.createElement(_web.animated.div, {
|
|
234
264
|
ref: activeLineRef,
|
|
@@ -243,6 +273,10 @@ const Tabs = p => {
|
|
|
243
273
|
[`${classPrefix}-tab-wrapper-stretch`]: props.stretch
|
|
244
274
|
})
|
|
245
275
|
}, _react.default.createElement("div", {
|
|
276
|
+
role: 'tab',
|
|
277
|
+
"aria-selected": pane.key === activeKey,
|
|
278
|
+
tabIndex: pane.key === activeKey ? 0 : -1,
|
|
279
|
+
ref: el => tabRefs.current[pane.key] = el,
|
|
246
280
|
onClick: () => {
|
|
247
281
|
const {
|
|
248
282
|
key
|
|
@@ -256,9 +290,7 @@ const Tabs = p => {
|
|
|
256
290
|
className: (0, _classnames.default)(`${classPrefix}-tab`, {
|
|
257
291
|
[`${classPrefix}-tab-active`]: pane.key === activeKey,
|
|
258
292
|
[`${classPrefix}-tab-disabled`]: pane.props.disabled
|
|
259
|
-
})
|
|
260
|
-
role: 'tab',
|
|
261
|
-
"aria-selected": pane.key === activeKey
|
|
293
|
+
})
|
|
262
294
|
}, pane.props.title)))))), panes.map(pane => {
|
|
263
295
|
if (pane.props.children === undefined) {
|
|
264
296
|
return null;
|
|
@@ -73,7 +73,6 @@
|
|
|
73
73
|
}
|
|
74
74
|
|
|
75
75
|
.adm-virtual-input:focus .adm-virtual-input-caret {
|
|
76
|
-
display: block;
|
|
77
76
|
animation-name: adm-caret-blink;
|
|
78
77
|
animation-duration: 1s;
|
|
79
78
|
animation-timing-function: linear;
|
|
@@ -84,6 +83,10 @@
|
|
|
84
83
|
color: var(--disabled-color);
|
|
85
84
|
}
|
|
86
85
|
|
|
86
|
+
.adm-virtual-input-caret-dragging .adm-virtual-input-caret {
|
|
87
|
+
animation: none !important;
|
|
88
|
+
}
|
|
89
|
+
|
|
87
90
|
@keyframes adm-caret-blink {
|
|
88
91
|
from {
|
|
89
92
|
opacity: 1;
|
|
@@ -3,6 +3,10 @@ import React from 'react';
|
|
|
3
3
|
import { NativeProps } from '../../utils/native-props';
|
|
4
4
|
import type { InputProps } from '../input';
|
|
5
5
|
import { NumberKeyboardProps } from '../number-keyboard';
|
|
6
|
+
export declare type Cursor = {
|
|
7
|
+
movable?: boolean;
|
|
8
|
+
onMove?: (position: number) => void;
|
|
9
|
+
};
|
|
6
10
|
export declare type VirtualInputProps = {
|
|
7
11
|
onFocus?: () => void;
|
|
8
12
|
onBlur?: () => void;
|
|
@@ -10,6 +14,7 @@ export declare type VirtualInputProps = {
|
|
|
10
14
|
keyboard?: ReactElement<NumberKeyboardProps>;
|
|
11
15
|
clearable?: boolean;
|
|
12
16
|
onClear?: () => void;
|
|
17
|
+
cursor?: Cursor;
|
|
13
18
|
} & Pick<InputProps, 'value' | 'onChange' | 'placeholder' | 'disabled' | 'clearIcon'> & NativeProps<'--font-size' | '--color' | '--placeholder-color' | '--disabled-color' | '--text-align' | '--caret-width' | '--caret-color'>;
|
|
14
19
|
export declare type VirtualInputRef = {
|
|
15
20
|
focus: () => void;
|
|
@@ -22,6 +27,7 @@ export declare const VirtualInput: React.ForwardRefExoticComponent<{
|
|
|
22
27
|
keyboard?: ReactElement<NumberKeyboardProps, string | React.JSXElementConstructor<any>> | undefined;
|
|
23
28
|
clearable?: boolean | undefined;
|
|
24
29
|
onClear?: (() => void) | undefined;
|
|
30
|
+
cursor?: Cursor | undefined;
|
|
25
31
|
} & Pick<InputProps, "value" | "onChange" | "disabled" | "placeholder" | "clearIcon"> & {
|
|
26
32
|
className?: string | undefined;
|
|
27
33
|
style?: (React.CSSProperties & Partial<Record<"--color" | "--font-size" | "--placeholder-color" | "--text-align" | "--disabled-color" | "--caret-width" | "--caret-color", string>>) | undefined;
|
|
@@ -17,7 +17,10 @@ function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj &&
|
|
|
17
17
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
18
18
|
const classPrefix = 'adm-virtual-input';
|
|
19
19
|
const defaultProps = {
|
|
20
|
-
defaultValue: ''
|
|
20
|
+
defaultValue: '',
|
|
21
|
+
cursor: {
|
|
22
|
+
movable: false
|
|
23
|
+
}
|
|
21
24
|
};
|
|
22
25
|
const VirtualInput = (0, _react.forwardRef)((props, ref) => {
|
|
23
26
|
const {
|
|
@@ -30,6 +33,13 @@ const VirtualInput = (0, _react.forwardRef)((props, ref) => {
|
|
|
30
33
|
const contentRef = (0, _react.useRef)(null);
|
|
31
34
|
const [hasFocus, setHasFocus] = (0, _react.useState)(false);
|
|
32
35
|
const [caretPosition, setCaretPosition] = (0, _react.useState)(value.length); // 光标位置,从 0 开始,如值是 2 则表示光标在顺序下标为 2 的数字之前
|
|
36
|
+
const keyboardDataRef = (0, _react.useRef)({}); // 临时记录虚拟键盘输入,在下次更新时用于判断光标位置如何调整
|
|
37
|
+
const touchDataRef = (0, _react.useRef)(); // 记录上一次 touch 时的坐标位置
|
|
38
|
+
const charRef = (0, _react.useRef)(null); // 第一个字符的 DOM
|
|
39
|
+
const charWidthRef = (0, _react.useRef)(0); // 单个字符宽度
|
|
40
|
+
const caretRef = (0, _react.useRef)(null); // 光标的 DOM
|
|
41
|
+
const [isCaretDragging, setIsCaretDragging] = (0, _react.useState)(false);
|
|
42
|
+
const touchMoveTimeoutRef = (0, _react.useRef)();
|
|
33
43
|
const clearIcon = (0, _withDefaultProps.mergeProp)(_react.default.createElement(_antdMobileIcons.CloseCircleFill, null), componentConfig.clearIcon, props.clearIcon);
|
|
34
44
|
function scrollToEnd() {
|
|
35
45
|
const root = rootRef.current;
|
|
@@ -41,6 +51,24 @@ const VirtualInput = (0, _react.forwardRef)((props, ref) => {
|
|
|
41
51
|
if (!content) return;
|
|
42
52
|
content.scrollLeft = content.clientWidth;
|
|
43
53
|
}
|
|
54
|
+
(0, _react.useEffect)(() => {
|
|
55
|
+
// 记录单个字符的宽度,用于光标移动时的计算
|
|
56
|
+
if (charRef.current) {
|
|
57
|
+
charWidthRef.current = charRef.current.getBoundingClientRect().width;
|
|
58
|
+
}
|
|
59
|
+
}, [value]);
|
|
60
|
+
(0, _react.useEffect)(() => {
|
|
61
|
+
// 经过外部受控逻辑后,再调整光标位置,如果受控逻辑改动了值则光标放到最后
|
|
62
|
+
if (value === keyboardDataRef.current.newValue) {
|
|
63
|
+
if (keyboardDataRef.current.mode === 'input') {
|
|
64
|
+
setCaretPosition(c => c + 1);
|
|
65
|
+
} else if (keyboardDataRef.current.mode === 'delete') {
|
|
66
|
+
setCaretPosition(c => c - 1);
|
|
67
|
+
}
|
|
68
|
+
} else {
|
|
69
|
+
setCaretPosition(value.length);
|
|
70
|
+
}
|
|
71
|
+
}, [value]);
|
|
44
72
|
(0, _ahooks.useIsomorphicLayoutEffect)(() => {
|
|
45
73
|
scrollToEnd();
|
|
46
74
|
}, [value]);
|
|
@@ -74,16 +102,24 @@ const VirtualInput = (0, _react.forwardRef)((props, ref) => {
|
|
|
74
102
|
onInput: v => {
|
|
75
103
|
var _a, _b;
|
|
76
104
|
const newValue = value.substring(0, caretPosition) + v + value.substring(caretPosition);
|
|
105
|
+
// 临时记录,用于后续光标位置
|
|
106
|
+
keyboardDataRef.current = {
|
|
107
|
+
newValue,
|
|
108
|
+
mode: 'input'
|
|
109
|
+
};
|
|
77
110
|
setValue(newValue);
|
|
78
|
-
setCaretPosition(c => c + 1);
|
|
79
111
|
(_b = (_a = keyboard.props).onInput) === null || _b === void 0 ? void 0 : _b.call(_a, v);
|
|
80
112
|
},
|
|
81
113
|
onDelete: () => {
|
|
82
114
|
var _a, _b;
|
|
83
115
|
if (caretPosition === 0) return;
|
|
84
116
|
const newValue = value.substring(0, caretPosition - 1) + value.substring(caretPosition);
|
|
117
|
+
// 临时记录,用于后续光标位置
|
|
118
|
+
keyboardDataRef.current = {
|
|
119
|
+
newValue,
|
|
120
|
+
mode: 'delete'
|
|
121
|
+
};
|
|
85
122
|
setValue(newValue);
|
|
86
|
-
setCaretPosition(caretPosition - 1);
|
|
87
123
|
(_b = (_a = keyboard.props).onDelete) === null || _b === void 0 ? void 0 : _b.call(_a);
|
|
88
124
|
},
|
|
89
125
|
visible: hasFocus,
|
|
@@ -103,23 +139,80 @@ const VirtualInput = (0, _react.forwardRef)((props, ref) => {
|
|
|
103
139
|
});
|
|
104
140
|
// 点击输入框时,将光标置于最后
|
|
105
141
|
const setCaretPositionToEnd = () => {
|
|
106
|
-
|
|
142
|
+
var _a, _b;
|
|
143
|
+
if (caretPosition !== value.length) {
|
|
144
|
+
setCaretPosition(value.length);
|
|
145
|
+
(_b = (_a = mergedProps.cursor) === null || _a === void 0 ? void 0 : _a.onMove) === null || _b === void 0 ? void 0 : _b.call(_a, value.length);
|
|
146
|
+
}
|
|
107
147
|
};
|
|
108
148
|
// 点击单个字符时,根据点击位置置于字符前或后
|
|
109
149
|
const changeCaretPosition = index => e => {
|
|
150
|
+
var _a, _b, _c;
|
|
151
|
+
if (mergedProps.disabled || !((_a = mergedProps.cursor) === null || _a === void 0 ? void 0 : _a.movable)) return;
|
|
110
152
|
e.stopPropagation();
|
|
111
153
|
const rect = e.target.getBoundingClientRect();
|
|
112
154
|
const midX = rect.left + rect.width / 2;
|
|
113
155
|
const clickX = e.clientX;
|
|
114
156
|
// 点击区域是否偏右
|
|
115
157
|
const isRight = clickX > midX;
|
|
116
|
-
|
|
158
|
+
const newCaretPosition = isRight ? index + 1 : index;
|
|
159
|
+
setCaretPosition(newCaretPosition);
|
|
160
|
+
(_c = (_b = mergedProps.cursor) === null || _b === void 0 ? void 0 : _b.onMove) === null || _c === void 0 ? void 0 : _c.call(_b, newCaretPosition);
|
|
161
|
+
};
|
|
162
|
+
// 在光标附近 touchmove 时也可以调整光标位置
|
|
163
|
+
const handleTouchStart = e => {
|
|
164
|
+
var _a;
|
|
165
|
+
if (mergedProps.disabled || !((_a = mergedProps.cursor) === null || _a === void 0 ? void 0 : _a.movable)) return;
|
|
166
|
+
if (!caretRef.current) return;
|
|
167
|
+
const touch = e.touches[0];
|
|
168
|
+
const caretRect = caretRef.current.getBoundingClientRect();
|
|
169
|
+
const distance = Math.abs(touch.clientX - (caretRect.left + caretRect.width / 2));
|
|
170
|
+
if (distance < 20) {
|
|
171
|
+
// 20px 阈值可调整
|
|
172
|
+
touchDataRef.current = {
|
|
173
|
+
startX: touch.clientX,
|
|
174
|
+
startCaretPosition: caretPosition
|
|
175
|
+
};
|
|
176
|
+
} else {
|
|
177
|
+
touchDataRef.current = null;
|
|
178
|
+
}
|
|
179
|
+
};
|
|
180
|
+
const handleTouchMove = e => {
|
|
181
|
+
var _a, _b, _c;
|
|
182
|
+
if (!touchDataRef.current || !((_a = mergedProps.cursor) === null || _a === void 0 ? void 0 : _a.movable)) return;
|
|
183
|
+
setIsCaretDragging(true);
|
|
184
|
+
const touch = e.touches[0];
|
|
185
|
+
const deltaX = touch.clientX - touchDataRef.current.startX;
|
|
186
|
+
const charWidth = charWidthRef.current;
|
|
187
|
+
const moveChars = Math.round(deltaX / charWidth);
|
|
188
|
+
let newCaretPosition = touchDataRef.current.startCaretPosition + moveChars;
|
|
189
|
+
// 边界处理
|
|
190
|
+
newCaretPosition = Math.max(0, Math.min(newCaretPosition, value.length));
|
|
191
|
+
setCaretPosition(newCaretPosition);
|
|
192
|
+
(_c = (_b = mergedProps.cursor) === null || _b === void 0 ? void 0 : _b.onMove) === null || _c === void 0 ? void 0 : _c.call(_b, newCaretPosition);
|
|
193
|
+
// 防止 touchend 不触发
|
|
194
|
+
if (touchMoveTimeoutRef.current) {
|
|
195
|
+
clearTimeout(touchMoveTimeoutRef.current);
|
|
196
|
+
}
|
|
197
|
+
touchMoveTimeoutRef.current = setTimeout(() => {
|
|
198
|
+
setIsCaretDragging(false);
|
|
199
|
+
touchMoveTimeoutRef.current = null;
|
|
200
|
+
}, 500);
|
|
201
|
+
};
|
|
202
|
+
const handleTouchEnd = () => {
|
|
203
|
+
touchDataRef.current = null;
|
|
204
|
+
setIsCaretDragging(false);
|
|
205
|
+
if (touchMoveTimeoutRef.current) {
|
|
206
|
+
clearTimeout(touchMoveTimeoutRef.current);
|
|
207
|
+
touchMoveTimeoutRef.current = null;
|
|
208
|
+
}
|
|
117
209
|
};
|
|
118
210
|
const chars = (value + '').split('');
|
|
119
211
|
return (0, _nativeProps.withNativeProps)(mergedProps, _react.default.createElement("div", {
|
|
120
212
|
ref: rootRef,
|
|
121
213
|
className: (0, _classnames.default)(classPrefix, {
|
|
122
|
-
[`${classPrefix}-disabled`]: mergedProps.disabled
|
|
214
|
+
[`${classPrefix}-disabled`]: mergedProps.disabled,
|
|
215
|
+
[`${classPrefix}-caret-dragging`]: isCaretDragging
|
|
123
216
|
}),
|
|
124
217
|
tabIndex: mergedProps.disabled ? undefined : 0,
|
|
125
218
|
role: 'textbox',
|
|
@@ -131,13 +224,18 @@ const VirtualInput = (0, _react.forwardRef)((props, ref) => {
|
|
|
131
224
|
ref: contentRef,
|
|
132
225
|
"aria-disabled": mergedProps.disabled,
|
|
133
226
|
"aria-label": mergedProps.placeholder,
|
|
134
|
-
onClick: setCaretPositionToEnd
|
|
227
|
+
onClick: setCaretPositionToEnd,
|
|
228
|
+
onTouchStart: handleTouchStart,
|
|
229
|
+
onTouchMove: handleTouchMove,
|
|
230
|
+
onTouchEnd: handleTouchEnd
|
|
135
231
|
}, chars.slice(0, caretPosition).map((i, index) => _react.default.createElement("span", {
|
|
232
|
+
ref: index === 0 ? charRef : undefined,
|
|
136
233
|
key: index,
|
|
137
234
|
onClick: changeCaretPosition(index)
|
|
138
235
|
}, i)), _react.default.createElement("div", {
|
|
139
236
|
className: `${classPrefix}-caret-container`
|
|
140
237
|
}, hasFocus && _react.default.createElement("div", {
|
|
238
|
+
ref: caretRef,
|
|
141
239
|
className: `${classPrefix}-caret`
|
|
142
240
|
})), chars.slice(caretPosition).map((i, index) => _react.default.createElement("span", {
|
|
143
241
|
key: index,
|
|
@@ -148,7 +246,6 @@ const VirtualInput = (0, _react.forwardRef)((props, ref) => {
|
|
|
148
246
|
var _a;
|
|
149
247
|
e.stopPropagation();
|
|
150
248
|
setValue('');
|
|
151
|
-
setCaretPosition(0);
|
|
152
249
|
(_a = mergedProps.onClear) === null || _a === void 0 ? void 0 : _a.call(mergedProps);
|
|
153
250
|
},
|
|
154
251
|
role: 'button',
|
|
@@ -91,6 +91,7 @@ export function convertStringArrayToDate(value) {
|
|
|
91
91
|
const yearString = (_a = value[0]) !== null && _a !== void 0 ? _a : '1900';
|
|
92
92
|
const weekString = (_b = value[1]) !== null && _b !== void 0 ? _b : '1';
|
|
93
93
|
const weekdayString = (_c = value[2]) !== null && _c !== void 0 ? _c : '1';
|
|
94
|
-
|
|
94
|
+
// See https://github.com/ant-design/ant-design-mobile/issues/6905
|
|
95
|
+
const day = dayjs(`${parseInt(yearString)}-01-04`).isoWeek(parseInt(weekString)).isoWeekday(parseInt(weekdayString)).hour(0).minute(0).second(0);
|
|
95
96
|
return day.toDate();
|
|
96
97
|
}
|
|
@@ -11,5 +11,8 @@ export declare type EllipsisProps = {
|
|
|
11
11
|
stopPropagationForActionButtons?: PropagationEvent[];
|
|
12
12
|
onContentClick?: (e: React.MouseEvent<HTMLDivElement, MouseEvent>) => void;
|
|
13
13
|
defaultExpanded?: boolean;
|
|
14
|
+
onExpand?: (expanded: boolean, info: {
|
|
15
|
+
event: React.MouseEvent<HTMLAnchorElement, MouseEvent>;
|
|
16
|
+
}) => void;
|
|
14
17
|
} & NativeProps;
|
|
15
18
|
export declare const Ellipsis: FC<EllipsisProps>;
|
|
@@ -32,13 +32,21 @@ export const Ellipsis = p => {
|
|
|
32
32
|
// ========================== Expanded ==========================
|
|
33
33
|
const [expanded, setExpanded] = React.useState(defaultExpanded);
|
|
34
34
|
const expandNode = expandText ? withStopPropagation(stopPropagationForActionButtons, React.createElement("a", {
|
|
35
|
-
onClick:
|
|
35
|
+
onClick: e => {
|
|
36
|
+
var _a;
|
|
36
37
|
setExpanded(true);
|
|
38
|
+
(_a = props.onExpand) === null || _a === void 0 ? void 0 : _a.call(props, true, {
|
|
39
|
+
event: e
|
|
40
|
+
});
|
|
37
41
|
}
|
|
38
42
|
}, expandText)) : null;
|
|
39
43
|
const collapseNode = collapseText ? withStopPropagation(stopPropagationForActionButtons, React.createElement("a", {
|
|
40
|
-
onClick:
|
|
44
|
+
onClick: e => {
|
|
45
|
+
var _a;
|
|
41
46
|
setExpanded(false);
|
|
47
|
+
(_a = props.onExpand) === null || _a === void 0 ? void 0 : _a.call(props, false, {
|
|
48
|
+
event: e
|
|
49
|
+
});
|
|
42
50
|
}
|
|
43
51
|
}, collapseText)) : null;
|
|
44
52
|
// ========================== Ellipsis ==========================
|
|
@@ -270,7 +270,7 @@ export const Swiper = forwardRef(staged((p, ref) => {
|
|
|
270
270
|
return React.createElement(React.Fragment, null, React.createElement("div", {
|
|
271
271
|
className: `${classPrefix}-slide-placeholder`,
|
|
272
272
|
style: {
|
|
273
|
-
width: `${startIndex * 100}%`
|
|
273
|
+
[isVertical ? 'height' : 'width']: `${startIndex * 100}%`
|
|
274
274
|
}
|
|
275
275
|
}), items);
|
|
276
276
|
}
|
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { animated, useSpring } from '@react-spring/web';
|
|
2
|
+
import { useIsomorphicLayoutEffect, useThrottleFn } from 'ahooks';
|
|
2
3
|
import classNames from 'classnames';
|
|
3
|
-
import {
|
|
4
|
-
import { withNativeProps } from '../../utils/native-props';
|
|
5
|
-
import { usePropsValue } from '../../utils/use-props-value';
|
|
4
|
+
import React, { isValidElement, useEffect, useRef } from 'react';
|
|
6
5
|
import { bound } from '../../utils/bound';
|
|
7
|
-
import {
|
|
6
|
+
import { withNativeProps } from '../../utils/native-props';
|
|
7
|
+
import { ShouldRender } from '../../utils/should-render';
|
|
8
|
+
import { traverseReactNode } from '../../utils/traverse-react-node';
|
|
9
|
+
import { useIsomorphicUpdateLayoutEffect } from '../../utils/use-isomorphic-update-layout-effect';
|
|
8
10
|
import { useMutationEffect } from '../../utils/use-mutation-effect';
|
|
11
|
+
import { usePropsValue } from '../../utils/use-props-value';
|
|
9
12
|
import { useResizeEffect } from '../../utils/use-resize-effect';
|
|
10
13
|
import { mergeProps } from '../../utils/with-default-props';
|
|
11
|
-
import { useIsomorphicUpdateLayoutEffect } from '../../utils/use-isomorphic-update-layout-effect';
|
|
12
|
-
import { ShouldRender } from '../../utils/should-render';
|
|
13
|
-
import { traverseReactNode } from '../../utils/traverse-react-node';
|
|
14
14
|
const classPrefix = `adm-tabs`;
|
|
15
15
|
export const Tab = () => {
|
|
16
16
|
return null;
|
|
@@ -25,6 +25,7 @@ export const Tabs = p => {
|
|
|
25
25
|
const props = mergeProps(defaultProps, p);
|
|
26
26
|
const tabListContainerRef = useRef(null);
|
|
27
27
|
const activeLineRef = useRef(null);
|
|
28
|
+
const tabRefs = useRef({});
|
|
28
29
|
const keyToIndexRecord = {};
|
|
29
30
|
let firstActiveKey = null;
|
|
30
31
|
const panes = [];
|
|
@@ -166,7 +167,7 @@ export const Tabs = p => {
|
|
|
166
167
|
});
|
|
167
168
|
const {
|
|
168
169
|
run: updateMask
|
|
169
|
-
} = useThrottleFn(
|
|
170
|
+
} = useThrottleFn(immediate => {
|
|
170
171
|
const container = tabListContainerRef.current;
|
|
171
172
|
if (!container) return;
|
|
172
173
|
const scrollLeft = container.scrollLeft;
|
|
@@ -197,6 +198,34 @@ export const Tabs = p => {
|
|
|
197
198
|
useIsomorphicLayoutEffect(() => {
|
|
198
199
|
updateMask(true);
|
|
199
200
|
}, []);
|
|
201
|
+
const handleKeyDown = e => {
|
|
202
|
+
const keys = Object.keys(keyToIndexRecord);
|
|
203
|
+
const currentIndex = keyToIndexRecord[activeKey];
|
|
204
|
+
const isNext = isRTL ? e.key === 'ArrowLeft' : e.key === 'ArrowRight';
|
|
205
|
+
const isPrev = isRTL ? e.key === 'ArrowRight' : e.key === 'ArrowLeft';
|
|
206
|
+
const offsetDirection = isNext ? 1 : -1;
|
|
207
|
+
const findNextEnabledTab = (startIndex, direction) => {
|
|
208
|
+
const length = keys.length;
|
|
209
|
+
for (let i = 0; i < length; i++) {
|
|
210
|
+
const index = (startIndex + direction * (i + 1) + length) % length;
|
|
211
|
+
const key = keys[index];
|
|
212
|
+
const pane = panes.find(p => p.key === key);
|
|
213
|
+
if (!(pane === null || pane === void 0 ? void 0 : pane.props.disabled)) return key;
|
|
214
|
+
}
|
|
215
|
+
return keys[startIndex];
|
|
216
|
+
};
|
|
217
|
+
const currentKey = findNextEnabledTab(currentIndex, offsetDirection);
|
|
218
|
+
if (isNext || isPrev) {
|
|
219
|
+
e.preventDefault();
|
|
220
|
+
setActiveKey(currentKey);
|
|
221
|
+
}
|
|
222
|
+
};
|
|
223
|
+
useEffect(() => {
|
|
224
|
+
var _a;
|
|
225
|
+
if (activeKey && tabRefs.current[activeKey]) {
|
|
226
|
+
(_a = tabRefs.current[activeKey]) === null || _a === void 0 ? void 0 : _a.focus();
|
|
227
|
+
}
|
|
228
|
+
}, [activeKey]);
|
|
200
229
|
return withNativeProps(props, React.createElement("div", {
|
|
201
230
|
className: classPrefix,
|
|
202
231
|
style: {
|
|
@@ -219,6 +248,7 @@ export const Tabs = p => {
|
|
|
219
248
|
ref: tabListContainerRef,
|
|
220
249
|
scrollLeft: scrollLeft,
|
|
221
250
|
onScroll: updateMask,
|
|
251
|
+
onKeyDown: handleKeyDown,
|
|
222
252
|
role: 'tablist'
|
|
223
253
|
}, React.createElement(animated.div, {
|
|
224
254
|
ref: activeLineRef,
|
|
@@ -233,6 +263,10 @@ export const Tabs = p => {
|
|
|
233
263
|
[`${classPrefix}-tab-wrapper-stretch`]: props.stretch
|
|
234
264
|
})
|
|
235
265
|
}, React.createElement("div", {
|
|
266
|
+
role: 'tab',
|
|
267
|
+
"aria-selected": pane.key === activeKey,
|
|
268
|
+
tabIndex: pane.key === activeKey ? 0 : -1,
|
|
269
|
+
ref: el => tabRefs.current[pane.key] = el,
|
|
236
270
|
onClick: () => {
|
|
237
271
|
const {
|
|
238
272
|
key
|
|
@@ -246,9 +280,7 @@ export const Tabs = p => {
|
|
|
246
280
|
className: classNames(`${classPrefix}-tab`, {
|
|
247
281
|
[`${classPrefix}-tab-active`]: pane.key === activeKey,
|
|
248
282
|
[`${classPrefix}-tab-disabled`]: pane.props.disabled
|
|
249
|
-
})
|
|
250
|
-
role: 'tab',
|
|
251
|
-
"aria-selected": pane.key === activeKey
|
|
283
|
+
})
|
|
252
284
|
}, pane.props.title)))))), panes.map(pane => {
|
|
253
285
|
if (pane.props.children === undefined) {
|
|
254
286
|
return null;
|
|
@@ -73,7 +73,6 @@
|
|
|
73
73
|
}
|
|
74
74
|
|
|
75
75
|
.adm-virtual-input:focus .adm-virtual-input-caret {
|
|
76
|
-
display: block;
|
|
77
76
|
animation-name: adm-caret-blink;
|
|
78
77
|
animation-duration: 1s;
|
|
79
78
|
animation-timing-function: linear;
|
|
@@ -84,6 +83,10 @@
|
|
|
84
83
|
color: var(--disabled-color);
|
|
85
84
|
}
|
|
86
85
|
|
|
86
|
+
.adm-virtual-input-caret-dragging .adm-virtual-input-caret {
|
|
87
|
+
animation: none !important;
|
|
88
|
+
}
|
|
89
|
+
|
|
87
90
|
@keyframes adm-caret-blink {
|
|
88
91
|
from {
|
|
89
92
|
opacity: 1;
|
|
@@ -3,6 +3,10 @@ import React from 'react';
|
|
|
3
3
|
import { NativeProps } from '../../utils/native-props';
|
|
4
4
|
import type { InputProps } from '../input';
|
|
5
5
|
import { NumberKeyboardProps } from '../number-keyboard';
|
|
6
|
+
export declare type Cursor = {
|
|
7
|
+
movable?: boolean;
|
|
8
|
+
onMove?: (position: number) => void;
|
|
9
|
+
};
|
|
6
10
|
export declare type VirtualInputProps = {
|
|
7
11
|
onFocus?: () => void;
|
|
8
12
|
onBlur?: () => void;
|
|
@@ -10,6 +14,7 @@ export declare type VirtualInputProps = {
|
|
|
10
14
|
keyboard?: ReactElement<NumberKeyboardProps>;
|
|
11
15
|
clearable?: boolean;
|
|
12
16
|
onClear?: () => void;
|
|
17
|
+
cursor?: Cursor;
|
|
13
18
|
} & Pick<InputProps, 'value' | 'onChange' | 'placeholder' | 'disabled' | 'clearIcon'> & NativeProps<'--font-size' | '--color' | '--placeholder-color' | '--disabled-color' | '--text-align' | '--caret-width' | '--caret-color'>;
|
|
14
19
|
export declare type VirtualInputRef = {
|
|
15
20
|
focus: () => void;
|
|
@@ -22,6 +27,7 @@ export declare const VirtualInput: React.ForwardRefExoticComponent<{
|
|
|
22
27
|
keyboard?: ReactElement<NumberKeyboardProps, string | React.JSXElementConstructor<any>> | undefined;
|
|
23
28
|
clearable?: boolean | undefined;
|
|
24
29
|
onClear?: (() => void) | undefined;
|
|
30
|
+
cursor?: Cursor | undefined;
|
|
25
31
|
} & Pick<InputProps, "value" | "onChange" | "disabled" | "placeholder" | "clearIcon"> & {
|
|
26
32
|
className?: string | undefined;
|
|
27
33
|
style?: (React.CSSProperties & Partial<Record<"--color" | "--font-size" | "--placeholder-color" | "--text-align" | "--disabled-color" | "--caret-width" | "--caret-color", string>>) | undefined;
|