@atlaskit/editor-plugin-breakout 2.6.0 → 2.7.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 +22 -0
  2. package/dist/cjs/breakoutPlugin.js +9 -7
  3. package/dist/cjs/pm-plugins/pragmatic-resizer.js +91 -16
  4. package/dist/cjs/pm-plugins/resizer-callbacks.js +50 -12
  5. package/dist/cjs/pm-plugins/resizing-mark-view.js +11 -4
  6. package/dist/cjs/pm-plugins/resizing-plugin.js +2 -2
  7. package/dist/cjs/pm-plugins/utils/analytics.js +23 -0
  8. package/dist/cjs/pm-plugins/utils/measure-framerate.js +122 -0
  9. package/dist/es2019/breakoutPlugin.js +4 -1
  10. package/dist/es2019/pm-plugins/pragmatic-resizer.js +75 -9
  11. package/dist/es2019/pm-plugins/resizer-callbacks.js +47 -6
  12. package/dist/es2019/pm-plugins/resizing-mark-view.js +9 -3
  13. package/dist/es2019/pm-plugins/resizing-plugin.js +2 -2
  14. package/dist/es2019/pm-plugins/utils/analytics.js +15 -0
  15. package/dist/es2019/pm-plugins/utils/measure-framerate.js +109 -0
  16. package/dist/esm/breakoutPlugin.js +9 -7
  17. package/dist/esm/pm-plugins/pragmatic-resizer.js +88 -15
  18. package/dist/esm/pm-plugins/resizer-callbacks.js +50 -12
  19. package/dist/esm/pm-plugins/resizing-mark-view.js +11 -4
  20. package/dist/esm/pm-plugins/resizing-plugin.js +2 -2
  21. package/dist/esm/pm-plugins/utils/analytics.js +17 -0
  22. package/dist/esm/pm-plugins/utils/measure-framerate.js +116 -0
  23. package/dist/types/breakoutPluginType.d.ts +3 -1
  24. package/dist/types/pm-plugins/pragmatic-resizer.d.ts +6 -1
  25. package/dist/types/pm-plugins/resizing-mark-view.d.ts +8 -2
  26. package/dist/types/pm-plugins/resizing-plugin.d.ts +3 -1
  27. package/dist/types/pm-plugins/utils/analytics.d.ts +7 -0
  28. package/dist/types/pm-plugins/utils/measure-framerate.d.ts +30 -0
  29. package/dist/types-ts4.5/breakoutPluginType.d.ts +3 -1
  30. package/dist/types-ts4.5/pm-plugins/pragmatic-resizer.d.ts +6 -1
  31. package/dist/types-ts4.5/pm-plugins/resizing-mark-view.d.ts +8 -2
  32. package/dist/types-ts4.5/pm-plugins/resizing-plugin.d.ts +3 -1
  33. package/dist/types-ts4.5/pm-plugins/utils/analytics.d.ts +7 -0
  34. package/dist/types-ts4.5/pm-plugins/utils/measure-framerate.d.ts +30 -0
  35. package/package.json +7 -5
package/CHANGELOG.md CHANGED
@@ -1,5 +1,27 @@
1
1
  # @atlaskit/editor-plugin-breakout
2
2
 
