@atlaskit/editor-plugin-block-controls 20.0.3 → 20.1.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 (107) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/dist/cjs/blockControlsPlugin.js +53 -17
  3. package/dist/cjs/editor-commands/show-drag-handle.js +17 -5
  4. package/dist/cjs/pm-plugins/decorations-anchor.js +2 -1
  5. package/dist/cjs/pm-plugins/decorations-drop-target-active.js +2 -1
  6. package/dist/cjs/pm-plugins/decorations-drop-target.js +2 -1
  7. package/dist/cjs/pm-plugins/decorations-surface-anchor.js +72 -0
  8. package/dist/cjs/pm-plugins/handle-mouse-down.js +2 -1
  9. package/dist/cjs/pm-plugins/handle-mouse-over.js +3 -2
  10. package/dist/cjs/pm-plugins/handle-sparse-mouse-over.js +125 -0
  11. package/dist/cjs/pm-plugins/main.js +66 -54
  12. package/dist/cjs/pm-plugins/sparse-surfaces.js +49 -0
  13. package/dist/cjs/pm-plugins/utils/sparse-surface-candidates.js +419 -0
  14. package/dist/cjs/pm-plugins/utils/sparse-surfaces-mapping.js +108 -0
  15. package/dist/cjs/pm-plugins/utils/sparse-surfaces-state.js +53 -0
  16. package/dist/cjs/pm-plugins/utils/sparse-surfaces-view.js +134 -0
  17. package/dist/cjs/pm-plugins/utils/surface-viewport.js +223 -0
  18. package/dist/cjs/pm-plugins/utils/transactions.js +5 -0
  19. package/dist/cjs/ui/block-controls-left-surfaces.js +31 -25
  20. package/dist/cjs/ui/block-controls-right-surfaces.js +31 -25
  21. package/dist/cjs/ui/block-controls-surface-context.js +1 -0
  22. package/dist/cjs/ui/block-controls-surface-drag-handle-registration.js +6 -7
  23. package/dist/cjs/ui/block-controls-surface-drag-handle.js +6 -2
  24. package/dist/cjs/ui/drag-handle.js +5 -3
  25. package/dist/cjs/ui/drop-target-layout.js +3 -2
  26. package/dist/cjs/ui/drop-target.js +3 -2
  27. package/dist/cjs/ui/global-styles.js +69 -27
  28. package/dist/cjs/ui/inline-drop-target.js +6 -5
  29. package/dist/cjs/ui/utils/anchor-name.js +2 -1
  30. package/dist/cjs/ui/utils/dom-attr-name.js +3 -2
  31. package/dist/cjs/ui/utils/get-surface-placement.js +2 -1
  32. package/dist/es2019/blockControlsPlugin.js +42 -8
  33. package/dist/es2019/editor-commands/show-drag-handle.js +14 -2
  34. package/dist/es2019/pm-plugins/decorations-anchor.js +2 -1
  35. package/dist/es2019/pm-plugins/decorations-drop-target-active.js +2 -1
  36. package/dist/es2019/pm-plugins/decorations-drop-target.js +2 -1
  37. package/dist/es2019/pm-plugins/decorations-surface-anchor.js +56 -0
  38. package/dist/es2019/pm-plugins/handle-mouse-down.js +2 -1
  39. package/dist/es2019/pm-plugins/handle-mouse-over.js +3 -2
  40. package/dist/es2019/pm-plugins/handle-sparse-mouse-over.js +116 -0
  41. package/dist/es2019/pm-plugins/main.js +70 -54
  42. package/dist/es2019/pm-plugins/sparse-surfaces.js +37 -0
  43. package/dist/es2019/pm-plugins/utils/sparse-surface-candidates.js +305 -0
  44. package/dist/es2019/pm-plugins/utils/sparse-surfaces-mapping.js +78 -0
  45. package/dist/es2019/pm-plugins/utils/sparse-surfaces-state.js +39 -0
  46. package/dist/es2019/pm-plugins/utils/sparse-surfaces-view.js +121 -0
  47. package/dist/es2019/pm-plugins/utils/surface-viewport.js +192 -0
  48. package/dist/es2019/pm-plugins/utils/transactions.js +5 -0
  49. package/dist/es2019/ui/block-controls-left-surfaces.js +21 -14
  50. package/dist/es2019/ui/block-controls-right-surfaces.js +21 -14
  51. package/dist/es2019/ui/block-controls-surface-context.js +1 -0
  52. package/dist/es2019/ui/block-controls-surface-drag-handle-registration.js +4 -5
  53. package/dist/es2019/ui/block-controls-surface-drag-handle.js +6 -2
  54. package/dist/es2019/ui/drag-handle.js +5 -3
  55. package/dist/es2019/ui/drop-target-layout.js +3 -2
  56. package/dist/es2019/ui/drop-target.js +3 -2
  57. package/dist/es2019/ui/global-styles.js +67 -28
  58. package/dist/es2019/ui/inline-drop-target.js +6 -5
  59. package/dist/es2019/ui/utils/anchor-name.js +2 -1
  60. package/dist/es2019/ui/utils/dom-attr-name.js +3 -2
  61. package/dist/es2019/ui/utils/get-surface-placement.js +2 -1
  62. package/dist/esm/blockControlsPlugin.js +53 -17
  63. package/dist/esm/editor-commands/show-drag-handle.js +17 -5
  64. package/dist/esm/pm-plugins/decorations-anchor.js +2 -1
  65. package/dist/esm/pm-plugins/decorations-drop-target-active.js +2 -1
  66. package/dist/esm/pm-plugins/decorations-drop-target.js +2 -1
  67. package/dist/esm/pm-plugins/decorations-surface-anchor.js +65 -0
  68. package/dist/esm/pm-plugins/handle-mouse-down.js +2 -1
  69. package/dist/esm/pm-plugins/handle-mouse-over.js +3 -2
  70. package/dist/esm/pm-plugins/handle-sparse-mouse-over.js +119 -0
  71. package/dist/esm/pm-plugins/main.js +66 -54
  72. package/dist/esm/pm-plugins/sparse-surfaces.js +43 -0
  73. package/dist/esm/pm-plugins/utils/sparse-surface-candidates.js +413 -0
  74. package/dist/esm/pm-plugins/utils/sparse-surfaces-mapping.js +101 -0
  75. package/dist/esm/pm-plugins/utils/sparse-surfaces-state.js +46 -0
  76. package/dist/esm/pm-plugins/utils/sparse-surfaces-view.js +127 -0
  77. package/dist/esm/pm-plugins/utils/surface-viewport.js +217 -0
  78. package/dist/esm/pm-plugins/utils/transactions.js +5 -0
  79. package/dist/esm/ui/block-controls-left-surfaces.js +33 -27
  80. package/dist/esm/ui/block-controls-right-surfaces.js +33 -27
  81. package/dist/esm/ui/block-controls-surface-context.js +1 -0
  82. package/dist/esm/ui/block-controls-surface-drag-handle-registration.js +7 -8
  83. package/dist/esm/ui/block-controls-surface-drag-handle.js +6 -2
  84. package/dist/esm/ui/drag-handle.js +5 -3
  85. package/dist/esm/ui/drop-target-layout.js +3 -2
  86. package/dist/esm/ui/drop-target.js +3 -2
  87. package/dist/esm/ui/global-styles.js +70 -28
  88. package/dist/esm/ui/inline-drop-target.js +6 -5
  89. package/dist/esm/ui/utils/anchor-name.js +2 -1
  90. package/dist/esm/ui/utils/dom-attr-name.js +3 -2
  91. package/dist/esm/ui/utils/get-surface-placement.js +2 -1
  92. package/dist/types/blockControlsPluginType.d.ts +10 -3
  93. package/dist/types/pm-plugins/decorations-surface-anchor.d.ts +22 -0
  94. package/dist/types/pm-plugins/handle-sparse-mouse-over.d.ts +5 -0
  95. package/dist/types/pm-plugins/main.d.ts +2 -9
  96. package/dist/types/pm-plugins/sparse-surfaces.d.ts +8 -0
  97. package/dist/types/pm-plugins/utils/sparse-surface-candidates.d.ts +89 -0
  98. package/dist/types/pm-plugins/utils/sparse-surfaces-mapping.d.ts +20 -0
  99. package/dist/types/pm-plugins/utils/sparse-surfaces-state.d.ts +27 -0
  100. package/dist/types/pm-plugins/utils/sparse-surfaces-view.d.ts +15 -0
  101. package/dist/types/pm-plugins/utils/surface-viewport.d.ts +10 -0
  102. package/dist/types/ui/utils/get-surface-placement.d.ts +3 -2
  103. package/package.json +5 -5
  104. package/dist/cjs/pm-plugins/utils/surface-node-positions.js +0 -100
  105. package/dist/es2019/pm-plugins/utils/surface-node-positions.js +0 -78
  106. package/dist/esm/pm-plugins/utils/surface-node-positions.js +0 -93
  107. package/dist/types/pm-plugins/utils/surface-node-positions.d.ts +0 -14
