@atlaskit/renderer 115.0.2 → 115.0.4

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 (37) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/dist/cjs/ui/Renderer/index.js +1 -1
  3. package/dist/cjs/ui/annotations/contexts/AnnotationManagerContext.js +421 -0
  4. package/dist/cjs/ui/annotations/draft/component.js +13 -1
  5. package/dist/cjs/ui/annotations/element/index.js +38 -6
  6. package/dist/cjs/ui/annotations/element/mark.js +16 -0
  7. package/dist/cjs/ui/annotations/hooks/use-events.js +77 -27
  8. package/dist/cjs/ui/annotations/hooks/use-load-annotations.js +18 -2
  9. package/dist/cjs/ui/annotations/index.js +49 -12
  10. package/dist/cjs/ui/annotations/selection/mounter.js +177 -4
  11. package/dist/es2019/ui/Renderer/index.js +1 -1
  12. package/dist/es2019/ui/annotations/contexts/AnnotationManagerContext.js +416 -0
  13. package/dist/es2019/ui/annotations/draft/component.js +15 -3
  14. package/dist/es2019/ui/annotations/element/index.js +39 -6
  15. package/dist/es2019/ui/annotations/element/mark.js +18 -0
  16. package/dist/es2019/ui/annotations/hooks/use-events.js +85 -28
  17. package/dist/es2019/ui/annotations/hooks/use-load-annotations.js +19 -2
  18. package/dist/es2019/ui/annotations/index.js +47 -10
  19. package/dist/es2019/ui/annotations/selection/mounter.js +177 -6
  20. package/dist/esm/ui/Renderer/index.js +1 -1
  21. package/dist/esm/ui/annotations/contexts/AnnotationManagerContext.js +411 -0
  22. package/dist/esm/ui/annotations/draft/component.js +14 -3
  23. package/dist/esm/ui/annotations/element/index.js +38 -6
  24. package/dist/esm/ui/annotations/element/mark.js +16 -0
  25. package/dist/esm/ui/annotations/hooks/use-events.js +78 -28
  26. package/dist/esm/ui/annotations/hooks/use-load-annotations.js +18 -2
  27. package/dist/esm/ui/annotations/index.js +45 -10
  28. package/dist/esm/ui/annotations/selection/mounter.js +179 -6
  29. package/dist/types/ui/annotations/contexts/AnnotationManagerContext.d.ts +71 -0
  30. package/dist/types/ui/annotations/draft/component.d.ts +5 -1
  31. package/dist/types/ui/annotations/element/mark.d.ts +6 -0
  32. package/dist/types/ui/annotations/index.d.ts +1 -0
  33. package/dist/types-ts4.5/ui/annotations/contexts/AnnotationManagerContext.d.ts +71 -0
  34. package/dist/types-ts4.5/ui/annotations/draft/component.d.ts +5 -1
  35. package/dist/types-ts4.5/ui/annotations/element/mark.d.ts +6 -0
  36. package/dist/types-ts4.5/ui/annotations/index.d.ts +1 -0
  37. package/package.json +13 -5
