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
|
@@ -8,7 +8,10 @@ import { mergeProp, mergeProps } from '../../utils/with-default-props';
|
|
|
8
8
|
import { useConfig } from '../config-provider';
|
|
9
9
|
const classPrefix = 'adm-virtual-input';
|
|
10
10
|
const defaultProps = {
|
|
11
|
-
defaultValue: ''
|
|
11
|
+
defaultValue: '',
|
|
12
|
+
cursor: {
|
|
13
|
+
movable: false
|
|
14
|
+
}
|
|
12
15
|
};
|
|
13
16
|
export const VirtualInput = forwardRef((props, ref) => {
|
|
14
17
|
const {
|
|
@@ -21,6 +24,13 @@ export const VirtualInput = forwardRef((props, ref) => {
|
|
|
21
24
|
const contentRef = useRef(null);
|
|
22
25
|
const [hasFocus, setHasFocus] = useState(false);
|
|
23
26
|
const [caretPosition, setCaretPosition] = useState(value.length); // 光标位置,从 0 开始,如值是 2 则表示光标在顺序下标为 2 的数字之前
|
|
27
|
+
const keyboardDataRef = useRef({}); // 临时记录虚拟键盘输入,在下次更新时用于判断光标位置如何调整
|
|
28
|
+
const touchDataRef = useRef(); // 记录上一次 touch 时的坐标位置
|
|
29
|
+
const charRef = useRef(null); // 第一个字符的 DOM
|
|
30
|
+
const charWidthRef = useRef(0); // 单个字符宽度
|
|
31
|
+
const caretRef = useRef(null); // 光标的 DOM
|
|
32
|
+
const [isCaretDragging, setIsCaretDragging] = useState(false);
|
|
33
|
+
const touchMoveTimeoutRef = useRef();
|
|
24
34
|
const clearIcon = mergeProp(React.createElement(CloseCircleFill, null), componentConfig.clearIcon, props.clearIcon);
|
|
25
35
|
function scrollToEnd() {
|
|
26
36
|
const root = rootRef.current;
|
|
@@ -32,6 +42,24 @@ export const VirtualInput = forwardRef((props, ref) => {
|
|
|
32
42
|
if (!content) return;
|
|
33
43
|
content.scrollLeft = content.clientWidth;
|
|
34
44
|
}
|
|
45
|
+
useEffect(() => {
|
|
46
|
+
// 记录单个字符的宽度,用于光标移动时的计算
|
|
47
|
+
if (charRef.current) {
|
|
48
|
+
charWidthRef.current = charRef.current.getBoundingClientRect().width;
|
|
49
|
+
}
|
|
50
|
+
}, [value]);
|
|
51
|
+
useEffect(() => {
|
|
52
|
+
// 经过外部受控逻辑后,再调整光标位置,如果受控逻辑改动了值则光标放到最后
|
|
53
|
+
if (value === keyboardDataRef.current.newValue) {
|
|
54
|
+
if (keyboardDataRef.current.mode === 'input') {
|
|
55
|
+
setCaretPosition(c => c + 1);
|
|
56
|
+
} else if (keyboardDataRef.current.mode === 'delete') {
|
|
57
|
+
setCaretPosition(c => c - 1);
|
|
58
|
+
}
|
|
59
|
+
} else {
|
|
60
|
+
setCaretPosition(value.length);
|
|
61
|
+
}
|
|
62
|
+
}, [value]);
|
|
35
63
|
useIsomorphicLayoutEffect(() => {
|
|
36
64
|
scrollToEnd();
|
|
37
65
|
}, [value]);
|
|
@@ -65,16 +93,24 @@ export const VirtualInput = forwardRef((props, ref) => {
|
|
|
65
93
|
onInput: v => {
|
|
66
94
|
var _a, _b;
|
|
67
95
|
const newValue = value.substring(0, caretPosition) + v + value.substring(caretPosition);
|
|
96
|
+
// 临时记录,用于后续光标位置
|
|
97
|
+
keyboardDataRef.current = {
|
|
98
|
+
newValue,
|
|
99
|
+
mode: 'input'
|
|
100
|
+
};
|
|
68
101
|
setValue(newValue);
|
|
69
|
-
setCaretPosition(c => c + 1);
|
|
70
102
|
(_b = (_a = keyboard.props).onInput) === null || _b === void 0 ? void 0 : _b.call(_a, v);
|
|
71
103
|
},
|
|
72
104
|
onDelete: () => {
|
|
73
105
|
var _a, _b;
|
|
74
106
|
if (caretPosition === 0) return;
|
|
75
107
|
const newValue = value.substring(0, caretPosition - 1) + value.substring(caretPosition);
|
|
108
|
+
// 临时记录,用于后续光标位置
|
|
109
|
+
keyboardDataRef.current = {
|
|
110
|
+
newValue,
|
|
111
|
+
mode: 'delete'
|
|
112
|
+
};
|
|
76
113
|
setValue(newValue);
|
|
77
|
-
setCaretPosition(caretPosition - 1);
|
|
78
114
|
(_b = (_a = keyboard.props).onDelete) === null || _b === void 0 ? void 0 : _b.call(_a);
|
|
79
115
|
},
|
|
80
116
|
visible: hasFocus,
|
|
@@ -94,23 +130,80 @@ export const VirtualInput = forwardRef((props, ref) => {
|
|
|
94
130
|
});
|
|
95
131
|
// 点击输入框时,将光标置于最后
|
|
96
132
|
const setCaretPositionToEnd = () => {
|
|
97
|
-
|
|
133
|
+
var _a, _b;
|
|
134
|
+
if (caretPosition !== value.length) {
|
|
135
|
+
setCaretPosition(value.length);
|
|
136
|
+
(_b = (_a = mergedProps.cursor) === null || _a === void 0 ? void 0 : _a.onMove) === null || _b === void 0 ? void 0 : _b.call(_a, value.length);
|
|
137
|
+
}
|
|
98
138
|
};
|
|
99
139
|
// 点击单个字符时,根据点击位置置于字符前或后
|
|
100
140
|
const changeCaretPosition = index => e => {
|
|
141
|
+
var _a, _b, _c;
|
|
142
|
+
if (mergedProps.disabled || !((_a = mergedProps.cursor) === null || _a === void 0 ? void 0 : _a.movable)) return;
|
|
101
143
|
e.stopPropagation();
|
|
102
144
|
const rect = e.target.getBoundingClientRect();
|
|
103
145
|
const midX = rect.left + rect.width / 2;
|
|
104
146
|
const clickX = e.clientX;
|
|
105
147
|
// 点击区域是否偏右
|
|
106
148
|
const isRight = clickX > midX;
|
|
107
|
-
|
|
149
|
+
const newCaretPosition = isRight ? index + 1 : index;
|
|
150
|
+
setCaretPosition(newCaretPosition);
|
|
151
|
+
(_c = (_b = mergedProps.cursor) === null || _b === void 0 ? void 0 : _b.onMove) === null || _c === void 0 ? void 0 : _c.call(_b, newCaretPosition);
|
|
152
|
+
};
|
|
153
|
+
// 在光标附近 touchmove 时也可以调整光标位置
|
|
154
|
+
const handleTouchStart = e => {
|
|
155
|
+
var _a;
|
|
156
|
+
if (mergedProps.disabled || !((_a = mergedProps.cursor) === null || _a === void 0 ? void 0 : _a.movable)) return;
|
|
157
|
+
if (!caretRef.current) return;
|
|
158
|
+
const touch = e.touches[0];
|
|
159
|
+
const caretRect = caretRef.current.getBoundingClientRect();
|
|
160
|
+
const distance = Math.abs(touch.clientX - (caretRect.left + caretRect.width / 2));
|
|
161
|
+
if (distance < 20) {
|
|
162
|
+
// 20px 阈值可调整
|
|
163
|
+
touchDataRef.current = {
|
|
164
|
+
startX: touch.clientX,
|
|
165
|
+
startCaretPosition: caretPosition
|
|
166
|
+
};
|
|
167
|
+
} else {
|
|
168
|
+
touchDataRef.current = null;
|
|
169
|
+
}
|
|
170
|
+
};
|
|
171
|
+
const handleTouchMove = e => {
|
|
172
|
+
var _a, _b, _c;
|
|
173
|
+
if (!touchDataRef.current || !((_a = mergedProps.cursor) === null || _a === void 0 ? void 0 : _a.movable)) return;
|
|
174
|
+
setIsCaretDragging(true);
|
|
175
|
+
const touch = e.touches[0];
|
|
176
|
+
const deltaX = touch.clientX - touchDataRef.current.startX;
|
|
177
|
+
const charWidth = charWidthRef.current;
|
|
178
|
+
const moveChars = Math.round(deltaX / charWidth);
|
|
179
|
+
let newCaretPosition = touchDataRef.current.startCaretPosition + moveChars;
|
|
180
|
+
// 边界处理
|
|
181
|
+
newCaretPosition = Math.max(0, Math.min(newCaretPosition, value.length));
|
|
182
|
+
setCaretPosition(newCaretPosition);
|
|
183
|
+
(_c = (_b = mergedProps.cursor) === null || _b === void 0 ? void 0 : _b.onMove) === null || _c === void 0 ? void 0 : _c.call(_b, newCaretPosition);
|
|
184
|
+
// 防止 touchend 不触发
|
|
185
|
+
if (touchMoveTimeoutRef.current) {
|
|
186
|
+
clearTimeout(touchMoveTimeoutRef.current);
|
|
187
|
+
}
|
|
188
|
+
touchMoveTimeoutRef.current = setTimeout(() => {
|
|
189
|
+
setIsCaretDragging(false);
|
|
190
|
+
touchMoveTimeoutRef.current = null;
|
|
191
|
+
}, 500);
|
|
192
|
+
};
|
|
193
|
+
const handleTouchEnd = () => {
|
|
194
|
+
touchDataRef.current = null;
|
|
195
|
+
setIsCaretDragging(false);
|
|
196
|
+
if (touchMoveTimeoutRef.current) {
|
|
197
|
+
clearTimeout(touchMoveTimeoutRef.current);
|
|
198
|
+
touchMoveTimeoutRef.current = null;
|
|
199
|
+
}
|
|
108
200
|
};
|
|
109
201
|
const chars = (value + '').split('');
|
|
110
202
|
return withNativeProps(mergedProps, React.createElement("div", {
|
|
111
203
|
ref: rootRef,
|
|
112
204
|
className: classNames(classPrefix, {
|
|
113
|
-
[`${classPrefix}-disabled`]: mergedProps.disabled
|
|
205
|
+
[`${classPrefix}-disabled`]: mergedProps.disabled,
|
|
206
|
+
[`${classPrefix}-caret-dragging`]: isCaretDragging
|
|
114
207
|
}),
|
|
115
208
|
tabIndex: mergedProps.disabled ? undefined : 0,
|
|
116
209
|
role: 'textbox',
|
|
@@ -122,13 +215,18 @@ export const VirtualInput = forwardRef((props, ref) => {
|
|
|
122
215
|
ref: contentRef,
|
|
123
216
|
"aria-disabled": mergedProps.disabled,
|
|
124
217
|
"aria-label": mergedProps.placeholder,
|
|
125
|
-
onClick: setCaretPositionToEnd
|
|
218
|
+
onClick: setCaretPositionToEnd,
|
|
219
|
+
onTouchStart: handleTouchStart,
|
|
220
|
+
onTouchMove: handleTouchMove,
|
|
221
|
+
onTouchEnd: handleTouchEnd
|
|
126
222
|
}, chars.slice(0, caretPosition).map((i, index) => React.createElement("span", {
|
|
223
|
+
ref: index === 0 ? charRef : undefined,
|
|
127
224
|
key: index,
|
|
128
225
|
onClick: changeCaretPosition(index)
|
|
129
226
|
}, i)), React.createElement("div", {
|
|
130
227
|
className: `${classPrefix}-caret-container`
|
|
131
228
|
}, hasFocus && React.createElement("div", {
|
|
229
|
+
ref: caretRef,
|
|
132
230
|
className: `${classPrefix}-caret`
|
|
133
231
|
})), chars.slice(caretPosition).map((i, index) => React.createElement("span", {
|
|
134
232
|
key: index,
|
|
@@ -139,7 +237,6 @@ export const VirtualInput = forwardRef((props, ref) => {
|
|
|
139
237
|
var _a;
|
|
140
238
|
e.stopPropagation();
|
|
141
239
|
setValue('');
|
|
142
|
-
setCaretPosition(0);
|
|
143
240
|
(_a = mergedProps.onClear) === null || _a === void 0 ? void 0 : _a.call(mergedProps);
|
|
144
241
|
},
|
|
145
242
|
role: 'button',
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "antd-mobile",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.41.0-alpha.0",
|
|
4
4
|
"homepage": "https://github.com/ant-design/ant-design-mobile#readme",
|
|
5
5
|
"bugs": {
|
|
6
6
|
"url": "https://github.com/ant-design/ant-design-mobile/issues"
|
|
@@ -53,8 +53,8 @@
|
|
|
53
53
|
"use-sync-external-store": "^1.2.0"
|
|
54
54
|
},
|
|
55
55
|
"peerDependencies": {
|
|
56
|
-
"react": "^16.8.0 || ^17.0.0 || ^18.0.0",
|
|
57
|
-
"react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0"
|
|
56
|
+
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
|
|
57
|
+
"react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
|
|
58
58
|
},
|
|
59
59
|
"GravityCDN": "./umd/antd-mobile.js",
|
|
60
60
|
"size-limit": [
|