@atlaskit/editor-plugin-annotation 1.2.1 → 1.3.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 (35) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/dist/cjs/commands/index.js +45 -4
  3. package/dist/cjs/nodeviews/index.js +1 -1
  4. package/dist/cjs/plugin.js +7 -3
  5. package/dist/cjs/pm-plugins/inline-comment.js +6 -3
  6. package/dist/cjs/pm-plugins/plugin-factory.js +21 -3
  7. package/dist/cjs/pm-plugins/reducer.js +6 -4
  8. package/dist/cjs/toolbar.js +0 -1
  9. package/dist/cjs/ui/AnnotationViewWrapper.js +1 -1
  10. package/dist/cjs/utils.js +50 -5
  11. package/dist/es2019/commands/index.js +47 -6
  12. package/dist/es2019/plugin.js +7 -3
  13. package/dist/es2019/pm-plugins/inline-comment.js +6 -4
  14. package/dist/es2019/pm-plugins/plugin-factory.js +21 -4
  15. package/dist/es2019/pm-plugins/reducer.js +8 -5
  16. package/dist/es2019/toolbar.js +0 -1
  17. package/dist/es2019/utils.js +52 -5
  18. package/dist/esm/commands/index.js +46 -5
  19. package/dist/esm/nodeviews/index.js +1 -1
  20. package/dist/esm/plugin.js +7 -3
  21. package/dist/esm/pm-plugins/inline-comment.js +6 -3
  22. package/dist/esm/pm-plugins/plugin-factory.js +22 -4
  23. package/dist/esm/pm-plugins/reducer.js +7 -5
  24. package/dist/esm/toolbar.js +0 -1
  25. package/dist/esm/ui/AnnotationViewWrapper.js +1 -1
  26. package/dist/esm/utils.js +50 -5
  27. package/dist/types/commands/index.d.ts +2 -2
  28. package/dist/types/pm-plugins/types.d.ts +5 -0
  29. package/dist/types/types.d.ts +5 -0
  30. package/dist/types/utils.d.ts +8 -2
  31. package/dist/types-ts4.5/commands/index.d.ts +2 -2
  32. package/dist/types-ts4.5/pm-plugins/types.d.ts +5 -0
  33. package/dist/types-ts4.5/types.d.ts +5 -0
  34. package/dist/types-ts4.5/utils.d.ts +8 -2
  35. package/package.json +2 -2
@@ -1,9 +1,9 @@
1
1
  import { AnnotationTypes } from '@atlaskit/adf-schema';
2
2
  import { ACTION, ACTION_SUBJECT, ACTION_SUBJECT_ID, EVENT_TYPE } from '@atlaskit/editor-common/analytics';
3
3
  import { currentMediaNodeWithPos } from '@atlaskit/editor-common/media-single';
4
- import { AnnotationSharedClassNames } from '@atlaskit/editor-common/styles';
4
+ import { AnnotationSharedClassNames, BlockAnnotationSharedClassNames } from '@atlaskit/editor-common/styles';
5
5
  import { canApplyAnnotationOnRange, containsAnyAnnotations, getAnnotationIdsFromRange, hasAnnotationMark, isParagraph, isText } from '@atlaskit/editor-common/utils';
6
- import { AllSelection, PluginKey, TextSelection } from '@atlaskit/editor-prosemirror/state';
6
+ import { AllSelection, NodeSelection, PluginKey, TextSelection } from '@atlaskit/editor-prosemirror/state';
7
7
  import { Decoration } from '@atlaskit/editor-prosemirror/view';
8
8
  import { AnnotationSelectionType } from './types';
9
9
  export { hasAnnotationMark, containsAnyAnnotations };
@@ -87,7 +87,10 @@ const validateAnnotationMark = annotationMark => {
87
87
  return allowedTypes.includes(type);
88
88
  }
89
89
  };
