@atlaskit/renderer 148.1.0 → 149.0.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 (65) hide show
  1. package/CHANGELOG.md +35 -0
  2. package/dist/cjs/actions/index.js +35 -3
  3. package/dist/cjs/react/index.js +8 -0
  4. package/dist/cjs/react/marks/annotation.js +3 -1
  5. package/dist/cjs/react/nodes/extension-comments.compiled.css +4 -0
  6. package/dist/cjs/react/nodes/extension-comments.js +144 -0
  7. package/dist/cjs/react/nodes/extension.js +86 -11
  8. package/dist/cjs/react/nodes/layoutColumn-compiled.js +1 -2
  9. package/dist/cjs/react/nodes/layoutColumn-emotion.js +1 -2
  10. package/dist/cjs/react/nodes/table/colgroup.js +1 -2
  11. package/dist/cjs/steps/index.js +23 -0
  12. package/dist/cjs/ui/Renderer/RendererStyleContainer.js +1 -1
  13. package/dist/cjs/ui/Renderer/index.js +1 -1
  14. package/dist/cjs/ui/annotations/contexts/AnnotationRangeContext.js +29 -11
  15. package/dist/cjs/ui/annotations/element/extension.compiled.css +6 -0
  16. package/dist/cjs/ui/annotations/element/extension.js +34 -0
  17. package/dist/cjs/ui/annotations/element/index.js +4 -2
  18. package/dist/cjs/ui/annotations/element/mark.js +11 -1
  19. package/dist/cjs/ui/annotations/index.js +2 -1
  20. package/dist/es2019/actions/index.js +33 -3
  21. package/dist/es2019/react/index.js +8 -0
  22. package/dist/es2019/react/marks/annotation.js +3 -1
  23. package/dist/es2019/react/nodes/extension-comments.compiled.css +4 -0
  24. package/dist/es2019/react/nodes/extension-comments.js +115 -0
  25. package/dist/es2019/react/nodes/extension.js +83 -7
  26. package/dist/es2019/react/nodes/layoutColumn-compiled.js +2 -2
  27. package/dist/es2019/react/nodes/layoutColumn-emotion.js +2 -2
  28. package/dist/es2019/react/nodes/table/colgroup.js +1 -2
  29. package/dist/es2019/steps/index.js +25 -0
  30. package/dist/es2019/ui/Renderer/RendererStyleContainer.js +1 -1
  31. package/dist/es2019/ui/Renderer/index.js +1 -1
  32. package/dist/es2019/ui/annotations/contexts/AnnotationRangeContext.js +28 -12
  33. package/dist/es2019/ui/annotations/element/extension.compiled.css +6 -0
  34. package/dist/es2019/ui/annotations/element/extension.js +26 -0
  35. package/dist/es2019/ui/annotations/element/index.js +4 -2
  36. package/dist/es2019/ui/annotations/element/mark.js +11 -1
  37. package/dist/es2019/ui/annotations/index.js +2 -1
  38. package/dist/esm/actions/index.js +35 -3
  39. package/dist/esm/react/index.js +8 -0
  40. package/dist/esm/react/marks/annotation.js +3 -1
  41. package/dist/esm/react/nodes/extension-comments.compiled.css +4 -0
  42. package/dist/esm/react/nodes/extension-comments.js +135 -0
  43. package/dist/esm/react/nodes/extension.js +86 -7
  44. package/dist/esm/react/nodes/layoutColumn-compiled.js +2 -2
  45. package/dist/esm/react/nodes/layoutColumn-emotion.js +2 -2
  46. package/dist/esm/react/nodes/table/colgroup.js +1 -2
  47. package/dist/esm/steps/index.js +23 -0
  48. package/dist/esm/ui/Renderer/RendererStyleContainer.js +1 -1
  49. package/dist/esm/ui/Renderer/index.js +1 -1
  50. package/dist/esm/ui/annotations/contexts/AnnotationRangeContext.js +30 -12
  51. package/dist/esm/ui/annotations/element/extension.compiled.css +6 -0
  52. package/dist/esm/ui/annotations/element/extension.js +27 -0
  53. package/dist/esm/ui/annotations/element/index.js +4 -2
  54. package/dist/esm/ui/annotations/element/mark.js +11 -1
  55. package/dist/esm/ui/annotations/index.js +2 -1
  56. package/dist/types/actions/index.d.ts +13 -0
  57. package/dist/types/react/marks/annotation.d.ts +1 -1
  58. package/dist/types/react/nodes/extension-comments.d.ts +17 -0
  59. package/dist/types/react/nodes/extension.d.ts +12 -0
  60. package/dist/types/react/types.d.ts +1 -0
  61. package/dist/types/ui/annotations/contexts/AnnotationRangeContext.d.ts +4 -2
  62. package/dist/types/ui/annotations/element/extension.d.ts +17 -0
  63. package/dist/types/ui/annotations/element/index.d.ts +2 -1
  64. package/dist/types/ui/annotations/element/mark.d.ts +3 -107
  65. package/package.json +5 -11
@@ -219,6 +219,24 @@ export function resolvePos(node, offset, findEnd = false) {
219
219
  }
220
220
  return resolvedPos + offset;
221
221
  }
