@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.
- package/CHANGELOG.md +22 -0
- package/dist/cjs/breakoutPlugin.js +9 -7
- package/dist/cjs/pm-plugins/pragmatic-resizer.js +91 -16
- package/dist/cjs/pm-plugins/resizer-callbacks.js +50 -12
- package/dist/cjs/pm-plugins/resizing-mark-view.js +11 -4
- package/dist/cjs/pm-plugins/resizing-plugin.js +2 -2
- package/dist/cjs/pm-plugins/utils/analytics.js +23 -0
- package/dist/cjs/pm-plugins/utils/measure-framerate.js +122 -0
- package/dist/es2019/breakoutPlugin.js +4 -1
- package/dist/es2019/pm-plugins/pragmatic-resizer.js +75 -9
- package/dist/es2019/pm-plugins/resizer-callbacks.js +47 -6
- package/dist/es2019/pm-plugins/resizing-mark-view.js +9 -3
- package/dist/es2019/pm-plugins/resizing-plugin.js +2 -2
- package/dist/es2019/pm-plugins/utils/analytics.js +15 -0
- package/dist/es2019/pm-plugins/utils/measure-framerate.js +109 -0
- package/dist/esm/breakoutPlugin.js +9 -7
- package/dist/esm/pm-plugins/pragmatic-resizer.js +88 -15
- package/dist/esm/pm-plugins/resizer-callbacks.js +50 -12
- package/dist/esm/pm-plugins/resizing-mark-view.js +11 -4
- package/dist/esm/pm-plugins/resizing-plugin.js +2 -2
- package/dist/esm/pm-plugins/utils/analytics.js +17 -0
- package/dist/esm/pm-plugins/utils/measure-framerate.js +116 -0
- package/dist/types/breakoutPluginType.d.ts +3 -1
- package/dist/types/pm-plugins/pragmatic-resizer.d.ts +6 -1
- package/dist/types/pm-plugins/resizing-mark-view.d.ts +8 -2
- package/dist/types/pm-plugins/resizing-plugin.d.ts +3 -1
- package/dist/types/pm-plugins/utils/analytics.d.ts +7 -0
- package/dist/types/pm-plugins/utils/measure-framerate.d.ts +30 -0
- package/dist/types-ts4.5/breakoutPluginType.d.ts +3 -1
- package/dist/types-ts4.5/pm-plugins/pragmatic-resizer.d.ts +6 -1
- package/dist/types-ts4.5/pm-plugins/resizing-mark-view.d.ts +8 -2
- package/dist/types-ts4.5/pm-plugins/resizing-plugin.d.ts +3 -1
- package/dist/types-ts4.5/pm-plugins/utils/analytics.d.ts +7 -0
- package/dist/types-ts4.5/pm-plugins/utils/measure-framerate.d.ts +30 -0
- 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
|
-
|
|
52
|
-
|
|
53
|
-
|
|
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
|
|
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
|
-
|
|
97
|
-
|
|
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 -
|
|
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
|
-
|
|
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(
|
|
236
|
-
var editorView =
|
|
237
|
-
popupsMountPoint =
|
|
238
|
-
popupsBoundariesElement =
|
|
239
|
-
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
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
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
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
handle
|
|
34
|
-
|
|
35
|
-
|
|
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(
|
|
44
|
-
var 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
|
-
|
|
51
|
-
|
|
52
|
-
|
|
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(
|
|
71
|
+
onDrag: function onDrag(_ref4) {
|
|
57
72
|
var _node, _api$guideline;
|
|
58
|
-
var location =
|
|
59
|
-
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(
|
|
74
|
-
var _api$guideline2
|
|
75
|
-
var location =
|
|
76
|
-
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
|
-
|
|
96
|
-
|
|
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 -
|
|
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
|
-
|
|
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
|
+
};
|