@@ -12,7 +12,7 @@ import { akEditorBreakoutPadding, akEditorCalculatedWideLayoutWidth, akEditorCal
12
12
  import { isExperimentEnabled } from '@atlaskit/platform-feature-experiments/is-experiment-enabled';
13
13
  import { editorExperiment } from '@atlaskit/tmp-editor-statsig/editor-experiment';
14
14
  import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
15
- import { ACTIVE_DRAG_HANDLE_ATTR, ACTIVE_DRAG_HANDLE_FALLBACK_ANCHOR_NAME, ACTIVE_QUICK_INSERT_ATTR, ACTIVE_QUICK_INSERT_FALLBACK_ANCHOR_NAME, DRAG_HANDLE_MAX_WIDTH_PLUS_GAP } from './consts';
15
+ import { ACTIVE_DRAG_HANDLE_FALLBACK_ANCHOR_NAME, ACTIVE_QUICK_INSERT_FALLBACK_ANCHOR_NAME, DRAG_HANDLE_MAX_WIDTH_PLUS_GAP } from './consts';
16
16
  import { NODE_ANCHOR_ATTR_NAME } from './utils/dom-attr-name';
17
17
 
18
18
  /**
@@ -462,18 +462,68 @@ const staticControlsAnchorStyles = css({
462
462
  }
463
463
  }
464
464
  });
465
+ const sparseSurfaceAnchorName = 'var(--block-controls-surface-anchor-name)';
465
466
 
466
- /**
467
- * Names the CSS anchor on top-level nodes, so the block controls surfaces can anchor to the blocks
468
- * they render against. Only top-level at the moment as we don't have use cases yet for persistent controls that are nested.
469
- */
470
- const surfaceAnchorStyles = css({
467
+ // Inner node-view boxes own the visible geometry for these nodes. The root arm keeps a sparse
468
+ // marker useful when a node view has not mounted its inner box yet.
469
+ const sparseSurfaceAnchorStyles = css({
471
470
  // eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors
472
471
  '.ProseMirror': {
473
- // eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors, @atlaskit/ui-styling-standard/no-unsafe-selectors, @atlaskit/ui-styling-standard/no-unsafe-values, @atlaskit/ui-styling-standard/no-imported-style-values
474
- [`[${NODE_ANCHOR_ATTR_NAME}]:not([${NODE_ANCHOR_ATTR_NAME}] [${NODE_ANCHOR_ATTR_NAME}]):not([${ACTIVE_DRAG_HANDLE_ATTR}], [${ACTIVE_QUICK_INSERT_ATTR}])`]: {
475
- // eslint-disable-next-line @atlaskit/ui-styling-standard/no-unsafe-values, @atlaskit/ui-styling-standard/no-imported-style-values
476
- anchorName: `var(${ANCHOR_VARIABLE_NAME}, attr(data-node-anchor type(<custom-ident>)))`
472
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors, @atlaskit/ui-styling-standard/no-unsafe-selectors
473
+ '[data-block-controls-surface-anchor][data-block-controls-surface-node-type="blockCard"]:has(.datasourceView-content-inner-wrap) .datasourceView-content-inner-wrap': {
474
+ anchorName: sparseSurfaceAnchorName
475
+ },
476
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors, @atlaskit/ui-styling-standard/no-unsafe-selectors
477
+ '[data-block-controls-surface-anchor][data-block-controls-surface-node-type="blockCard"]:not(:has(.datasourceView-content-inner-wrap))': {
478
+ anchorName: sparseSurfaceAnchorName
479
+ },
480
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors, @atlaskit/ui-styling-standard/no-unsafe-selectors
481
+ '[data-block-controls-surface-anchor][data-block-controls-surface-node-type="bodiedExtension"]:has(.extension-container[data-layout]) .extension-container[data-layout]': {
482
+ anchorName: sparseSurfaceAnchorName
483
+ },
484
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors, @atlaskit/ui-styling-standard/no-unsafe-selectors
485
+ '[data-block-controls-surface-anchor][data-block-controls-surface-node-type="bodiedExtension"]:not(:has(.extension-container[data-layout]))': {
486
+ anchorName: sparseSurfaceAnchorName
487
+ },
488
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors, @atlaskit/ui-styling-standard/no-unsafe-selectors
489
+ '[data-block-controls-surface-anchor][data-block-controls-surface-node-type="embedCard"]:has(.rich-media-item) .rich-media-item': {
490
+ anchorName: sparseSurfaceAnchorName
491
+ },
492
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors, @atlaskit/ui-styling-standard/no-unsafe-selectors
493
+ '[data-block-controls-surface-anchor][data-block-controls-surface-node-type="embedCard"]:not(:has(.rich-media-item))': {
494
+ anchorName: sparseSurfaceAnchorName
495
+ },
496
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors, @atlaskit/ui-styling-standard/no-unsafe-selectors
497
+ '[data-block-controls-surface-anchor][data-block-controls-surface-node-type="extension"]:has(.extension-container[data-layout]) .extension-container[data-layout]': {
498
+ anchorName: sparseSurfaceAnchorName
499
+ },
500
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors, @atlaskit/ui-styling-standard/no-unsafe-selectors
501
+ '[data-block-controls-surface-anchor][data-block-controls-surface-node-type="extension"]:not(:has(.extension-container[data-layout]))': {
502
+ anchorName: sparseSurfaceAnchorName
503
+ },
504
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors, @atlaskit/ui-styling-standard/no-unsafe-selectors
505
+ '[data-block-controls-surface-anchor][data-block-controls-surface-node-type="mediaSingle"]:has(.resizer-item) .resizer-item': {
506
+ anchorName: sparseSurfaceAnchorName
507
+ },
508
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors, @atlaskit/ui-styling-standard/no-unsafe-selectors
509
+ '[data-block-controls-surface-anchor][data-block-controls-surface-node-type="mediaSingle"]:not(:has(.resizer-item))': {
510
+ anchorName: sparseSurfaceAnchorName
511
+ },
512
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors, @atlaskit/ui-styling-standard/no-unsafe-selectors
513
+ '[data-block-controls-surface-anchor][data-block-controls-surface-node-type="multiBodiedExtension"]:has(.extension-container[data-layout]) .extension-container[data-layout]': {
514
+ anchorName: sparseSurfaceAnchorName
515
+ },
516
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors, @atlaskit/ui-styling-standard/no-unsafe-selectors
517
+ '[data-block-controls-surface-anchor][data-block-controls-surface-node-type="multiBodiedExtension"]:not(:has(.extension-container[data-layout]))': {
518
+ anchorName: sparseSurfaceAnchorName
519
+ },
520
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors, @atlaskit/ui-styling-standard/no-unsafe-selectors
521
+ '[data-block-controls-surface-anchor][data-block-controls-surface-node-type="table"]:has(.resizer-item) .resizer-item': {
522
+ anchorName: sparseSurfaceAnchorName
523
+ },
524
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-nested-selectors, @atlaskit/ui-styling-standard/no-unsafe-selectors
525
+ '[data-block-controls-surface-anchor][data-block-controls-surface-node-type="table"]:not(:has(.resizer-item))': {
526
+ anchorName: sparseSurfaceAnchorName
477
527
  }
478
528
  }
479
529
  });
@@ -517,33 +567,22 @@ export const GlobalStylesWrapper = ({
517
567
  isDragging: (_states$blockControls = states.blockControlsState) === null || _states$blockControls === void 0 ? void 0 : _states$blockControls.isDragging
518
568
  };
519
569
  });
520
- const isDragging = expValEquals('platform_editor_block_controls_perf_optimization', 'isEnabled', true) ? isDraggingFromState : false;
570
+ const sparseSurfacesEnabled = isExperimentEnabled('platform_editor_block_control_migration');
571
+ const isDragging = sparseSurfacesEnabled || expValEquals('platform_editor_block_controls_perf_optimization', 'isEnabled', true) ? isDraggingFromState : false;
521
572
  const shouldRenderAnchors = isCSSAnchorSupported() && expValEquals('platform_editor_native_anchor_with_dnd', 'isEnabled', true);
522
-
523
- // The surfaces anchor to blocks they render against rather than only to the hovered one, so they
524
- // need a name on every node. Added alongside whichever conditional rule applies rather than
525
- // replacing it: this one matches only non-active nodes, so the two sets are disjoint.
526
- //
527
- // The migration check is what scopes this. Unlike the surfaces, this component renders for every
528
- // editor, so without it the rule would name anchors on documents that have no surface to anchor.
529
- const shouldRenderSurfaceAnchors =
530
- // eslint-disable-next-line @atlaskit/platform/no-preconditioning -- browser capability, not a flag: an anchor name is meaningless where `anchor()` cannot resolve
531
- Boolean(isCSSAnchorSupported()) && isExperimentEnabled('platform_editor_block_control_migration');
573
+ const sparseSurfaceAnchorsEnabled = Boolean(isCSSAnchorSupported()) && sparseSurfacesEnabled;
532
574
  const toolbarFlagsEnabled = areToolbarFlagsEnabled(Boolean(api === null || api === void 0 ? void 0 : api.toolbar));
533
575
  return jsx(Global
534
576
  // eslint-disable-next-line @atlassian/perf-linting/no-unstable-inline-props -- Ignored via go/ees017 (to be fixed)
535
577
  , {
536
- styles: [globalStyles(), globalDnDStyle, expValEquals('platform_editor_native_anchor_with_dnd', 'isEnabled', true) ? extendedHoverZoneNext() : extendedHoverZone(), isDragging && (expValEquals('platform_editor_native_anchor_with_dnd', 'isEnabled', true) ? extendedDragZoneNext : extendedDragZone), editorExperiment('platform_editor_preview_panel_responsiveness', true, {
578
+ styles: [globalStyles(), globalDnDStyle, (!sparseSurfacesEnabled || isDragging) && (expValEquals('platform_editor_native_anchor_with_dnd', 'isEnabled', true) || isExperimentEnabled('platform_editor_block_control_migration') ? extendedHoverZoneNext() : extendedHoverZone()), isDragging && (expValEquals('platform_editor_native_anchor_with_dnd', 'isEnabled', true) || isExperimentEnabled('platform_editor_block_control_migration') ? extendedDragZoneNext : extendedDragZone), (!sparseSurfacesEnabled || isDragging) && editorExperiment('platform_editor_preview_panel_responsiveness', true, {
537
579
  exposure: true
538
- }) ? expValEquals('platform_editor_native_anchor_with_dnd', 'isEnabled', true) ? extendHoverZoneReducedNext : extendHoverZoneReduced : undefined,
580
+ }) ? expValEquals('platform_editor_native_anchor_with_dnd', 'isEnabled', true) || isExperimentEnabled('platform_editor_block_control_migration') ? extendHoverZoneReducedNext : extendHoverZoneReduced : undefined,
539
581
  // platform_editor_controls note: this allows drag handles to render on empty lines
540
- toolbarFlagsEnabled ? undefined : withInlineNodeStyle, withDeleteLinesStyleFix, withMediaSingleStyleFix, legacyBreakoutWideLayoutStyle, headingWithIndentationInLayoutStyleFix, editorExperiment('advanced_layouts', true) ? blockCardWithoutLayout : undefined, withDividerInPanelStyleFix, withFormatInLayoutStyleFix, expValEquals('platform_editor_native_anchor_with_dnd', 'isEnabled', true) ? withRelativePosStyleNext : withRelativePosStyle, expValEquals('platform_editor_native_anchor_with_dnd', 'isEnabled', true) ? withAnchorNameZindexStyleNext : withAnchorNameZindexStyle, expValEquals('platform_editor_native_anchor_with_dnd', 'isEnabled', true) && expValEquals('advanced_layouts', 'isEnabled', true) ? layoutColumnExtendedHoverZone : layoutColumnWithoutHoverZone, expValEquals('platform_editor_controls_reliable_anchor', 'isEnabled', true) ?
582
+ toolbarFlagsEnabled ? undefined : withInlineNodeStyle, withDeleteLinesStyleFix, withMediaSingleStyleFix, legacyBreakoutWideLayoutStyle, headingWithIndentationInLayoutStyleFix, editorExperiment('advanced_layouts', true) ? blockCardWithoutLayout : undefined, withDividerInPanelStyleFix, withFormatInLayoutStyleFix, (!sparseSurfacesEnabled || isDragging) && (expValEquals('platform_editor_native_anchor_with_dnd', 'isEnabled', true) || isExperimentEnabled('platform_editor_block_control_migration') ? withRelativePosStyleNext : withRelativePosStyle), (!sparseSurfacesEnabled || isDragging) && (expValEquals('platform_editor_native_anchor_with_dnd', 'isEnabled', true) || isExperimentEnabled('platform_editor_block_control_migration') ? withAnchorNameZindexStyleNext : withAnchorNameZindexStyle), (!sparseSurfacesEnabled || isDragging) && ((expValEquals('platform_editor_native_anchor_with_dnd', 'isEnabled', true) || isExperimentEnabled('platform_editor_block_control_migration')) && expValEquals('advanced_layouts', 'isEnabled', true) ? layoutColumnExtendedHoverZone : layoutColumnWithoutHoverZone), sparseSurfaceAnchorsEnabled ? isDragging ? dragAnchorStyles : false : expValEquals('platform_editor_controls_reliable_anchor', 'isEnabled', true) ?
541
583
  // dragAnchorStyles sets anchor-name on ALL nodes during drag (needed for drop target positioning).
542
584
  // staticControlsAnchorStyles handles anchor-name via node decorations for non-drag state.
543
585
  // shouldRenderAnchors guards both: only apply anchor styles on browsers that support CSS anchor positioning.
544
- shouldRenderAnchors ? isDragging ? dragAnchorStyles : staticControlsAnchorStyles : false : shouldRenderAnchors && (isDragging ? dragAnchorStyles : dragHandlerAnchorStyles),
545
- // Last so that, at equal specificity, the surfaces' own anchor names are the ones that
546
- // stand. It cannot overlap the active-node rules above, which this selector excludes.
547
- shouldRenderSurfaceAnchors && surfaceAnchorStyles]
586
+ shouldRenderAnchors ? isDragging ? dragAnchorStyles : staticControlsAnchorStyles : false : shouldRenderAnchors && (isDragging ? dragAnchorStyles : dragHandlerAnchorStyles), sparseSurfaceAnchorsEnabled && sparseSurfaceAnchorStyles]
548
587
  });
549
588
  };
@@ -9,6 +9,7 @@ import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
9
9
  // eslint-disable-next-line @atlaskit/ui-styling-standard/use-compiled, @typescript-eslint/consistent-type-imports
10
10
  import { css, jsx } from '@emotion/react';
11
11
  import { akEditorBreakoutPadding } from '@atlaskit/editor-shared-styles';
12
+ import { isExperimentEnabled } from '@atlaskit/platform-feature-experiments/is-experiment-enabled';
12
13
  import { DropIndicator } from '@atlaskit/pragmatic-drag-and-drop-react-drop-indicator/box';
13
14
  import { dropTargetForElements } from '@atlaskit/pragmatic-drag-and-drop/adapter/element-adapter';
14
15
  import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
@@ -88,7 +89,7 @@ export const InlineDropTarget = ({
88
89
  const ref = useRef(null);
89
90
  const [isDraggedOver, setIsDraggedOver] = useState(false);
90
91
  const anchorName = useMemo(() => {
91
- if (expValEquals('platform_editor_native_anchor_with_dnd', 'isEnabled', true)) {
92
+ if (expValEquals('platform_editor_native_anchor_with_dnd', 'isEnabled', true) || isExperimentEnabled('platform_editor_block_control_migration')) {
92
93
  var _getPos;
93
94
  return nextNode ? (api === null || api === void 0 ? void 0 : api.core.actions.getAnchorIdForNode(nextNode, (_getPos = getPos()) !== null && _getPos !== void 0 ? _getPos : -1)) || '' : '';
94
95
  }
@@ -119,7 +120,7 @@ export const InlineDropTarget = ({
119
120
  innerContainerWidth = `calc(var(--ak-editor--line-length) * ${percentageWidth})`;
120
121
  }
121
122
  } else if (nextNode.type.name === 'table' && nextNode.firstChild) {
122
- const tableWidthAnchor = expValEquals('platform_editor_native_anchor_with_dnd', 'isEnabled', true) ? typeof nextNodePos === 'number' ? (api === null || api === void 0 ? void 0 : api.core.actions.getAnchorIdForNode(nextNode.firstChild, nextNodePos + 1)) || '' : '' : getNodeAnchor(nextNode.firstChild);
123
+ const tableWidthAnchor = expValEquals('platform_editor_native_anchor_with_dnd', 'isEnabled', true) || isExperimentEnabled('platform_editor_block_control_migration') ? typeof nextNodePos === 'number' ? (api === null || api === void 0 ? void 0 : api.core.actions.getAnchorIdForNode(nextNode.firstChild, nextNodePos + 1)) || '' : '' : getNodeAnchor(nextNode.firstChild);
123
124
  const isNumberColumnEnabled = Boolean(nextNode.attrs.isNumberColumnEnabled);
124
125
  if (isAnchorSupported()) {
125
126
  innerContainerWidth = isNumberColumnEnabled ? `calc(anchor-size(${tableWidthAnchor} width) + ${TABLE_NUMBERED_COLUMN_WIDTH}px)` : `anchor-size(${tableWidthAnchor} width)`;
@@ -132,7 +133,7 @@ export const InlineDropTarget = ({
132
133
  innerContainerWidth = `min(${nextNode.attrs.width}px, ${innerContainerWidth})`;
133
134
  }
134
135
  } else if (nextNode.type.name === 'mediaSingle' && nextNode.firstChild) {
135
- if (expValEquals('platform_editor_native_anchor_with_dnd', 'isEnabled', true)) {
136
+ if (expValEquals('platform_editor_native_anchor_with_dnd', 'isEnabled', true) || isExperimentEnabled('platform_editor_block_control_migration')) {
136
137
  var _nextNode$firstChild;
137
138
  // check pos is a number
138
139
  if (typeof nextNodePos === 'number' && ((_nextNode$firstChild = nextNode.firstChild) === null || _nextNode$firstChild === void 0 ? void 0 : _nextNode$firstChild.type.name) === 'media') {
@@ -147,7 +148,7 @@ export const InlineDropTarget = ({
147
148
  let heightTargetAnchorName = targetAnchorName;
148
149
  if (nextNode.type.name === 'layoutSection' && nextNode.firstChild && nextNode.lastChild) {
149
150
  if (isLeftPosition) {
150
- if (expValEquals('platform_editor_native_anchor_with_dnd', 'isEnabled', true)) {
151
+ if (expValEquals('platform_editor_native_anchor_with_dnd', 'isEnabled', true) || isExperimentEnabled('platform_editor_block_control_migration')) {
151
152
  if (typeof nextNodePos === 'number') {
152
153
  heightTargetAnchorName = (api === null || api === void 0 ? void 0 : api.core.actions.getAnchorIdForNode(nextNode.firstChild, nextNodePos + 1)) || '';
153
154
  } else {
@@ -157,7 +158,7 @@ export const InlineDropTarget = ({
157
158
  heightTargetAnchorName = getNodeAnchor(nextNode.firstChild);
158
159
  }
159
160
  } else {
160
- if (expValEquals('platform_editor_native_anchor_with_dnd', 'isEnabled', true)) {
161
+ if (expValEquals('platform_editor_native_anchor_with_dnd', 'isEnabled', true) || isExperimentEnabled('platform_editor_block_control_migration')) {
161
162
  if (typeof nextNodePos === 'number') {
162
163
  const lastNodeStartPos = nextNode.content.size - nextNode.lastChild.nodeSize;
163
164
  heightTargetAnchorName = (api === null || api === void 0 ? void 0 : api.core.actions.getAnchorIdForNode(nextNode.lastChild, lastNodeStartPos + 1)) || '';
@@ -1,3 +1,4 @@
1
+ import { isExperimentEnabled } from '@atlaskit/platform-feature-experiments/is-experiment-enabled';
1
2
  import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
2
3
  import { findNodeDecs } from '../../pm-plugins/decorations-anchor';
3
4
  import { key } from '../../pm-plugins/main';
@@ -11,7 +12,7 @@ export const refreshAnchorName = ({
11
12
  anchorName
12
13
  }) => {
13
14
  let newAnchorName = anchorName || '';
14
- if (expValEquals('platform_editor_native_anchor_with_dnd', 'isEnabled', true)) {
15
+ if (expValEquals('platform_editor_native_anchor_with_dnd', 'isEnabled', true) || isExperimentEnabled('platform_editor_block_control_migration')) {
15
16
  return newAnchorName;
16
17
  }
17
18
  const pos = getPos();
@@ -1,14 +1,15 @@
1
+ import { isExperimentEnabled } from '@atlaskit/platform-feature-experiments/is-experiment-enabled';
1
2
  import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
2
3
  export const NODE_ANCHOR_ATTR_NAME = 'data-node-anchor';
3
4
  export const NODE_NODE_TYPE_ATTR_NAME = 'data-prosemirror-node-name';
4
5
  export const getAnchorAttrName = () => {
5
- if (expValEquals('platform_editor_native_anchor_with_dnd', 'isEnabled', true)) {
6
+ if (expValEquals('platform_editor_native_anchor_with_dnd', 'isEnabled', true) || isExperimentEnabled('platform_editor_block_control_migration')) {
6
7
  return NODE_ANCHOR_ATTR_NAME;
7
8
  }
8
9
  return 'data-drag-handler-anchor-name';
9
10
  };
10
11
  export const getTypeNameAttrName = () => {
11
- if (expValEquals('platform_editor_native_anchor_with_dnd', 'isEnabled', true)) {
12
+ if (expValEquals('platform_editor_native_anchor_with_dnd', 'isEnabled', true) || isExperimentEnabled('platform_editor_block_control_migration')) {
12
13
  return NODE_NODE_TYPE_ATTR_NAME;
13
14
  }
14
15
  return 'data-drag-handler-node-type';
@@ -96,6 +96,7 @@ const INVALID_ANCHOR_FALLBACK_TOP = `-${INVALID_ANCHOR_OFFSCREEN_PX}px`;
96
96
  const INVALID_ANCHOR_FALLBACK_BOTTOM = `${INVALID_ANCHOR_OFFSCREEN_PX}px`;
97
97
  export const getAnchoredSurfacePlacement = ({
98
98
  anchorName,
99
+ layout,
99
100
  nodeType,
100
101
  nodeTypeWithLevel,
101
102
  parentNodeType,
@@ -127,7 +128,7 @@ export const getAnchoredSurfacePlacement = ({
127
128
  } : {}),
128
129
  left: side === 'right' ? `calc(anchor(${anchorName} right) + ${gap}px)` : `anchor(${anchorName} left)`,
129
130
  positionAnchor: anchorName,
130
- top: `calc(anchor(${anchorName} top, ${INVALID_ANCHOR_FALLBACK_TOP}) + ${topPositionAdjustment(nodeTypeWithLevel)}px)`,
131
+ top: `calc(anchor(${anchorName} top, ${INVALID_ANCHOR_FALLBACK_TOP}) + ${topPositionAdjustment(nodeTypeWithLevel, layout)}px)`,
131
132
  // The left side grows away from the node without knowing its own width, so it pulls itself
132
133
  // back past its own box and the gap. The right side grows into the margin, so the gap is
133
134
  // already folded into `left` above.
@@ -18,12 +18,14 @@ import { moveNode } from './editor-commands/move-node';
18
18
  import { moveNodeWithBlockMenu as _moveNodeWithBlockMenu } from './editor-commands/move-node-with-block-menu';
19
19
  import { moveToLayout } from './editor-commands/move-to-layout';
20
20
  import { canMoveNodeUpOrDown } from './editor-commands/utils/move-node-utils';
21
+ import { getNodeTypeWithLevel } from './pm-plugins/decorations-common';
21
22
  import { firstNodeDecPlugin } from './pm-plugins/first-node-dec-plugin';
22
23
  import { createInteractionTrackingPlugin, interactionTrackingPluginKey } from './pm-plugins/interaction-tracking/pm-plugin';
23
24
  import { createPlugin, key } from './pm-plugins/main';
24
25
  import { startPreservingSelection as _startPreservingSelection, stopPreservingSelection as _stopPreservingSelection } from './pm-plugins/selection-preservation/editor-commands';
25
26
  import { selectionPreservationPluginKey } from './pm-plugins/selection-preservation/plugin-key';
26
27
  import { createSelectionPreservationPlugin } from './pm-plugins/selection-preservation/pm-plugin';
28
+ import { createSparseSurfacesPlugin, sparseSurfacesKey } from './pm-plugins/sparse-surfaces';
27
29
  import { expandAndUpdateSelection as _expandAndUpdateSelection } from './pm-plugins/utils/expand-and-update-selection';
28
30
  import { selectNode } from './pm-plugins/utils/getSelection';
29
31
  import { BlockControlsLeftSurfaces } from './ui/block-controls-left-surfaces';
@@ -39,7 +41,6 @@ export var blockControlsPlugin = function blockControlsPlugin(_ref) {
39
41
  var rightSideControlsEnabled = (_config$rightSideCont = config === null || config === void 0 ? void 0 : config.rightSideControlsEnabled) !== null && _config$rightSideCont !== void 0 ? _config$rightSideCont : false;
40
42
  var quickInsertButtonEnabled = (_config$quickInsertBu = config === null || config === void 0 ? void 0 : config.quickInsertButtonEnabled) !== null && _config$quickInsertBu !== void 0 ? _config$quickInsertBu : true;
41
43
  var registryBlockControlsEnabled = isExperimentEnabled('platform_editor_block_control_migration');
42
- var legacyBlockControlsEnabled = !registryBlockControlsEnabled;
43
44
  if (registryBlockControlsEnabled) {
44
45
  var _api$uiControlRegistr, _api$uiControlRegistr2;
45
46
  api === null || api === void 0 || (_api$uiControlRegistr = api.uiControlRegistry) === null || _api$uiControlRegistr === void 0 || _api$uiControlRegistr.actions.register([BLOCK_CONTROLS_LEFT_SURFACE, _objectSpread(_objectSpread({}, BLOCK_CONTROLS_LEFT_SECTION), {}, {
@@ -135,9 +136,17 @@ export var blockControlsPlugin = function blockControlsPlugin(_ref) {
135
136
  plugin: function plugin(_ref2) {
136
137
  var getIntl = _ref2.getIntl,
137
138
  nodeViewPortalProviderAPI = _ref2.nodeViewPortalProviderAPI;
138
- return createPlugin(api, getIntl, nodeViewPortalProviderAPI, nodeDecorationRegistry, rightSideControlsEnabled, quickInsertButtonEnabled && legacyBlockControlsEnabled, legacyBlockControlsEnabled);
139
+ return createPlugin(api, getIntl, nodeViewPortalProviderAPI, registryBlockControlsEnabled ? [] : nodeDecorationRegistry, rightSideControlsEnabled, quickInsertButtonEnabled && !registryBlockControlsEnabled);
139
140
  }
140
141
  }];
142
+ if (registryBlockControlsEnabled) {
143
+ pmPlugins.push({
144
+ name: 'blockControlsSparseSurfaces',
145
+ plugin: function plugin() {
146
+ return createSparseSurfacesPlugin(api);
147
+ }
148
+ });
149
+ }
141
150
  if (editorExperiment('platform_editor_controls', 'variant1')) {
142
151
  pmPlugins.push({
143
152
  name: 'blockControlsInteractionTrackingPlugin',
@@ -156,7 +165,7 @@ export var blockControlsPlugin = function blockControlsPlugin(_ref) {
156
165
  // Not registered under the registry migration: the decoration puts an inline
157
166
  // `margin-top: 0` on the first document node, which fights features that render their own
158
167
  // content above it — a leading show-diff widget is left flush against the node below.
159
- if (areToolbarFlagsEnabled(Boolean(api === null || api === void 0 ? void 0 : api.toolbar)) && legacyBlockControlsEnabled) {
168
+ if (areToolbarFlagsEnabled(Boolean(api === null || api === void 0 ? void 0 : api.toolbar)) && !registryBlockControlsEnabled) {
160
169
  pmPlugins.push({
161
170
  name: 'firstNodeDec',
162
171
  plugin: firstNodeDecPlugin
@@ -203,10 +212,34 @@ export var blockControlsPlugin = function blockControlsPlugin(_ref) {
203
212
  return tr;
204
213
  };
205
214
  },
206
- toggleBlockMenu: function toggleBlockMenu(options) {
215
+ showControlAtPosition: function showControlAtPosition(pos, control, options) {
207
216
  return function (_ref6) {
208
- var _api$userIntent, _api$blockControls2, _options$anchorName, _api$blockControls3;
209
217
  var tr = _ref6.tr;
218
+ var node = tr.doc.nodeAt(pos);
219
+ if (!node) {
220
+ return tr;
221
+ }
222
+ var anchorName = api === null || api === void 0 ? void 0 : api.core.actions.getAnchorIdForNode(node, pos);
223
+ if (!anchorName) {
224
+ return tr;
225
+ }
226
+ var currMeta = tr.getMeta(key);
227
+ tr.setMeta(key, _objectSpread(_objectSpread({}, currMeta), {}, {
228
+ activeNode: {
229
+ pos: pos,
230
+ anchorName: anchorName,
231
+ controlKey: control.key,
232
+ nodeType: getNodeTypeWithLevel(node),
233
+ handleOptions: options
234
+ }
235
+ }));
236
+ return tr;
237
+ };
238
+ },
239
+ toggleBlockMenu: function toggleBlockMenu(options) {
240
+ return function (_ref7) {
241
+ var _api$userIntent, _api$blockControls2, _options$triggerByNod, _options$anchorName, _api$blockControls3;
242
+ var tr = _ref7.tr;
210
243
  var currMeta = tr.getMeta(key);
211
244
  var currentUserIntent = api === null || api === void 0 || (_api$userIntent = api.userIntent) === null || _api$userIntent === void 0 || (_api$userIntent = _api$userIntent.sharedState.currentState()) === null || _api$userIntent === void 0 ? void 0 : _api$userIntent.currentUserIntent;
212
245
  var isMenuCurrentlyOpen = api === null || api === void 0 || (_api$blockControls2 = api.blockControls) === null || _api$blockControls2 === void 0 || (_api$blockControls2 = _api$blockControls2.sharedState.currentState()) === null || _api$blockControls2 === void 0 ? void 0 : _api$blockControls2.isMenuOpen;
@@ -231,8 +264,9 @@ export var blockControlsPlugin = function blockControlsPlugin(_ref) {
231
264
  return tr;
232
265
  }
233
266
 
234
- // Do not open menu on layoutColumn and close opened menu when layoutColumn drag handle is clicked
235
- if (options !== null && options !== void 0 && (_options$anchorName = options.anchorName) !== null && _options$anchorName !== void 0 && _options$anchorName.includes('layoutColumn')) {
267
+ // Do not open the block menu for layout columns. Anchor resolution can lag behind
268
+ // a migrated surface click, so prefer the explicit node metadata when available.
269
+ if ((options === null || options === void 0 || (_options$triggerByNod = options.triggerByNode) === null || _options$triggerByNod === void 0 ? void 0 : _options$triggerByNod.nodeType) === 'layoutColumn' || options !== null && options !== void 0 && (_options$anchorName = options.anchorName) !== null && _options$anchorName !== void 0 && _options$anchorName.includes('layoutColumn')) {
236
270
  if (currentUserIntent === 'blockMenuOpen') {
237
271
  var _api$userIntent3;
238
272
  api === null || api === void 0 || (_api$userIntent3 = api.userIntent) === null || _api$userIntent3 === void 0 || _api$userIntent3.commands.setCurrentUserIntent('default')({
@@ -308,9 +342,9 @@ export var blockControlsPlugin = function blockControlsPlugin(_ref) {
308
342
  };
309
343
  },
310
344
  setNodeDragged: function setNodeDragged(getPos, anchorName, nodeType) {
311
- return function (_ref7) {
345
+ return function (_ref8) {
312
346
  var _api$userIntent6;
313
- var tr = _ref7.tr;
347
+ var tr = _ref8.tr;
314
348
  var pos = getPos();
315
349
  if (pos === undefined) {
316
350
  return tr;
@@ -340,9 +374,9 @@ export var blockControlsPlugin = function blockControlsPlugin(_ref) {
340
374
  };
341
375
  },
342
376
  setMultiSelectPositions: function setMultiSelectPositions(anchor, head) {
343
- return function (_ref8) {
377
+ return function (_ref9) {
344
378
  var _api$selection, _$to$nodeBefore, _$from$nodeAfter;
345
- var tr = _ref8.tr;
379
+ var tr = _ref9.tr;
346
380
  var _tr$selection = tr.selection,
347
381
  userAnchor = _tr$selection.anchor,
348
382
  userHead = _tr$selection.head;
@@ -394,8 +428,8 @@ export var blockControlsPlugin = function blockControlsPlugin(_ref) {
394
428
  };
395
429
  },
396
430
  setSelectedViaDragHandle: function setSelectedViaDragHandle(isSelectedViaDragHandle) {
397
- return function (_ref9) {
398
- var tr = _ref9.tr;
431
+ return function (_ref0) {
432
+ var tr = _ref0.tr;
399
433
  var currMeta = tr.getMeta(key);
400
434
  return tr.setMeta(key, _objectSpread(_objectSpread({}, currMeta), {}, {
401
435
  isSelectedViaDragHandle: isSelectedViaDragHandle
@@ -437,8 +471,10 @@ export var blockControlsPlugin = function blockControlsPlugin(_ref) {
437
471
  isSelectedViaDragHandle: (_key$getState$isSelec = (_key$getState10 = key.getState(editorState)) === null || _key$getState10 === void 0 ? void 0 : _key$getState10.isSelectedViaDragHandle) !== null && _key$getState$isSelec !== void 0 ? _key$getState$isSelec : false
438
472
  };
439
473
  if (registryBlockControlsEnabled) {
440
- var _key$getState$surface, _key$getState11;
441
- sharedState.surfaceNodePositions = (_key$getState$surface = (_key$getState11 = key.getState(editorState)) === null || _key$getState11 === void 0 ? void 0 : _key$getState11.surfaceNodePositions) !== null && _key$getState$surface !== void 0 ? _key$getState$surface : [];
474
+ var surfaces = sparseSurfacesKey.getState(editorState);
475
+ sharedState.surfaceNodePositions = surfaces === null || surfaces === void 0 ? void 0 : surfaces.candidates.positions;
476
+ sharedState.surfaceAnchors = surfaces === null || surfaces === void 0 ? void 0 : surfaces.anchors;
477
+ sharedState.surfaceActiveNodes = surfaces === null || surfaces === void 0 ? void 0 : surfaces.activeNodesByPosition;
442
478
  }
443
479
  if (editorExperiment('platform_editor_controls', 'variant1')) {
444
480
  var _interactionTrackingP2, _interactionTrackingP3, _interactionTrackingP4;
@@ -450,8 +486,8 @@ export var blockControlsPlugin = function blockControlsPlugin(_ref) {
450
486
  sharedState.preservedSelection = (_selectionPreservatio = selectionPreservationPluginKey.getState(editorState)) === null || _selectionPreservatio === void 0 ? void 0 : _selectionPreservatio.preservedSelection;
451
487
  return sharedState;
452
488
  },
453
- contentComponent: function contentComponent(_ref0) {
454
- var editorView = _ref0.editorView;
489
+ contentComponent: function contentComponent(_ref1) {
490
+ var editorView = _ref1.editorView;
455
491
  return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(GlobalStylesWrapper, {
456
492
  api: api
457
493
  }), registryBlockControlsEnabled && editorView && api ? /*#__PURE__*/React.createElement(SurfaceEditorViewContext.Provider, {
@@ -1,6 +1,8 @@
1
1
  import { findParentNodeOfType } from '@atlaskit/editor-prosemirror/utils';
2
+ import { isExperimentEnabled } from '@atlaskit/platform-feature-experiments/is-experiment-enabled';
2
3
  import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
3
4
  import { findNodeDecs } from '../pm-plugins/decorations-anchor';
5
+ import { getNodeTypeWithLevel } from '../pm-plugins/decorations-common';
4
6
  import { getDecorations, key } from '../pm-plugins/main';
5
7
  import { getNestedNodePosition, getNestedNodeStartingPosition } from '../pm-plugins/utils/getNestedNodePosition';
6
8
  import { NODE_ANCHOR_ATTR_NAME, NODE_NODE_TYPE_ATTR_NAME } from '../ui/utils/dom-attr-name';
@@ -9,7 +11,6 @@ var findParentPosForHandle = function findParentPosForHandle(state) {
9
11
  var $from = state.selection.$from;
10
12
  var _ref = key.getState(state) || {},
11
13
  activeNode = _ref.activeNode;
12
-
13
14
  // if a node handle is already focused, return the parent pos of that node (with focused handle)
14
15
  if (activeNode && (_activeNode$handleOpt = activeNode.handleOptions) !== null && _activeNode$handleOpt !== void 0 && _activeNode$handleOpt.isFocused) {
15
16
  var $activeNodePos = state.doc.resolve(activeNode.pos);
@@ -33,7 +34,7 @@ var findParentPosForHandle = function findParentPosForHandle(state) {
33
34
  }
34
35
 
35
36
  // else find closest parent node
36
- return expValEquals('platform_editor_native_anchor_with_dnd', 'isEnabled', true) ?
37
+ return expValEquals('platform_editor_native_anchor_with_dnd', 'isEnabled', true) || isExperimentEnabled('platform_editor_block_control_migration') ?
37
38
  // With native anchor enabled, all nodes have anchor name attribute despite no drag handle support, e.g. listItem, caption,
38
39
  // as opposed to old approach, node decoration is only added to the node that have drag handle,
39
40
  // hence, we need to return the exact position of the node that can have drag handle
@@ -107,13 +108,24 @@ var findNextAnchorNode = function findNextAnchorNode(view) {
107
108
  };
108
109
  export var showDragHandleAtSelection = function showDragHandleAtSelection(api) {
109
110
  return function (state, _, view) {
111
+ if (api && isExperimentEnabled('platform_editor_block_control_migration')) {
112
+ var pos = findParentPosForHandle(state);
113
+ var node = pos === undefined ? undefined : state.doc.nodeAt(pos);
114
+ var anchorName = node && pos !== undefined ? api.core.actions.getAnchorIdForNode(node, pos) : undefined;
115
+ if (!node || pos === undefined || !anchorName) {
116
+ return false;
117
+ }
118
+ return api.core.actions.execute(api.blockControls.commands.showDragHandleAt(pos, anchorName, getNodeTypeWithLevel(node), {
119
+ isFocused: true
120
+ }));
121
+ }
110
122
  if (view && expValEquals('platform_editor_native_anchor_with_dnd', 'isEnabled', true)) {
111
123
  var anchorNode = findNextAnchorNode(view);
112
124
  if (api && anchorNode) {
113
- var pos = anchorNode.pos,
114
- anchorName = anchorNode.anchorName,
125
+ var _pos = anchorNode.pos,
126
+ _anchorName = anchorNode.anchorName,
115
127
  nodeType = anchorNode.nodeType;
116
- api.core.actions.execute(api.blockControls.commands.showDragHandleAt(pos, anchorName, nodeType, {
128
+ api.core.actions.execute(api.blockControls.commands.showDragHandleAt(_pos, _anchorName, nodeType, {
117
129
  isFocused: true
118
130
  }));
119
131
  return true;
@@ -1,5 +1,6 @@
1
1
  import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
2
  import { Decoration } from '@atlaskit/editor-prosemirror/view';
3
+ import { isExperimentEnabled } from '@atlaskit/platform-feature-experiments/is-experiment-enabled';
3
4
  import { editorExperiment } from '@atlaskit/tmp-editor-statsig/editor-experiment';
4
5
  import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
5
6
  import { getNodeAnchor, getNodeTypeWithLevel, NESTED_DEPTH, TYPE_NODE_DEC } from './decorations-common';
@@ -70,7 +71,7 @@ export var findNodeDecs = function findNodeDecs(state, decorations, from, to) {
70
71
  };
71
72
  export var nodeDecorations = function nodeDecorations(newState, from, to) {
72
73
  var decs = [];
73
- if (expValEquals('platform_editor_native_anchor_with_dnd', 'isEnabled', true)) {
74
+ if (expValEquals('platform_editor_native_anchor_with_dnd', 'isEnabled', true) || isExperimentEnabled('platform_editor_block_control_migration')) {
74
75
  return [];
75
76
  }
76
77
  var docFrom = from === undefined || from < 0 ? 0 : from;
@@ -4,6 +4,7 @@ import { expandSelectionBounds } from '@atlaskit/editor-common/selection';
4
4
  import { isEmptyParagraph } from '@atlaskit/editor-common/utils';
5
5
  import { getBaseNodeTypeName } from '@atlaskit/editor-common/utils/node-type-utils';
6
6
  import { findChildrenByType } from '@atlaskit/editor-prosemirror/utils';
7
+ import { isExperimentEnabled } from '@atlaskit/platform-feature-experiments/is-experiment-enabled';
7
8
  import { editorExperiment } from '@atlaskit/tmp-editor-statsig/editor-experiment';
8
9
  import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
9
10
  import { getNodeAnchor } from './decorations-common';
@@ -251,7 +252,7 @@ export var getActiveDropTargetDecorations = function getActiveDropTargetDecorati
251
252
  }
252
253
  }
253
254
  }
254
- defaultActiveAnchorTracker.emit(expValEquals('platform_editor_native_anchor_with_dnd', 'isEnabled', true) ? api.core.actions.getAnchorIdForNode(anchorEmitNodeWithPos.node, anchorEmitNodeWithPos.pos) || '' : getNodeAnchor(anchorEmitNodeWithPos.node));
255
+ defaultActiveAnchorTracker.emit(expValEquals('platform_editor_native_anchor_with_dnd', 'isEnabled', true) || isExperimentEnabled('platform_editor_block_control_migration') ? api.core.actions.getAnchorIdForNode(anchorEmitNodeWithPos.node, anchorEmitNodeWithPos.pos) || '' : getNodeAnchor(anchorEmitNodeWithPos.node));
255
256
  return {
256
257
  decsToAdd: decsToAdd,
257
258
  decsToRemove: decsToRemove
@@ -10,6 +10,7 @@ import { expandSelectionBounds } from '@atlaskit/editor-common/selection';
10
10
  import { isEmptyParagraph } from '@atlaskit/editor-common/utils';
11
11
  import { getBaseNodeTypeName } from '@atlaskit/editor-common/utils/node-type-utils';
12
12
  import { Decoration } from '@atlaskit/editor-prosemirror/view';
13
+ import { isExperimentEnabled } from '@atlaskit/platform-feature-experiments/is-experiment-enabled';
13
14
  import { editorExperiment } from '@atlaskit/tmp-editor-statsig/editor-experiment';
14
15
  import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
15
16
  import { nodeMargins } from '../ui/consts';
@@ -146,7 +147,7 @@ export var createLayoutDropTargetDecoration = function createLayoutDropTargetDec
146
147
  element.setAttribute('data-blocks-drop-target-container', 'true');
147
148
  element.setAttribute('data-blocks-drop-target-key', key);
148
149
  element.style.clear = 'unset';
149
- var DropTargetLayoutComponent = expValEquals('platform_editor_native_anchor_with_dnd', 'isEnabled', true) ? DropTargetLayoutNativeAnchorSupport : DropTargetLayout;
150
+ var DropTargetLayoutComponent = expValEquals('platform_editor_native_anchor_with_dnd', 'isEnabled', true) || isExperimentEnabled('platform_editor_block_control_migration') ? DropTargetLayoutNativeAnchorSupport : DropTargetLayout;
150
151
  nodeViewPortalProviderAPI.render(function () {
151
152
  return /*#__PURE__*/createElement(DropTargetLayoutComponent, _objectSpread(_objectSpread({}, props), {}, {
152
153
  getPos: getPos,
@@ -0,0 +1,65 @@
1
+ import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
+ function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t.return || t.return(); } finally { if (u) throw o; } } }; }
3
+ function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
4
+ function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
5
+ import { Decoration, DecorationSet } from '@atlaskit/editor-prosemirror/view';
6
+ export var TYPE_SURFACE_ANCHOR_DEC = 'block-controls-surface-anchor';
7
+ export var SURFACE_ANCHOR_ATTR = 'data-block-controls-surface-anchor';
8
+ export var SURFACE_NODE_TYPE_ATTR = 'data-block-controls-surface-node-type';
9
+ export var SURFACE_ANCHOR_VARIABLE = '--block-controls-surface-anchor-name';
10
+
11
+ /**
12
+ * These node views expose the box used by the measured placement fallback rather than their
13
+ * ProseMirror node wrapper. The marker carries the name through a custom property so sparse CSS
14
+ * can name that inner box without adding a widget or changing the node view.
15
+ */
16
+ var INNER_CONTENT_NODE_TYPES = new Set(['blockCard', 'bodiedExtension', 'embedCard', 'extension', 'mediaSingle', 'multiBodiedExtension', 'table']);
17
+ var getMarkerStyle = function getMarkerStyle(nodeType, anchorName) {
18
+ var inheritedName = "".concat(SURFACE_ANCHOR_VARIABLE, ": ").concat(anchorName, ";");
19
+
20
+ // Inner boxes get their anchor from the sparse global selector. Naming only the node wrapper
21
+ // would position media/table/extension controls against the wrapper instead of visible content.
22
+ return INNER_CONTENT_NODE_TYPES.has(nodeType) ? inheritedName : "".concat(inheritedName, " anchor-name: ").concat(anchorName, ";");
23
+ };
24
+
25
+ /**
26
+ * Builds sparse CSS anchor decorations from already-qualified cached positions. Anchor identity is
27
+ * supplied by the editor's native node-anchor provider so sparse surfaces and consumers share the
28
+ * same `data-node-anchor`.
29
+ */
30
+ export var createSurfaceAnchorDecorations = function createSurfaceAnchorDecorations(state, positions, resolveAnchorName, previousAnchors) {
31
+ var anchors = new Map();
32
+ var decorations = [];
33
+ var _iterator = _createForOfIteratorHelper(positions),
34
+ _step;
35
+ try {
36
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
37
+ var position = _step.value;
38
+ if (anchors.has(position)) {
39
+ continue;
40
+ }
41
+ var node = state.doc.nodeAt(position);
42
+ if (!(node !== null && node !== void 0 && node.isBlock)) {
43
+ continue;
44
+ }
45
+ var anchorName = resolveAnchorName(node, position, previousAnchors === null || previousAnchors === void 0 ? void 0 : previousAnchors.get(position));
46
+ if (!anchorName) {
47
+ continue;
48
+ }
49
+ anchors.set(position, anchorName);
50
+ decorations.push(Decoration.node(position, position + node.nodeSize, _defineProperty(_defineProperty(_defineProperty({}, SURFACE_ANCHOR_ATTR, anchorName), SURFACE_NODE_TYPE_ATTR, node.type.name), "style", getMarkerStyle(node.type.name, anchorName)), {
51
+ type: TYPE_SURFACE_ANCHOR_DEC,
52
+ anchorName: anchorName,
53
+ nodeType: node.type.name
54
+ }));
55
+ }
56
+ } catch (err) {
57
+ _iterator.e(err);
58
+ } finally {
59
+ _iterator.f();
60
+ }
61
+ return {
62
+ anchors: anchors,
63
+ decorations: DecorationSet.create(state.doc, decorations)
64
+ };
65
+ };
@@ -1,4 +1,5 @@
1
1
  import { DRAG_HANDLE_SELECTOR } from '@atlaskit/editor-common/styles';
2
+ import { isExperimentEnabled } from '@atlaskit/platform-feature-experiments/is-experiment-enabled';
2
3
  import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
3
4
  export var handleMouseDown = function handleMouseDown(api) {
4
5
  return function (view, event) {
@@ -13,7 +14,7 @@ export var handleMouseDown = function handleMouseDown(api) {
13
14
  if (!rootNode) {
14
15
  return false;
15
16
  }
16
- if (expValEquals('platform_editor_native_anchor_with_dnd', 'isEnabled', true)) {
17
+ if (expValEquals('platform_editor_native_anchor_with_dnd', 'isEnabled', true) || isExperimentEnabled('platform_editor_block_control_migration')) {
17
18
  var _rootNode$type$name, _rootNode$type$name2;
18
19
  var anchorName = api === null || api === void 0 ? void 0 : api.core.actions.getAnchorIdForNode(rootNode, rootPos);
19
20
 
@@ -2,6 +2,7 @@ import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
2
2
  import memoizeOne from 'memoize-one';
3
3
  import { isMultiBlockSelection } from '@atlaskit/editor-common/selection';
4
4
  import { areToolbarFlagsEnabled } from '@atlaskit/editor-common/toolbar-flag-check';
5
+ import { isExperimentEnabled } from '@atlaskit/platform-feature-experiments/is-experiment-enabled';
5
6
  import { fg } from '@atlaskit/platform-feature-flags/fg';
6
7
  import { editorExperiment } from '@atlaskit/tmp-editor-statsig/editor-experiment';
7
8
  import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
@@ -133,7 +134,7 @@ export var handleMouseOver = function handleMouseOver(view, event, api) {
133
134
  // Ignored via go/ees005
134
135
  // eslint-disable-next-line @atlaskit/editor/no-as-casting
135
136
  var target = event.target;
136
- var isNativeAnchorSupported = expValEquals('platform_editor_native_anchor_with_dnd', 'isEnabled', true);
137
+ var isNativeAnchorSupported = expValEquals('platform_editor_native_anchor_with_dnd', 'isEnabled', true) || isExperimentEnabled('platform_editor_block_control_migration');
137
138
  if (target !== null && target !== void 0 && (_target$classList = target.classList) !== null && _target$classList !== void 0 && _target$classList.contains('ProseMirror')) {
138
139
  return false;
139
140
  }
@@ -205,7 +206,7 @@ export var handleMouseOver = function handleMouseOver(view, event, api) {
205
206
  // This must happen before anchorName is read so the correct node's handle is shown.
206
207
  rootElement = redirectParagraphToWrappedMedia(rootElement, isNativeAnchorSupported);
207
208
  var anchorName;
208
- if (expValEquals('platform_editor_native_anchor_with_dnd', 'isEnabled', true)) {
209
+ if (expValEquals('platform_editor_native_anchor_with_dnd', 'isEnabled', true) || isExperimentEnabled('platform_editor_block_control_migration')) {
209
210
  anchorName = rootElement.getAttribute(getAnchorAttrName());
210
211
 
211
212
  // don't show handles if we can't find an anchor