222
+ function getSelectedCommentTargetPosition(range) {
223
+ const {
224
+ startContainer,
225
+ startOffset,
226
+ endContainer,
227
+ endOffset
228
+ } = range;
229
+ if (startContainer !== endContainer || endOffset !== startOffset + 1) {
230
+ return false;
231
+ }
232
+ const selectedNode = startContainer.childNodes[startOffset];
233
+ if (!selectedNode || !isElementNode(selectedNode) || selectedNode.dataset.inlineCommentsTarget !== 'true' || !isPositionPointer(selectedNode)) {
234
+ return false;
235
+ }
236
+
237
+ // Subtract 1 from the renderer start position to get the position before the extension node.
238
+ return getStartPos(selectedNode) - 1;
239
+ }
222
240
  export function getPosFromRange(range) {
223
241
  const {
224
242
  startContainer,
@@ -226,6 +244,13 @@ export function getPosFromRange(range) {
226
244
  endContainer,
227
245
  endOffset
228
246
  } = range;
247
+ const selectedCommentTargetPosition = fg('cc_maui_annotations_on_extensions') && getSelectedCommentTargetPosition(range);
248
+ if (selectedCommentTargetPosition !== false) {
249
+ return {
250
+ from: selectedCommentTargetPosition,
251
+ to: selectedCommentTargetPosition
252
+ };
253
+ }
229
254
  const possibleMediaOrMediaSingleElement = findParent(startContainer);
230
255
 
231
256
  // Video hover targets return media single, not media, thus, the extra check in condition.
@@ -2967,7 +2967,7 @@ export const RendererStyleContainer = props => {
2967
2967
  // eslint-disable-next-line @atlaskit/platform/no-preconditioning
2968
2968
  fg('editor_inline_comments_on_inline_nodes') && rendererAnnotationStylesCommentHeightFix, expValEquals('platform_editor_copy_link_a11y_inconsistency_fix', 'isEnabled', true) ? baseOtherStyles : baseOtherStylesDuplicateAnchor, expandSsrMarginStyles,
2969
2969
  // this should be placed after baseOtherStyles
2970
- expValEquals('platform_editor_render_bodied_extension_as_inline', 'isEnabled', true) && (expValEquals('platform_editor_remove_important_in_render_ext', 'isEnabled', true) ? extensionAsInlineStyle : oldExtensionAsInlineStyle), fg('platform_forge_inline_bodied_macro') && [migratedInlineBodiedFlowStyle, forgeInlineBodiedSpacingStyle], inlineExtensionRendererMarginFix, allowNestedHeaderLinks && (expValEquals('platform_editor_copy_link_a11y_inconsistency_fix', 'isEnabled', true) ? alignedHeadingAnchorStyle : alignedHeadingAnchorStyleDuplicateAnchor), mediaSingleSharedStyle, firstWrappedMediaStyles, tableSharedStyle, expValEquals('platform_editor_table_q4_loveability', 'isEnabled', true) && roundedTableOuterBorderOverlayStyles, expValEquals('platform_editor_table_q4_loveability', 'isEnabled', true) && roundedTableRemixBlockHighlightStyles, tableContentModeScopedStyles, tableContentModeExtensionContainmentStyles, tableContentModeNestedTableStyles, tableRendererHeaderStylesForTableCellOnly, fg('platform_editor_bordered_panel_nested_in_table') && tableRendererNestedPanelStyles, isBackgroundClipBrowserFixNeeded() && tableStylesBackGroundClipForGeckoForTableCellOnly, firstNodeWithNotMarginTopWithNestedDnD, rendererTableStyles, isStickyScrollbarOn && stickyScrollbarStyles, isStickyScrollbarOn && isExperimentEnabled('platform_editor_table_css_overflow_shadow') && stickyScrollbarOverflowShadowFixStyles, rendererTableHeaderEqualHeightStylesForTableCellOnly, allowColumnSorting && rendererTableSortableColumnStyles, allowColumnSorting && expValEqualsNoExposure('platform_editor_table_menu_updates', 'isEnabled', true) && rendererTableSortableColumnValignStyles, allowColumnSorting && allowNestedHeaderLinks && (expValEquals('platform_editor_copy_link_a11y_inconsistency_fix', 'isEnabled', true) ? rendererTableHeaderEqualHeightStylesAllowNestedHeaderLinks : rendererTableHeaderEqualHeightStylesAllowNestedHeaderLinksDuplicateAnchor), rendererTableColumnStyles, stickyHeaderStyles, codeBlockAndLayoutStyles, columnLayoutSharedStyle, isAdvancedLayoutsOn && columnLayoutResponsiveSharedStyle, isAdvancedLayoutsOn && columnLayoutResponsiveRendererStyles, isAdvancedLayoutsOn && layoutSectionForAdvancedLayoutsStyles, !useBlockRenderForCodeBlock && gridRenderForCodeBlockStyles, browser.safari && codeBlockInListSafariFixStyles, fg('platform_renderer_ssr_block_margin_fix') && [blockSsrMarginStyles, layoutBlockSsrMarginStyles, browser.safari && codeBlockInListSsrMarginSafariFixStyles], appearance === 'full-page' && !isPreviewPanelResponsivenessOn && responsiveBreakoutWidth, appearance === 'full-page' && isPreviewPanelResponsivenessOn && responsiveBreakoutWidthWithReducedPadding, (appearance === 'full-width' || appearance === 'max') && responsiveBreakoutWidthFullWidth, expValEquals('platform_editor_lovability_emoji_scaling', 'isEnabled', true) ? contentMode === 'compact' ? scaledDenseEmojiStyles : scaledEmojiStyles : contentMode === 'compact' ? denseStyles : undefined, contentMode === 'compact' ? scaledDenseUnicodeEmojiStylesNew : scaledUnicodeEmojiStylesNew, syncBlockStyles, centerWrapperStyles, isInsideSyncBlock ? syncBlockRendererStyles : null, isInsideSyncBlock && tableFakeBorderStyles, isInsideSyncBlock && expValEquals('platform_editor_table_q4_loveability', 'isEnabled', true) ? roundedTableFakeBorderOverlayStyles : null, expValEquals('platform_editor_hide_extension_renderer_support', 'isEnabled', true) && hideExtensionStyles],
2970
+ expValEquals('platform_editor_render_bodied_extension_as_inline', 'isEnabled', true) && (expValEquals('platform_editor_remove_important_in_render_ext', 'isEnabled', true) ? extensionAsInlineStyle : oldExtensionAsInlineStyle), fg('platform_forge_inline_bodied_macro') && [migratedInlineBodiedFlowStyle, forgeInlineBodiedSpacingStyle], inlineExtensionRendererMarginFix, allowNestedHeaderLinks && (expValEquals('platform_editor_copy_link_a11y_inconsistency_fix', 'isEnabled', true) ? alignedHeadingAnchorStyle : alignedHeadingAnchorStyleDuplicateAnchor), mediaSingleSharedStyle, firstWrappedMediaStyles, tableSharedStyle, expValEquals('platform_editor_table_q4_loveability', 'isEnabled', true) && roundedTableOuterBorderOverlayStyles, expValEquals('platform_editor_table_q4_loveability', 'isEnabled', true) && roundedTableRemixBlockHighlightStyles, tableContentModeScopedStyles, tableContentModeExtensionContainmentStyles, tableContentModeNestedTableStyles, tableRendererHeaderStylesForTableCellOnly, fg('platform_editor_bordered_panel_nested_in_table') && tableRendererNestedPanelStyles, isBackgroundClipBrowserFixNeeded() && tableStylesBackGroundClipForGeckoForTableCellOnly, firstNodeWithNotMarginTopWithNestedDnD, rendererTableStyles, isStickyScrollbarOn && stickyScrollbarStyles, isStickyScrollbarOn && isExperimentEnabled('platform_editor_table_css_overflow_shadow') && stickyScrollbarOverflowShadowFixStyles, rendererTableHeaderEqualHeightStylesForTableCellOnly, allowColumnSorting && rendererTableSortableColumnStyles, allowColumnSorting && expValEqualsNoExposure('platform_editor_table_menu_updates', 'isEnabled', true) && rendererTableSortableColumnValignStyles, allowColumnSorting && allowNestedHeaderLinks && (expValEquals('platform_editor_copy_link_a11y_inconsistency_fix', 'isEnabled', true) ? rendererTableHeaderEqualHeightStylesAllowNestedHeaderLinks : rendererTableHeaderEqualHeightStylesAllowNestedHeaderLinksDuplicateAnchor), rendererTableColumnStyles, stickyHeaderStyles, codeBlockAndLayoutStyles, columnLayoutSharedStyle, isAdvancedLayoutsOn && columnLayoutResponsiveSharedStyle, isAdvancedLayoutsOn && columnLayoutResponsiveRendererStyles, isAdvancedLayoutsOn && layoutSectionForAdvancedLayoutsStyles, !useBlockRenderForCodeBlock && gridRenderForCodeBlockStyles, browser.safari && codeBlockInListSafariFixStyles, blockSsrMarginStyles, layoutBlockSsrMarginStyles, browser.safari && codeBlockInListSsrMarginSafariFixStyles, appearance === 'full-page' && !isPreviewPanelResponsivenessOn && responsiveBreakoutWidth, appearance === 'full-page' && isPreviewPanelResponsivenessOn && responsiveBreakoutWidthWithReducedPadding, (appearance === 'full-width' || appearance === 'max') && responsiveBreakoutWidthFullWidth, expValEquals('platform_editor_lovability_emoji_scaling', 'isEnabled', true) ? contentMode === 'compact' ? scaledDenseEmojiStyles : scaledEmojiStyles : contentMode === 'compact' ? denseStyles : undefined, contentMode === 'compact' ? scaledDenseUnicodeEmojiStylesNew : scaledUnicodeEmojiStylesNew, syncBlockStyles, centerWrapperStyles, isInsideSyncBlock ? syncBlockRendererStyles : null, isInsideSyncBlock && tableFakeBorderStyles, isInsideSyncBlock && expValEquals('platform_editor_table_q4_loveability', 'isEnabled', true) ? roundedTableFakeBorderOverlayStyles : null, expValEquals('platform_editor_hide_extension_renderer_support', 'isEnabled', true) && hideExtensionStyles],
2971
2971
  "data-testid": testId
2972
2972
  }, children);