3
+ ## 2.7.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#166997](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/pull-requests/166997)
8
+ [`826de0a17dc7e`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/826de0a17dc7e) -
9
+ Introduce new breakout oprational event in editor-common, export the type and use in
10
+ editor-plugin-breakout. Add performance measurement for FPS for resizing
11
+
12
+ ### Patch Changes
13
+
14
+ - Updated dependencies
15
+
16
+ ## 2.6.1
17
+
18
+ ### Patch Changes
19
+
20
+ - [#166490](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/pull-requests/166490)
21
+ [`9f140155c14be`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/9f140155c14be) -
22
+ [ux] Shows tooltip on the resize handle when it is hovered.
23
+ - Updated dependencies
24
+
3
25
  ## 2.6.0
4
26
 
5
27
  ### Minor Changes
@@ -209,8 +209,10 @@ var breakoutPlugin = exports.breakoutPlugin = function breakoutPlugin(_ref4) {
209
209
  if ((0, _experiments.editorExperiment)('platform_editor_breakout_resizing', true)) {
210
210
  return [{
211
211
  name: 'breakout-resizing',
212
- plugin: function plugin() {
213
- return (0, _resizingPlugin.createResizingPlugin)(api, options);
212
+ plugin: function plugin(_ref5) {
213
+ var getIntl = _ref5.getIntl,
214
+ nodeViewPortalProviderAPI = _ref5.nodeViewPortalProviderAPI;
215
+ return (0, _resizingPlugin.createResizingPlugin)(api, getIntl, nodeViewPortalProviderAPI, options);
214
216
  }
215
217
  }];
216
218
  }
@@ -241,11 +243,11 @@ var breakoutPlugin = exports.breakoutPlugin = function breakoutPlugin(_ref4) {
241
243
  }
242
244
  return pluginState;
243
245
  },
244
- contentComponent: function contentComponent(_ref5) {
245
- var editorView = _ref5.editorView,
246
- popupsMountPoint = _ref5.popupsMountPoint,
247
- popupsBoundariesElement = _ref5.popupsBoundariesElement,
248
- popupsScrollableElement = _ref5.popupsScrollableElement;
246
+ contentComponent: function contentComponent(_ref6) {
247
+ var editorView = _ref6.editorView,
248
+ popupsMountPoint = _ref6.popupsMountPoint,
249
+ popupsBoundariesElement = _ref6.popupsBoundariesElement,
250
+ popupsScrollableElement = _ref6.popupsScrollableElement;
249
251
  // This is a bit crappy, but should be resolved once we move to a static schema.
250
252
  if (options && !options.allowBreakoutButton) {
251
253
  return null;
@@ -1,20 +1,71 @@
1
1
  "use strict";
2
2
 
3
3
  var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ var _typeof = require("@babel/runtime/helpers/typeof");
4
5
  Object.defineProperty(exports, "__esModule", {
5
6
  value: true
6
7
  });
7
- exports.createPragmaticResizer = void 0;
8
+ exports.resizeHandleMessage = exports.createPragmaticResizer = void 0;
8
9
  var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
10
+ var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
11
+ var _react = _interopRequireWildcard(require("react"));
9
12
  var _bindEventListener = require("bind-event-listener");
13
+ var _v = _interopRequireDefault(require("uuid/v4"));
14
+ var _messages = require("@atlaskit/editor-common/messages");
15
+ var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
10
16
  var _adapter = require("@atlaskit/pragmatic-drag-and-drop/element/adapter");
11
17
  var _disableNativeDragPreview = require("@atlaskit/pragmatic-drag-and-drop/element/disable-native-drag-preview");
12
18
  var _preventUnhandled = require("@atlaskit/pragmatic-drag-and-drop/prevent-unhandled");
13
- var createPragmaticResizer = exports.createPragmaticResizer = function createPragmaticResizer(_ref) {
14
- var target = _ref.target,
15
- _onDragStart = _ref.onDragStart,
16
- onDrag = _ref.onDrag,
17
- _onDrop = _ref.onDrop;
19
+ var _tooltip = _interopRequireDefault(require("@atlaskit/tooltip"));
20
+ function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != _typeof(e) && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t in e) "default" !== _t && {}.hasOwnProperty.call(e, _t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, _t)) && (i.get || i.set) ? o(f, _t, i) : f[_t] = e[_t]); return f; })(e, t); }
21
+ var getNodeName = function getNodeName(nodeName) {
22
+ if (nodeName === 'layoutSection') {
23
+ return 'layout';
24
+ } else if (nodeName === 'codeBlock' || nodeName === 'expand') {
25
+ return nodeName;
26
+ } else {
27
+ return 'node';
28
+ }
29
+ };
30
+ var resizeHandleMessage = exports.resizeHandleMessage = {
31
+ expand: _messages.breakoutMessages.resizeExpand,
32
+ codeBlock: _messages.breakoutMessages.resizeCodeBlock,
33
+ layout: _messages.breakoutMessages.resizeLayout,
34
+ node: _messages.breakoutMessages.resizeElement
35
+ };
36
+ var RailWithTooltip = function RailWithTooltip(_ref) {
37
+ var rail = _ref.rail,
38
+ target = _ref.target,
39
+ intl = _ref.intl;
40
+ var _useState = (0, _react.useState)('node'),
41
+ _useState2 = (0, _slicedToArray2.default)(_useState, 2),
42
+ nodeName = _useState2[0],
43
+ setNodeName = _useState2[1];
44
+ (0, _react.useLayoutEffect)(function () {
45
+ var node = target.querySelector('[data-prosemirror-node-name]');
46
+ var name = getNodeName(node === null || node === void 0 ? void 0 : node.dataset.prosemirrorNodeName);
47
+ setNodeName(name);
48
+ }, [target]);
49
+ return /*#__PURE__*/_react.default.createElement(_tooltip.default, {
50
+ content: intl.formatMessage(resizeHandleMessage[nodeName]),
51
+ position: "mouse"
52
+ }, /*#__PURE__*/_react.default.createElement("div", {
53
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop -- Ignored via go/DSP-18766
54
+ className: "pm-breakout-resize-handle-rail-inside-tooltip",
55
+ ref: function ref(el) {
56
+ if (el && rail.parentNode !== el) {
57
+ el.appendChild(rail);
58
+ }
59
+ }
60
+ }));
61
+ };
62
+ var createPragmaticResizer = exports.createPragmaticResizer = function createPragmaticResizer(_ref2) {
63
+ var target = _ref2.target,
64
+ _onDragStart = _ref2.onDragStart,
65
+ onDrag = _ref2.onDrag,
66
+ _onDrop = _ref2.onDrop,
67
+ intl = _ref2.intl,
68
+ nodeViewPortalProviderAPI = _ref2.nodeViewPortalProviderAPI;
18
69
  var state = 'default';
19
70
  var createHandle = function createHandle(side) {
20
71
  var handle = document.createElement('div');
@@ -34,21 +85,45 @@ var createPragmaticResizer = exports.createPragmaticResizer = function createPra
34
85
  var thumb = document.createElement('div');
35
86
  thumb.classList.add('pm-breakout-resize-handle-thumb');
36
87
  rail.appendChild(thumb);
37
- handle.appendChild(rail);
38
- handle.appendChild(handleHitBox);
39
- return {
40
- handle: handle,
41
- rail: rail,
42
- handleHitBox: handleHitBox
43
- };
88
+ if ((0, _platformFeatureFlags.fg)('platform_editor_breakout_resizing_hello_release')) {
89
+ var tooltipContainer = document.createElement('div');
90
+ tooltipContainer.classList.add('pm-breakout-resize-handle-rail-wrapper');
91
+ handle.appendChild(tooltipContainer);
92
+ handle.appendChild(handleHitBox);
93
+ var key = (0, _v.default)();
94
+ nodeViewPortalProviderAPI.render(function () {
95
+ return /*#__PURE__*/_react.default.createElement(RailWithTooltip, {
96
+ rail: rail,
97
+ target: target,
98
+ intl: intl
99
+ });
100
+ }, tooltipContainer, key);
101
+ return {
102
+ handle: handle,
103
+ rail: rail,
104
+ handleHitBox: handleHitBox,
105
+ destroyTooltip: function destroyTooltip() {
106
+ return nodeViewPortalProviderAPI.remove(key);
107
+ }
108
+ };
109
+ } else {
110
+ handle.appendChild(rail);
111
+ handle.appendChild(handleHitBox);
112
+ return {
113
+ handle: handle,
114
+ rail: rail,
115
+ handleHitBox: handleHitBox,
116
+ destroyTooltip: function destroyTooltip() {}
117
+ };
118
+ }
44
119
  };
45
120
  var rightHandle = createHandle('right');
46
121
  var leftHandle = createHandle('left');
47
122
  var registerHandle = function registerHandle(handleElement, handleSide) {
48
123
  return (0, _adapter.draggable)({
49
124
  element: handleElement,
50
- onGenerateDragPreview: function onGenerateDragPreview(_ref2) {
51
- var nativeSetDragImage = _ref2.nativeSetDragImage;
125
+ onGenerateDragPreview: function onGenerateDragPreview(_ref3) {
126
+ var nativeSetDragImage = _ref3.nativeSetDragImage;
52
127
  (0, _disableNativeDragPreview.disableNativeDragPreview)({
53
128
  nativeSetDragImage: nativeSetDragImage
54
129
  });
@@ -92,7 +167,7 @@ var createPragmaticResizer = exports.createPragmaticResizer = function createPra
92
167
  })];
93
168
  };
94
169
  var unbindFns = [].concat((0, _toConsumableArray2.default)(registerEvents(target)), (0, _toConsumableArray2.default)(registerEvents(rightHandle.handleHitBox)), (0, _toConsumableArray2.default)(registerEvents(leftHandle.handleHitBox)), (0, _toConsumableArray2.default)(registerEvents(rightHandle.rail)), (0, _toConsumableArray2.default)(registerEvents(leftHandle.rail)));
95
- var destroyFns = [registerHandle(rightHandle.handle, 'right'), registerHandle(leftHandle.handle, 'left')];
170
+ var destroyFns = [registerHandle(rightHandle.handle, 'right'), registerHandle(leftHandle.handle, 'left')].concat((0, _toConsumableArray2.default)((0, _platformFeatureFlags.fg)('platform_editor_breakout_resizing_hello_release') ? [rightHandle.destroyTooltip, leftHandle.destroyTooltip] : []));
96
171
  return {
97
172
  rightHandle: rightHandle.handle,
98
173
  leftHandle: leftHandle.handle,
@@ -10,6 +10,8 @@ var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
10
10
  var _setBreakoutWidth = require("../editor-commands/set-breakout-width");
11
11
  var _getGuidelines = require("./get-guidelines");
12
12
  var _resizingMarkView = require("./resizing-mark-view");
13
+ var _analytics = require("./utils/analytics");
14
+ var _measureFramerate2 = require("./utils/measure-framerate");
13
15
  var RESIZE_RATIO = 2;
14
16
  var SNAP_GAP = 10;
15
17
  var WIDTHS = {
@@ -48,22 +50,38 @@ function createResizerCallbacks(_ref2) {
48
50
  api = _ref2.api;
49
51
  var node = null;
50
52
  var guidelines = [];
53
+ var _measureFramerate = (0, _measureFramerate2.measureFramerate)(),
54
+ startMeasure = _measureFramerate.startMeasure,
55
+ endMeasure = _measureFramerate.endMeasure,
56
+ countFrames = _measureFramerate.countFrames;
51
57
  var getEditorWidth = function getEditorWidth() {
52
58
  var _api$width;
53
59
  return api === null || api === void 0 || (_api$width = api.width) === null || _api$width === void 0 ? void 0 : _api$width.sharedState.currentState();
54
60
  };
55
61
  return {
56
62
  onDragStart: function onDragStart() {
57
- var _api$userIntent;
58
- api === null || api === void 0 || api.core.actions.execute((_api$userIntent = api.userIntent) === null || _api$userIntent === void 0 ? void 0 : _api$userIntent.commands.setCurrentUserIntent('dragging'));
59
- view.dispatch(view.state.tr.setMeta('is-resizer-resizing', true));
63
+ if ((0, _platformFeatureFlags.fg)('platform_editor_breakout_resizing_hello_release')) {
64
+ startMeasure();
65
+ }
66
+ api === null || api === void 0 || api.core.actions.execute(function (_ref3) {
67
+ var _api$userIntent;
68
+ var tr = _ref3.tr;
69
+ (_api$userIntent = api.userIntent) === null || _api$userIntent === void 0 || _api$userIntent.commands.setCurrentUserIntent('dragging')({
70
+ tr: tr
71
+ });
72
+ tr.setMeta('is-resizer-resizing', true);
73
+ return tr;
74
+ });
60
75
  var pos = view.posAtDOM(dom, 0);
61
76
  node = view.state.doc.nodeAt(pos);
62
77
  },
63
- onDrag: function onDrag(_ref3) {
78
+ onDrag: function onDrag(_ref4) {
64
79
  var _node, _api$guideline;
65
- var location = _ref3.location,
66
- source = _ref3.source;
80
+ var location = _ref4.location,
81
+ source = _ref4.source;
82
+ if ((0, _platformFeatureFlags.fg)('platform_editor_breakout_resizing_hello_release')) {
83
+ countFrames();
84
+ }
67
85
  var initialWidth = mark.attrs.width;
68
86
  var newWidth = getProposedWidth({
69
87
  initialWidth: initialWidth,
@@ -77,10 +95,19 @@ function createResizerCallbacks(_ref2) {
77
95
  });
78
96
  contentDOM.style.setProperty(_resizingMarkView.LOCAL_RESIZE_PROPERTY, "".concat(newWidth, "px"));
79
97
  },
80
- onDrop: function onDrop(_ref4) {
81
- var _api$guideline2, _api$userIntent2;
82
- var location = _ref4.location,
83
- source = _ref4.source;
98
+ onDrop: function onDrop(_ref5) {
99
+ var _api$guideline2;
100
+ var location = _ref5.location,
101
+ source = _ref5.source;
102
+ var payloads = [];
103
+ if ((0, _platformFeatureFlags.fg)('platform_editor_breakout_resizing_hello_release')) {
104
+ var frameRateSamples = endMeasure();
105
+ payloads = (0, _analytics.generateResizeFrameRatePayloads)({
106
+ docSize: view.state.doc.nodeSize,
107
+ frameRateSamples: (0, _measureFramerate2.reduceResizeFrameRateSamples)(frameRateSamples),
108
+ originalNode: node
109
+ });
110
+ }
84
111
  var isResizedToFullWidth = !!guidelines.find(function (guideline) {
85
112
  return guideline.key.includes('full_width') && guideline.active;
86
113
  });
@@ -99,8 +126,19 @@ function createResizerCallbacks(_ref2) {
99
126
  });
100
127
  (0, _setBreakoutWidth.setBreakoutWidth)(newWidth, mode, pos)(view.state, view.dispatch);
101
128
  contentDOM.style.removeProperty(_resizingMarkView.LOCAL_RESIZE_PROPERTY);
102
- view.dispatch(view.state.tr.setMeta('is-resizer-resizing', false).setMeta('scrollIntoView', false));
103
- api === null || api === void 0 || api.core.actions.execute((_api$userIntent2 = api.userIntent) === null || _api$userIntent2 === void 0 ? void 0 : _api$userIntent2.commands.setCurrentUserIntent('default'));
129
+ api === null || api === void 0 || api.core.actions.execute(function (_ref6) {
130
+ var _api$userIntent2;
131
+ var tr = _ref6.tr;
132
+ (_api$userIntent2 = api.userIntent) === null || _api$userIntent2 === void 0 || _api$userIntent2.commands.setCurrentUserIntent('default')({
133
+ tr: tr
134
+ });
135
+ tr.setMeta('is-resizer-resizing', false).setMeta('scrollIntoView', false);
136
+ payloads.forEach(function (payload) {
137
+ var _api$analytics;
138
+ (_api$analytics = api.analytics) === null || _api$analytics === void 0 || (_api$analytics = _api$analytics.actions) === null || _api$analytics === void 0 || _api$analytics.attachAnalyticsEvent(payload)(tr);
139
+ });
140
+ return tr;
141
+ });
104
142
  }
105
143
  };
106
144
  }
@@ -19,12 +19,14 @@ var ResizingMarkView = exports.ResizingMarkView = /*#__PURE__*/function () {
19
19
  * Wrap node view in a resizing mark view
20
20
  * @param {Mark} mark - The breakout mark to resize
21
21
  * @param {EditorView} view - The editor view
22
- * @param {ExtractInjectionAPI<BreakoutPlugin> | undefined} api - the pluginInjectionAPI
22
+ * @param {ExtractInjectionAPI<BreakoutPlugin> | undefined} api - The pluginInjectionAPI
23
+ * @param {Function} getIntl - () => IntlShape
24
+ * @param {PortalProviderAPI} - The nodeViewPortalProviderAPI
23
25
  * @example
24
26
  * ```ts
25
27
  * ```
26
28
  */
27
- function ResizingMarkView(mark, view, api) {
29
+ function ResizingMarkView(mark, view, api, getIntl, nodeViewPortalProviderAPI) {
28
30
  (0, _classCallCheck2.default)(this, ResizingMarkView);
29
31
  var dom = document.createElement('div');
30
32
  var contentDOM = document.createElement('div');
@@ -60,9 +62,14 @@ var ResizingMarkView = exports.ResizingMarkView = /*#__PURE__*/function () {
60
62
  mark: mark,
61
63
  api: api
62
64
  });
63
- var _createPragmaticResiz = (0, _pragmaticResizer.createPragmaticResizer)(_objectSpread({
65
+ this.intl = getIntl();
66
+ this.nodeViewPortalProviderAPI = nodeViewPortalProviderAPI;
67
+ var _createPragmaticResiz = (0, _pragmaticResizer.createPragmaticResizer)(_objectSpread(_objectSpread({
64
68
  target: contentDOM
65
- }, callbacks)),
69
+ }, callbacks), {}, {
70
+ intl: this.intl,
71
+ nodeViewPortalProviderAPI: this.nodeViewPortalProviderAPI
72
+ })),
66
73
  leftHandle = _createPragmaticResiz.leftHandle,
67
74
  rightHandle = _createPragmaticResiz.rightHandle,
68
75
  destroy = _createPragmaticResiz.destroy;
@@ -49,13 +49,13 @@ var addBreakoutToResizableNode = function addBreakoutToResizableNode(_ref) {
49
49
  };
50
50
  };
51
51
  var resizingPluginKey = exports.resizingPluginKey = new _state.PluginKey('breakout-resizing');
52
- var createResizingPlugin = exports.createResizingPlugin = function createResizingPlugin(api, options) {
52
+ var createResizingPlugin = exports.createResizingPlugin = function createResizingPlugin(api, getIntl, nodeViewPortalProviderAPI, options) {
53
53
  return new _safePlugin.SafePlugin({
54
54
  key: resizingPluginKey,
55
55
  props: {
56
56
  markViews: {
57
57
  breakout: function breakout(mark, view) {
58
- return new _resizingMarkView.ResizingMarkView(mark, view, api);
58
+ return new _resizingMarkView.ResizingMarkView(mark, view, api, getIntl, nodeViewPortalProviderAPI);
59
59
  }
60
60
  },
61
61
  handleKeyDown: _handleKeyDown.handleKeyDown
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.generateResizeFrameRatePayloads = void 0;
7
+ var _analytics = require("@atlaskit/editor-common/analytics");
8
+ var generateResizeFrameRatePayloads = exports.generateResizeFrameRatePayloads = function generateResizeFrameRatePayloads(props) {
9
+ return props.frameRateSamples.map(function (frameRateSample, index) {
10
+ return {
11
+ action: _analytics.ACTION.RESIZED_PERF_SAMPLING,
12
+ actionSubject: _analytics.ACTION_SUBJECT.ELEMENT,
13
+ eventType: _analytics.EVENT_TYPE.OPERATIONAL,
14
+ attributes: {
15
+ nodeType: props.originalNode.type.name,
16
+ frameRate: frameRateSample,
17
+ nodeSize: props.originalNode.nodeSize,
18
+ docSize: props.docSize,
19
+ isInitialSample: index === 0
20
+ }
21
+ };
22
+ });
23
+ };
@@ -0,0 +1,122 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.reduceResizeFrameRateSamples = exports.measureFramerate = void 0;
7
+ /**
8
+ * Measure the FPS of a resizing component.
9
+ *
10
+ * This is a simplified version of the `useMeasureFramerate` hook from `editor-plugin-table`.
11
+ * (packages/editor/editor-plugin-table/src/pm-plugins/utils/analytics.ts)
12
+ */
13
+
14
+ var reduceResizeFrameRateSamples = exports.reduceResizeFrameRateSamples = function reduceResizeFrameRateSamples(frameRateSamples) {
15
+ if (frameRateSamples.length > 1) {
16
+ var frameRateSum = frameRateSamples.reduce(function (sum, frameRate, index) {
17
+ if (index === 0) {
18
+ return sum;
19
+ } else {
20
+ return sum + frameRate;
21
+ }
22
+ }, 0);
23
+ var averageFrameRate = Math.round(frameRateSum / (frameRateSamples.length - 1));
24
+ return [frameRateSamples[0], averageFrameRate];
25
+ } else {
26
+ return frameRateSamples;
27
+ }
28
+ };
29
+ /**
30
+ * Measures the framerate of a component over a given time period.
31
+ * @param {object} [config] - Configuration options for framerate measurement.
32
+ * @returns {object} An object containing startMeasure, endMeasure, and countFrames methods.
33
+ * @example
34
+ * const { startMeasure, endMeasure, countFrames } = measureFramerate();
35
+ * startMeasure();
36
+ * // ... animation loop with countFrames() calls
37
+ * const samples = endMeasure(); // [60, 58, 62]
38
+ */
39
+ var measureFramerate = exports.measureFramerate = function measureFramerate(config) {
40
+ var _ref = config || {},
41
+ _ref$maxSamples = _ref.maxSamples,
42
+ maxSamples = _ref$maxSamples === void 0 ? 10 : _ref$maxSamples,
43
+ _ref$minFrames = _ref.minFrames,
44
+ minFrames = _ref$minFrames === void 0 ? 5 : _ref$minFrames,
45
+ _ref$minTimeMs = _ref.minTimeMs,
46
+ minTimeMs = _ref$minTimeMs === void 0 ? 500 : _ref$minTimeMs,
47
+ _ref$sampleRateMs = _ref.sampleRateMs,
48
+ sampleRateMs = _ref$sampleRateMs === void 0 ? 1000 : _ref$sampleRateMs,
49
+ _ref$timeoutMs = _ref.timeoutMs,
50
+ timeoutMs = _ref$timeoutMs === void 0 ? 200 : _ref$timeoutMs;
51
+ var frameCount = 0;
52
+ var lastTime = 0;
53
+ var timeoutId;
54
+ var frameRateSamples = [];
55
+ var startMeasure = function startMeasure() {
56
+ frameCount = 0;
57
+ lastTime = performance.now();
58
+ };
59
+
60
+ /**
61
+ * Returns an array of frame rate samples as integers.
62
+ * @returns {number[]} An array of frame rate samples as integers.
63
+ * @example
64
+ * const samples = endMeasure(); // [60, 58, 62]
65
+ */
66
+ var endMeasure = function endMeasure() {
67
+ var samples = frameRateSamples;
68
+ frameRateSamples = [];
69
+ return samples;
70
+ };
71
+ var sampleFrameRate = function sampleFrameRate() {
72
+ var delay = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
73
+ var currentTime = performance.now();
74
+ var deltaTime = currentTime - lastTime - delay;
75
+ var isValidSample = deltaTime > minTimeMs && frameCount >= minFrames;
76
+ if (isValidSample) {
77
+ var frameRate = Math.round(frameCount / (deltaTime / 1000));
78
+ frameRateSamples.push(frameRate);
79
+ }
80
+ frameCount = 0;
81
+ lastTime = 0;
82
+ };
83
+
84
+ /**
85
+ * Counts the number of frames that occur within a given time period. Intended to be called
86
+ * inside a `requestAnimationFrame` callback.
87
+ * @example
88
+ * const animate = () => {
89
+ * countFrames();
90
+ * requestAnimationFrame(animate);
91
+ * };
92
+ */
93
+ var countFrames = function countFrames() {
94
+ if (frameRateSamples.length >= maxSamples && timeoutId) {
95
+ clearTimeout(timeoutId);
96
+ return;
97
+ }
98
+
99
+ /**
100
+ * Allows us to keep counting frames even if `startMeasure` is not called
101
+ */
102
+ if (lastTime === 0) {
103
+ lastTime = performance.now();
104
+ }
105
+ frameCount++;
106
+ if (timeoutId) {
107
+ clearTimeout(timeoutId);
108
+ }
109
+ if (performance.now() - lastTime > sampleRateMs) {
110
+ sampleFrameRate();
111
+ } else {
112
+ timeoutId = setTimeout(function () {
113
+ return sampleFrameRate(timeoutMs);
114
+ }, timeoutMs);
115
+ }
116
+ };
117
+ return {
118
+ startMeasure: startMeasure,
119
+ endMeasure: endMeasure,
120
+ countFrames: countFrames
121
+ };
122
+ };
@@ -195,7 +195,10 @@ export const breakoutPlugin = ({
195
195
  if (editorExperiment('platform_editor_breakout_resizing', true)) {
196
196
  return [{
197
197
  name: 'breakout-resizing',
198
- plugin: () => createResizingPlugin(api, options)
198
+ plugin: ({
199
+ getIntl,
200
+ nodeViewPortalProviderAPI
201
+ }) => createResizingPlugin(api, getIntl, nodeViewPortalProviderAPI, options)
199
202
  }];
200
203
  }
201
204
  return [{
@@ -1,12 +1,58 @@
1
+ import React, { useLayoutEffect, useState } from 'react';
1
2
  import { bind } from 'bind-event-listener';
3
+ import uuid from 'uuid/v4';
4
+ import { breakoutMessages as messages } from '@atlaskit/editor-common/messages';
5
+ import { fg } from '@atlaskit/platform-feature-flags';
2
6
  import { draggable } from '@atlaskit/pragmatic-drag-and-drop/element/adapter';
3
7
  import { disableNativeDragPreview } from '@atlaskit/pragmatic-drag-and-drop/element/disable-native-drag-preview';
4
8
  import { preventUnhandled } from '@atlaskit/pragmatic-drag-and-drop/prevent-unhandled';
9
+ import Tooltip from '@atlaskit/tooltip';
10
+ const getNodeName = nodeName => {
11
+ if (nodeName === 'layoutSection') {
12
+ return 'layout';
13
+ } else if (nodeName === 'codeBlock' || nodeName === 'expand') {
14
+ return nodeName;
15
+ } else {
16
+ return 'node';
17
+ }
18
+ };
19
+ export const resizeHandleMessage = {
20
+ expand: messages.resizeExpand,
21
+ codeBlock: messages.resizeCodeBlock,
22
+ layout: messages.resizeLayout,
23
+ node: messages.resizeElement
24
+ };
25
+ const RailWithTooltip = ({
26
+ rail,
27
+ target,
28
+ intl
29
+ }) => {
30
+ const [nodeName, setNodeName] = useState('node');
31
+ useLayoutEffect(() => {
32
+ const node = target.querySelector('[data-prosemirror-node-name]');
33
+ const name = getNodeName(node === null || node === void 0 ? void 0 : node.dataset.prosemirrorNodeName);
34
+ setNodeName(name);
35
+ }, [target]);
36
+ return /*#__PURE__*/React.createElement(Tooltip, {
37
+ content: intl.formatMessage(resizeHandleMessage[nodeName]),
38
+ position: "mouse"
39
+ }, /*#__PURE__*/React.createElement("div", {
40
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop -- Ignored via go/DSP-18766
41
+ className: "pm-breakout-resize-handle-rail-inside-tooltip",
42
+ ref: el => {
43
+ if (el && rail.parentNode !== el) {
44
+ el.appendChild(rail);
45
+ }
46
+ }
47
+ }));
48
+ };
5
49
  export const createPragmaticResizer = ({
6
50
  target,
7
51
  onDragStart,
8
52
  onDrag,
9
- onDrop
53
+ onDrop,
54
+ intl,
55
+ nodeViewPortalProviderAPI
10
56
  }) => {
11
57
  let state = 'default';
12
58
  const createHandle = side => {
@@ -27,13 +73,33 @@ export const createPragmaticResizer = ({
27
73
  const thumb = document.createElement('div');
28
74
  thumb.classList.add('pm-breakout-resize-handle-thumb');
29
75
  rail.appendChild(thumb);
30
- handle.appendChild(rail);
31
- handle.appendChild(handleHitBox);
32
- return {
33
- handle,
34
- rail,
35
- handleHitBox
36
- };
76
+ if (fg('platform_editor_breakout_resizing_hello_release')) {
77
+ const tooltipContainer = document.createElement('div');
78
+ tooltipContainer.classList.add('pm-breakout-resize-handle-rail-wrapper');
79
+ handle.appendChild(tooltipContainer);
80
+ handle.appendChild(handleHitBox);
81
+ const key = uuid();
82
+ nodeViewPortalProviderAPI.render(() => /*#__PURE__*/React.createElement(RailWithTooltip, {
83
+ rail: rail,
84
+ target: target,
85
+ intl: intl
86
+ }), tooltipContainer, key);
87
+ return {
88
+ handle,
89
+ rail,
90
+ handleHitBox,
91
+ destroyTooltip: () => nodeViewPortalProviderAPI.remove(key)
92
+ };
93
+ } else {
94
+ handle.appendChild(rail);
95
+ handle.appendChild(handleHitBox);
96
+ return {
97
+ handle,
98
+ rail,
99
+ handleHitBox,
100
+ destroyTooltip: () => {}
101
+ };
102
+ }
37
103
  };
38
104
  const rightHandle = createHandle('right');
39
105
  const leftHandle = createHandle('left');
@@ -84,7 +150,7 @@ export const createPragmaticResizer = ({
84
150
  })];
85
151
  };
86
152
  const unbindFns = [...registerEvents(target), ...registerEvents(rightHandle.handleHitBox), ...registerEvents(leftHandle.handleHitBox), ...registerEvents(rightHandle.rail), ...registerEvents(leftHandle.rail)];
87
- const destroyFns = [registerHandle(rightHandle.handle, 'right'), registerHandle(leftHandle.handle, 'left')];
153
+ const destroyFns = [registerHandle(rightHandle.handle, 'right'), registerHandle(leftHandle.handle, 'left'), ...(fg('platform_editor_breakout_resizing_hello_release') ? [rightHandle.destroyTooltip, leftHandle.destroyTooltip] : [])];
88
154
  return {
89
155
  rightHandle: rightHandle.handle,
90
156
  leftHandle: leftHandle.handle,