90
-
90
+ export const decorationKey = {
91
+ block: 'blockCommentDecoration',
92
+ inline: 'inlineCommentDecoration'
93
+ };
91
94
  /*
92
95
  * add decoration for the comment selection in draft state
93
96
  * (when creating new comment)
@@ -95,11 +98,15 @@ const validateAnnotationMark = annotationMark => {
95
98
  export const addDraftDecoration = (start, end, targetType = 'inline') => {
96
99
  if (targetType === 'block') {
97
100
  return Decoration.node(start, end, {
98
- class: `${AnnotationSharedClassNames.draft}`
101
+ class: `${BlockAnnotationSharedClassNames.draft}`
102
+ }, {
103
+ key: decorationKey.block
99
104
  });
100
105
  }
101
106
  return Decoration.inline(start, end, {
102
107
  class: `${AnnotationSharedClassNames.draft}`
108
+ }, {
109
+ key: decorationKey.inline
103
110
  });
104
111
  };
105
112
  export const getAnnotationViewKey = annotations => {
@@ -136,7 +143,44 @@ export const findAnnotationsInSelection = (selection, doc) => {
136
143
  reorderAnnotations(annotations, $anchor);
137
144
  return annotations;
138
145
  };
139
-
146
+ export const resolveDraftBookmark = (editorState, bookmark, supportedBlockNodes = []) => {
147
+ const {
148
+ doc
149
+ } = editorState;
150
+ const resolvedBookmark = bookmark.resolve(doc);
151
+ const {
152
+ from,
153
+ to,
154
+ head
155
+ } = resolvedBookmark;
156
+ let draftBookmark = {
157
+ from,
158
+ to,
159
+ head
160
+ };
161
+ if (resolvedBookmark instanceof NodeSelection) {
162
+ // It's possible that annotation is only allowed in child node instead parent (e.g. mediaSingle vs media),
163
+ // thus, we traverse the node to find the first node that supports annotation and return its position
164
+ let nodeFound = false;
165
+ doc.nodesBetween(from, to, (node, pos) => {
166
+ // if we find the node, breakout the traversal to make sure we always record the first supported node
167
+ if (nodeFound) {
168
+ return false;
169
+ }
170
+ const nodeEndsAt = pos + node.nodeSize;
171
+ if (supportedBlockNodes.includes(node.type.name)) {
172
+ draftBookmark = {
173
+ from: pos,
174
+ to: nodeEndsAt,
175
+ head: nodeEndsAt
176
+ };
177
+ nodeFound = true;
178
+ return false;
179
+ }
180
+ });
181
+ }
182
+ return draftBookmark;
183
+ };
140
184
  /**
141
185
  * get selection from position to apply new comment for
142
186
  * @return bookmarked positions if they exists, otherwise current selection positions
@@ -263,6 +307,9 @@ function isEmptyTextSelection(selection, schema) {
263
307
  });
264
308
  return !hasContent;
265
309
  }
310
+ export const isSupportedBlockNode = (node, supportedBlockNodes = []) => {
311
+ return supportedBlockNodes.indexOf(node.type.name) >= 0 || node.type.name === 'mediaSingle' && supportedBlockNodes.indexOf('media') >= 0;
312
+ };
266
313
 
267
314
  /**
268
315
  * Checks if any of the nodes in a given selection are completely whitespace
@@ -1,10 +1,11 @@
1
1
  import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
2
  import { AnnotationTypes } from '@atlaskit/adf-schema';
3
3
  import { INPUT_METHOD } from '@atlaskit/editor-common/analytics';
4
+ import { NodeSelection } from '@atlaskit/editor-prosemirror/state';
4
5
  import { createCommand } from '../pm-plugins/plugin-factory';
5
6
  import { ACTIONS } from '../pm-plugins/types';
6
7
  import { AnnotationSelectionType } from '../types';
7
- import { getPluginState, isSelectionValid } from '../utils';
8
+ import { getPluginState, isSelectionValid, isSupportedBlockNode } from '../utils';
8
9
  import transform from './transform';
9
10
  export var updateInlineCommentResolvedState = function updateInlineCommentResolvedState(editorAnalyticsAPI) {
10
11
  return function (partialNewState, resolveMethod) {
@@ -31,11 +32,48 @@ export var clearDirtyMark = function clearDirtyMark() {
31
32
  type: ACTIONS.INLINE_COMMENT_CLEAR_DIRTY_MARK
32
33
  });
33
34
  };
35
+ var removeInlineCommentFromNode = function removeInlineCommentFromNode(id) {
36
+ var supportedBlockNodes = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
37
+ var state = arguments.length > 2 ? arguments[2] : undefined;
38
+ var dispatch = arguments.length > 3 ? arguments[3] : undefined;
39
+ var tr = state.tr,
40
+ selection = state.selection;
41
+ if (selection instanceof NodeSelection && isSupportedBlockNode(selection.node, supportedBlockNodes)) {
42
+ var $from = selection.$from;
43
+ var currNode = selection.node;
44
+ var from = $from.start();
45
+
46
+ // for media annotation, the selection is on media Single
47
+ if (currNode.type === state.schema.nodes.mediaSingle && currNode.firstChild) {
48
+ currNode = currNode.firstChild;
49
+ from = from + 1;
50
+ }
51
+ var annotationMarkType = state.schema.marks.annotation;
52
+ var hasAnnotation = currNode.marks.some(function (mark) {
53
+ return mark.type === annotationMarkType;
54
+ });
55
+ if (!hasAnnotation) {
56
+ return false;
57
+ }
58
+ tr.removeNodeMark(from, annotationMarkType.create({
59
+ id: id,
60
+ type: AnnotationTypes.INLINE_COMMENT
61
+ }));
62
+ if (dispatch) {
63
+ dispatch(tr);
64
+ }
65
+ return true;
66
+ }
67
+ return false;
68
+ };
34
69
  export var removeInlineCommentNearSelection = function removeInlineCommentNearSelection(id) {
35
- var _supportedNodes = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
70
+ var supportedNodes = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
36
71
  return function (state, dispatch) {
37
72
  var tr = state.tr,
38
73
  $from = state.selection.$from;
74
+ if (removeInlineCommentFromNode(id, supportedNodes, state, dispatch)) {
75
+ return true;
76
+ }
39
77
  var annotationMarkType = state.schema.marks.annotation;
40
78
  var hasAnnotation = $from.marks().some(function (mark) {
41
79
  return mark.type === annotationMarkType;
@@ -55,7 +93,7 @@ export var removeInlineCommentNearSelection = function removeInlineCommentNearSe
55
93
  return true;
56
94
  };
57
95
  };
58
- var getDraftCommandAction = function getDraftCommandAction(drafting, targetType, isCommentOnMediaOn) {
96
+ var getDraftCommandAction = function getDraftCommandAction(drafting, targetType, isCommentOnMediaOn, supportedBlockNodes) {
59
97
  return function (editorState) {
60
98
  // validate selection only when entering draft mode
61
99
  if (drafting && isSelectionValid(editorState, isCommentOnMediaOn) !== AnnotationSelectionType.VALID) {
@@ -66,17 +104,20 @@ var getDraftCommandAction = function getDraftCommandAction(drafting, targetType,
66
104
  data: {
67
105
  drafting: drafting,
68
106
  editorState: editorState,
69
- targetType: targetType
107
+ targetType: targetType,
108
+ isCommentOnMediaOn: isCommentOnMediaOn,
109
+ supportedBlockNodes: supportedBlockNodes
70
110
  }
71
111
  };
72
112
  };
73
113
  };
74
114
  export var setInlineCommentDraftState = function setInlineCommentDraftState(editorAnalyticsAPI) {
115
+ var supportedBlockNodes = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
75
116
  return function (drafting) {
76
117
  var inputMethod = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : INPUT_METHOD.TOOLBAR;
77
118
  var targetType = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'inline';
78
119
  var isCommentOnMediaOn = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
79
- var commandAction = getDraftCommandAction(drafting, targetType, isCommentOnMediaOn);
120
+ var commandAction = getDraftCommandAction(drafting, targetType, isCommentOnMediaOn, supportedBlockNodes);
80
121
  return createCommand(commandAction, transform.addOpenCloseAnalytics(editorAnalyticsAPI)(drafting, inputMethod));
81
122
  };
82
123
  };
@@ -4,7 +4,7 @@ import _inherits from "@babel/runtime/helpers/inherits";
4
4
  import _possibleConstructorReturn from "@babel/runtime/helpers/possibleConstructorReturn";
5
5
  import _getPrototypeOf from "@babel/runtime/helpers/getPrototypeOf";
6
6
  function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }
7
- function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }
7
+ function _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }
8
8
  import React from 'react';
9
9
  import ReactNodeView from '@atlaskit/editor-common/react-node-view';
10
10
  import { AnnotationSharedClassNames } from '@atlaskit/editor-common/styles';
@@ -24,13 +24,16 @@ export var annotationPlugin = function annotationPlugin(_ref) {
24
24
  },
25
25
  actions: {
26
26
  stripNonExistingAnnotations: stripNonExistingAnnotations,
27
- setInlineCommentDraftState: setInlineCommentDraftState(api === null || api === void 0 || (_api$analytics = api.analytics) === null || _api$analytics === void 0 ? void 0 : _api$analytics.actions)
27
+ setInlineCommentDraftState: setInlineCommentDraftState(api === null || api === void 0 || (_api$analytics = api.analytics) === null || _api$analytics === void 0 ? void 0 : _api$analytics.actions, annotationProviders === null || annotationProviders === void 0 ? void 0 : annotationProviders.inlineComment.supportedBlockNodes)
28
28
  },
29
29
  getSharedState: function getSharedState(editorState) {
30
30
  if (!editorState) {
31
31
  return undefined;
32
32
  }
33
- return getPluginState(editorState) || undefined;
33
+ var pluginState = getPluginState(editorState) || undefined;
34
+ var clonedPluginState = Object.assign({}, pluginState);
35
+ clonedPluginState === null || clonedPluginState === void 0 || delete clonedPluginState.featureFlagsPluginState;
36
+ return clonedPluginState;
34
37
  },
35
38
  pmPlugins: function pmPlugins() {
36
39
  return [{
@@ -46,7 +49,8 @@ export var annotationPlugin = function annotationPlugin(_ref) {
46
49
  portalProviderAPI: portalProviderAPI,
47
50
  eventDispatcher: eventDispatcher,
48
51
  provider: annotationProviders.inlineComment,
49
- editorAnalyticsAPI: api === null || api === void 0 || (_api$analytics2 = api.analytics) === null || _api$analytics2 === void 0 ? void 0 : _api$analytics2.actions
52
+ editorAnalyticsAPI: api === null || api === void 0 || (_api$analytics2 = api.analytics) === null || _api$analytics2 === void 0 ? void 0 : _api$analytics2.actions,
53
+ featureFlagsPluginState: featureFlags
50
54
  });
51
55
  }
52
56
  return;
@@ -70,6 +70,7 @@ var fetchState = /*#__PURE__*/function () {
70
70
  }();
