useCursor.js 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263
  1. import { useRef } from 'react';
  2. import warning from "rc-util/es/warning";
  3. /**
  4. * Keep input cursor in the correct position if possible.
  5. * Is this necessary since we have `formatter` which may mass the content?
  6. */
  7. export default function useCursor(input, focused) {
  8. var selectionRef = useRef(null);
  9. function recordCursor() {
  10. // Record position
  11. try {
  12. var start = input.selectionStart,
  13. end = input.selectionEnd,
  14. value = input.value;
  15. var beforeTxt = value.substring(0, start);
  16. var afterTxt = value.substring(end);
  17. selectionRef.current = {
  18. start: start,
  19. end: end,
  20. value: value,
  21. beforeTxt: beforeTxt,
  22. afterTxt: afterTxt
  23. };
  24. } catch (e) {
  25. // Fix error in Chrome:
  26. // Failed to read the 'selectionStart' property from 'HTMLInputElement'
  27. // http://stackoverflow.com/q/21177489/3040605
  28. }
  29. }
  30. /**
  31. * Restore logic:
  32. * 1. back string same
  33. * 2. start string same
  34. */
  35. function restoreCursor() {
  36. if (input && selectionRef.current && focused) {
  37. try {
  38. var value = input.value;
  39. var _selectionRef$current = selectionRef.current,
  40. beforeTxt = _selectionRef$current.beforeTxt,
  41. afterTxt = _selectionRef$current.afterTxt,
  42. start = _selectionRef$current.start;
  43. var startPos = value.length;
  44. if (value.startsWith(beforeTxt)) {
  45. startPos = beforeTxt.length;
  46. } else if (value.endsWith(afterTxt)) {
  47. startPos = value.length - selectionRef.current.afterTxt.length;
  48. } else {
  49. var beforeLastChar = beforeTxt[start - 1];
  50. var newIndex = value.indexOf(beforeLastChar, start - 1);
  51. if (newIndex !== -1) {
  52. startPos = newIndex + 1;
  53. }
  54. }
  55. input.setSelectionRange(startPos, startPos);
  56. } catch (e) {
  57. warning(false, "Something warning of cursor restore. Please fire issue about this: ".concat(e.message));
  58. }
  59. }
  60. }
  61. return [recordCursor, restoreCursor];
  62. }