@@ -0,0 +1,416 @@
1
+ import React, { createContext, useContext, useEffect, useMemo, useReducer } from 'react';
2
+ import { AnnotationMarkStates, AnnotationTypes } from '@atlaskit/adf-schema';
3
+ import { AnnotationUpdateEvent } from '@atlaskit/editor-common/types';
4
+ const initState = {
5
+ isDrafting: false,
6
+ draftId: undefined,
7
+ draftMarkRef: undefined,
8
+ draftActionResult: undefined,
9
+ annotations: {},
10
+ currentSelectedAnnotationId: undefined,
11
+ currentSelectedMarkRef: undefined,
12
+ currentHoveredAnnotationId: undefined
13
+ };
14
+ const AnnotationManagerStateContext = /*#__PURE__*/createContext(initState);
15
+ const AnnotationManagerDispatchContext = /*#__PURE__*/createContext({
16
+ annotationManager: undefined,
17
+ dispatch: () => {}
18
+ });
19
+ function reducer(state, action) {
20
+ switch (action.type) {
21
+ case 'reset':
22
+ {
23
+ return {
24
+ ...state,
25
+ ...initState
26
+ };
27
+ }
28
+ case 'loadAnnotation':
29
+ {
30
+ const currentIds = Object.keys(state.annotations);
31
+ const uids = Array.from(new Set(currentIds.concat(action.data.map(a => a.id))));
32
+ const updates = [];
33
+ for (const id of uids) {
34
+ var _state$annotations$id, _state$annotations$id2;
35
+ const loadedAnnotation = action.data.find(a => a.id === id);
36
+ if (!loadedAnnotation && ((_state$annotations$id = state.annotations[id]) === null || _state$annotations$id === void 0 ? void 0 : _state$annotations$id.markState) === AnnotationMarkStates.ACTIVE) {
37
+ // If the annotation is not in the loaded data, we need to remove it from the state. However,
38
+ // rather then removing it, we will set the mark state to resolved. This is to align it better with
39
+ // how the editor works.
40
+ updates.push({
41
+ id,
42
+ markState: AnnotationMarkStates.RESOLVED
43
+ });
44
+ continue;
45
+ }
46
+ if (!!(loadedAnnotation !== null && loadedAnnotation !== void 0 && loadedAnnotation.markState) && ((_state$annotations$id2 = state.annotations[id]) === null || _state$annotations$id2 === void 0 ? void 0 : _state$annotations$id2.markState) !== loadedAnnotation.markState) {
47
+ updates.push({
48
+ id,
49
+ markState: loadedAnnotation.markState
50
+ });
51
+ continue;
52
+ }
53
+ }
54
+ if (updates.length > 0) {
55
+ return {
56
+ ...state,
57
+ annotations: updates.reduce((nextAnnotations, update) => {
58
+ return {
59
+ ...nextAnnotations,
60
+ [update.id]: {
61
+ ...nextAnnotations[update.id],
62
+ ...update
63
+ }
64
+ };
65
+ }, state.annotations)
66
+ };
67
+ }
68
+ return state;
69
+ }
70
+ case 'updateAnnotation':
71
+ {
72
+ const current = state.annotations[action.data.id];
73
+ const {
74
+ id,
75
+ selected,
76
+ hovered,
77
+ markState = current === null || current === void 0 ? void 0 : current.markState
78
+ } = action.data;
79
+ const updates = [];
80
+
81
+ // If the annotation is not currently in the state, we need to add it to the state.
82
+ if (!current) {
83
+ updates.push({
84
+ id,
85
+ markState: markState !== null && markState !== void 0 ? markState : AnnotationMarkStates.ACTIVE
86
+ });
87
+ }
88
+
89
+ // The goal of the following is to enforce a single selection and a single hover state across all annotations.
90
+ let nextSelectedId = state.currentSelectedAnnotationId;
91
+ if (selected && nextSelectedId !== id) {
92
+ nextSelectedId = id;
93
+ }
94
+ // If the annotation is currently selected and it's being unselected, we need to remove it from the
95
+ // current selected annotation id.
96
+ if (selected === false && nextSelectedId === id) {
97
+ nextSelectedId = undefined;
98
+ }
99
+ let nextHoveredId = state.currentHoveredAnnotationId;
100
+ if (hovered && nextHoveredId !== id) {
101
+ nextHoveredId = id;
102
+ }
103
+ // If the annotation is currently hovered and it's being unhovered, we need to remove it from the
104
+ // current hovered annotation id.
105
+ if (hovered === false && nextHoveredId === id) {
106
+ nextHoveredId = undefined;
107
+ }
108
+
109
+ // If the annotations mark state is not the same as the current mark state, we need to update it.
110
+ if ((current === null || current === void 0 ? void 0 : current.markState) !== markState) {
111
+ updates.push({
112
+ id,
113
+ markState: markState !== null && markState !== void 0 ? markState : AnnotationMarkStates.ACTIVE
114
+ });
115
+
116
+ // If the annotation is currently selected and it's being resolved, then we need to remove it from the
117
+ // current selected annotation id also.
118
+ if (markState === AnnotationMarkStates.RESOLVED && nextSelectedId === id) {
119
+ nextSelectedId = undefined;
120
+ }
121
+ }
122
+ if (updates.length > 0 || nextSelectedId !== state.currentSelectedAnnotationId || nextHoveredId !== state.currentHoveredAnnotationId) {
123
+ return {
124
+ ...state,
125
+ currentSelectedAnnotationId: nextSelectedId,
126
+ currentHoveredAnnotationId: nextHoveredId,
127
+ annotations: updates.reduce((nextAnnotations, update) => {
128
+ return {
129
+ ...nextAnnotations,
130
+ [update.id]: {
131
+ ...nextAnnotations[update.id],
132
+ ...update
133
+ }
134
+ };
135
+ }, state.annotations)
136
+ };
137
+ }
138
+ return state;
139
+ }
140
+ case 'resetSelectedAnnotation':
141
+ {
142
+ if (state.currentSelectedAnnotationId !== undefined) {
143
+ return {
144
+ ...state,
145
+ currentSelectedAnnotationId: undefined,
146
+ currentSelectedMarkRef: undefined
147
+ };
148
+ }
149
+ return state;
150
+ }
151
+ case 'resetHoveredAnnotation':
152
+ {
153
+ if (state.currentHoveredAnnotationId !== undefined) {
154
+ return {
155
+ ...state,
156
+ currentHoveredAnnotationId: undefined
157
+ };
158
+ }
159
+ return state;
160
+ }
161
+ case 'setDrafting':
162
+ {
163
+ if (state.isDrafting !== action.data.isDrafting || state.draftId !== action.data.draftId || state.draftActionResult !== action.data.draftActionResult) {
164
+ // XXX: When a draft is open the current selected annotation should no longer be selected. We need
165
+ // to decide what is better UX,
166
+ // 1 - do we want to deselct the selected annotation on draft open, if so then when draft is closed the s
167
+ // selected annotation will not come back
168
+ // 2 - do we want to still allow the selected annotation to be selected when draft is open, however the underlying
169
+ // mark style just shows the annotation as not selected when a draft is active. Then when a draft closes
170
+ // we can reopen the previous selected annotation.
171
+ return {
172
+ ...state,
173
+ isDrafting: action.data.isDrafting,
174
+ draftId: action.data.draftId,
175
+ draftActionResult: action.data.draftActionResult
176
+ };
177
+ }
178
+ return state;
179
+ }
180
+ case 'setDraftMarkRef':
181
+ {
182
+ if (state.draftMarkRef !== action.data.draftMarkRef) {
183
+ return {
184
+ ...state,
185
+ draftMarkRef: action.data.draftMarkRef
186
+ };
187
+ }
188
+ return state;
189
+ }
190
+ case 'setSelectedMarkRef':
191
+ {
192
+ if (state.currentSelectedMarkRef !== action.data.markRef) {
193
+ return {
194
+ ...state,
195
+ currentSelectedMarkRef: action.data.markRef
196
+ };
197
+ }
198
+ return state;
199
+ }
200
+ }
201
+ }
202
+ export const AnnotationManagerProvider = ({
203
+ children,
204
+ annotationManager,
205
+ updateSubscriber
206
+ }) => {
207
+ const [state, dispatch] = useReducer(reducer, initState);
208
+ useEffect(() => {
209
+ const getDraft = () => {
210
+ var _state$draftActionRes;
211
+ if (!state.isDrafting || !state.draftActionResult || !state.draftMarkRef || !state.draftId) {
212
+ return {
213
+ success: false,
214
+ reason: 'draft-not-started'
215
+ };
216
+ }
217
+ return {
218
+ success: true,
219
+ inlineNodeTypes: (_state$draftActionRes = state.draftActionResult.inlineNodeTypes) !== null && _state$draftActionRes !== void 0 ? _state$draftActionRes : [],
220
+ targetElement: state.draftMarkRef,
221
+ actionResult: {
222
+ step: state.draftActionResult.step,
223
+ doc: state.draftActionResult.doc,
224
+ inlineNodeTypes: state.draftActionResult.inlineNodeTypes,
225
+ targetNodeType: state.draftActionResult.targetNodeType,
226
+ originalSelection: state.draftActionResult.originalSelection,
227
+ numMatches: state.draftActionResult.numMatches,
228
+ matchIndex: state.draftActionResult.matchIndex,
229
+ pos: state.draftActionResult.pos
230
+ }
231
+ };
232
+ };
233
+ annotationManager === null || annotationManager === void 0 ? void 0 : annotationManager.hook('getDraft', getDraft);
234
+ return () => {
235
+ annotationManager === null || annotationManager === void 0 ? void 0 : annotationManager.unhook('getDraft', getDraft);
236
+ };
237
+ }, [annotationManager, state.draftId, state.isDrafting, state.draftMarkRef, state.draftActionResult]);
238
+
239
+ // We need to watch for the draft mark element to exist, so we can inform any listeners that the draft has been started
240
+ // and give them a reference to the element
241
+ useEffect(() => {
242
+ if (state.isDrafting && state.draftId && state.draftMarkRef && state.draftActionResult) {
243
+ var _state$draftActionRes2;
244
+ annotationManager === null || annotationManager === void 0 ? void 0 : annotationManager.emit({
245
+ name: 'draftAnnotationStarted',
246
+ data: {
247
+ inlineNodeTypes: (_state$draftActionRes2 = state.draftActionResult.inlineNodeTypes) !== null && _state$draftActionRes2 !== void 0 ? _state$draftActionRes2 : [],
248
+ targetElement: state.draftMarkRef,
249
+ actionResult: {
250
+ step: state.draftActionResult.step,
251
+ doc: state.draftActionResult.doc,
252
+ inlineNodeTypes: state.draftActionResult.inlineNodeTypes,
253
+ targetNodeType: state.draftActionResult.targetNodeType,
254
+ originalSelection: state.draftActionResult.originalSelection,
255
+ numMatches: state.draftActionResult.numMatches,
256
+ matchIndex: state.draftActionResult.matchIndex,
257
+ pos: state.draftActionResult.pos
258
+ }
259
+ }
260
+ });
261
+ }
262
+ }, [annotationManager, state.draftId, state.isDrafting, state.draftMarkRef, state.draftActionResult]);
263
+
264
+ // useEffect(() => {
265
+ // const setIsAnnotationSelected = (id: AnnotationId, isSelected: boolean): SelectAnnotationResult => {
266
+ // if (!state.annotations?.[id]) {
267
+ // return {
268
+ // success: false,
269
+ // reason: 'id-not-valid',
270
+ // };
271
+ // }
272
+
273
+ // dispatch({
274
+ // type: 'updateAnnotation',
275
+ // data: {
276
+ // id,
277
+ // selected: isSelected,
278
+ // },
279
+ // })
280
+
281
+ // return {
282
+ // success: true,
283
+ // isSelected,
284
+ // };
285
+ // };
286
+
287
+ // annotationManager?.hook('setIsAnnotationSelected', setIsAnnotationSelected);
288
+ // return () => {
289
+ // annotationManager?.unhook('setIsAnnotationSelected', setIsAnnotationSelected);
290
+ // };
291
+ // }, [state.annotations]);
292
+
293
+ // useEffect(() => {
294
+ // console.log('annotationsSelectedChanged', state.annotationsSelectedChanged);
295
+
296
+ // // if (state.isDrafting && state.currentDraftId && state.draftMarkRef) {
297
+ // // annotationManager?.emit({
298
+ // // name: 'annotationSelectionChanged',
299
+ // // data: {
300
+ // // annotationId: state.currentDraftId,
301
+ // // inlineNodeTypes: [],
302
+ // // isSelected: true,
303
+ // // },
304
+ // // });
305
+ // // }
306
+ // }, [annotationManager, state.annotationsSelectedChanged]);
307
+
308
+ /**
309
+ * This is a temporary solution to ensure that the annotation manager state is in sync with the
310
+ * old updateSubscriber. The updateSubscriber will eventually be deprecated and the state will be managed
311
+ * by the annotation manager itself.
312
+ */
313
+ useEffect(() => {
314
+ const onSetAnnotationState = payload => {
315
+ if (!payload) {
316
+ return;
317
+ }
318
+ Object.values(payload).forEach(annotation => {
319
+ if (annotation.id && annotation.annotationType === AnnotationTypes.INLINE_COMMENT && !annotation.state) {
320
+ var _annotation$state;
321
+ dispatch({
322
+ type: 'updateAnnotation',
323
+ data: {
324
+ id: annotation.id,
325
+ markState: (_annotation$state = annotation.state) !== null && _annotation$state !== void 0 ? _annotation$state : undefined
326
+ }
327
+ });
328
+ }
329
+ });
330
+ };
331
+ const onAnnotationSelected = payload => {
332
+ dispatch({
333
+ type: 'updateAnnotation',
334
+ data: {
335
+ id: payload.annotationId,
336
+ selected: true
337
+ }
338
+ });
339
+ };
340
+ const onAnnotationHovered = payload => {
341
+ dispatch({
342
+ type: 'updateAnnotation',
343
+ data: {
344
+ id: payload.annotationId,
345
+ hovered: true
346
+ }
347
+ });
348
+ };
349
+ const onAnnotationSelectedRemoved = () => {
350
+ dispatch({
351
+ type: 'resetSelectedAnnotation'
352
+ });
353
+ };
354
+ const onAnnotationHoveredRemoved = () => {
355
+ dispatch({
356
+ type: 'resetHoveredAnnotation'
357
+ });
358
+ };
359
+ const onAnnotationClick = ({
360
+ annotationIds,
361
+ eventTarget,
362
+ eventTargetType,
363
+ viewMethod
364
+ }) => {
365
+ dispatch({
366
+ type: 'updateAnnotation',
367
+ data: {
368
+ id: annotationIds[0],
369
+ selected: true
370
+ }
371
+ });
372
+ dispatch({
373
+ type: 'setSelectedMarkRef',
374
+ data: {
375
+ markRef: eventTarget
376
+ }
377
+ });
378
+ };
379
+ const onAnnotationDeselect = () => {
380
+ dispatch({
381
+ type: 'resetSelectedAnnotation'
382
+ });
383
+ };
384
+ updateSubscriber === null || updateSubscriber === void 0 ? void 0 : updateSubscriber.on(AnnotationUpdateEvent.SET_ANNOTATION_STATE, onSetAnnotationState);
385
+ updateSubscriber === null || updateSubscriber === void 0 ? void 0 : updateSubscriber.on(AnnotationUpdateEvent.SET_ANNOTATION_FOCUS, onAnnotationSelected);
386
+ updateSubscriber === null || updateSubscriber === void 0 ? void 0 : updateSubscriber.on(AnnotationUpdateEvent.SET_ANNOTATION_HOVERED, onAnnotationHovered);
387
+ updateSubscriber === null || updateSubscriber === void 0 ? void 0 : updateSubscriber.on(AnnotationUpdateEvent.REMOVE_ANNOTATION_FOCUS, onAnnotationSelectedRemoved);
388
+ updateSubscriber === null || updateSubscriber === void 0 ? void 0 : updateSubscriber.on(AnnotationUpdateEvent.REMOVE_ANNOTATION_HOVERED, onAnnotationHoveredRemoved);
389
+ updateSubscriber === null || updateSubscriber === void 0 ? void 0 : updateSubscriber.on(AnnotationUpdateEvent.ON_ANNOTATION_CLICK, onAnnotationClick);
390
+ updateSubscriber === null || updateSubscriber === void 0 ? void 0 : updateSubscriber.on(AnnotationUpdateEvent.DESELECT_ANNOTATIONS, onAnnotationDeselect);
391
+ return () => {
392
+ updateSubscriber === null || updateSubscriber === void 0 ? void 0 : updateSubscriber.off(AnnotationUpdateEvent.SET_ANNOTATION_STATE, onSetAnnotationState);
393
+ updateSubscriber === null || updateSubscriber === void 0 ? void 0 : updateSubscriber.off(AnnotationUpdateEvent.SET_ANNOTATION_FOCUS, onAnnotationSelected);
394
+ updateSubscriber === null || updateSubscriber === void 0 ? void 0 : updateSubscriber.off(AnnotationUpdateEvent.SET_ANNOTATION_HOVERED, onAnnotationHovered);
395
+ updateSubscriber === null || updateSubscriber === void 0 ? void 0 : updateSubscriber.off(AnnotationUpdateEvent.REMOVE_ANNOTATION_FOCUS, onAnnotationSelectedRemoved);
396
+ updateSubscriber === null || updateSubscriber === void 0 ? void 0 : updateSubscriber.off(AnnotationUpdateEvent.REMOVE_ANNOTATION_HOVERED, onAnnotationHoveredRemoved);
397
+ updateSubscriber === null || updateSubscriber === void 0 ? void 0 : updateSubscriber.off(AnnotationUpdateEvent.ON_ANNOTATION_CLICK, onAnnotationClick);
398
+ updateSubscriber === null || updateSubscriber === void 0 ? void 0 : updateSubscriber.off(AnnotationUpdateEvent.DESELECT_ANNOTATIONS, onAnnotationDeselect);
399
+ };
400
+ }, [updateSubscriber]);
401
+ const dispatchData = useMemo(() => ({
402
+ annotationManager,
403
+ dispatch
404
+ }), [annotationManager, dispatch]);
405
+ return /*#__PURE__*/React.createElement(AnnotationManagerStateContext.Provider, {
406
+ value: state
407
+ }, /*#__PURE__*/React.createElement(AnnotationManagerDispatchContext.Provider, {
408
+ value: dispatchData
409
+ }, children));
410
+ };
411
+ export const useAnnotationManagerState = () => {
412
+ return useContext(AnnotationManagerStateContext);
413
+ };
414
+ export const useAnnotationManagerDispatch = () => {
415
+ return useContext(AnnotationManagerDispatchContext);
416
+ };
@@ -3,8 +3,7 @@ import _extends from "@babel/runtime/helpers/extends";
3
3
  * @jsxRuntime classic