71
71
  var initialState = function initialState() {
72
72
  var disallowOnWhitespace = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
73
+ var featureFlagsPluginState = arguments.length > 1 ? arguments[1] : undefined;
73
74
  return {
74
75
  annotations: {},
75
76
  selectedAnnotations: [],
@@ -79,7 +80,8 @@ var initialState = function initialState() {
79
80
  disallowOnWhitespace: disallowOnWhitespace,
80
81
  isInlineCommentViewClosed: false,
81
82
  isVisible: true,
82
- skipSelectionHandling: false
83
+ skipSelectionHandling: false,
84
+ featureFlagsPluginState: featureFlagsPluginState
83
85
  };
84
86
  };
85
87
  var hideToolbar = function hideToolbar(state, dispatch) {
@@ -133,10 +135,11 @@ var onSetVisibility = function onSetVisibility(view) {
133
135
  export var inlineCommentPlugin = function inlineCommentPlugin(options) {
134
136
  var provider = options.provider,
135
137
  portalProviderAPI = options.portalProviderAPI,
136
- eventDispatcher = options.eventDispatcher;
138
+ eventDispatcher = options.eventDispatcher,
139
+ featureFlagsPluginState = options.featureFlagsPluginState;
137
140
  return new SafePlugin({
138
141
  key: inlineCommentPluginKey,
139
- state: createPluginState(options.dispatch, initialState(provider.disallowOnWhitespace)),
142
+ state: createPluginState(options.dispatch, initialState(provider.disallowOnWhitespace, featureFlagsPluginState)),
140
143
  view: function view(editorView) {
141
144
  // Get initial state
142
145
  // Need to pass `editorView` to mitigate editor state going stale
@@ -2,7 +2,8 @@ import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
2
  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; }
3
3
  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; }
4
4
  import { pluginFactory } from '@atlaskit/editor-common/utils';
5
- import { findAnnotationsInSelection, inlineCommentPluginKey, isSelectedAnnotationsChanged } from '../utils';
5
+ import { DecorationSet } from '@atlaskit/editor-prosemirror/view';
6
+ import { decorationKey, findAnnotationsInSelection, inlineCommentPluginKey, isSelectedAnnotationsChanged } from '../utils';
6
7
  import reducer from './reducer';
7
8
  var handleDocChanged = function handleDocChanged(tr, prevPluginState) {
8
9
  if (!tr.getMeta('replaceDocument')) {
@@ -43,13 +44,30 @@ var getSelectionChangedHandler = function getSelectionChangedHandler(reopenComme
43
44
  var _pluginFactory = pluginFactory(inlineCommentPluginKey, reducer, {
44
45
  onSelectionChanged: getSelectionChangedHandler(true),
45
46
  onDocChanged: handleDocChanged,
46
- mapping: function mapping(tr, pluginState) {
47
+ mapping: function mapping(tr, pluginState, editorState) {
47
48
  var draftDecorationSet = pluginState.draftDecorationSet,
48
- bookmark = pluginState.bookmark;
49
- var mappedDecorationSet, mappedBookmark;
49
+ bookmark = pluginState.bookmark,
50
+ featureFlagsPluginState = pluginState.featureFlagsPluginState;
51
+ var mappedDecorationSet = DecorationSet.empty,
52
+ mappedBookmark;
53
+ var hasMappedDecorations = false;
50
54
  if (draftDecorationSet) {
51
55
  mappedDecorationSet = draftDecorationSet.map(tr.mapping, tr.doc);
52
56
  }
57
+ if (featureFlagsPluginState !== null && featureFlagsPluginState !== void 0 && featureFlagsPluginState.commentsOnMedia) {
58
+ hasMappedDecorations = mappedDecorationSet.find(undefined, undefined, function (spec) {
59
+ return Object.values(decorationKey).includes(spec.key);
60
+ }).length > 0;
61
+
62
+ // When changes to decoration target make decoration invalid (e.g. delete text, add mark to node),
63
+ // we need to reset bookmark to hide create component and to avoid invalid draft being published
64
+ if (!hasMappedDecorations) {
65
+ return _objectSpread(_objectSpread({}, pluginState), {}, {
66
+ draftDecorationSet: mappedDecorationSet,
67
+ bookmark: undefined
68
+ });
69
+ }
70
+ }
53
71
  if (bookmark) {
54
72
  mappedBookmark = bookmark.map(tr.mapping);
55
73
  }
@@ -3,7 +3,7 @@ import _defineProperty from "@babel/runtime/helpers/defineProperty";
3
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
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; }
5
5
  import { DecorationSet } from '@atlaskit/editor-prosemirror/view';
6
- import { addDraftDecoration } from '../utils';
6
+ import { addDraftDecoration, resolveDraftBookmark } from '../utils';
7
7
  import { ACTIONS } from './types';
8
8
  export default (function (pluginState, action) {
9
9
  switch (action.type) {
@@ -17,7 +17,7 @@ export default (function (pluginState, action) {
17
17
  mouseData: mouseData
18
18
  });
19
19
  case ACTIONS.SET_INLINE_COMMENT_DRAFT_STATE:
20
- return getNewDraftState(pluginState, action.data.drafting, action.data.editorState, action.data.targetType);
20
+ return getNewDraftState(pluginState, action.data.drafting, action.data.editorState, action.data.targetType, action.data.isCommentOnMediaOn, action.data.supportedBlockNodes);
21
21
  case ACTIONS.INLINE_COMMENT_CLEAR_DIRTY_MARK:
22
22
  return _objectSpread(_objectSpread({}, pluginState), {}, {
23
23
  dirtyAnnotations: false,
@@ -52,7 +52,7 @@ export default (function (pluginState, action) {
52
52
  return pluginState;
53
53
  }
54
54
  });
55
- function getNewDraftState(pluginState, drafting, editorState, targetType) {
55
+ function getNewDraftState(pluginState, drafting, editorState, targetType, isCommentOnMediaOn, supportedBlockNodes) {
56
56
  var draftDecorationSet = pluginState.draftDecorationSet;
57
57
  if (!draftDecorationSet || !drafting) {
58
58
  draftDecorationSet = DecorationSet.empty;
@@ -63,8 +63,10 @@ function getNewDraftState(pluginState, drafting, editorState, targetType) {
63
63
  newState.bookmark = undefined;
64
64
  if (drafting && editorState) {
65
65
  newState.bookmark = editorState.selection.getBookmark();
66
- var resolvedBookmark = newState.bookmark.resolve(editorState.doc);
67
- var draftDecoration = addDraftDecoration(resolvedBookmark.from, resolvedBookmark.to, targetType);
66
+ var _ref = isCommentOnMediaOn ? resolveDraftBookmark(editorState, newState.bookmark, supportedBlockNodes) : newState.bookmark.resolve(editorState.doc),
67
+ from = _ref.from,
68
+ to = _ref.to;
69
+ var draftDecoration = addDraftDecoration(from, to, targetType);
68
70
  newState.draftDecorationSet = draftDecorationSet.add(editorState.doc, [draftDecoration]);
69
71
  }
70
72
  return newState;
@@ -51,7 +51,6 @@ export var buildToolbar = function buildToolbar(editorAnalyticsAPI) {
51
51
  },
52
52
  supportsViewMode: true // TODO: MODES-3950 Clean up this floating toolbar view mode logic
53
53
  };
54
-
55
54
  var annotation = schema.marks.annotation;
56
55
  var validNodes = Object.keys(schema.nodes).reduce(function (acc, current) {
57
56
  var type = schema.nodes[current];
@@ -4,7 +4,7 @@ import _inherits from "@babel/runtime/helpers/inherits";
4
4
  import _possibleConstructorReturn from "@babel/runtime/helpers/possibleConstructorReturn";
5
5
  import _getPrototypeOf from "@babel/runtime/helpers/getPrototypeOf";
6
6
  function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }
7
- function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }
7
+ function _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }
8
8
  import React from 'react';
9
9
  // eslint-disable-next-line @repo/internal/react/no-class-components
10
10
  export var AnnotationViewWrapper = /*#__PURE__*/function (_React$PureComponent) {
package/dist/esm/utils.js CHANGED
@@ -1,9 +1,9 @@
1
1
  import { AnnotationTypes } from '@atlaskit/adf-schema';
2
2
  import { ACTION, ACTION_SUBJECT, ACTION_SUBJECT_ID, EVENT_TYPE } from '@atlaskit/editor-common/analytics';
3
3
  import { currentMediaNodeWithPos } from '@atlaskit/editor-common/media-single';
4
- import { AnnotationSharedClassNames } from '@atlaskit/editor-common/styles';
4
+ import { AnnotationSharedClassNames, BlockAnnotationSharedClassNames } from '@atlaskit/editor-common/styles';
5
5
  import { canApplyAnnotationOnRange, containsAnyAnnotations, getAnnotationIdsFromRange, hasAnnotationMark, isParagraph, isText } from '@atlaskit/editor-common/utils';
6
- import { AllSelection, PluginKey, TextSelection } from '@atlaskit/editor-prosemirror/state';
6
+ import { AllSelection, NodeSelection, PluginKey, TextSelection } from '@atlaskit/editor-prosemirror/state';
7
7
  import { Decoration } from '@atlaskit/editor-prosemirror/view';
8
8
  import { AnnotationSelectionType } from './types';
9
9
  export { hasAnnotationMark, containsAnyAnnotations };
@@ -98,7 +98,10 @@ var validateAnnotationMark = function validateAnnotationMark(annotationMark) {
98
98
  return allowedTypes.includes(type);
99
99
  }
100
100
  };
101
-
101
+ export var decorationKey = {
102
+ block: 'blockCommentDecoration',
103
+ inline: 'inlineCommentDecoration'
104
+ };
102
105
  /*
103
106
  * add decoration for the comment selection in draft state
104
107
  * (when creating new comment)
@@ -107,11 +110,15 @@ export var addDraftDecoration = function addDraftDecoration(start, end) {
107
110
  var targetType = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'inline';
108
111
  if (targetType === 'block') {
109
112
  return Decoration.node(start, end, {
110
- class: "".concat(AnnotationSharedClassNames.draft)
113
+ class: "".concat(BlockAnnotationSharedClassNames.draft)
114
+ }, {
115
+ key: decorationKey.block
111
116
  });
112
117
  }
113
118
  return Decoration.inline(start, end, {
114
119
  class: "".concat(AnnotationSharedClassNames.draft)
120
+ }, {
121
+ key: decorationKey.inline
115
122
  });
116
123
  };
117
124
  export var getAnnotationViewKey = function getAnnotationViewKey(annotations) {
@@ -152,7 +159,41 @@ export var findAnnotationsInSelection = function findAnnotationsInSelection(sele
152
159
  reorderAnnotations(annotations, $anchor);
153
160
  return annotations;
154
161
  };
155
-
162
+ export var resolveDraftBookmark = function resolveDraftBookmark(editorState, bookmark) {
163
+ var supportedBlockNodes = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : [];
164
+ var doc = editorState.doc;
165
+ var resolvedBookmark = bookmark.resolve(doc);
166
+ var from = resolvedBookmark.from,
167
+ to = resolvedBookmark.to,
168
+ head = resolvedBookmark.head;
169
+ var draftBookmark = {
170
+ from: from,
171
+ to: to,
172
+ head: head
173
+ };
174
+ if (resolvedBookmark instanceof NodeSelection) {
175
+ // It's possible that annotation is only allowed in child node instead parent (e.g. mediaSingle vs media),
176
+ // thus, we traverse the node to find the first node that supports annotation and return its position
177
+ var nodeFound = false;
178
+ doc.nodesBetween(from, to, function (node, pos) {
179
+ // if we find the node, breakout the traversal to make sure we always record the first supported node
180
+ if (nodeFound) {
181
+ return false;
182
+ }
183
+ var nodeEndsAt = pos + node.nodeSize;
184
+ if (supportedBlockNodes.includes(node.type.name)) {
185
+ draftBookmark = {
186
+ from: pos,
187
+ to: nodeEndsAt,
188
+ head: nodeEndsAt
189
+ };
190
+ nodeFound = true;
191
+ return false;
192
+ }
193
+ });
194
+ }
195
+ return draftBookmark;
196
+ };
156
197
  /**
157
198
  * get selection from position to apply new comment for
158
199
  * @return bookmarked positions if they exists, otherwise current selection positions
@@ -272,6 +313,10 @@ function isEmptyTextSelection(selection, schema) {
272
313
  });
273
314
  return !hasContent;
274
315
  }
316
+ export var isSupportedBlockNode = function isSupportedBlockNode(node) {
317
+ var supportedBlockNodes = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
318
+ return supportedBlockNodes.indexOf(node.type.name) >= 0 || node.type.name === 'mediaSingle' && supportedBlockNodes.indexOf('media') >= 0;
319
+ };
275
320
 
276
321
  /**
277
322
  * Checks if any of the nodes in a given selection are completely whitespace
@@ -6,8 +6,8 @@ import type { AnnotationPlugin, InlineCommentInputMethod, TargetType } from '../
6
6
  export declare const updateInlineCommentResolvedState: (editorAnalyticsAPI: EditorAnalyticsAPI | undefined) => (partialNewState: InlineCommentMap, resolveMethod?: RESOLVE_METHOD) => Command;
7
7
  export declare const closeComponent: () => Command;
8
8
  export declare const clearDirtyMark: () => Command;
9
- export declare const removeInlineCommentNearSelection: (id: string, _supportedNodes?: string[]) => Command;
10
- export declare const setInlineCommentDraftState: (editorAnalyticsAPI: EditorAnalyticsAPI | undefined) => (drafting: boolean, inputMethod?: InlineCommentInputMethod, targetType?: TargetType, isCommentOnMediaOn?: boolean) => Command;
9
+ export declare const removeInlineCommentNearSelection: (id: string, supportedNodes?: string[]) => Command;
10
+ export declare const setInlineCommentDraftState: (editorAnalyticsAPI: EditorAnalyticsAPI | undefined, supportedBlockNodes?: string[]) => (drafting: boolean, inputMethod?: InlineCommentInputMethod, targetType?: TargetType, isCommentOnMediaOn?: boolean) => Command;
11
11
  export declare const addInlineComment: (editorAnalyticsAPI: EditorAnalyticsAPI | undefined, editorAPI?: ExtractInjectionAPI<AnnotationPlugin> | undefined) => (id: string) => Command;
12
12
  export declare const updateMouseState: (mouseData: InlineCommentMouseData) => Command;
13
13
  export declare const setSelectedAnnotation: (id: string) => Command;
@@ -1,6 +1,7 @@
1
1
  import type { EditorAnalyticsAPI } from '@atlaskit/editor-common/analytics';
2
2
  import type { Dispatch, EventDispatcher } from '@atlaskit/editor-common/event-dispatcher';
3
3
  import type { PortalProviderAPI } from '@atlaskit/editor-common/portal-provider';
4
+ import type { FeatureFlags } from '@atlaskit/editor-common/types';
4
5
  import type { EditorState, SelectionBookmark } from '@atlaskit/editor-prosemirror/state';
5
6
  import type { DecorationSet } from '@atlaskit/editor-prosemirror/view';
6
7
  import type { AnnotationInfo, InlineCommentAnnotationProvider, TargetType } from '../types';
@@ -20,6 +21,7 @@ export interface InlineCommentPluginOptions {
20
21
  portalProviderAPI: PortalProviderAPI;
21
22
  provider: InlineCommentAnnotationProvider;
22
23
  editorAnalyticsAPI: EditorAnalyticsAPI | undefined;
24
+ featureFlagsPluginState?: FeatureFlags;
23
25
  }
24
26
  export interface InlineCommentMouseData {
25
27
  isSelecting: boolean;
@@ -36,6 +38,8 @@ export type InlineCommentAction = {
36
38
  drafting: boolean;
37
39
  editorState: EditorState;
38
40
  targetType?: TargetType;
41
+ isCommentOnMediaOn?: boolean;
42
+ supportedBlockNodes?: string[];
39
43
  };
40
44
  } | {
41
45
  type: ACTIONS.INLINE_COMMENT_UPDATE_MOUSE_STATE;
@@ -76,4 +80,5 @@ export type InlineCommentPluginState = {
76
80
  isInlineCommentViewClosed: boolean;
77
81
  isVisible: boolean;
78
82
  skipSelectionHandling: boolean;
83
+ featureFlagsPluginState?: FeatureFlags;
79
84
  };
@@ -129,4 +129,9 @@ export type CoordsAtPos = {
129
129
  left: number;
130
130
  right: number;
131
131
  };
132
+ export type DraftBookmark = {
133
+ from: number;
134
+ to: number;
135
+ head: number;
136
+ };
132
137
  export {};
@@ -1,11 +1,11 @@
1
1
  import type { AnalyticsEventPayloadCallback } from '@atlaskit/editor-common/analytics';
2
2
  import { containsAnyAnnotations, hasAnnotationMark } from '@atlaskit/editor-common/utils';
3
3
  import type { Mark, Node, ResolvedPos, Schema, Slice } from '@atlaskit/editor-prosemirror/model';
4
- import type { EditorState, Selection } from '@atlaskit/editor-prosemirror/state';
4
+ import type { EditorState, Selection, SelectionBookmark } from '@atlaskit/editor-prosemirror/state';
5
5
  import { AllSelection, PluginKey, TextSelection } from '@atlaskit/editor-prosemirror/state';
6
6
  import { Decoration } from '@atlaskit/editor-prosemirror/view';
7
7
  import type { InlineCommentPluginState } from './pm-plugins/types';
8
- import type { AnnotationInfo, InlineCommentInputMethod, TargetType } from './types';
8
+ import type { AnnotationInfo, DraftBookmark, InlineCommentInputMethod, TargetType } from './types';
9
9
  import { AnnotationSelectionType } from './types';
10
10
  export { hasAnnotationMark, containsAnyAnnotations };
11
11
  /**
@@ -14,9 +14,14 @@ export { hasAnnotationMark, containsAnyAnnotations };
14
14
  */
15
15
  export declare const surroundingMarks: ($pos: ResolvedPos) => (readonly Mark[])[];
16
16
  export declare const getAllAnnotations: (doc: Node) => string[];
17
+ export declare const decorationKey: {
18
+ block: string;
19
+ inline: string;
20
+ };
17
21
  export declare const addDraftDecoration: (start: number, end: number, targetType?: TargetType) => Decoration;
18
22
  export declare const getAnnotationViewKey: (annotations: AnnotationInfo[]) => string;
19
23
  export declare const findAnnotationsInSelection: (selection: Selection, doc: Node) => AnnotationInfo[];
24
+ export declare const resolveDraftBookmark: (editorState: EditorState, bookmark: SelectionBookmark, supportedBlockNodes?: string[]) => DraftBookmark;
20
25
  /**
21
26
  * get selection from position to apply new comment for
22
27
  * @return bookmarked positions if they exists, otherwise current selection positions
@@ -30,6 +35,7 @@ export declare const getPluginState: (state: EditorState) => InlineCommentPlugin
30
35
  export declare const getDraftCommandAnalyticsPayload: (drafting: boolean, inputMethod: InlineCommentInputMethod) => AnalyticsEventPayloadCallback;
31
36
  export declare const isSelectionValid: (state: EditorState, isCommentOnMediaOn?: boolean, _supportedNodes?: string[]) => AnnotationSelectionType;
32
37
  export declare const hasInvalidNodes: (state: EditorState) => boolean;
38
+ export declare const isSupportedBlockNode: (node: Node, supportedBlockNodes?: string[]) => boolean;
33
39
  /**
34
40
  * Checks if any of the nodes in a given selection are completely whitespace
35
41
  * This is to conform to Confluence annotation specifications
@@ -6,8 +6,8 @@ import type { AnnotationPlugin, InlineCommentInputMethod, TargetType } from '../
6
6
  export declare const updateInlineCommentResolvedState: (editorAnalyticsAPI: EditorAnalyticsAPI | undefined) => (partialNewState: InlineCommentMap, resolveMethod?: RESOLVE_METHOD) => Command;
7
7
  export declare const closeComponent: () => Command;
8
8
  export declare const clearDirtyMark: () => Command;
9
- export declare const removeInlineCommentNearSelection: (id: string, _supportedNodes?: string[]) => Command;
10
- export declare const setInlineCommentDraftState: (editorAnalyticsAPI: EditorAnalyticsAPI | undefined) => (drafting: boolean, inputMethod?: InlineCommentInputMethod, targetType?: TargetType, isCommentOnMediaOn?: boolean) => Command;
9
+ export declare const removeInlineCommentNearSelection: (id: string, supportedNodes?: string[]) => Command;
10
+ export declare const setInlineCommentDraftState: (editorAnalyticsAPI: EditorAnalyticsAPI | undefined, supportedBlockNodes?: string[]) => (drafting: boolean, inputMethod?: InlineCommentInputMethod, targetType?: TargetType, isCommentOnMediaOn?: boolean) => Command;
11
11
  export declare const addInlineComment: (editorAnalyticsAPI: EditorAnalyticsAPI | undefined, editorAPI?: ExtractInjectionAPI<AnnotationPlugin> | undefined) => (id: string) => Command;
12
12
  export declare const updateMouseState: (mouseData: InlineCommentMouseData) => Command;
13
13
  export declare const setSelectedAnnotation: (id: string) => Command;
@@ -1,6 +1,7 @@
1
1
  import type { EditorAnalyticsAPI } from '@atlaskit/editor-common/analytics';
2
2
  import type { Dispatch, EventDispatcher } from '@atlaskit/editor-common/event-dispatcher';
3
3
  import type { PortalProviderAPI } from '@atlaskit/editor-common/portal-provider';
4
+ import type { FeatureFlags } from '@atlaskit/editor-common/types';
4
5
  import type { EditorState, SelectionBookmark } from '@atlaskit/editor-prosemirror/state';
5
6
  import type { DecorationSet } from '@atlaskit/editor-prosemirror/view';
6
7
  import type { AnnotationInfo, InlineCommentAnnotationProvider, TargetType } from '../types';
@@ -20,6 +21,7 @@ export interface InlineCommentPluginOptions {
20
21
  portalProviderAPI: PortalProviderAPI;
21
22
  provider: InlineCommentAnnotationProvider;
22
23
  editorAnalyticsAPI: EditorAnalyticsAPI | undefined;
24
+ featureFlagsPluginState?: FeatureFlags;
23
25
  }
24
26
  export interface InlineCommentMouseData {
25
27
  isSelecting: boolean;
@@ -36,6 +38,8 @@ export type InlineCommentAction = {
36
38
  drafting: boolean;
37
39
  editorState: EditorState;
38
40
  targetType?: TargetType;
41
+ isCommentOnMediaOn?: boolean;
42
+ supportedBlockNodes?: string[];
39
43
  };
40
44
  } | {
41
45
  type: ACTIONS.INLINE_COMMENT_UPDATE_MOUSE_STATE;
@@ -76,4 +80,5 @@ export type InlineCommentPluginState = {
76
80
  isInlineCommentViewClosed: boolean;
77
81
  isVisible: boolean;
78
82
  skipSelectionHandling: boolean;
83
+ featureFlagsPluginState?: FeatureFlags;
79
84
  };
@@ -129,4 +129,9 @@ export type CoordsAtPos = {
129
129
  left: number;
130
130
  right: number;
131
131
  };
132
+ export type DraftBookmark = {
133
+ from: number;
134
+ to: number;
135
+ head: number;
136
+ };
132
137
  export {};
@@ -1,11 +1,11 @@
1
1
  import type { AnalyticsEventPayloadCallback } from '@atlaskit/editor-common/analytics';
2
2
  import { containsAnyAnnotations, hasAnnotationMark } from '@atlaskit/editor-common/utils';
3
3
  import type { Mark, Node, ResolvedPos, Schema, Slice } from '@atlaskit/editor-prosemirror/model';
4
- import type { EditorState, Selection } from '@atlaskit/editor-prosemirror/state';
4
+ import type { EditorState, Selection, SelectionBookmark } from '@atlaskit/editor-prosemirror/state';
5
5
  import { AllSelection, PluginKey, TextSelection } from '@atlaskit/editor-prosemirror/state';
6
6
  import { Decoration } from '@atlaskit/editor-prosemirror/view';
7
7
  import type { InlineCommentPluginState } from './pm-plugins/types';
8
- import type { AnnotationInfo, InlineCommentInputMethod, TargetType } from './types';
8
+ import type { AnnotationInfo, DraftBookmark, InlineCommentInputMethod, TargetType } from './types';
9
9
  import { AnnotationSelectionType } from './types';
10
10
  export { hasAnnotationMark, containsAnyAnnotations };
11
11
  /**
@@ -14,9 +14,14 @@ export { hasAnnotationMark, containsAnyAnnotations };
14
14
  */
15
15
  export declare const surroundingMarks: ($pos: ResolvedPos) => (readonly Mark[])[];
16
16
  export declare const getAllAnnotations: (doc: Node) => string[];
17
+ export declare const decorationKey: {
18
+ block: string;
19
+ inline: string;
20
+ };
17
21
  export declare const addDraftDecoration: (start: number, end: number, targetType?: TargetType) => Decoration;
18
22
  export declare const getAnnotationViewKey: (annotations: AnnotationInfo[]) => string;
19
23
  export declare const findAnnotationsInSelection: (selection: Selection, doc: Node) => AnnotationInfo[];
24
+ export declare const resolveDraftBookmark: (editorState: EditorState, bookmark: SelectionBookmark, supportedBlockNodes?: string[]) => DraftBookmark;
20
25
  /**
21
26
  * get selection from position to apply new comment for
22
27
  * @return bookmarked positions if they exists, otherwise current selection positions
@@ -30,6 +35,7 @@ export declare const getPluginState: (state: EditorState) => InlineCommentPlugin
30
35
  export declare const getDraftCommandAnalyticsPayload: (drafting: boolean, inputMethod: InlineCommentInputMethod) => AnalyticsEventPayloadCallback;
31
36
  export declare const isSelectionValid: (state: EditorState, isCommentOnMediaOn?: boolean, _supportedNodes?: string[]) => AnnotationSelectionType;
32
37
  export declare const hasInvalidNodes: (state: EditorState) => boolean;
38
+ export declare const isSupportedBlockNode: (node: Node, supportedBlockNodes?: string[]) => boolean;
33
39
  /**
34
40
  * Checks if any of the nodes in a given selection are completely whitespace
35
41
  * This is to conform to Confluence annotation specifications