@atlaskit/renderer 109.10.7 → 109.11.1

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 (40) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/dist/cjs/actions/index.js +4 -1
  3. package/dist/cjs/ui/Renderer/index.js +1 -1
  4. package/dist/cjs/ui/annotations/context.js +16 -6
  5. package/dist/cjs/ui/annotations/contexts/AnnotationRangeContext.js +48 -8
  6. package/dist/cjs/ui/annotations/hooks/user-selection.js +18 -14
  7. package/dist/cjs/ui/annotations/selection/mounter.js +15 -4
  8. package/dist/cjs/ui/annotations/selection/range-validator.js +14 -5
  9. package/dist/cjs/ui/annotations/wrapper.js +15 -1
  10. package/dist/es2019/actions/index.js +4 -1
  11. package/dist/es2019/ui/Renderer/index.js +1 -1
  12. package/dist/es2019/ui/annotations/context.js +19 -7
  13. package/dist/es2019/ui/annotations/contexts/AnnotationRangeContext.js +42 -3
  14. package/dist/es2019/ui/annotations/hooks/user-selection.js +19 -15
  15. package/dist/es2019/ui/annotations/selection/mounter.js +15 -4
  16. package/dist/es2019/ui/annotations/selection/range-validator.js +12 -4
  17. package/dist/es2019/ui/annotations/wrapper.js +17 -1
  18. package/dist/esm/actions/index.js +4 -1
  19. package/dist/esm/ui/Renderer/index.js +1 -1
  20. package/dist/esm/ui/annotations/context.js +16 -6
  21. package/dist/esm/ui/annotations/contexts/AnnotationRangeContext.js +48 -8
  22. package/dist/esm/ui/annotations/hooks/user-selection.js +19 -15
  23. package/dist/esm/ui/annotations/selection/mounter.js +15 -4
  24. package/dist/esm/ui/annotations/selection/range-validator.js +14 -5
  25. package/dist/esm/ui/annotations/wrapper.js +15 -1
  26. package/dist/types/actions/index.d.ts +7 -6
  27. package/dist/types/ui/annotations/context.d.ts +2 -0
  28. package/dist/types/ui/annotations/contexts/AnnotationRangeContext.d.ts +3 -0
  29. package/dist/types/ui/annotations/hooks/user-selection.d.ts +1 -1
  30. package/dist/types/ui/annotations/hover/mounter.d.ts +2 -2
  31. package/dist/types/ui/annotations/selection/mounter.d.ts +5 -4
  32. package/dist/types/ui/annotations/selection/range-validator.d.ts +2 -2
  33. package/dist/types-ts4.5/actions/index.d.ts +7 -6
  34. package/dist/types-ts4.5/ui/annotations/context.d.ts +2 -0
  35. package/dist/types-ts4.5/ui/annotations/contexts/AnnotationRangeContext.d.ts +3 -0
  36. package/dist/types-ts4.5/ui/annotations/hooks/user-selection.d.ts +1 -0
  37. package/dist/types-ts4.5/ui/annotations/hover/mounter.d.ts +2 -2
  38. package/dist/types-ts4.5/ui/annotations/selection/mounter.d.ts +5 -4
  39. package/dist/types-ts4.5/ui/annotations/selection/range-validator.d.ts +2 -2
  40. package/package.json +3 -3
@@ -1,6 +1,5 @@
1
- import { useContext, useEffect } from 'react';
1
+ import { useEffect, useRef } from 'react';
2
2
  import { useAnnotationRangeDispatch, useAnnotationRangeState } from '../contexts/AnnotationRangeContext';
3
- import { AnnotationsDraftContext } from '../context';
4
3
  import { isRangeInsideOfRendererContainer } from './utils';