2973
2973
  };
@@ -57,7 +57,7 @@ export const DEGRADED_SEVERITY_THRESHOLD = 3000;
57
57
  const TABLE_INFO_TIMEOUT = 10000;
58
58
  const RENDER_EVENT_SAMPLE_RATE = 0.1;
59
59
  const packageName = "@atlaskit/renderer";
60
- const packageVersion = "148.0.4";
60
+ const packageVersion = "149.0.0";
61
61
  const setAsQueryContainerStyles = css({
62
62
  containerName: 'ak-renderer-wrapper',
63
63
  containerType: 'inline-size'
@@ -1,4 +1,5 @@
1
- import React, { createContext, useCallback, useContext, useMemo, useReducer } from 'react';
1
+ import React, { createContext, useCallback, useContext, useMemo, useReducer, useRef } from 'react';
2
+ import { fg } from '@atlaskit/platform-feature-flags/fg';
2
3
 
3
4
  // oxlint-disable-next-line eslint/no-redeclare
4
5
 
@@ -117,8 +118,10 @@ export const AnnotationRangeDispatchContext = /*#__PURE__*/createContext({
117
118
  });
118
119
  export const AnnotationRangeProviderInner = ({
119
120
  children,
120
- allowCommentsOnMedia
121
+ allowCommentsOnMedia,
122
+ hasBlockNodeSupport
121
123
  }) => {
124
+ const extensionCommentsEnabled = !!hasBlockNodeSupport && fg('cc_maui_annotations_on_extensions');
122
125
  const [{
123
126
  selectionRange,
124
127
  hoverRange,
@@ -138,21 +141,32 @@ export const AnnotationRangeProviderInner = ({
138
141
  type: 'setSelection',
139
142
  range
140
143
  }), []);
144
+ const hoverDraftRangeRef = useRef(hoverDraftRange);
145
+ hoverDraftRangeRef.current = hoverDraftRange;
141
146
  const setHoverTarget = useCallback(target => {
142
- // the HoverComponent expects an element deeply nested inside media, these classes work with the current implementation
143
- const mediaNode = target.querySelector('.media-card-inline-player, .media-file-card-view');
144
- if (!mediaNode) {
147
+ const draftRange = hoverDraftRangeRef.current;
148
+ const draftTarget = draftRange === null || draftRange === void 0 ? void 0 : draftRange.startContainer.childNodes[draftRange.startOffset];
149
+ if (extensionCommentsEnabled && draftTarget instanceof HTMLElement && draftTarget.matches('.ak-renderer-extension[data-inline-comments-target="true"]')) {
150
+ // Keep the composer callbacks bound to the chart chosen when its draft opened.
151
+ return;
152
+ }
153
+ // The HoverComponent expects an element deeply nested inside media or the eligible
154
+ // block node's wrapper. Each selector is only included when its comment type is
155
+ // supported, so hover targeting never activates on an ineligible block node.
156
+ const selectors = [allowCommentsOnMedia && '.media-card-inline-player, .media-file-card-view', extensionCommentsEnabled && '.ak-renderer-extension[data-inline-comments-target="true"]'].filter(selector => Boolean(selector)).join(', ');
157
+ const hoverableNode = extensionCommentsEnabled && target.matches('.ak-renderer-extension[data-inline-comments-target="true"]') ? target : selectors ? target.querySelector(selectors) : null;
158
+ if (!hoverableNode) {
145
159
  return;
146
160
  }
147
- // eslint-disable-next-line @atlaskit/platform/no-direct-document-usage -- range for media hover highlight
161
+ // eslint-disable-next-line @atlaskit/platform/no-direct-document-usage -- range for media/extension hover highlight
148
162
  const range = document.createRange();
149
- range.setStartBefore(mediaNode);
150
- range.setEndAfter(mediaNode);
163
+ range.setStartBefore(hoverableNode);
164
+ range.setEndAfter(hoverableNode);
151
165
  dispatch({
152
166
  type: 'setHover',
153
167
  range
154
168
  });
155
- }, []);
169
+ }, [allowCommentsOnMedia, extensionCommentsEnabled]);
156
170
  const promoteSelectionToDraft = useCallback(position => {
157
171
  dispatch({
158
172
  type: 'promoteSelectionToDraft',
@@ -191,12 +205,12 @@ export const AnnotationRangeProviderInner = ({
191
205
  clearSelectionRange,
192
206
  clearHoverRange,
193
207
  setSelectionRange,
194
- setHoverTarget: !!allowCommentsOnMedia ? setHoverTarget : undefined,
208
+ setHoverTarget: allowCommentsOnMedia || extensionCommentsEnabled ? setHoverTarget : undefined,
195
209
  promoteSelectionToDraft,
196
210
  promoteHoverToDraft,
197
211
  clearSelectionDraft,
198
212
  clearHoverDraft
199
- }), [allowCommentsOnMedia, clearSelectionRange, clearHoverRange, setSelectionRange, setHoverTarget, promoteSelectionToDraft, promoteHoverToDraft, clearSelectionDraft, clearHoverDraft]);
213
+ }), [allowCommentsOnMedia, extensionCommentsEnabled, clearSelectionRange, clearHoverRange, setSelectionRange, setHoverTarget, promoteSelectionToDraft, promoteHoverToDraft, clearSelectionDraft, clearHoverDraft]);
200
214
  return /*#__PURE__*/React.createElement(AnnotationRangeStateContext.Provider, {
201
215
  value: stateData
202
216
  }, /*#__PURE__*/React.createElement(AnnotationRangeDispatchContext.Provider, {
@@ -206,6 +220,7 @@ export const AnnotationRangeProviderInner = ({
206
220
  export const AnnotationRangeProvider = ({
207
221
  children,
208
222
  allowCommentsOnMedia,
223
+ hasBlockNodeSupport,
209
224
  isNestedRender
210
225
  }) => {
211
226
  /*
@@ -214,7 +229,8 @@ export const AnnotationRangeProvider = ({
214
229
  * and we need the original context to create annotations on extensions.
215
230
  */
216
231
  return isNestedRender ? /*#__PURE__*/React.createElement(React.Fragment, null, children) : /*#__PURE__*/React.createElement(AnnotationRangeProviderInner, {
217
- allowCommentsOnMedia: allowCommentsOnMedia
232
+ allowCommentsOnMedia: allowCommentsOnMedia,
233
+ hasBlockNodeSupport: hasBlockNodeSupport
218
234
  }, children);
219
235
  };
220
236
  export const useAnnotationRangeState = () => {
@@ -0,0 +1,6 @@
1
+ ._154iidpf{top:0}
2
+ ._1ltvidpf{left:0}
3
+ ._1xi2idpf{right:0}
4
+ ._94n5idpf{bottom:0}
5
+ ._kqswstnw{position:absolute}
6
+ ._lcxvglyw{pointer-events:none}
@@ -0,0 +1,26 @@
1
+ /* extension.tsx generated by @compiled/babel-plugin v3.0.2 */
2
+ import "./extension.compiled.css";
3
+ import { ax, ix } from "@compiled/react/runtime";
4
+ import React from 'react';
5
+ const styles = {
6
+ anchor: "_kqswstnw _154iidpf _1xi2idpf _94n5idpf _1ltvidpf _lcxvglyw"
7
+ };
8
+
9
+ /** Full-chart anchors for comment navigation, without wrapping or intercepting the iframe. */
10
+ export const ExtensionAnnotation = ({
11
+ id,
12
+ dataAttributes,
13
+ markRef
14
+ }) => /*#__PURE__*/React.createElement("div", {
15
+ id: id,
16
+ ref: markRef,
17
+ "data-id": dataAttributes['data-id'],
18
+ "data-mark-type": dataAttributes['data-mark-type'],
19
+ "data-mark-annotation-type": dataAttributes['data-mark-annotation-type'],
20
+ "data-mark-annotation-state": dataAttributes['data-mark-annotation-state'],
21
+ "data-block-mark": dataAttributes['data-block-mark'],
22
+ "data-renderer-mark": dataAttributes['data-renderer-mark'],
23
+ "data-has-focus": dataAttributes['data-has-focus'],
24
+ "data-is-hovered": dataAttributes['data-is-hovered'],
25
+ className: ax([styles.anchor])
26
+ });
@@ -12,7 +12,8 @@ const MarkElement = ({
12
12
  children,
13
13
  dataAttributes,
14
14
  id,
15
- useBlockLevel
15
+ useBlockLevel,
16
+ isExtension
16
17
  }) => {
17
18
  const updateSubscriber = useInlineCommentSubscriberContext();
18
19
  const states = useContext(InlineCommentsStateContext);
@@ -93,7 +94,8 @@ const MarkElement = ({
93
94
  hasFocus: hasFocus,
94
95
  isHovered: isHovered,
95
96
  state: states[id],
96
- useBlockLevel: useBlockLevel
97
+ useBlockLevel: useBlockLevel,
98
+ isExtension: isExtension
97
99
  }, children);
98
100
  };
99
101
  export { MarkElement };
@@ -12,6 +12,7 @@ import { AnnotationMarkStates } from '@atlaskit/adf-schema/annotation';
12
12
  import { fg } from '@atlaskit/platform-feature-flags/fg';
13
13
  import { inlineCommentMessages } from '../../../messages';
14
14
  import { useAnnotationManagerDispatch, useAnnotationManagerState } from '../contexts/AnnotationManagerContext';
15
+ import { ExtensionAnnotation } from './extension';
15
16
  const markStyles = css({
16
17
  color: 'inherit',
17
18
  backgroundColor: 'unset',
@@ -130,7 +131,8 @@ export const MarkComponent = ({
130
131
  hasFocus,
131
132
  isHovered,
132
133
  onClick,
133
- useBlockLevel
134
+ useBlockLevel,
135
+ isExtension
134
136
  }) => {
135
137
  const intl = useIntl();
136
138
  const annotationIds = useMemo(() => [...new Set([...annotationParentIds, id])], [id, annotationParentIds]);
@@ -223,6 +225,14 @@ export const MarkComponent = ({
223
225
  'aria-details': annotationIds.join(', '),
224
226
  ...desktopAccessibilityAttributes
225
227
  };
228
+ if (isExtension && fg('cc_maui_annotations_on_extensions')) {
229
+ // The chart's badge owns interaction. Anchors only supply geometry and annotation state.
230
+ return jsx(ExtensionAnnotation, {
231
+ id: id,
232
+ dataAttributes: overriddenData,
233
+ markRef: id === currentSelectedAnnotationId ? markRef : undefined
234
+ });
235
+ }
226
236
  return jsx(useBlockLevel ? 'div' : 'mark', {
227
237
  ref: id === currentSelectedAnnotationId ? markRef : undefined,
228
238
  id,
@@ -30,7 +30,7 @@ export const AnnotationsPositionContext = /*#__PURE__*/React.createContext({
30
30
  startPos: 1
31
31
  });
32
32
  export const AnnotationsWrapperInner = props => {
33
- var _providers$inlineComm, _providers$inlineComm2;
33
+ var _providers$inlineComm, _providers$inlineComm2, _providers$inlineComm3;
34
34
  const {
35
35
  children,
36
36
  rendererRef,
@@ -51,6 +51,7 @@ export const AnnotationsWrapperInner = props => {
51
51
  value: inlineCommentAnnotationsState
52
52
  }, /*#__PURE__*/React.createElement(AnnotationRangeProvider, {
53
53
  allowCommentsOnMedia: (_providers$inlineComm = providers === null || providers === void 0 ? void 0 : (_providers$inlineComm2 = providers.inlineComment) === null || _providers$inlineComm2 === void 0 ? void 0 : _providers$inlineComm2.allowCommentsOnMedia) !== null && _providers$inlineComm !== void 0 ? _providers$inlineComm : false,
54
+ hasBlockNodeSupport: Boolean(providers === null || providers === void 0 ? void 0 : (_providers$inlineComm3 = providers.inlineComment) === null || _providers$inlineComm3 === void 0 ? void 0 : _providers$inlineComm3.isBlockNodeSupported),
54
55
  isNestedRender: isNestedRender
55
56
  }, /*#__PURE__*/React.createElement(AnnotationHoverContext, null, /*#__PURE__*/React.createElement(AnnotationsContextWrapper, {
56
57
  createAnalyticsEvent: createAnalyticsEvent,
@@ -87,9 +87,10 @@ var RendererActions = /*#__PURE__*/function () {
87
87
  var to;
88
88
  var nodePos;
89
89
  var step;
90
+ var schema = this.schema;
90
91
  this.doc.descendants(function (node, pos) {
91
92
  var found = mark.isInSet(node.marks);
92
- if (found && node.type.name === 'media') {
93
+ if (found && isBlockAnnotationTarget(node, schema)) {
93
94
  nodePos = pos;
94
95
  }
95
96
  if (found && !from) {
@@ -184,13 +185,12 @@ var RendererActions = /*#__PURE__*/function () {
184
185
  key: "isRangeAnnotatable",
185
186
  value: function isRangeAnnotatable(range) {
186
187
  try {
187
- var _startContainer$paren, _endContainer$parentE;
188
188
  if (!range) {
189
189
  return false;
190
190
  }
191
191
  var startContainer = range.startContainer,
192
192
  endContainer = range.endContainer;
193
- if ((_startContainer$paren = startContainer.parentElement) !== null && _startContainer$paren !== void 0 && _startContainer$paren.closest('.ak-renderer-extension') || (_endContainer$parentE = endContainer.parentElement) !== null && _endContainer$parentE !== void 0 && _endContainer$parentE.closest('.ak-renderer-extension')) {
193
+ if (this.isInsideNestedExtensionRenderer(startContainer) || this.isInsideNestedExtensionRenderer(endContainer)) {
194
194
  return false;
195
195
  }
196
196
  return this.isValidAnnotationRange(range);
@@ -206,6 +206,38 @@ var RendererActions = /*#__PURE__*/function () {
206
206
  }
207
207
  }
208
208
 
209
+ /**
210
+ * A range only threatens a nested renderer's own document (e.g. a bodiedExtension's macro
211
+ * body, which renders its own nested `<Renderer>`) when it sits inside that nested renderer's
212
+ * `.ak-renderer-document`. Landing directly on the extension's own outer wrapper -- with no
213
+ * nested document in between -- must stay annotatable so the whole chart/extension can be
214
+ * targeted (MAUI-1256), rather than being rejected outright the way any range touching
215
+ * `.ak-renderer-extension` previously was.
216
+ *
217
+ * Behind `cc_maui_annotations_on_extensions` -- the same gate MAUI-1255 added for extension
218
+ * node-mark support -- to preserve the previous behaviour (reject anything touching
219
+ * `.ak-renderer-extension`) while the feature is off.
220
+ */
221
+ }, {
222
+ key: "isInsideNestedExtensionRenderer",
223
+ value: function isInsideNestedExtensionRenderer(container) {
224
+ // Preserve the legacy parent-based rejection while the gate is disabled.
225
+ if (!fg('cc_maui_annotations_on_extensions')) {
226
+ var _container$parentElem;
227
+ return !!((_container$parentElem = container.parentElement) !== null && _container$parentElem !== void 0 && _container$parentElem.closest('.ak-renderer-extension'));
228
+ }
229
+ var element = container instanceof Element ? container : container.parentElement;
230
+ if (!element) {
231
+ return false;
232
+ }
233
+ var extensionAncestor = element.closest('.ak-renderer-extension');
234
+ if (!extensionAncestor) {
235
+ return false;
236
+ }
237
+ var nestedDocument = element.closest('.ak-renderer-document');
238
+ return !!nestedDocument && extensionAncestor.contains(nestedDocument);
239
+ }
240
+
209
241
  // eslint-disable-next-line @repo/internal/deprecations/deprecation-ticket-required -- Ignored via go/ED-25883
210
242
  /**
211
243
  * This is replaced by `isRangeAnnotatable`.
@@ -97,6 +97,11 @@ var ReactSerializer = /*#__PURE__*/function () {
97
97
  if (shouldSkipLinkMark(mark) || shouldSkipBorderMark(mark)) {
98
98
  return content;
99
99
  }
100
+ // Extension annotations are sibling anchors inside the stable extension shell.
101
+ // Wrapping the extension here would remount its iframe whenever marks change.
102
+ if (node.type.name === 'extension' && mark.type.name === 'annotation' && _this.allowAnnotations && fg('cc_maui_annotations_on_extensions')) {
103
+ return content;
104
+ }
100
105
  return _this.renderMark(markToReact(mark), _this.withMediaMarkProps(node, mark, _this.getMarkProps(mark, [], node)), "".concat(mark.type.name, "-").concat(index), content);
101
106
  }, serializedContent);
102
107
  return withExpandBodyBlock(node, currentPath, index, serialized);
@@ -549,6 +554,9 @@ var ReactSerializer = /*#__PURE__*/function () {
549
554
  var _this$getExtensionHei;
550
555
  var path = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
551
556
  return _objectSpread(_objectSpread({}, this.getProps(node, path)), {}, {
557
+ allowAnnotations: this.allowAnnotations,
558
+ allowAnnotationsDraftMode: this.surroundTextNodesWithTextWrapper,
559
+ extensionNode: node,
552
560
  extensionViewportSizes: this.extensionViewportSizes,
553
561
  hideExtensionKeysWhilePending: this.hideExtensionKeysWhilePending,
554
562
  nodeHeight: (_this$getExtensionHei = this.getExtensionHeight) === null || _this$getExtensionHei === void 0 ? void 0 : _this$getExtensionHei.call(this, node),
@@ -17,6 +17,7 @@ var AnnotationComponent = function AnnotationComponent(_ref) {
17
17
  annotationParentIds = _ref$annotationParent === void 0 ? [] : _ref$annotationParent,
18
18
  allowAnnotations = _ref.allowAnnotations,
19
19
  useBlockLevel = _ref.useBlockLevel,
20
+ isExtension = _ref.isExtension,
20
21
  isMediaInline = _ref.isMediaInline;
21
22
  var data = _objectSpread(_objectSpread({}, dataAttributes), buildAnnotationMarkDataAttributes({
22
23
  id: id,
@@ -36,7 +37,8 @@ var AnnotationComponent = function AnnotationComponent(_ref) {
36
37
  dataAttributes: data,
37
38
  annotationParentIds: annotationParentIds,
38
39
  annotationType: annotationType,
39
- useBlockLevel: useBlockLevel
40
+ useBlockLevel: useBlockLevel,
41
+ isExtension: isExtension
40
42
  }, children);
41
43
  }
42
44
  return (
@@ -0,0 +1,4 @@
1
+ ._154iu2gc{top:var(--ds-space-100,8px)}
2
+ ._1xi2u2gc{right:var(--ds-space-100,8px)}
3
+ ._kqswh2mm{position:relative}
4
+ ._kqswstnw{position:absolute}
@@ -0,0 +1,135 @@
1
+ /* extension-comments.tsx generated by @compiled/babel-plugin v3.0.2 */
2
+ import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
3
+ import "./extension-comments.compiled.css";
4
+ import { ax, ix } from "@compiled/react/runtime";
5
+ import React, { useCallback, useEffect, useMemo, useState } from 'react';
6
+ import { AnnotationMarkStates, AnnotationTypes } from '@atlaskit/adf-schema/annotation';
7
+ import { VIEW_METHOD } from '@atlaskit/editor-common/analytics';
8
+ import { CommentBadgeNext } from '@atlaskit/editor-common/media-single';
9
+ import { AnnotationUpdateEvent } from '@atlaskit/editor-common/types';
10
+ import { useAnnotationManagerState } from '../../ui/annotations/contexts/AnnotationManagerContext';
11
+ import { useAnnotationRangeState } from '../../ui/annotations/contexts/AnnotationRangeContext';
12
+ import { useInlineCommentSubscriberContext } from '../../ui/annotations/hooks/use-inline-comment-subscriber';
13
+ import { useInlineCommentsFilter } from '../../ui/annotations/hooks/use-inline-comments-filter';
14
+ import AnnotationComponent from '../marks/annotation';
15
+ var containerStyles = null;
16
+ var annotationParentIds = [];
17
+ var annotationDataAttributes = {
18
+ 'data-renderer-mark': true,
19
+ 'data-block-mark': true
20
+ };
21
+ var badgeStyles = null;
22
+ var ExtensionCommentsEnabled = function ExtensionCommentsEnabled(_ref) {
23
+ var marks = _ref.marks,
24
+ children = _ref.children,
25
+ enabled = _ref.enabled,
26
+ allowAnnotations = _ref.allowAnnotations,
27
+ allowAnnotationsDraftMode = _ref.allowAnnotationsDraftMode,
28
+ startPos = _ref.startPos;
29
+ var _useAnnotationRangeSt = useAnnotationRangeState(),
30
+ hoverDraftDocumentPosition = _useAnnotationRangeSt.hoverDraftDocumentPosition;
31
+ var isDraft = Boolean(enabled && allowAnnotationsDraftMode && hoverDraftDocumentPosition && hoverDraftDocumentPosition.from + 1 === startPos);
32
+ var updateSubscriber = useInlineCommentSubscriberContext();
33
+ var annotationIds = useMemo(function () {
34
+ var _marks$filter$map;
35
+ return (_marks$filter$map = marks === null || marks === void 0 ? void 0 : marks.filter(function (mark) {
36
+ return mark.type.name === 'annotation';
37
+ }).map(function (mark) {
38
+ return mark.attrs.id;
39
+ })) !== null && _marks$filter$map !== void 0 ? _marks$filter$map : [];
40
+ }, [marks]);
41
+ var activeIds = useInlineCommentsFilter({
42
+ annotationIds: annotationIds,
43
+ filter: {
44
+ state: AnnotationMarkStates.ACTIVE
45
+ }
46
+ });
47
+ var _useState = useState(),
48
+ _useState2 = _slicedToArray(_useState, 2),
49
+ focusedId = _useState2[0],
50
+ setFocusedId = _useState2[1];
51
+ var _useState3 = useState(false),
52
+ _useState4 = _slicedToArray(_useState3, 2),
53
+ entered = _useState4[0],
54
+ setEntered = _useState4[1];
55
+ var _useAnnotationManager = useAnnotationManagerState(),
56
+ currentSelectedAnnotationId = _useAnnotationManager.currentSelectedAnnotationId;
57
+ var active = activeIds.some(function (id) {
58
+ return id === focusedId || id === currentSelectedAnnotationId;
59
+ });
60
+ useEffect(function () {
61
+ if (!updateSubscriber) {
62
+ return;
63
+ }
64
+ var onFocus = function onFocus(payload) {
65
+ return setFocusedId(payload === null || payload === void 0 ? void 0 : payload.annotationId);
66
+ };
67
+ var onBlur = function onBlur() {
68
+ return setFocusedId(undefined);
69
+ };
70
+ updateSubscriber.on(AnnotationUpdateEvent.SET_ANNOTATION_FOCUS, onFocus);
71
+ updateSubscriber.on(AnnotationUpdateEvent.REMOVE_ANNOTATION_FOCUS, onBlur);
72
+ return function () {
73
+ updateSubscriber.off(AnnotationUpdateEvent.SET_ANNOTATION_FOCUS, onFocus);
74
+ updateSubscriber.off(AnnotationUpdateEvent.REMOVE_ANNOTATION_FOCUS, onBlur);
75
+ };
76
+ }, [updateSubscriber]);
77
+ var onClick = useCallback(function (event) {
78
+ event.preventDefault();
79
+ event.stopPropagation();
80
+ // Anchor the thread to this chart, not an icon inside the badge or a nested renderer.
81
+ var extension = event.currentTarget.closest('.ak-renderer-extension');
82
+ if (extension && activeIds.length) {
83
+ updateSubscriber === null || updateSubscriber === void 0 || updateSubscriber.emit(AnnotationUpdateEvent.ON_ANNOTATION_CLICK, {
84
+ annotationIds: activeIds,
85
+ eventTarget: extension,
86
+ eventTargetType: 'extension',
87
+ viewMethod: VIEW_METHOD.BADGE
88
+ });
89
+ }
90
+ }, [activeIds, updateSubscriber]);
91
+ var onMouseEnter = useCallback(function () {
92
+ return setEntered(true);
93
+ }, []);
94
+ var onMouseLeave = useCallback(function () {
95
+ return setEntered(false);
96
+ }, []);
97
+ return /*#__PURE__*/React.createElement("div", {
98
+ "data-annotation-draft-mark": isDraft || undefined,
99
+ "data-renderer-mark": isDraft || undefined,
100
+ "data-renderer-start-pos": isDraft ? startPos : undefined,
101
+ className: ax(["_kqswh2mm"])
102
+ }, children, allowAnnotations && annotationIds.map(function (id) {
103
+ return /*#__PURE__*/React.createElement(AnnotationComponent, {
104
+ key: id,
105
+ id: id,
106
+ annotationType: AnnotationTypes.INLINE_COMMENT,
107
+ annotationParentIds: annotationParentIds,
108
+ allowAnnotations: true,
109
+ useBlockLevel: true,
110
+ isExtension: true,
111
+ dataAttributes: annotationDataAttributes
112
+ });
113
+ }), enabled && activeIds.length > 0 && updateSubscriber && /*#__PURE__*/React.createElement("div", {
114
+ className: ax(["_kqswstnw _154iu2gc _1xi2u2gc"])
115
+ }, /*#__PURE__*/React.createElement(CommentBadgeNext, {
116
+ status: active ? 'active' : entered ? 'entered' : 'default',
117
+ onClick: onClick,
118
+ onMouseEnter: onMouseEnter,
119
+ onMouseLeave: onMouseLeave
120
+ })));
121
+ };
122
+
123
+ /** Only node-aware provider-approved extensions receive comment visuals. */
124
+ export var ExtensionComments = function ExtensionComments(props) {
125
+ if (!props.enabled && !props.allowAnnotations) {
126
+ return /*#__PURE__*/React.createElement(React.Fragment, null, props.children);
127
+ }
128
+ return /*#__PURE__*/React.createElement(ExtensionCommentsEnabled, {
129
+ enabled: props.enabled,
130
+ allowAnnotations: props.allowAnnotations,
131
+ allowAnnotationsDraftMode: props.allowAnnotationsDraftMode,
132
+ startPos: props.startPos,
133
+ marks: props.marks
134
+ }, props.children);
135
+ };