4
4
  * @jsx jsx
5
5
  */
6
-
7
- import React, { Fragment } from 'react';
6
+ import React, { Fragment, useCallback } from 'react';
8
7
  // eslint-disable-next-line @atlaskit/ui-styling-standard/use-compiled -- Ignored via go/DSP-18766
9
8
  import { css, jsx } from '@emotion/react';
10
9
  import { InsertDraftPosition } from '../types';
@@ -14,6 +13,7 @@ import { calcInsertDraftPositionOnText } from './position';
14
13
  import { dataAttributes } from './dom';
15
14
  import { segmentText } from '../../../react/utils/segment-text';
16
15
  import { renderTextSegments } from '../../../react/utils/render-text-segments';
16
+ import { useAnnotationManagerDispatch } from '../contexts/AnnotationManagerContext';
17
17
 
18
18
  // Localized AnnotationSharedCSSByState().common and AnnotationSharedCSSByState().focus
19
19
  const markStyles = css({
@@ -39,12 +39,24 @@ export const AnnotationDraft = ({
39
39
  draftPosition,
40
40
  children
41
41
  }) => {
42
+ const {
43
+ dispatch
44
+ } = useAnnotationManagerDispatch();
45
+ const markRef = useCallback(node => {
46
+ dispatch({
47
+ type: 'setDraftMarkRef',
48
+ data: {
49
+ draftMarkRef: node !== null && node !== void 0 ? node : undefined
50
+ }
51
+ });
52
+ }, [dispatch]);
42
53
  return jsx("mark", _extends({
43
54
  "data-renderer-mark": true
44
55
  // Ignored via go/ees005
45
56
  // eslint-disable-next-line react/jsx-props-no-spreading
46
57
  }, dataAttributes(draftPosition), {
47
- css: markStyles
58
+ css: markStyles,
59
+ ref: markRef
48
60
  }), children);
49
61
  };
50
62
  export const getAnnotationIndex = (annotationPosition, fragmentCount) => {
@@ -1,11 +1,13 @@
1
1
  import React, { useMemo, useCallback, useContext } from 'react';
2
2
  import { AnnotationMarkStates } from '@atlaskit/adf-schema';
3
+ import { AnnotationUpdateEvent } from '@atlaskit/editor-common/types';
4
+ import { fg } from '@atlaskit/platform-feature-flags';
3
5
  import { MarkComponent } from './mark';
4
6
  import { useInlineCommentsFilter } from '../hooks/use-inline-comments-filter';
5
7
  import { useInlineCommentSubscriberContext } from '../hooks/use-inline-comment-subscriber';
6
8
  import { useHasFocusEvent } from '../hooks/use-events';
7
9
  import { InlineCommentsStateContext } from '../context';
8
- import { AnnotationUpdateEvent } from '@atlaskit/editor-common/types';
10
+ import { useAnnotationManagerDispatch } from '../contexts/AnnotationManagerContext';
9
11
  const MarkElement = ({
10
12
  annotationParentIds,
11
13
  children,
@@ -23,6 +25,10 @@ const MarkElement = ({
23
25
  updateSubscriber
24
26
  });
25
27
  const dataAttributesMemorized = useMemo(() => dataAttributes, [dataAttributes]);
28
+ const {
29
+ dispatch,
30
+ annotationManager
31
+ } = useAnnotationManagerDispatch();
26
32
  const onClick = useCallback(props => {
27
33
  if (!updateSubscriber) {
28
34
  return;
@@ -34,11 +40,38 @@ const MarkElement = ({
34
40
  eventTarget,
35
41
  annotationIds
36
42
  } = props;
37
- updateSubscriber.emit(AnnotationUpdateEvent.ON_ANNOTATION_CLICK, {
38
- annotationIds,
39
- eventTarget
40
- });
41
- }, [updateSubscriber, useBlockLevel]);
43
+ if (fg('platform_editor_comments_api_manager')) {
44
+ if (hasFocus) {
45
+ return;
46
+ }
47
+ annotationManager === null || annotationManager === void 0 ? void 0 : annotationManager.checkPreemptiveGate().then(canSelect => {
48
+ if (canSelect) {
49
+ dispatch({
50
+ type: 'updateAnnotation',
51
+ data: {
52
+ id: annotationIds[0],
53
+ selected: true
54
+ }
55
+ });
56
+ dispatch({
57
+ type: 'setSelectedMarkRef',
58
+ data: {
59
+ markRef: eventTarget
60
+ }
61
+ });
62
+ } else {
63
+ // TODO: EDITOR-595 - If the preemptive gate returns false, should we track the analytics event?
64
+ }
65
+ }).catch(error => {
66
+ // TODO: EDITOR-595 - An error occurred while checking the preemptive gate. We should report this error.
67
+ });
68
+ } else {
69
+ updateSubscriber.emit(AnnotationUpdateEvent.ON_ANNOTATION_CLICK, {
70
+ annotationIds,
71
+ eventTarget
72
+ });
73
+ }
74
+ }, [updateSubscriber, useBlockLevel, dispatch, annotationManager, hasFocus]);
42
75
  const activeParentIds = useInlineCommentsFilter({
43
76
  annotationIds: annotationParentIds,
44
77
  filter: {
@@ -10,6 +10,7 @@ import { AnnotationMarkStates } from '@atlaskit/adf-schema';
10
10
  import { fg } from '@atlaskit/platform-feature-flags';
11
11
  import { useIntl } from 'react-intl-next';
12
12
  import { inlineCommentMessages } from '../../../messages';
13
+ import { useAnnotationManagerDispatch, useAnnotationManagerState } from '../contexts/AnnotationManagerContext';
13
14
  const markStyles = css({
14
15
  color: 'inherit',
15
16
  backgroundColor: 'unset',
@@ -131,6 +132,22 @@ export const MarkComponent = ({
131
132
  }) => {
132
133
  const intl = useIntl();
133
134
  const annotationIds = useMemo(() => [...new Set([...annotationParentIds, id])], [id, annotationParentIds]);
135
+ const {
136
+ dispatch
137
+ } = useAnnotationManagerDispatch();
138
+ const {
139
+ currentSelectedAnnotationId
140
+ } = useAnnotationManagerState();
141
+ const markRef = useCallback(node => {
142
+ if (id === currentSelectedAnnotationId && node) {
143
+ dispatch({
144
+ type: 'setSelectedMarkRef',
145
+ data: {
146
+ markRef: node
147
+ }
148
+ });
149
+ }
150
+ }, [dispatch, id, currentSelectedAnnotationId]);
134
151
  const onMarkClick = useCallback(event => {
135
152
  // prevent inline mark logic for media block marks
136
153
  if (event.currentTarget instanceof HTMLElement && event.currentTarget.getAttribute('data-block-mark')) {
@@ -191,6 +208,7 @@ export const MarkComponent = ({
191
208
  ...desktopAccessibilityAttributes
192
209
  };
193
210
  return jsx(useBlockLevel ? 'div' : 'mark', {
211
+ ref: id === currentSelectedAnnotationId ? markRef : undefined,
194
212
  id,
195
213
  [fg('editor_inline_comments_on_inline_nodes') ? 'onClickCapture' : 'onClick']: onMarkClick,
196
214
  ...accessibility,