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.
Files changed (58) hide show
  1. package/2x/bundle/antd-mobile.cjs.development.js +150 -16
  2. package/2x/bundle/antd-mobile.cjs.js +6 -6
  3. package/2x/bundle/antd-mobile.es.development.js +150 -16
  4. package/2x/bundle/antd-mobile.es.js +3983 -3914
  5. package/2x/bundle/antd-mobile.umd.development.js +150 -16
  6. package/2x/bundle/antd-mobile.umd.js +7 -7
  7. package/2x/bundle/style.css +4 -1
  8. package/2x/cjs/components/date-picker/date-picker-week-utils.js +2 -1
  9. package/2x/cjs/components/ellipsis/ellipsis.d.ts +3 -0
  10. package/2x/cjs/components/ellipsis/ellipsis.js +10 -2
  11. package/2x/cjs/components/swiper/swiper.js +1 -1
  12. package/2x/cjs/components/tabs/tabs.js +45 -13
  13. package/2x/cjs/components/virtual-input/virtual-input.css +4 -1
  14. package/2x/cjs/components/virtual-input/virtual-input.d.ts +6 -0
  15. package/2x/cjs/components/virtual-input/virtual-input.js +105 -8
  16. package/2x/es/components/date-picker/date-picker-week-utils.js +2 -1
  17. package/2x/es/components/ellipsis/ellipsis.d.ts +3 -0
  18. package/2x/es/components/ellipsis/ellipsis.js +10 -2
  19. package/2x/es/components/swiper/swiper.js +1 -1
  20. package/2x/es/components/tabs/tabs.js +44 -12
  21. package/2x/es/components/virtual-input/virtual-input.css +4 -1
  22. package/2x/es/components/virtual-input/virtual-input.d.ts +6 -0
  23. package/2x/es/components/virtual-input/virtual-input.js +105 -8
  24. package/2x/package.json +3 -3
  25. package/bundle/antd-mobile.cjs.development.js +150 -16
  26. package/bundle/antd-mobile.cjs.js +6 -6
  27. package/bundle/antd-mobile.compatible.umd.js +1 -1
  28. package/bundle/antd-mobile.es.development.js +150 -16
  29. package/bundle/antd-mobile.es.js +3983 -3914
  30. package/bundle/antd-mobile.umd.development.js +150 -16
  31. package/bundle/antd-mobile.umd.js +7 -7
  32. package/bundle/style.css +1 -1
  33. package/cjs/components/date-picker/date-picker-week-utils.js +2 -1
  34. package/cjs/components/ellipsis/ellipsis.d.ts +3 -0
  35. package/cjs/components/ellipsis/ellipsis.js +10 -2
  36. package/cjs/components/swiper/swiper.js +1 -1
  37. package/cjs/components/tabs/tabs.js +45 -13
  38. package/cjs/components/virtual-input/virtual-input.css +3 -1
  39. package/cjs/components/virtual-input/virtual-input.d.ts +6 -0
  40. package/cjs/components/virtual-input/virtual-input.js +105 -8
  41. package/es/components/date-picker/date-picker-week-utils.js +2 -1
  42. package/es/components/ellipsis/ellipsis.d.ts +3 -0
  43. package/es/components/ellipsis/ellipsis.js +10 -2
  44. package/es/components/swiper/swiper.js +1 -1
  45. package/es/components/tabs/tabs.js +44 -12
  46. package/es/components/virtual-input/virtual-input.css +3 -1
  47. package/es/components/virtual-input/virtual-input.d.ts +6 -0
  48. package/es/components/virtual-input/virtual-input.js +105 -8
  49. package/package.json +3 -3
  50. package/umd/antd-mobile.js +1 -1
  51. package/2x/cjs/components/ellipsis/~ellipsis.d.ts +0 -15
  52. package/2x/cjs/components/ellipsis/~ellipsis.js +0 -161
  53. package/2x/es/components/ellipsis/~ellipsis.d.ts +0 -15
  54. package/2x/es/components/ellipsis/~ellipsis.js +0 -151
  55. package/cjs/components/ellipsis/~ellipsis.d.ts +0 -15
  56. package/cjs/components/ellipsis/~ellipsis.js +0 -161
  57. package/es/components/ellipsis/~ellipsis.d.ts +0 -15
  58. 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
