You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

127 lines
3.3 KiB

  1. /**
  2. * Copyright (c) Facebook, Inc. and its affiliates.
  3. *
  4. * This source code is licensed under the MIT license found in the
  5. * LICENSE file in the root directory of this source tree.
  6. *
  7. * @format
  8. * @flow strict-local
  9. * @emails oncall+draft_js
  10. */
  11. 'use strict';
  12. const Immutable = require("immutable");
  13. const {
  14. Record
  15. } = Immutable;
  16. const defaultRecord: {
  17. anchorKey: string,
  18. anchorOffset: number,
  19. focusKey: string,
  20. focusOffset: number,
  21. isBackward: boolean,
  22. hasFocus: boolean,
  23. ...
  24. } = {
  25. anchorKey: '',
  26. anchorOffset: 0,
  27. focusKey: '',
  28. focusOffset: 0,
  29. isBackward: false,
  30. hasFocus: false
  31. };
  32. /* $FlowFixMe This comment suppresses an error found when automatically adding
  33. * a type annotation with the codemod Komodo/Annotate_exports. To see the error
  34. * delete this comment and run Flow. */
  35. const SelectionStateRecord = (Record(defaultRecord): any);
  36. class SelectionState extends SelectionStateRecord {
  37. serialize(): string {
  38. return 'Anchor: ' + this.getAnchorKey() + ':' + this.getAnchorOffset() + ', ' + 'Focus: ' + this.getFocusKey() + ':' + this.getFocusOffset() + ', ' + 'Is Backward: ' + String(this.getIsBackward()) + ', ' + 'Has Focus: ' + String(this.getHasFocus());
  39. }
  40. getAnchorKey(): string {
  41. return this.get('anchorKey');
  42. }
  43. getAnchorOffset(): number {
  44. return this.get('anchorOffset');
  45. }
  46. getFocusKey(): string {
  47. return this.get('focusKey');
  48. }
  49. getFocusOffset(): number {
  50. return this.get('focusOffset');
  51. }
  52. getIsBackward(): boolean {
  53. return this.get('isBackward');
  54. }
  55. getHasFocus(): boolean {
  56. return this.get('hasFocus');
  57. }
  58. /**
  59. * Return whether the specified range overlaps with an edge of the
  60. * SelectionState.
  61. */
  62. hasEdgeWithin(blockKey: string, start: number, end: number): boolean {
  63. const anchorKey = this.getAnchorKey();
  64. const focusKey = this.getFocusKey();
  65. if (anchorKey === focusKey && anchorKey === blockKey) {
  66. const selectionStart = this.getStartOffset();
  67. const selectionEnd = this.getEndOffset();
  68. return start <= selectionStart && selectionStart <= end || // selectionStart is between start and end, or
  69. start <= selectionEnd && selectionEnd <= end // selectionEnd is between start and end
  70. ;
  71. }
  72. if (blockKey !== anchorKey && blockKey !== focusKey) {
  73. return false;
  74. }
  75. const offsetToCheck = blockKey === anchorKey ? this.getAnchorOffset() : this.getFocusOffset();
  76. return start <= offsetToCheck && end >= offsetToCheck;
  77. }
  78. isCollapsed(): boolean {
  79. return this.getAnchorKey() === this.getFocusKey() && this.getAnchorOffset() === this.getFocusOffset();
  80. }
  81. getStartKey(): string {
  82. return this.getIsBackward() ? this.getFocusKey() : this.getAnchorKey();
  83. }
  84. getStartOffset(): number {
  85. return this.getIsBackward() ? this.getFocusOffset() : this.getAnchorOffset();
  86. }
  87. getEndKey(): string {
  88. return this.getIsBackward() ? this.getAnchorKey() : this.getFocusKey();
  89. }
  90. getEndOffset(): number {
  91. return this.getIsBackward() ? this.getAnchorOffset() : this.getFocusOffset();
  92. }
  93. static createEmpty(key: string): SelectionState {
  94. return new SelectionState({
  95. anchorKey: key,
  96. anchorOffset: 0,
  97. focusKey: key,
  98. focusOffset: 0,
  99. isBackward: false,
  100. hasFocus: false
  101. });
  102. }
  103. }
  104. module.exports = SelectionState;