5
4
  export const useUserSelectionRange = props => {
6
5
  const {
@@ -8,35 +7,40 @@ export const useUserSelectionRange = props => {
8
7
  current: rendererDOM
9
8
  }
10
9
  } = props;
10
+ const selectionTimeoutRef = useRef();
11
11
  const {
12
- clearSelectionRange,
12
+ clearRange,
13
13
  setRange
14
14
  } = useAnnotationRangeDispatch();
15
15
  const {
16
16
  range,
17
+ draftRange,
17
18
  type
18
19
  } = useAnnotationRangeState();
19
- const annotationDraftPosition = useContext(AnnotationsDraftContext);
20
- const hasAnnotationDraft = !!annotationDraftPosition;
21
20
  useEffect(() => {
22
21
  if (!document || !rendererDOM) {
23
22
  return;
24
23
  }
25
24
  const onSelectionChange = event => {
26
- const sel = document.getSelection();
27
- if (!sel || sel.type !== 'Range' || sel.rangeCount !== 1 || hasAnnotationDraft) {
28
- return;
29
- }
30
- const _range = sel.getRangeAt(0);
31
- if (rendererDOM && isRangeInsideOfRendererContainer(rendererDOM, _range)) {
32
- setRange(_range.cloneRange());
25
+ if (selectionTimeoutRef.current) {
26
+ clearTimeout(selectionTimeoutRef.current);
33
27
  }
28
+ selectionTimeoutRef.current = setTimeout(() => {
29
+ const sel = document.getSelection();
30
+ if (!sel || sel.type !== 'Range' || sel.rangeCount !== 1) {
31
+ return;
32
+ }
33
+ const _range = sel.getRangeAt(0);
34
+ if (rendererDOM && isRangeInsideOfRendererContainer(rendererDOM, _range)) {
35
+ setRange(_range.cloneRange());
36
+ }
37
+ }, 250);
34
38
  };
35
39
  document.addEventListener('selectionchange', onSelectionChange);
36
40
  return () => {
37
41
  document.removeEventListener('selectionchange', onSelectionChange);
38
- clearSelectionRange();
42
+ clearRange();
39
43
  };
40
- }, [rendererDOM, hasAnnotationDraft, setRange, clearSelectionRange]);
41
- return [type === 'selection' ? range : null, clearSelectionRange];
44
+ }, [rendererDOM, setRange, clearRange]);
45
+ return [type === 'selection' ? range : null, draftRange, clearRange];
42
46
  };