- setCaretPosition(value.length);
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
- setCaretPosition(isRight ? index + 1 : index);
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/2x/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "antd-mobile",
3
- "version": "5.40.0",
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": [
@@ -12250,6 +12250,7 @@ const Tabs$1 = (p) => {
12250
12250
  const props = mergeProps(defaultProps$S, p);
12251
12251
  const tabListContainerRef = React$2.useRef(null);
12252
12252
  const activeLineRef = React$2.useRef(null);
12253
+ const tabRefs = React$2.useRef({});
12253
12254
  const keyToIndexRecord = {};
12254
12255
  let firstActiveKey = null;
12255
12256
  const panes = [];
@@ -12389,7 +12390,7 @@ const Tabs$1 = (p) => {
12389
12390
  });
12390
12391
  const {
12391
12392
  run: updateMask
12392
- } = useThrottleFn((immediate = false) => {
12393
+ } = useThrottleFn((immediate) => {
12393
12394
  const container = tabListContainerRef.current;
12394
12395
  if (!container)
12395
12396
  return;
@@ -12416,6 +12417,35 @@ const Tabs$1 = (p) => {
12416
12417
  useIsomorphicLayoutEffect$3(() => {
12417
12418
  updateMask(true);
12418
12419
  }, []);
12420
+ const handleKeyDown = (e2) => {
12421
+ const keys2 = Object.keys(keyToIndexRecord);
12422
+ const currentIndex = keyToIndexRecord[activeKey];
12423
+ const isNext = isRTL2 ? e2.key === "ArrowLeft" : e2.key === "ArrowRight";
12424
+ const isPrev = isRTL2 ? e2.key === "ArrowRight" : e2.key === "ArrowLeft";
12425
+ const offsetDirection = isNext ? 1 : -1;
12426
+ const findNextEnabledTab = (startIndex, direction) => {
12427
+ const length = keys2.length;
12428
+ for (let i2 = 0; i2 < length; i2++) {
12429
+ const index2 = (startIndex + direction * (i2 + 1) + length) % length;
12430
+ const key = keys2[index2];
12431
+ const pane = panes.find((p2) => p2.key === key);
12432
+ if (!(pane === null || pane === void 0 ? void 0 : pane.props.disabled))
12433
+ return key;
12434
+ }
12435
+ return keys2[startIndex];
12436
+ };
12437
+ const currentKey = findNextEnabledTab(currentIndex, offsetDirection);
12438
+ if (isNext || isPrev) {
12439
+ e2.preventDefault();
12440
+ setActiveKey(currentKey);
12441
+ }
12442
+ };
12443
+ React$2.useEffect(() => {
12444
+ var _a2;
12445
+ if (activeKey && tabRefs.current[activeKey]) {
12446
+ (_a2 = tabRefs.current[activeKey]) === null || _a2 === void 0 ? void 0 : _a2.focus();
12447
+ }
12448
+ }, [activeKey]);
12419
12449
  return withNativeProps(props, React$2.createElement("div", {
12420
12450
  className: classPrefix$15,
12421
12451
  style: {
@@ -12438,6 +12468,7 @@ const Tabs$1 = (p) => {
12438
12468
  ref: tabListContainerRef,
12439
12469
  scrollLeft,
12440
12470
  onScroll: updateMask,
12471
+ onKeyDown: handleKeyDown,
12441
12472
  role: "tablist"
12442
12473
  }, React$2.createElement(animated.div, {
12443
12474
  ref: activeLineRef,
@@ -12452,6 +12483,10 @@ const Tabs$1 = (p) => {
12452
12483
  [`${classPrefix$15}-tab-wrapper-stretch`]: props.stretch
12453
12484
  })
12454
12485
  }, React$2.createElement("div", {
12486
+ role: "tab",
12487
+ "aria-selected": pane.key === activeKey,
12488
+ tabIndex: pane.key === activeKey ? 0 : -1,
12489
+ ref: (el) => tabRefs.current[pane.key] = el,
12455
12490
  onClick: () => {
12456
12491
  const {
12457
12492
  key
@@ -12466,9 +12501,7 @@ const Tabs$1 = (p) => {
12466
12501
  className: classNames(`${classPrefix$15}-tab`, {
12467
12502
  [`${classPrefix$15}-tab-active`]: pane.key === activeKey,
12468
12503
  [`${classPrefix$15}-tab-disabled`]: pane.props.disabled
12469
- }),
12470
- role: "tab",
12471
- "aria-selected": pane.key === activeKey
12504
+ })
12472
12505
  }, pane.props.title)))))), panes.map((pane) => {
12473
12506
  if (pane.props.children === void 0) {
12474
12507
  return null;
@@ -13856,7 +13889,7 @@ function convertStringArrayToDate$1(value) {
13856
13889
  const yearString = (_a = value[0]) !== null && _a !== void 0 ? _a : "1900";
13857
13890
  const weekString = (_b = value[1]) !== null && _b !== void 0 ? _b : "1";
13858
13891
  const weekdayString = (_c = value[2]) !== null && _c !== void 0 ? _c : "1";
13859
- const day = dayjs(`${parseInt(yearString)}-01-01`).isoWeek(parseInt(weekString)).isoWeekday(parseInt(weekdayString)).hour(0).minute(0).second(0);
13892
+ const day = dayjs(`${parseInt(yearString)}-01-04`).isoWeek(parseInt(weekString)).isoWeekday(parseInt(weekdayString)).hour(0).minute(0).second(0);
13860
13893
  return day.toDate();
13861
13894
  }
13862
13895
  const precisionLengthRecord = {
@@ -14583,13 +14616,21 @@ const Ellipsis = (p) => {
14583
14616
  const rootRef = React$2.useRef(null);
14584
14617
  const [expanded, setExpanded] = React$2.useState(defaultExpanded);
14585
14618
  const expandNode = expandText ? withStopPropagation(stopPropagationForActionButtons, React$2.createElement("a", {
14586
- onClick: () => {
14619
+ onClick: (e2) => {
14620
+ var _a;
14587
14621
  setExpanded(true);
14622
+ (_a = props.onExpand) === null || _a === void 0 ? void 0 : _a.call(props, true, {
14623
+ event: e2
14624
+ });
14588
14625
  }
14589
14626
  }, expandText)) : null;
14590
14627
  const collapseNode = collapseText ? withStopPropagation(stopPropagationForActionButtons, React$2.createElement("a", {
14591
- onClick: () => {
14628
+ onClick: (e2) => {
14629
+ var _a;
14592
14630
  setExpanded(false);
14631
+ (_a = props.onExpand) === null || _a === void 0 ? void 0 : _a.call(props, false, {
14632
+ event: e2
14633
+ });
14593
14634
  }
14594
14635
  }, collapseText)) : null;
14595
14636
  const [measureNodes, forceResize] = useMeasure(rootRef, content, rows, direction, expanded, expandNode, collapseNode);
@@ -26606,7 +26647,7 @@ const Swiper = React$2.forwardRef(staged_1((p, ref2) => {
26606
26647
  return React$2.createElement(React$2.Fragment, null, React$2.createElement("div", {
26607
26648
  className: `${classPrefix$a}-slide-placeholder`,
26608
26649
  style: {
26609
- width: `${startIndex * 100}%`
26650
+ [isVertical ? "height" : "width"]: `${startIndex * 100}%`
26610
26651
  }
26611
26652
  }), items);
26612
26653
  }
@@ -27477,7 +27518,10 @@ const index = attachPropertiesToComponent(TreeSelect, {
27477
27518
  });
27478
27519
  const classPrefix$2 = "adm-virtual-input";
27479
27520
  const defaultProps$2 = {
27480
- defaultValue: ""
27521
+ defaultValue: "",
27522
+ cursor: {
27523
+ movable: false
27524
+ }
27481
27525
  };
27482
27526
  const VirtualInput = React$2.forwardRef((props, ref2) => {
27483
27527
  const {
@@ -27490,6 +27534,13 @@ const VirtualInput = React$2.forwardRef((props, ref2) => {
27490
27534
  const contentRef = React$2.useRef(null);
27491
27535
  const [hasFocus, setHasFocus] = React$2.useState(false);
27492
27536
  const [caretPosition, setCaretPosition] = React$2.useState(value.length);
27537
+ const keyboardDataRef = React$2.useRef({});
27538
+ const touchDataRef = React$2.useRef();
27539
+ const charRef = React$2.useRef(null);
27540
+ const charWidthRef = React$2.useRef(0);
27541
+ const caretRef = React$2.useRef(null);
27542
+ const [isCaretDragging, setIsCaretDragging] = React$2.useState(false);
27543
+ const touchMoveTimeoutRef = React$2.useRef();
27493
27544
  const clearIcon = mergeProp(React$2.createElement(CloseCircleFill, null), componentConfig.clearIcon, props.clearIcon);
27494
27545
  function scrollToEnd() {
27495
27546
  const root2 = rootRef.current;
@@ -27503,6 +27554,22 @@ const VirtualInput = React$2.forwardRef((props, ref2) => {
27503
27554
  return;
27504
27555
  content.scrollLeft = content.clientWidth;
27505
27556
  }
27557
+ React$2.useEffect(() => {
27558
+ if (charRef.current) {
27559
+ charWidthRef.current = charRef.current.getBoundingClientRect().width;
27560
+ }
27561
+ }, [value]);
27562
+ React$2.useEffect(() => {
27563
+ if (value === keyboardDataRef.current.newValue) {
27564
+ if (keyboardDataRef.current.mode === "input") {
27565
+ setCaretPosition((c) => c + 1);
27566
+ } else if (keyboardDataRef.current.mode === "delete") {
27567
+ setCaretPosition((c) => c - 1);
27568
+ }
27569
+ } else {
27570
+ setCaretPosition(value.length);
27571
+ }
27572
+ }, [value]);
27506
27573
  useIsomorphicLayoutEffect$3(() => {
27507
27574
  scrollToEnd();
27508
27575
  }, [value]);
@@ -27536,8 +27603,11 @@ const VirtualInput = React$2.forwardRef((props, ref2) => {
27536
27603
  onInput: (v) => {
27537
27604
  var _a, _b;
27538
27605
  const newValue = value.substring(0, caretPosition) + v + value.substring(caretPosition);
27606
+ keyboardDataRef.current = {
27607
+ newValue,
27608
+ mode: "input"
27609
+ };
27539
27610
  setValue(newValue);
27540
- setCaretPosition((c) => c + 1);
27541
27611
  (_b = (_a = keyboard.props).onInput) === null || _b === void 0 ? void 0 : _b.call(_a, v);
27542
27612
  },
27543
27613
  onDelete: () => {
@@ -27545,8 +27615,11 @@ const VirtualInput = React$2.forwardRef((props, ref2) => {
27545
27615
  if (caretPosition === 0)
27546
27616
  return;
27547
27617
  const newValue = value.substring(0, caretPosition - 1) + value.substring(caretPosition);
27618
+ keyboardDataRef.current = {
27619
+ newValue,
27620
+ mode: "delete"
27621
+ };
27548
27622
  setValue(newValue);
27549
- setCaretPosition(caretPosition - 1);
27550
27623
  (_b = (_a = keyboard.props).onDelete) === null || _b === void 0 ? void 0 : _b.call(_a);
27551
27624
  },
27552
27625
  visible: hasFocus,
@@ -27563,21 +27636,78 @@ const VirtualInput = React$2.forwardRef((props, ref2) => {
27563
27636
  getContainer: null
27564
27637
  });
27565
27638
  const setCaretPositionToEnd = () => {
27566
- setCaretPosition(value.length);
27639
+ var _a, _b;
27640
+ if (caretPosition !== value.length) {
27641
+ setCaretPosition(value.length);
27642
+ (_b = (_a = mergedProps.cursor) === null || _a === void 0 ? void 0 : _a.onMove) === null || _b === void 0 ? void 0 : _b.call(_a, value.length);
27643
+ }
27567
27644
  };
27568
27645
  const changeCaretPosition = (index2) => (e2) => {
27646
+ var _a, _b, _c;
27647
+ if (mergedProps.disabled || !((_a = mergedProps.cursor) === null || _a === void 0 ? void 0 : _a.movable))
27648
+ return;
27569
27649
  e2.stopPropagation();
27570
27650
  const rect = e2.target.getBoundingClientRect();
27571
27651
  const midX = rect.left + rect.width / 2;
27572
27652
  const clickX = e2.clientX;
27573
27653
  const isRight = clickX > midX;
27574
- setCaretPosition(isRight ? index2 + 1 : index2);
27654
+ const newCaretPosition = isRight ? index2 + 1 : index2;
27655
+ setCaretPosition(newCaretPosition);
27656
+ (_c = (_b = mergedProps.cursor) === null || _b === void 0 ? void 0 : _b.onMove) === null || _c === void 0 ? void 0 : _c.call(_b, newCaretPosition);
27657
+ };
27658
+ const handleTouchStart = (e2) => {
27659
+ var _a;
27660
+ if (mergedProps.disabled || !((_a = mergedProps.cursor) === null || _a === void 0 ? void 0 : _a.movable))
27661
+ return;
27662
+ if (!caretRef.current)
27663
+ return;
27664
+ const touch = e2.touches[0];
27665
+ const caretRect = caretRef.current.getBoundingClientRect();
27666
+ const distance = Math.abs(touch.clientX - (caretRect.left + caretRect.width / 2));
27667
+ if (distance < 20) {
27668
+ touchDataRef.current = {
27669
+ startX: touch.clientX,
27670
+ startCaretPosition: caretPosition
27671
+ };
27672
+ } else {
27673
+ touchDataRef.current = null;
27674
+ }
27675
+ };
27676
+ const handleTouchMove = (e2) => {
27677
+ var _a, _b, _c;
27678
+ if (!touchDataRef.current || !((_a = mergedProps.cursor) === null || _a === void 0 ? void 0 : _a.movable))
27679
+ return;
27680
+ setIsCaretDragging(true);
27681
+ const touch = e2.touches[0];
27682
+ const deltaX = touch.clientX - touchDataRef.current.startX;
27683
+ const charWidth = charWidthRef.current;
27684
+ const moveChars = Math.round(deltaX / charWidth);
27685
+ let newCaretPosition = touchDataRef.current.startCaretPosition + moveChars;
27686
+ newCaretPosition = Math.max(0, Math.min(newCaretPosition, value.length));
27687
+ setCaretPosition(newCaretPosition);
27688
+ (_c = (_b = mergedProps.cursor) === null || _b === void 0 ? void 0 : _b.onMove) === null || _c === void 0 ? void 0 : _c.call(_b, newCaretPosition);
27689
+ if (touchMoveTimeoutRef.current) {
27690
+ clearTimeout(touchMoveTimeoutRef.current);
27691
+ }
27692
+ touchMoveTimeoutRef.current = setTimeout(() => {
27693
+ setIsCaretDragging(false);
27694
+ touchMoveTimeoutRef.current = null;
27695
+ }, 500);
27696
+ };
27697
+ const handleTouchEnd = () => {
27698
+ touchDataRef.current = null;
27699
+ setIsCaretDragging(false);
27700
+ if (touchMoveTimeoutRef.current) {
27701
+ clearTimeout(touchMoveTimeoutRef.current);
27702
+ touchMoveTimeoutRef.current = null;
27703
+ }
27575
27704
  };
27576
27705
  const chars = (value + "").split("");
27577
27706
  return withNativeProps(mergedProps, React$2.createElement("div", {
27578
27707
  ref: rootRef,
27579
27708
  className: classNames(classPrefix$2, {
27580
- [`${classPrefix$2}-disabled`]: mergedProps.disabled
27709
+ [`${classPrefix$2}-disabled`]: mergedProps.disabled,
27710
+ [`${classPrefix$2}-caret-dragging`]: isCaretDragging
27581
27711
  }),
27582
27712
  tabIndex: mergedProps.disabled ? void 0 : 0,
27583
27713
  role: "textbox",
@@ -27589,13 +27719,18 @@ const VirtualInput = React$2.forwardRef((props, ref2) => {
27589
27719
  ref: contentRef,
27590
27720
  "aria-disabled": mergedProps.disabled,
27591
27721
  "aria-label": mergedProps.placeholder,
27592
- onClick: setCaretPositionToEnd
27722
+ onClick: setCaretPositionToEnd,
27723
+ onTouchStart: handleTouchStart,
27724
+ onTouchMove: handleTouchMove,
27725
+ onTouchEnd: handleTouchEnd
27593
27726
  }, chars.slice(0, caretPosition).map((i2, index2) => React$2.createElement("span", {
27727
+ ref: index2 === 0 ? charRef : void 0,
27594
27728
  key: index2,
27595
27729
  onClick: changeCaretPosition(index2)
27596
27730
  }, i2)), React$2.createElement("div", {
27597
27731
  className: `${classPrefix$2}-caret-container`
27598
27732
  }, hasFocus && React$2.createElement("div", {
27733
+ ref: caretRef,
27599
27734
  className: `${classPrefix$2}-caret`
27600
27735
  })), chars.slice(caretPosition).map((i2, index2) => React$2.createElement("span", {
27601
27736
  key: index2,
@@ -27606,7 +27741,6 @@ const VirtualInput = React$2.forwardRef((props, ref2) => {
27606
27741
  var _a;
27607
27742
  e2.stopPropagation();
27608
27743
  setValue("");
27609
- setCaretPosition(0);
27610
27744
  (_a = mergedProps.onClear) === null || _a === void 0 ? void 0 : _a.call(mergedProps);
27611
27745
  },
27612
27746
  role: "button",