@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
@@ -3,6 +3,8 @@ import { fg } from '@atlaskit/platform-feature-flags';
3
3
  import { setBreakoutWidth } from '../editor-commands/set-breakout-width';
4
4
  import { getGuidelines } from './get-guidelines';
5
5
  import { LOCAL_RESIZE_PROPERTY } from './resizing-mark-view';
6
+ import { generateResizeFrameRatePayloads } from './utils/analytics';
7
+ import { measureFramerate, reduceResizeFrameRateSamples } from './utils/measure-framerate';
6
8
  const RESIZE_RATIO = 2;
7
9
  const SNAP_GAP = 10;
8
10
  const WIDTHS = {
@@ -42,15 +44,30 @@ export function createResizerCallbacks({
42
44
  }) {
43
45
  let node = null;
44
46
  let guidelines = [];
47
+ const {
48
+ startMeasure,
49
+ endMeasure,
50
+ countFrames
51
+ } = measureFramerate();
45
52
  const getEditorWidth = () => {
46
53
  var _api$width;
47
54
  return api === null || api === void 0 ? void 0 : (_api$width = api.width) === null || _api$width === void 0 ? void 0 : _api$width.sharedState.currentState();
48
55
  };
49
56
  return {
50
57
  onDragStart: () => {
51
- var _api$userIntent;
52
- api === null || api === void 0 ? void 0 : api.core.actions.execute((_api$userIntent = api.userIntent) === null || _api$userIntent === void 0 ? void 0 : _api$userIntent.commands.setCurrentUserIntent('dragging'));
53
- view.dispatch(view.state.tr.setMeta('is-resizer-resizing', true));
58
+ if (fg('platform_editor_breakout_resizing_hello_release')) {
59
+ startMeasure();
60
+ }
61
+ api === null || api === void 0 ? void 0 : api.core.actions.execute(({
62
+ tr
63
+ }) => {
64
+ var _api$userIntent;
65
+ (_api$userIntent = api.userIntent) === null || _api$userIntent === void 0 ? void 0 : _api$userIntent.commands.setCurrentUserIntent('dragging')({
66
+ tr
67
+ });
68
+ tr.setMeta('is-resizer-resizing', true);
69
+ return tr;
70
+ });
54
71
  const pos = view.posAtDOM(dom, 0);
55
72
  node = view.state.doc.nodeAt(pos);
56
73
  },
@@ -59,6 +76,9 @@ export function createResizerCallbacks({
59
76
  source
60
77
  }) => {
61
78
  var _node, _api$guideline, _api$guideline$action;
79
+ if (fg('platform_editor_breakout_resizing_hello_release')) {
80
+ countFrames();
81
+ }
62
82
  const initialWidth = mark.attrs.width;
63
83
  const newWidth = getProposedWidth({
64
84
  initialWidth,
@@ -76,7 +96,16 @@ export function createResizerCallbacks({
76
96
  location,
77
97
  source
78
98
  }) {
79
- var _api$guideline2, _api$guideline2$actio, _api$userIntent2;
99
+ var _api$guideline2, _api$guideline2$actio;
100
+ let payloads = [];
101
+ if (fg('platform_editor_breakout_resizing_hello_release')) {
102
+ const frameRateSamples = endMeasure();
103
+ payloads = generateResizeFrameRatePayloads({
104
+ docSize: view.state.doc.nodeSize,
105
+ frameRateSamples: reduceResizeFrameRateSamples(frameRateSamples),
106
+ originalNode: node
107
+ });
108
+ }
80
109
  const isResizedToFullWidth = !!guidelines.find(guideline => guideline.key.includes('full_width') && guideline.active);
81
110
  guidelines = getGuidelines(false, 0, getEditorWidth);
82
111
  api === null || api === void 0 ? void 0 : (_api$guideline2 = api.guideline) === null || _api$guideline2 === void 0 ? void 0 : (_api$guideline2$actio = _api$guideline2.actions) === null || _api$guideline2$actio === void 0 ? void 0 : _api$guideline2$actio.displayGuideline(view)({
@@ -93,8 +122,20 @@ export function createResizerCallbacks({
93
122
  });
94
123
  setBreakoutWidth(newWidth, mode, pos)(view.state, view.dispatch);
95
124
  contentDOM.style.removeProperty(LOCAL_RESIZE_PROPERTY);
96
- view.dispatch(view.state.tr.setMeta('is-resizer-resizing', false).setMeta('scrollIntoView', false));
97
- api === null || api === void 0 ? void 0 : api.core.actions.execute((_api$userIntent2 = api.userIntent) === null || _api$userIntent2 === void 0 ? void 0 : _api$userIntent2.commands.setCurrentUserIntent('default'));
125
+ api === null || api === void 0 ? void 0 : api.core.actions.execute(({
126
+ tr
127
+ }) => {
128
+ var _api$userIntent2;
129
+ (_api$userIntent2 = api.userIntent) === null || _api$userIntent2 === void 0 ? void 0 : _api$userIntent2.commands.setCurrentUserIntent('default')({
130
+ tr
131
+ });
132
+ tr.setMeta('is-resizer-resizing', false).setMeta('scrollIntoView', false);
133
+ payloads.forEach(payload => {
134
+ var _api$analytics, _api$analytics$action;
135
+ (_api$analytics = api.analytics) === null || _api$analytics === void 0 ? void 0 : (_api$analytics$action = _api$analytics.actions) === null || _api$analytics$action === void 0 ? void 0 : _api$analytics$action.attachAnalyticsEvent(payload)(tr);
136
+ });
137
+ return tr;
138
+ });
98
139
  }
99
140
  };
100
141
  }
@@ -7,12 +7,14 @@ export class ResizingMarkView {
7
7
  * Wrap node view in a resizing mark view
8
8
  * @param {Mark} mark - The breakout mark to resize
9
9
  * @param {EditorView} view - The editor view
10
- * @param {ExtractInjectionAPI<BreakoutPlugin> | undefined} api - the pluginInjectionAPI
10
+ * @param {ExtractInjectionAPI<BreakoutPlugin> | undefined} api - The pluginInjectionAPI
11
+ * @param {Function} getIntl - () => IntlShape
12
+ * @param {PortalProviderAPI} - The nodeViewPortalProviderAPI
11
13
  * @example
12
14
  * ```ts
13
15
  * ```
14
16
  */
15
- constructor(mark, view, api) {
17
+ constructor(mark, view, api, getIntl, nodeViewPortalProviderAPI) {
16
18
  const dom = document.createElement('div');
17
19
  const contentDOM = document.createElement('div');
18
20
  contentDOM.className = BreakoutCssClassName.BREAKOUT_MARK_DOM;
@@ -47,13 +49,17 @@ export class ResizingMarkView {
47
49
  mark,
48
50
  api
49
51
  });
52
+ this.intl = getIntl();
53
+ this.nodeViewPortalProviderAPI = nodeViewPortalProviderAPI;
50
54
  const {
51
55
  leftHandle,
52
56
  rightHandle,
53
57
  destroy
54
58
  } = createPragmaticResizer({
55
59
  target: contentDOM,
56
- ...callbacks
60
+ ...callbacks,
61
+ intl: this.intl,
62
+ nodeViewPortalProviderAPI: this.nodeViewPortalProviderAPI
57
63
  });
58
64
  dom.prepend(leftHandle);
59
65
  dom.appendChild(rightHandle);
@@ -44,13 +44,13 @@ const addBreakoutToResizableNode = ({
44
44
  };
45
45
  };
46
46
  export const resizingPluginKey = new PluginKey('breakout-resizing');
47
- export const createResizingPlugin = (api, options) => {
47
+ export const createResizingPlugin = (api, getIntl, nodeViewPortalProviderAPI, options) => {
48
48
  return new SafePlugin({
49
49
  key: resizingPluginKey,
50
50
  props: {
51
51
  markViews: {
52
52
  breakout: (mark, view) => {
53
- return new ResizingMarkView(mark, view, api);
53
+ return new ResizingMarkView(mark, view, api, getIntl, nodeViewPortalProviderAPI);
54
54
  }
55
55
  },
56
56
  handleKeyDown
@@ -0,0 +1,15 @@
1
+ import { ACTION, ACTION_SUBJECT, EVENT_TYPE } from '@atlaskit/editor-common/analytics';
2
+ export const generateResizeFrameRatePayloads = props => {
3
+ return props.frameRateSamples.map((frameRateSample, index) => ({
4
+ action: ACTION.RESIZED_PERF_SAMPLING,
5
+ actionSubject: ACTION_SUBJECT.ELEMENT,
6
+ eventType: EVENT_TYPE.OPERATIONAL,
7
+ attributes: {
8
+ nodeType: props.originalNode.type.name,
9
+ frameRate: frameRateSample,
10
+ nodeSize: props.originalNode.nodeSize,
11
+ docSize: props.docSize,
12
+ isInitialSample: index === 0
13
+ }
14
+ }));
15
+ };
@@ -0,0 +1,109 @@
1
+ /**
2
+ * Measure the FPS of a resizing component.
3
+ *
4
+ * This is a simplified version of the `useMeasureFramerate` hook from `editor-plugin-table`.
5
+ * (packages/editor/editor-plugin-table/src/pm-plugins/utils/analytics.ts)
6
+ */
7
+
8
+ export const reduceResizeFrameRateSamples = frameRateSamples => {
9
+ if (frameRateSamples.length > 1) {
10
+ const frameRateSum = frameRateSamples.reduce((sum, frameRate, index) => {
11
+ if (index === 0) {
12
+ return sum;
13
+ } else {
14
+ return sum + frameRate;
15
+ }
16
+ }, 0);
17
+ const averageFrameRate = Math.round(frameRateSum / (frameRateSamples.length - 1));
18
+ return [frameRateSamples[0], averageFrameRate];
19
+ } else {
20
+ return frameRateSamples;
21
+ }
22
+ };
23
+ /**
24
+ * Measures the framerate of a component over a given time period.
25
+ * @param {object} [config] - Configuration options for framerate measurement.
26
+ * @returns {object} An object containing startMeasure, endMeasure, and countFrames methods.
27
+ * @example
28
+ * const { startMeasure, endMeasure, countFrames } = measureFramerate();
29
+ * startMeasure();
30
+ * // ... animation loop with countFrames() calls
31
+ * const samples = endMeasure(); // [60, 58, 62]
32
+ */
33
+ export const measureFramerate = config => {
34
+ const {
35
+ maxSamples = 10,
36
+ minFrames = 5,
37
+ minTimeMs = 500,
38
+ sampleRateMs = 1000,
39
+ timeoutMs = 200
40
+ } = config || {};
41
+ let frameCount = 0;
42
+ let lastTime = 0;
43
+ let timeoutId;
44
+ let frameRateSamples = [];
45
+ const startMeasure = () => {
46
+ frameCount = 0;
47
+ lastTime = performance.now();
48
+ };
49
+
50
+ /**
51
+ * Returns an array of frame rate samples as integers.
52
+ * @returns {number[]} An array of frame rate samples as integers.
53
+ * @example
54
+ * const samples = endMeasure(); // [60, 58, 62]
55
+ */
56
+ const endMeasure = () => {
57
+ const samples = frameRateSamples;
58
+ frameRateSamples = [];
59
+ return samples;
60
+ };
61
+ const sampleFrameRate = (delay = 0) => {
62
+ const currentTime = performance.now();
63
+ const deltaTime = currentTime - lastTime - delay;
64
+ const isValidSample = deltaTime > minTimeMs && frameCount >= minFrames;
65
+ if (isValidSample) {
66
+ const frameRate = Math.round(frameCount / (deltaTime / 1000));
67
+ frameRateSamples.push(frameRate);
68
+ }
69
+ frameCount = 0;
70
+ lastTime = 0;
71
+ };
72
+
73
+ /**
74
+ * Counts the number of frames that occur within a given time period. Intended to be called
75
+ * inside a `requestAnimationFrame` callback.
76
+ * @example
77
+ * const animate = () => {
78
+ * countFrames();
79
+ * requestAnimationFrame(animate);
80
+ * };
81
+ */
82
+ const countFrames = () => {
83
+ if (frameRateSamples.length >= maxSamples && timeoutId) {
84
+ clearTimeout(timeoutId);
85
+ return;
86
+ }
87
+
88
+ /**
89
+ * Allows us to keep counting frames even if `startMeasure` is not called
90
+ */
91
+ if (lastTime === 0) {
92
+ lastTime = performance.now();
93
+ }
94
+ frameCount++;
95
+ if (timeoutId) {
96
+ clearTimeout(timeoutId);
97
+ }
98
+ if (performance.now() - lastTime > sampleRateMs) {
99
+ sampleFrameRate();
100
+ } else {
101
+ timeoutId = setTimeout(() => sampleFrameRate(timeoutMs), timeoutMs);
102
+ }
103
+ };
104
+ return {
105
+ startMeasure,
106
+ endMeasure,
107
+ countFrames
108
+ };
109
+ };
@@ -200,8 +200,10 @@ export var breakoutPlugin = function breakoutPlugin(_ref4) {
200
200
  if (editorExperiment('platform_editor_breakout_resizing', true)) {
201
201
  return [{
202
202
  name: 'breakout-resizing',
203
- plugin: function plugin() {
204
- return createResizingPlugin(api, options);
203
+ plugin: function plugin(_ref5) {
204
+ var getIntl = _ref5.getIntl,
205
+ nodeViewPortalProviderAPI = _ref5.nodeViewPortalProviderAPI;
206
+ return createResizingPlugin(api, getIntl, nodeViewPortalProviderAPI, options);
205
207
  }
206
208
  }];
207
209
  }
@@ -232,11 +234,11 @@ export var breakoutPlugin = function breakoutPlugin(_ref4) {
232
234
  }
233
235
  return pluginState;
234
236
  },
235
- contentComponent: function contentComponent(_ref5) {
236
- var editorView = _ref5.editorView,
237
- popupsMountPoint = _ref5.popupsMountPoint,
238
- popupsBoundariesElement = _ref5.popupsBoundariesElement,
239
- popupsScrollableElement = _ref5.popupsScrollableElement;
237
+ contentComponent: function contentComponent(_ref6) {
238
+ var editorView = _ref6.editorView,
239
+ popupsMountPoint = _ref6.popupsMountPoint,
240
+ popupsBoundariesElement = _ref6.popupsBoundariesElement,
241
+ popupsScrollableElement = _ref6.popupsScrollableElement;
240
242
  // This is a bit crappy, but should be resolved once we move to a static schema.
241
243
  if (options && !options.allowBreakoutButton) {
242
244
  return null;
@@ -1,13 +1,62 @@
1
1
  import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
2
+ import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
3
+ import React, { useLayoutEffect, useState } from 'react';
2
4
  import { bind } from 'bind-event-listener';
5
+ import uuid from 'uuid/v4';
6
+ import { breakoutMessages as messages } from '@atlaskit/editor-common/messages';
7
+ import { fg } from '@atlaskit/platform-feature-flags';
3
8
  import { draggable } from '@atlaskit/pragmatic-drag-and-drop/element/adapter';
4
9
  import { disableNativeDragPreview } from '@atlaskit/pragmatic-drag-and-drop/element/disable-native-drag-preview';
5
10
  import { preventUnhandled } from '@atlaskit/pragmatic-drag-and-drop/prevent-unhandled';
6
- export var createPragmaticResizer = function createPragmaticResizer(_ref) {
7
- var target = _ref.target,
8
- _onDragStart = _ref.onDragStart,
9
- onDrag = _ref.onDrag,
10
- _onDrop = _ref.onDrop;
11
+ import Tooltip from '@atlaskit/tooltip';
12
+ var getNodeName = function getNodeName(nodeName) {
13
+ if (nodeName === 'layoutSection') {
14
+ return 'layout';
15
+ } else if (nodeName === 'codeBlock' || nodeName === 'expand') {
16
+ return nodeName;
17
+ } else {
18
+ return 'node';
19
+ }
20
+ };
21
+ export var resizeHandleMessage = {
22
+ expand: messages.resizeExpand,
23
+ codeBlock: messages.resizeCodeBlock,
24
+ layout: messages.resizeLayout,
25
+ node: messages.resizeElement
26
+ };
27
+ var RailWithTooltip = function RailWithTooltip(_ref) {
28
+ var rail = _ref.rail,
29
+ target = _ref.target,
30
+ intl = _ref.intl;
31
+ var _useState = useState('node'),
32
+ _useState2 = _slicedToArray(_useState, 2),
33
+ nodeName = _useState2[0],
34
+ setNodeName = _useState2[1];
35
+ useLayoutEffect(function () {
36
+ var node = target.querySelector('[data-prosemirror-node-name]');
37
+ var name = getNodeName(node === null || node === void 0 ? void 0 : node.dataset.prosemirrorNodeName);
38
+ setNodeName(name);
39
+ }, [target]);
40
+ return /*#__PURE__*/React.createElement(Tooltip, {
41
+ content: intl.formatMessage(resizeHandleMessage[nodeName]),
42
+ position: "mouse"
43
+ }, /*#__PURE__*/React.createElement("div", {
44
+ // eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop -- Ignored via go/DSP-18766
45
+ className: "pm-breakout-resize-handle-rail-inside-tooltip",
46
+ ref: function ref(el) {
47
+ if (el && rail.parentNode !== el) {
48
+ el.appendChild(rail);
49
+ }
50
+ }
51
+ }));
52
+ };
53
+ export var createPragmaticResizer = function createPragmaticResizer(_ref2) {
54
+ var target = _ref2.target,
55
+ _onDragStart = _ref2.onDragStart,
56
+ onDrag = _ref2.onDrag,
57
+ _onDrop = _ref2.onDrop,
58
+ intl = _ref2.intl,
59
+ nodeViewPortalProviderAPI = _ref2.nodeViewPortalProviderAPI;
11
60
  var state = 'default';
12
61
  var createHandle = function createHandle(side) {
13
62
  var handle = document.createElement('div');
@@ -27,21 +76,45 @@ export var createPragmaticResizer = function createPragmaticResizer(_ref) {
27
76
  var thumb = document.createElement('div');
28
77
  thumb.classList.add('pm-breakout-resize-handle-thumb');
29
78
  rail.appendChild(thumb);
30
- handle.appendChild(rail);
31
- handle.appendChild(handleHitBox);
32
- return {
33
- handle: handle,
34
- rail: rail,
35
- handleHitBox: handleHitBox
36
- };
79
+ if (fg('platform_editor_breakout_resizing_hello_release')) {
80
+ var tooltipContainer = document.createElement('div');
81
+ tooltipContainer.classList.add('pm-breakout-resize-handle-rail-wrapper');
82
+ handle.appendChild(tooltipContainer);
83
+ handle.appendChild(handleHitBox);
84
+ var key = uuid();
85
+ nodeViewPortalProviderAPI.render(function () {
86
+ return /*#__PURE__*/React.createElement(RailWithTooltip, {
87
+ rail: rail,
88
+ target: target,
89
+ intl: intl
90
+ });
91
+ }, tooltipContainer, key);
92
+ return {
93
+ handle: handle,
94
+ rail: rail,
95
+ handleHitBox: handleHitBox,
96
+ destroyTooltip: function destroyTooltip() {
97
+ return nodeViewPortalProviderAPI.remove(key);
98
+ }
99
+ };
100
+ } else {
101
+ handle.appendChild(rail);
102
+ handle.appendChild(handleHitBox);
103
+ return {
104
+ handle: handle,
105
+ rail: rail,
106
+ handleHitBox: handleHitBox,
107
+ destroyTooltip: function destroyTooltip() {}
108
+ };
109
+ }
37
110
  };
38
111
  var rightHandle = createHandle('right');
39
112
  var leftHandle = createHandle('left');
40
113
  var registerHandle = function registerHandle(handleElement, handleSide) {
41
114
  return draggable({
42
115
  element: handleElement,
43
- onGenerateDragPreview: function onGenerateDragPreview(_ref2) {
44
- var nativeSetDragImage = _ref2.nativeSetDragImage;
116
+ onGenerateDragPreview: function onGenerateDragPreview(_ref3) {
117
+ var nativeSetDragImage = _ref3.nativeSetDragImage;
45
118
  disableNativeDragPreview({
46
119
  nativeSetDragImage: nativeSetDragImage
47
120
  });
@@ -85,7 +158,7 @@ export var createPragmaticResizer = function createPragmaticResizer(_ref) {
85
158
  })];
86
159
  };
87
160
  var unbindFns = [].concat(_toConsumableArray(registerEvents(target)), _toConsumableArray(registerEvents(rightHandle.handleHitBox)), _toConsumableArray(registerEvents(leftHandle.handleHitBox)), _toConsumableArray(registerEvents(rightHandle.rail)), _toConsumableArray(registerEvents(leftHandle.rail)));
88
- var destroyFns = [registerHandle(rightHandle.handle, 'right'), registerHandle(leftHandle.handle, 'left')];
161
+ var destroyFns = [registerHandle(rightHandle.handle, 'right'), registerHandle(leftHandle.handle, 'left')].concat(_toConsumableArray(fg('platform_editor_breakout_resizing_hello_release') ? [rightHandle.destroyTooltip, leftHandle.destroyTooltip] : []));
89
162
  return {
90
163
  rightHandle: rightHandle.handle,
91
164
  leftHandle: leftHandle.handle,
@@ -3,6 +3,8 @@ import { fg } from '@atlaskit/platform-feature-flags';
3
3
  import { setBreakoutWidth } from '../editor-commands/set-breakout-width';
4
4
  import { getGuidelines } from './get-guidelines';
5
5
  import { LOCAL_RESIZE_PROPERTY } from './resizing-mark-view';
6
+ import { generateResizeFrameRatePayloads } from './utils/analytics';
7
+ import { measureFramerate, reduceResizeFrameRateSamples } from './utils/measure-framerate';
6
8
  var RESIZE_RATIO = 2;
7
9
  var SNAP_GAP = 10;
8
10
  var WIDTHS = {
@@ -41,22 +43,38 @@ export function createResizerCallbacks(_ref2) {
41
43
  api = _ref2.api;
42
44
  var node = null;
43
45
  var guidelines = [];
46
+ var _measureFramerate = measureFramerate(),
47
+ startMeasure = _measureFramerate.startMeasure,
48
+ endMeasure = _measureFramerate.endMeasure,
49
+ countFrames = _measureFramerate.countFrames;
44
50
  var getEditorWidth = function getEditorWidth() {
45
51
  var _api$width;
46
52
  return api === null || api === void 0 || (_api$width = api.width) === null || _api$width === void 0 ? void 0 : _api$width.sharedState.currentState();
47
53
  };
48
54
  return {
49
55
  onDragStart: function onDragStart() {
50
- var _api$userIntent;
51
- 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'));
52
- view.dispatch(view.state.tr.setMeta('is-resizer-resizing', true));
56
+ if (fg('platform_editor_breakout_resizing_hello_release')) {
57
+ startMeasure();
58
+ }
59
+ api === null || api === void 0 || api.core.actions.execute(function (_ref3) {
60
+ var _api$userIntent;
61
+ var tr = _ref3.tr;
62
+ (_api$userIntent = api.userIntent) === null || _api$userIntent === void 0 || _api$userIntent.commands.setCurrentUserIntent('dragging')({
63
+ tr: tr
64
+ });
65
+ tr.setMeta('is-resizer-resizing', true);
66
+ return tr;
67
+ });
53
68
  var pos = view.posAtDOM(dom, 0);
54
69
  node = view.state.doc.nodeAt(pos);
55
70
  },
56
- onDrag: function onDrag(_ref3) {
71
+ onDrag: function onDrag(_ref4) {
57
72
  var _node, _api$guideline;
58
- var location = _ref3.location,
59
- source = _ref3.source;
73
+ var location = _ref4.location,
74
+ source = _ref4.source;
75
+ if (fg('platform_editor_breakout_resizing_hello_release')) {
76
+ countFrames();
77
+ }
60
78
  var initialWidth = mark.attrs.width;
61
79
  var newWidth = getProposedWidth({
62
80
  initialWidth: initialWidth,
@@ -70,10 +88,19 @@ export function createResizerCallbacks(_ref2) {
70
88
  });
71
89
  contentDOM.style.setProperty(LOCAL_RESIZE_PROPERTY, "".concat(newWidth, "px"));
72
90
  },
73
- onDrop: function onDrop(_ref4) {
74
- var _api$guideline2, _api$userIntent2;
75
- var location = _ref4.location,
76
- source = _ref4.source;
91
+ onDrop: function onDrop(_ref5) {
92
+ var _api$guideline2;
93
+ var location = _ref5.location,
94
+ source = _ref5.source;
95
+ var payloads = [];
96
+ if (fg('platform_editor_breakout_resizing_hello_release')) {
97
+ var frameRateSamples = endMeasure();
98
+ payloads = generateResizeFrameRatePayloads({
99
+ docSize: view.state.doc.nodeSize,
100
+ frameRateSamples: reduceResizeFrameRateSamples(frameRateSamples),
101
+ originalNode: node
102
+ });
103
+ }
77
104
  var isResizedToFullWidth = !!guidelines.find(function (guideline) {
78
105
  return guideline.key.includes('full_width') && guideline.active;
79
106
  });
@@ -92,8 +119,19 @@ export function createResizerCallbacks(_ref2) {
92
119
  });
93
120
  setBreakoutWidth(newWidth, mode, pos)(view.state, view.dispatch);
94
121
  contentDOM.style.removeProperty(LOCAL_RESIZE_PROPERTY);
95
- view.dispatch(view.state.tr.setMeta('is-resizer-resizing', false).setMeta('scrollIntoView', false));
96
- 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'));
122
+ api === null || api === void 0 || api.core.actions.execute(function (_ref6) {
123
+ var _api$userIntent2;
124
+ var tr = _ref6.tr;
125
+ (_api$userIntent2 = api.userIntent) === null || _api$userIntent2 === void 0 || _api$userIntent2.commands.setCurrentUserIntent('default')({
126
+ tr: tr
127
+ });
128
+ tr.setMeta('is-resizer-resizing', false).setMeta('scrollIntoView', false);
129
+ payloads.forEach(function (payload) {
130
+ var _api$analytics;
131
+ (_api$analytics = api.analytics) === null || _api$analytics === void 0 || (_api$analytics = _api$analytics.actions) === null || _api$analytics === void 0 || _api$analytics.attachAnalyticsEvent(payload)(tr);
132
+ });
133
+ return tr;
134
+ });
97
135
  }
98
136
  };
99
137
  }
@@ -12,12 +12,14 @@ export var ResizingMarkView = /*#__PURE__*/function () {
12
12
  * Wrap node view in a resizing mark view
13
13
  * @param {Mark} mark - The breakout mark to resize
14
14
  * @param {EditorView} view - The editor view
15
- * @param {ExtractInjectionAPI<BreakoutPlugin> | undefined} api - the pluginInjectionAPI
15
+ * @param {ExtractInjectionAPI<BreakoutPlugin> | undefined} api - The pluginInjectionAPI
16
+ * @param {Function} getIntl - () => IntlShape
17
+ * @param {PortalProviderAPI} - The nodeViewPortalProviderAPI
16
18
  * @example
17
19
  * ```ts
18
20
  * ```
19
21
  */
20
- function ResizingMarkView(mark, view, api) {
22
+ function ResizingMarkView(mark, view, api, getIntl, nodeViewPortalProviderAPI) {
21
23
  _classCallCheck(this, ResizingMarkView);
22
24
  var dom = document.createElement('div');
23
25
  var contentDOM = document.createElement('div');
@@ -53,9 +55,14 @@ export var ResizingMarkView = /*#__PURE__*/function () {
53
55
  mark: mark,
54
56
  api: api
55
57
  });
56
- var _createPragmaticResiz = createPragmaticResizer(_objectSpread({
58
+ this.intl = getIntl();
59
+ this.nodeViewPortalProviderAPI = nodeViewPortalProviderAPI;
60
+ var _createPragmaticResiz = createPragmaticResizer(_objectSpread(_objectSpread({
57
61
  target: contentDOM
58
- }, callbacks)),
62
+ }, callbacks), {}, {
63
+ intl: this.intl,
64
+ nodeViewPortalProviderAPI: this.nodeViewPortalProviderAPI
65
+ })),
59
66
  leftHandle = _createPragmaticResiz.leftHandle,
60
67
  rightHandle = _createPragmaticResiz.rightHandle,
61
68
  destroy = _createPragmaticResiz.destroy;
@@ -43,13 +43,13 @@ var addBreakoutToResizableNode = function addBreakoutToResizableNode(_ref) {
43
43
  };
44
44
  };
45
45
  export var resizingPluginKey = new PluginKey('breakout-resizing');
46
- export var createResizingPlugin = function createResizingPlugin(api, options) {
46
+ export var createResizingPlugin = function createResizingPlugin(api, getIntl, nodeViewPortalProviderAPI, options) {
47
47
  return new SafePlugin({
48
48
  key: resizingPluginKey,
49
49
  props: {
50
50
  markViews: {
51
51
  breakout: function breakout(mark, view) {
52
- return new ResizingMarkView(mark, view, api);
52
+ return new ResizingMarkView(mark, view, api, getIntl, nodeViewPortalProviderAPI);
53
53
  }
54
54
  },
55
55
  handleKeyDown: handleKeyDown
@@ -0,0 +1,17 @@
1
+ import { ACTION, ACTION_SUBJECT, EVENT_TYPE } from '@atlaskit/editor-common/analytics';
2
+ export var generateResizeFrameRatePayloads = function generateResizeFrameRatePayloads(props) {
3
+ return props.frameRateSamples.map(function (frameRateSample, index) {
4
+ return {
5
+ action: ACTION.RESIZED_PERF_SAMPLING,
6
+ actionSubject: ACTION_SUBJECT.ELEMENT,
7
+ eventType: EVENT_TYPE.OPERATIONAL,
8
+ attributes: {
9
+ nodeType: props.originalNode.type.name,
10
+ frameRate: frameRateSample,
11
+ nodeSize: props.originalNode.nodeSize,
12
+ docSize: props.docSize,
13
+ isInitialSample: index === 0
14
+ }
15
+ };
16
+ });
17
+ };