@@ -8,6 +8,7 @@ export const SelectionInlineCommentMounter = /*#__PURE__*/React.memo(props => {
8
8
  const {
9
9
  component: Component,
10
10
  range,
11
+ draftRange,
11
12
  isAnnotationAllowed,
12
13
  wrapperDOM,
13
14
  onClose: onCloseProps,
@@ -21,7 +22,16 @@ export const SelectionInlineCommentMounter = /*#__PURE__*/React.memo(props => {
21
22
  const [draftDocumentPosition, setDraftDocumentPosition] = useState();
22
23
  const actions = useContext(ActionsContext);
23
24
  const onCreateCallback = useCallback(annotationId => {
24
- if (!isAnnotationAllowed || !documentPosition || !applyAnnotation) {
25
+ // We want to support creation on a documentPosition if the user is only using ranges
26
+ // but we want to prioritize draft positions if they are being used by consumers
27
+ const positionToAnnotate = draftDocumentPosition || documentPosition;
28
+ if (!positionToAnnotate || !applyAnnotation) {
29
+ return false;
30
+ }
31
+
32
+ // Evaluate position validity when the user commits the position to be annotated
33
+ const isCreateAllowedOnPosition = actions.isValidAnnotationPosition(positionToAnnotate);
34
+ if (!isCreateAllowedOnPosition) {
25
35
  return false;
26
36
  }
27
37
  const annotation = {
@@ -37,8 +47,8 @@ export const SelectionInlineCommentMounter = /*#__PURE__*/React.memo(props => {
37
47
  eventType: EVENT_TYPE.TRACK
38
48
  }).fire(FabricChannel.editor);
39
49
  }
40
- return applyAnnotation(draftDocumentPosition || documentPosition, annotation);
41
- }, [isAnnotationAllowed, documentPosition, applyAnnotation, draftDocumentPosition, createAnalyticsEvent]);
50
+ return applyAnnotation(positionToAnnotate, annotation);
51
+ }, [actions, documentPosition, applyAnnotation, draftDocumentPosition, createAnalyticsEvent]);
42
52
  const createIndexCallback = useCallback(() => {
43
53
  if (!documentPosition || !generateIndexMatch) {
44
54
  return false;
@@ -65,7 +75,7 @@ export const SelectionInlineCommentMounter = /*#__PURE__*/React.memo(props => {
65
75
  setDraftDocumentPosition(documentPosition);
66
76
  applyAnnotationDraftAt(documentPosition);
67
77
  if (createAnalyticsEvent) {
68
- const uniqueAnnotationsInRange = actions.getAnnotationsByPosition(range);
78
+ const uniqueAnnotationsInRange = range ? actions.getAnnotationsByPosition(range) : [];
69
79
  createAnalyticsEvent({
70
80
  action: ACTION.OPENED,
71
81
  actionSubject: ACTION_SUBJECT.ANNOTATION,
@@ -110,6 +120,7 @@ export const SelectionInlineCommentMounter = /*#__PURE__*/React.memo(props => {
110
120
  }, [onCloseProps, removeDraftModeCallback, createAnalyticsEvent]);
111
121
  return /*#__PURE__*/React.createElement(Component, {
112
122
  range: range,
123
+ draftRange: draftRange,
113
124
  wrapperDOM: wrapperDOM.current,
114
125
  isAnnotationAllowed: isAnnotationAllowed,
115
126
  onClose: onCloseCallback,
@@ -11,21 +11,29 @@ export const SelectionRangeValidator = props => {
11
11
  createAnalyticsEvent
12
12
  } = props;
13
13
  const actions = useContext(ActionsContext);
14
- const [range, clearRange] = useUserSelectionRange({
14
+ const [range, draftRange, clearRange] = useUserSelectionRange({
15
15
  rendererRef
16
16
  });
17
- if (!range) {
17
+ if (!range && !draftRange) {
18
18
  return null;
19
19
  }
20
20
  const documentPosition = actions.getPositionFromRange(range);
21
- const isAnnotationAllowed = documentPosition && actions.isValidAnnotationPosition(documentPosition);
21
+
22
+ // This property is drilled down to consumers when a new range is selected to test it's validity
23
+ let isAnnotationAllowedOnRange = false;
24
+ try {
25
+ isAnnotationAllowedOnRange = documentPosition && actions.isValidAnnotationPosition(documentPosition);
26
+ } catch {
27
+ isAnnotationAllowedOnRange = false;
28
+ }
22
29
  return /*#__PURE__*/React.createElement(SelectionInlineCommentMounter, {
23
30
  range: range,
31
+ draftRange: draftRange,
24
32
  wrapperDOM: rendererRef,
25
33
  component: selectionComponent,
26
34
  onClose: clearRange,
27
35
  documentPosition: documentPosition,
28
- isAnnotationAllowed: isAnnotationAllowed,
36
+ isAnnotationAllowed: isAnnotationAllowedOnRange,
29
37
  applyAnnotation: actions.applyAnnotation.bind(actions),
30
38
  applyAnnotationDraftAt: applyAnnotationDraftAt,
31
39
  generateIndexMatch: actions.generateAnnotationIndexMatch.bind(actions),
@@ -2,8 +2,16 @@ import React, { useCallback, useContext } from 'react';
2
2
  import { AnnotationsDraftContextWrapper, ProvidersContext } from './context';
3
3
  import { HoverRangeValidator } from './hover';
4
4
  import { SelectionRangeValidator } from './selection';
5
+ import { useAnnotationRangeDispatch, useAnnotationRangeState } from './contexts/AnnotationRangeContext';
5
6
  export const AnnotationsContextWrapper = props => {
6
7
  const providers = useContext(ProvidersContext);
8
+ const {
9
+ range
10
+ } = useAnnotationRangeState();
11
+ const {
12
+ setDraftRange,
13
+ clearDraftRange
14
+ } = useAnnotationRangeDispatch();
7
15
  const {
8
16
  rendererRef,
9
17
  createAnalyticsEvent,
@@ -12,6 +20,11 @@ export const AnnotationsContextWrapper = props => {
12
20
  const inlineCommentProvider = providers && providers.inlineComment;
13
21
  const selectionComponent = inlineCommentProvider && inlineCommentProvider.selectionComponent;
14
22
  const hoverComponent = inlineCommentProvider && inlineCommentProvider.hoverComponent;
23
+
24
+ // We want to set the draft to the range the user highlighted
25
+ const setRangeForDraft = useCallback(() => {
26
+ setDraftRange(range);
27
+ }, [range, setDraftRange]);
15
28
  const render = useCallback(({
16
29
  applyAnnotationDraftAt,
17
30
  clearAnnotationDraft
@@ -33,5 +46,8 @@ export const AnnotationsContextWrapper = props => {
33
46
  if (!selectionComponent && !hoverComponent) {
34
47
  return /*#__PURE__*/React.createElement(React.Fragment, null, children);
35
48
  }
36
- return /*#__PURE__*/React.createElement(AnnotationsDraftContextWrapper, null, render);
49
+ return /*#__PURE__*/React.createElement(AnnotationsDraftContextWrapper, {
50
+ setDraftRange: setRangeForDraft,
51
+ clearDraftRange: clearDraftRange
52
+ }, render);
37
53
  };
@@ -134,6 +134,9 @@ var RendererActions = /*#__PURE__*/function () {
134
134
  }, {
135
135
  key: "isValidAnnotationRange",
136
136
  value: function isValidAnnotationRange(range) {
137
+ if (!range) {
138
+ return false;
139
+ }
137
140
  var pos = getPosFromRange(range);
138
141
  if (!pos || !this.doc) {
139
142
  return false;
@@ -151,7 +154,7 @@ var RendererActions = /*#__PURE__*/function () {
151
154
  }, {
152
155
  key: "getPositionFromRange",
153
156
  value: function getPositionFromRange(range) {
154
- if (!this.doc || !this.schema) {
157
+ if (!this.doc || !this.schema || !range) {
155
158
  return false;
156
159
  }
157
160
  return getPosFromRange(range);
@@ -46,7 +46,7 @@ import { EditorMediaClientProvider } from '../../react/utils/EditorMediaClientPr
46
46
  export var NORMAL_SEVERITY_THRESHOLD = 2000;
47
47
  export var DEGRADED_SEVERITY_THRESHOLD = 3000;
48
48
  var packageName = "@atlaskit/renderer";
49
- var packageVersion = "109.10.7";
49
+ var packageVersion = "109.11.1";
50
50
  export var Renderer = /*#__PURE__*/function (_PureComponent) {
51
51
  _inherits(Renderer, _PureComponent);
52
52
  var _super = _createSuper(Renderer);
@@ -25,14 +25,24 @@ export var AnnotationsDraftContextWrapper = /*#__PURE__*/function (_React$Compon
25
25
  position: null
26
26
  });
27
27
  _defineProperty(_assertThisInitialized(_this), "applyAnnotationDraftAt", function (nextPosition) {
28
- var position = _this.state.position;
29
- if (!position) {
30
- _this.setState({
31
- position: nextPosition
32
- });
33
- }
28
+ var setDraftRange = _this.props.setDraftRange;
29
+
30
+ // Set the draft range to preserve it downstream
31
+ setDraftRange();
32
+
33
+ // We need to support a new draft being made while one exists and overwrite it
34
+ // Set the document position for the newly created draft
35
+ _this.setState({
36
+ position: nextPosition
37
+ });
34
38
  });
35
39
  _defineProperty(_assertThisInitialized(_this), "clearAnnotationDraft", function () {
40
+ var clearDraftRange = _this.props.clearDraftRange;
41
+
42
+ // Clear the draft range
43
+ clearDraftRange();
44
+
45
+ // Clear the draft position in the document
36
46
  _this.setState({
37
47
  position: null
38
48
  });
@@ -1,4 +1,7 @@
1
1
  import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
2
+ import _defineProperty from "@babel/runtime/helpers/defineProperty";
3
+ function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
4
+ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
2
5
  import React, { createContext, useCallback, useContext, useMemo, useReducer } from 'react';
3
6
  function reducer(state, action) {
4
7
  switch (action.type) {
@@ -6,40 +9,58 @@ function reducer(state, action) {
6
9
  if (!!state.range || !!state.type) {
7
10
  return {
8
11
  range: null,
12
+ draftRange: null,
9
13
  type: null
10
14
  };
11
15
  }
12
16
  return state;
13
17
  case 'clearSelection':
14
18
  if (state.type === 'selection') {
15
- return {
19
+ return _objectSpread(_objectSpread({}, state), {}, {
16
20
  range: null,
17
21
  type: null
18
- };
22
+ });
23
+ }
24
+ return state;
25
+ case 'clearDraftSelection':
26
+ if (state.type === 'selection') {
27
+ return _objectSpread(_objectSpread({}, state), {}, {
28
+ draftRange: null
29
+ });
19
30
  }
20
31
  return state;
21
32
  case 'clearHover':
22
33
  if (state.type === 'hover') {
23
34
  return {
24
35
  range: null,
36
+ draftRange: null,
25
37
  type: null
26
38
  };
27
39
  }
28
40
  return state;
29
41
  case 'setSelection':
30
42
  if (state.range !== action.range || state.type !== 'selection') {
31
- return {
43
+ return _objectSpread(_objectSpread({}, state), {}, {
32
44
  range: action.range,
33
45
  type: 'selection'
46
+ });
47
+ }
48
+ return state;
49
+ case 'setDraftSelection':
50
+ if (state.draftRange !== action.draftRange || state.type !== 'selection') {
51
+ return {
52
+ range: null,
53
+ draftRange: action.draftRange,
54
+ type: null
34
55
  };
35
56
  }
36
57
  return state;
37
58
  case 'setHover':
38
59
  if (state.range !== action.range || state.type !== 'hover') {
39
- return {
60
+ return _objectSpread(_objectSpread({}, state), {}, {
40
61
  range: action.range,
41
62
  type: 'hover'
42
- };
63
+ });
43
64
  }
44
65
  return state;
45
66
  }
@@ -47,24 +68,29 @@ function reducer(state, action) {
47
68
  }
48
69
  export var AnnotationRangeStateContext = /*#__PURE__*/createContext({
49
70
  range: null,
71
+ draftRange: null,
50
72
  type: null
51
73
  });
52
74
  export var AnnotationRangeDispatchContext = /*#__PURE__*/createContext({
53
75
  clearRange: function clearRange() {},
54
76
  clearSelectionRange: function clearSelectionRange() {},
77
+ clearDraftRange: function clearDraftRange() {},
55
78
  clearHoverRange: function clearHoverRange() {},
56
- setRange: function setRange() {}
79
+ setRange: function setRange() {},
80
+ setDraftRange: function setDraftRange() {}
57
81
  });
58
82
  export var AnnotationRangeProvider = function AnnotationRangeProvider(_ref) {
59
83
  var children = _ref.children,
60
84
  allowCommentsOnMedia = _ref.allowCommentsOnMedia;
61
85
  var _useReducer = useReducer(reducer, {
62
86
  range: null,
87
+ draftRange: null,
63
88
  type: null
64
89
  }),
65
90
  _useReducer2 = _slicedToArray(_useReducer, 2),
66
91
  _useReducer2$ = _useReducer2[0],
67
92
  range = _useReducer2$.range,
93
+ draftRange = _useReducer2$.draftRange,
68
94
  type = _useReducer2$.type,
69
95
  dispatch = _useReducer2[1];
70
96
  var clearRange = useCallback(function () {
@@ -77,6 +103,11 @@ export var AnnotationRangeProvider = function AnnotationRangeProvider(_ref) {
77
103
  type: 'clearSelection'
78
104
  });
79
105
  }, []);
106
+ var clearDraftRange = useCallback(function () {
107
+ return dispatch({
108
+ type: 'clearDraftSelection'
109
+ });
110
+ }, []);
80
111
  var clearHoverRange = useCallback(function () {
81
112
  return dispatch({
82
113
  type: 'clearHover'
@@ -88,6 +119,12 @@ export var AnnotationRangeProvider = function AnnotationRangeProvider(_ref) {
88
119
  range: range
89
120
  });
90
121
  }, []);
122
+ var setDraftRange = useCallback(function (range) {
123
+ dispatch({
124
+ type: 'setDraftSelection',
125
+ draftRange: range
126
+ });
127
+ }, []);
91
128
  var setHoverTarget = useCallback(function (target) {
92
129
  var range = document.createRange();
93
130
  range.setStartBefore(target);
@@ -100,18 +137,21 @@ export var AnnotationRangeProvider = function AnnotationRangeProvider(_ref) {
100
137
  var stateData = useMemo(function () {
101
138
  return {
102
139
  range: range,
140
+ draftRange: draftRange,
103
141
  type: type
104
142
  };
105
- }, [range, type]);
143
+ }, [range, draftRange, type]);
106
144
  var dispatchData = useMemo(function () {
107
145
  return {
108
146
  clearRange: clearRange,
109
147
  clearSelectionRange: clearSelectionRange,
148
+ clearDraftRange: clearDraftRange,
110
149
  clearHoverRange: clearHoverRange,
111
150
  setRange: setRange,
151
+ setDraftRange: setDraftRange,
112
152
  setHoverTarget: !!allowCommentsOnMedia ? setHoverTarget : undefined
113
153
  };
114
- }, [allowCommentsOnMedia, clearRange, clearSelectionRange, clearHoverRange, setRange, setHoverTarget]);
154
+ }, [allowCommentsOnMedia, clearRange, clearSelectionRange, clearDraftRange, clearHoverRange, setRange, setDraftRange, setHoverTarget]);
115
155
  return /*#__PURE__*/React.createElement(AnnotationRangeStateContext.Provider, {
116
156
  value: stateData
117
157
  }, /*#__PURE__*/React.createElement(AnnotationRangeDispatchContext.Provider, {
@@ -1,36 +1,40 @@
1
- import { useContext, useEffect } from 'react';
1
+ import { useEffect, useRef } from 'react';
2
2
  import { useAnnotationRangeDispatch, useAnnotationRangeState } from '../contexts/AnnotationRangeContext';
3
- import { AnnotationsDraftContext } from '../context';
4
3
  import { isRangeInsideOfRendererContainer } from './utils';
5
4
  export var useUserSelectionRange = function useUserSelectionRange(props) {
6
5
  var rendererDOM = props.rendererRef.current;
6
+ var selectionTimeoutRef = useRef();
7
7
  var _useAnnotationRangeDi = useAnnotationRangeDispatch(),
8
- clearSelectionRange = _useAnnotationRangeDi.clearSelectionRange,
8
+ clearRange = _useAnnotationRangeDi.clearRange,
9
9
  setRange = _useAnnotationRangeDi.setRange;
10
10
  var _useAnnotationRangeSt = useAnnotationRangeState(),
11
11
  range = _useAnnotationRangeSt.range,
12
+ draftRange = _useAnnotationRangeSt.draftRange,
12
13
  type = _useAnnotationRangeSt.type;
13
- var annotationDraftPosition = useContext(AnnotationsDraftContext);
14
- var hasAnnotationDraft = !!annotationDraftPosition;
15
14
  useEffect(function () {
16
15
  if (!document || !rendererDOM) {
17
16
  return;
18
17
  }
19
18
  var onSelectionChange = function onSelectionChange(event) {
20
- var sel = document.getSelection();
21
- if (!sel || sel.type !== 'Range' || sel.rangeCount !== 1 || hasAnnotationDraft) {
22
- return;
23
- }
24
- var _range = sel.getRangeAt(0);
25
- if (rendererDOM && isRangeInsideOfRendererContainer(rendererDOM, _range)) {
26
- setRange(_range.cloneRange());
19
+ if (selectionTimeoutRef.current) {
20
+ clearTimeout(selectionTimeoutRef.current);
27
21
  }
22
+ selectionTimeoutRef.current = setTimeout(function () {
23
+ var sel = document.getSelection();
24
+ if (!sel || sel.type !== 'Range' || sel.rangeCount !== 1) {
25
+ return;
26
+ }
27
+ var _range = sel.getRangeAt(0);
28
+ if (rendererDOM && isRangeInsideOfRendererContainer(rendererDOM, _range)) {
29
+ setRange(_range.cloneRange());
30
+ }
31
+ }, 250);
28
32
  };
29
33
  document.addEventListener('selectionchange', onSelectionChange);
30
34
  return function () {
31
35
  document.removeEventListener('selectionchange', onSelectionChange);
32
- clearSelectionRange();
36
+ clearRange();
33
37
  };
34
- }, [rendererDOM, hasAnnotationDraft, setRange, clearSelectionRange]);
35
- return [type === 'selection' ? range : null, clearSelectionRange];
38
+ }, [rendererDOM, setRange, clearRange]);
39
+ return [type === 'selection' ? range : null, draftRange, clearRange];
36
40
  };
@@ -8,6 +8,7 @@ import { RendererContext as ActionsContext } from '../../RendererActionsContext'
8
8
  export var SelectionInlineCommentMounter = /*#__PURE__*/React.memo(function (props) {
9
9
  var Component = props.component,
10
10
  range = props.range,
11
+ draftRange = props.draftRange,
11
12
  isAnnotationAllowed = props.isAnnotationAllowed,
12
13
  wrapperDOM = props.wrapperDOM,
13
14
  onCloseProps = props.onClose,
@@ -23,7 +24,16 @@ export var SelectionInlineCommentMounter = /*#__PURE__*/React.memo(function (pro
23
24
  setDraftDocumentPosition = _useState2[1];
24
25
  var actions = useContext(ActionsContext);
25
26
  var onCreateCallback = useCallback(function (annotationId) {
26
- if (!isAnnotationAllowed || !documentPosition || !applyAnnotation) {
27
+ // We want to support creation on a documentPosition if the user is only using ranges
28
+ // but we want to prioritize draft positions if they are being used by consumers
29
+ var positionToAnnotate = draftDocumentPosition || documentPosition;
30
+ if (!positionToAnnotate || !applyAnnotation) {
31
+ return false;
32
+ }
33
+
34
+ // Evaluate position validity when the user commits the position to be annotated
35
+ var isCreateAllowedOnPosition = actions.isValidAnnotationPosition(positionToAnnotate);
36
+ if (!isCreateAllowedOnPosition) {
27
37
  return false;
28
38
  }
29
39
  var annotation = {
@@ -39,8 +49,8 @@ export var SelectionInlineCommentMounter = /*#__PURE__*/React.memo(function (pro
39
49
  eventType: EVENT_TYPE.TRACK
40
50
  }).fire(FabricChannel.editor);
41
51
  }
42
- return applyAnnotation(draftDocumentPosition || documentPosition, annotation);
43
- }, [isAnnotationAllowed, documentPosition, applyAnnotation, draftDocumentPosition, createAnalyticsEvent]);
52
+ return applyAnnotation(positionToAnnotate, annotation);
53
+ }, [actions, documentPosition, applyAnnotation, draftDocumentPosition, createAnalyticsEvent]);
44
54
  var createIndexCallback = useCallback(function () {
45
55
  if (!documentPosition || !generateIndexMatch) {
46
56
  return false;
@@ -68,7 +78,7 @@ export var SelectionInlineCommentMounter = /*#__PURE__*/React.memo(function (pro
68
78
  setDraftDocumentPosition(documentPosition);
69
79
  applyAnnotationDraftAt(documentPosition);
70
80
  if (createAnalyticsEvent) {
71
- var uniqueAnnotationsInRange = actions.getAnnotationsByPosition(range);
81
+ var uniqueAnnotationsInRange = range ? actions.getAnnotationsByPosition(range) : [];
72
82
  createAnalyticsEvent({
73
83
  action: ACTION.OPENED,
74
84
  actionSubject: ACTION_SUBJECT.ANNOTATION,
@@ -113,6 +123,7 @@ export var SelectionInlineCommentMounter = /*#__PURE__*/React.memo(function (pro
113
123
  }, [onCloseProps, removeDraftModeCallback, createAnalyticsEvent]);
114
124
  return /*#__PURE__*/React.createElement(Component, {
115
125
  range: range,
126
+ draftRange: draftRange,
116
127
  wrapperDOM: wrapperDOM.current,
117
128
  isAnnotationAllowed: isAnnotationAllowed,
118
129
  onClose: onCloseCallback,
@@ -13,21 +13,30 @@ export var SelectionRangeValidator = function SelectionRangeValidator(props) {
13
13
  var _useUserSelectionRang = useUserSelectionRange({
14
14
  rendererRef: rendererRef
15
15
  }),
16
- _useUserSelectionRang2 = _slicedToArray(_useUserSelectionRang, 2),
16
+ _useUserSelectionRang2 = _slicedToArray(_useUserSelectionRang, 3),
17
17
  range = _useUserSelectionRang2[0],
18
- clearRange = _useUserSelectionRang2[1];
19
- if (!range) {
18
+ draftRange = _useUserSelectionRang2[1],
19
+ clearRange = _useUserSelectionRang2[2];
20
+ if (!range && !draftRange) {
20
21
  return null;
21
22
  }
22
23
  var documentPosition = actions.getPositionFromRange(range);
23
- var isAnnotationAllowed = documentPosition && actions.isValidAnnotationPosition(documentPosition);
24
+
25
+ // This property is drilled down to consumers when a new range is selected to test it's validity
26
+ var isAnnotationAllowedOnRange = false;
27
+ try {
28
+ isAnnotationAllowedOnRange = documentPosition && actions.isValidAnnotationPosition(documentPosition);
29
+ } catch (_unused) {
30
+ isAnnotationAllowedOnRange = false;
31
+ }
24
32
  return /*#__PURE__*/React.createElement(SelectionInlineCommentMounter, {
25
33
  range: range,
34
+ draftRange: draftRange,
26
35
  wrapperDOM: rendererRef,
27
36
  component: selectionComponent,
28
37
  onClose: clearRange,
29
38
  documentPosition: documentPosition,
30
- isAnnotationAllowed: isAnnotationAllowed,
39
+ isAnnotationAllowed: isAnnotationAllowedOnRange,
31
40
  applyAnnotation: actions.applyAnnotation.bind(actions),
32
41
  applyAnnotationDraftAt: applyAnnotationDraftAt,
33
42
  generateIndexMatch: actions.generateAnnotationIndexMatch.bind(actions),
@@ -2,14 +2,25 @@ import React, { useCallback, useContext } from 'react';
2
2
  import { AnnotationsDraftContextWrapper, ProvidersContext } from './context';
3
3
  import { HoverRangeValidator } from './hover';
4
4
  import { SelectionRangeValidator } from './selection';
5
+ import { useAnnotationRangeDispatch, useAnnotationRangeState } from './contexts/AnnotationRangeContext';
5
6
  export var AnnotationsContextWrapper = function AnnotationsContextWrapper(props) {
6
7
  var providers = useContext(ProvidersContext);
8
+ var _useAnnotationRangeSt = useAnnotationRangeState(),
9
+ range = _useAnnotationRangeSt.range;
10
+ var _useAnnotationRangeDi = useAnnotationRangeDispatch(),
11
+ setDraftRange = _useAnnotationRangeDi.setDraftRange,
12
+ clearDraftRange = _useAnnotationRangeDi.clearDraftRange;
7
13
  var rendererRef = props.rendererRef,
8
14
  createAnalyticsEvent = props.createAnalyticsEvent,
9
15
  children = props.children;
10
16
  var inlineCommentProvider = providers && providers.inlineComment;
11
17
  var selectionComponent = inlineCommentProvider && inlineCommentProvider.selectionComponent;
12
18
  var hoverComponent = inlineCommentProvider && inlineCommentProvider.hoverComponent;
19
+
20
+ // We want to set the draft to the range the user highlighted
21
+ var setRangeForDraft = useCallback(function () {
22
+ setDraftRange(range);
23
+ }, [range, setDraftRange]);
13
24
  var render = useCallback(function (_ref) {
14
25
  var applyAnnotationDraftAt = _ref.applyAnnotationDraftAt,
15
26
  clearAnnotationDraft = _ref.clearAnnotationDraft;
@@ -30,5 +41,8 @@ export var AnnotationsContextWrapper = function AnnotationsContextWrapper(props)
30
41
  if (!selectionComponent && !hoverComponent) {
31
42
  return /*#__PURE__*/React.createElement(React.Fragment, null, children);
32
43
  }
33
- return /*#__PURE__*/React.createElement(AnnotationsDraftContextWrapper, null, render);
44
+ return /*#__PURE__*/React.createElement(AnnotationsDraftContextWrapper, {
45
+ setDraftRange: setRangeForDraft,
46
+ clearDraftRange: clearDraftRange
47
+ }, render);
34
48
  };
@@ -1,10 +1,11 @@
1
1
  /// <reference types="react" />
2
- import { JSONDocNode } from '@atlaskit/editor-json-transformer';
2
+ import type { JSONDocNode } from '@atlaskit/editor-json-transformer';
3
3
  import type { AnnotationActionResult, AnnotationByMatches } from '@atlaskit/editor-common/types';
4
4
  import { AnnotationTypes } from '@atlaskit/adf-schema';
5
- import { Node, Schema, Mark } from '@atlaskit/editor-prosemirror/model';
6
- import { Step, RemoveMarkStep } from '@atlaskit/editor-prosemirror/transform';
7
- import { AnalyticsEventPayload } from '../analytics/events';
5
+ import type { Node, Schema, Mark } from '@atlaskit/editor-prosemirror/model';
6
+ import type { Step } from '@atlaskit/editor-prosemirror/transform';
7
+ import { RemoveMarkStep } from '@atlaskit/editor-prosemirror/transform';
8
+ import type { AnalyticsEventPayload } from '../analytics/events';
8
9
  type ActionResult = {
9
10
  step: Step;
10
11
  doc: JSONDocNode;
@@ -50,9 +51,9 @@ export default class RendererActions implements RendererActionsOptions, Annotati
50
51
  doc: JSONDocNode;
51
52
  };
52
53
  annotate(range: Range, annotationId: string, annotationType: 'inlineComment'): AnnotationActionResult;
53
- isValidAnnotationRange(range: Range): boolean;
54
+ isValidAnnotationRange(range: Range | null): boolean;
54
55
  isValidAnnotationPosition(pos: Position): boolean;
55
- getPositionFromRange(range: Range): Position | false;
56
+ getPositionFromRange(range: Range | null): Position | false;
56
57
  getAnnotationMarks(): Mark[];
57
58
  getAnnotationsByPosition(range: Range): string[];
58
59
  applyAnnotation(pos: Position, annotation: Annotation): AnnotationActionResult;
@@ -8,6 +8,8 @@ export type AnnotationsDraftContextWrapperChildrenProps = {
8
8
  };
9
9
  export type RenderCallbackType = (props: React.PropsWithChildren<AnnotationsDraftContextWrapperChildrenProps>) => React.ReactNode;
10
10
  type Props = {
11
+ setDraftRange: () => void;
12
+ clearDraftRange: () => void;
11
13
  children: RenderCallbackType;
12
14
  };
13
15
  type State = {
@@ -2,13 +2,16 @@ import type { ReactNode } from 'react';
2
2
  import React from 'react';
3
3
  interface AnnotationRangeStateContext {
4
4
  range: Range | null;
5
+ draftRange: Range | null;
5
6
  type: 'selection' | 'hover' | null;
6
7
  }
7
8
  interface AnnotationRangeDispatchContext {
8
9
  clearRange: () => void;
9
10
  clearSelectionRange: () => void;
11
+ clearDraftRange: () => void;
10
12
  clearHoverRange: () => void;
11
13
  setRange: (range: Range) => void;
14
+ setDraftRange: (draftRange: Range | null) => void;
12
15
  setHoverTarget?: (target: HTMLElement) => void;
13
16
  }
14
17
  export declare const AnnotationRangeStateContext: React.Context<AnnotationRangeStateContext>;
@@ -2,5 +2,5 @@
2
2
  type Props = {
3
3
  rendererRef: React.RefObject<HTMLDivElement>;
4
4
  };
5
- export declare const useUserSelectionRange: (props: Props) => [Range | null, () => void];
5
+ export declare const useUserSelectionRange: (props: Props) => [Range | null, Range | null, () => void];
6
6
  export {};