@atlaskit/editor-plugin-table 2.7.1 → 2.8.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 (31) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/dist/cjs/plugins/table/nodeviews/TableResizer.js +25 -26
  3. package/dist/cjs/plugins/table/toolbar.js +13 -17
  4. package/dist/cjs/plugins/table/utils/analytics.js +146 -2
  5. package/dist/cjs/version.json +1 -1
  6. package/dist/es2019/plugins/table/nodeviews/TableResizer.js +27 -27
  7. package/dist/es2019/plugins/table/toolbar.js +11 -16
  8. package/dist/es2019/plugins/table/utils/analytics.js +130 -0
  9. package/dist/es2019/version.json +1 -1
  10. package/dist/esm/plugins/table/nodeviews/TableResizer.js +26 -27
  11. package/dist/esm/plugins/table/toolbar.js +13 -17
  12. package/dist/esm/plugins/table/utils/analytics.js +139 -0
  13. package/dist/esm/version.json +1 -1
  14. package/dist/types/plugins/table/types.d.ts +0 -1
  15. package/dist/types/plugins/table/utils/analytics.d.ts +28 -1
  16. package/dist/types-ts4.5/plugins/table/types.d.ts +0 -1
  17. package/dist/types-ts4.5/plugins/table/utils/analytics.d.ts +28 -1
  18. package/package.json +3 -2
  19. package/report.api.md +0 -2
  20. package/src/__tests__/integration/floating-toolbar.ts +0 -7
  21. package/src/__tests__/unit/nodeviews/TableContainer.tsx +57 -1
  22. package/src/__tests__/unit/utils/analytics.ts +98 -0
  23. package/src/__tests__/visual-regression/__image_snapshots__/cell-options-menu-ts-table-cell-options-menu-delete-column-menu-item-should-remove-the-table-column-on-click-1-snap.png +2 -2
  24. package/src/__tests__/visual-regression/__image_snapshots__/cell-options-menu-ts-table-cell-options-menu-delete-column-menu-item-visual-hints-should-be-added-to-the-table-column-on-hover-1-snap.png +2 -2
  25. package/src/__tests__/visual-regression/__image_snapshots__/cell-options-menu-ts-table-cell-options-menu-delete-row-menu-item-should-remove-the-table-row-on-click-1-snap.png +2 -2
  26. package/src/__tests__/visual-regression/__image_snapshots__/cell-options-menu-ts-table-cell-options-menu-delete-row-menu-item-visual-hints-should-be-added-to-the-table-row-on-hover-1-snap.png +2 -2
  27. package/src/plugins/table/nodeviews/TableResizer.tsx +35 -34
  28. package/src/plugins/table/toolbar.tsx +13 -32
  29. package/src/plugins/table/types.ts +0 -1
  30. package/src/plugins/table/utils/analytics.ts +168 -0
  31. package/tmp/api-report-tmp.d.ts +0 -2
@@ -1,5 +1,9 @@
1
+ import { useEffect, useRef } from 'react';
2
+ import { ACTION_SUBJECT, EVENT_TYPE, TABLE_ACTION } from '@atlaskit/editor-common/analytics';
1
3
  import { TableMap } from '@atlaskit/editor-tables/table-map';
2
4
  import { findTable, getSelectionRect } from '@atlaskit/editor-tables/utils';
5
+ import { hasTableBeenResized } from '../pm-plugins/table-resizing/utils';
6
+ import { getTableWidth } from '../utils';
3
7
  export function getSelectedTableInfo(selection) {
4
8
  let map;
5
9
  let totalRowCount = 0;
@@ -54,4 +58,130 @@ export const withEditorAnalyticsAPI = payload => editorAnalyticsAPI => {
54
58
  }
55
59
  return true;
56
60
  }, view);
61
+ };
62
+ export const generateResizedPayload = props => {
63
+ var _props$originalNode$a;
64
+ const tableMap = TableMap.get(props.resizedNode);
65
+ return {
66
+ action: TABLE_ACTION.RESIZED,
67
+ actionSubject: ACTION_SUBJECT.TABLE,
68
+ eventType: EVENT_TYPE.TRACK,
69
+ attributes: {
70
+ newWidth: props.resizedNode.attrs.width,
71
+ prevWidth: (_props$originalNode$a = props.originalNode.attrs.width) !== null && _props$originalNode$a !== void 0 ? _props$originalNode$a : null,
72
+ nodeSize: props.resizedNode.nodeSize,
73
+ totalTableWidth: hasTableBeenResized(props.resizedNode) ? getTableWidth(props.resizedNode) : null,
74
+ totalRowCount: tableMap.height,
75
+ totalColumnCount: tableMap.width
76
+ }
77
+ };
78
+ };
79
+ export const reduceResizeFrameRateSamples = frameRateSamples => {
80
+ if (frameRateSamples.length > 1) {
81
+ const frameRateSum = frameRateSamples.reduce((sum, frameRate, index) => {
82
+ if (index === 0) {
83
+ return sum;
84
+ } else {
85
+ return sum + frameRate;
86
+ }
87
+ }, 0);
88
+ const averageFrameRate = Math.round(frameRateSum / (frameRateSamples.length - 1));
89
+ return [frameRateSamples[0], averageFrameRate];
90
+ } else {
91
+ return frameRateSamples;
92
+ }
93
+ };
94
+ export const generateResizeFrameRatePayloads = props => {
95
+ const reducedResizeFrameRateSamples = reduceResizeFrameRateSamples(props.frameRateSamples);
96
+ return reducedResizeFrameRateSamples.map((frameRateSample, index) => ({
97
+ action: TABLE_ACTION.RESIZE_PERF_SAMPLING,
98
+ actionSubject: ACTION_SUBJECT.TABLE,
99
+ eventType: EVENT_TYPE.OPERATIONAL,
100
+ attributes: {
101
+ frameRate: frameRateSample,
102
+ nodeSize: props.originalNode.nodeSize,
103
+ docSize: props.docSize,
104
+ isInitialSample: index === 0
105
+ }
106
+ }));
107
+ };
108
+
109
+ /**
110
+ * Measures the framerate of a component over a given time period.
111
+ */
112
+ export const useMeasureFramerate = (config = {}) => {
113
+ const {
114
+ maxSamples = 10,
115
+ minFrames = 5,
116
+ minTimeMs = 500,
117
+ sampleRateMs = 1000,
118
+ timeoutMs = 200
119
+ } = config;
120
+ let frameCount = useRef(0);
121
+ let lastTime = useRef(0);
122
+ let timeoutId = useRef();
123
+ let frameRateSamples = useRef([]);
124
+ useEffect(() => {
125
+ return () => {
126
+ if (timeoutId.current) {
127
+ clearTimeout(timeoutId.current);
128
+ }
129
+ };
130
+ }, []);
131
+ const startMeasure = () => {
132
+ frameCount.current = 0;
133
+ lastTime.current = performance.now();
134
+ };
135
+
136
+ /**
137
+ * Returns an array of frame rate samples as integers.
138
+ */
139
+ const endMeasure = () => {
140
+ const samples = frameRateSamples.current;
141
+ frameRateSamples.current = [];
142
+ return samples;
143
+ };
144
+ const sampleFrameRate = (delay = 0) => {
145
+ const currentTime = performance.now();
146
+ const deltaTime = currentTime - lastTime.current - delay;
147
+ const isValidSample = deltaTime > minTimeMs && frameCount.current >= minFrames;
148
+ if (isValidSample) {
149
+ const frameRate = Math.round(frameCount.current / (deltaTime / 1000));
150
+ frameRateSamples.current.push(frameRate);
151
+ }
152
+ frameCount.current = 0;
153
+ lastTime.current = 0;
154
+ };
155
+
156
+ /**
157
+ * Counts the number of frames that occur within a given time period. Intended to be called
158
+ * inside a `requestAnimationFrame` callback.
159
+ */
160
+ const countFrames = () => {
161
+ if (frameRateSamples.current.length >= maxSamples && timeoutId.current) {
162
+ clearTimeout(timeoutId.current);
163
+ return;
164
+ }
165
+
166
+ /**
167
+ * Allows us to keep counting frames even if `startMeasure` is not called
168
+ */
169
+ if (lastTime.current === 0) {
170
+ lastTime.current = performance.now();
171
+ }
172
+ frameCount.current++;
173
+ if (timeoutId.current) {
174
+ clearTimeout(timeoutId.current);
175
+ }
176
+ if (performance.now() - lastTime.current > sampleRateMs) {
177
+ sampleFrameRate();
178
+ } else {
179
+ timeoutId.current = setTimeout(() => sampleFrameRate(timeoutMs), timeoutMs);
180
+ }
181
+ };
182
+ return {
183
+ startMeasure,
184
+ endMeasure,
185
+ countFrames
186
+ };
57
187
  };
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "@atlaskit/editor-plugin-table",
3
- "version": "2.7.1",
3
+ "version": "2.8.0",
4
4
  "sideEffects": false
5
5
  }
@@ -4,39 +4,20 @@ function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (O
4
4
  function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
5
5
  import React, { useCallback, useMemo, useRef, useState } from 'react';
6
6
  import rafSchd from 'raf-schd';
7
- import { ACTION_SUBJECT, EVENT_TYPE, TABLE_ACTION } from '@atlaskit/editor-common/analytics';
8
7
  import { getGuidelinesWithHighlights } from '@atlaskit/editor-common/guideline';
9
8
  import { ResizerNext } from '@atlaskit/editor-common/resizer';
10
9
  import { resizerHandleShadowClassName } from '@atlaskit/editor-common/styles';
11
- import { TableMap } from '@atlaskit/editor-tables';
12
10
  import { findTable } from '@atlaskit/editor-tables/utils';
13
- import { COLUMN_MIN_WIDTH, getColgroupChildrenLength, hasTableBeenResized, previewScaleTable, scaleTable } from '../pm-plugins/table-resizing/utils';
11
+ import { COLUMN_MIN_WIDTH, getColgroupChildrenLength, previewScaleTable, scaleTable } from '../pm-plugins/table-resizing/utils';
14
12
  import { pluginKey as tableWidthPluginKey } from '../pm-plugins/table-width';
15
13
  import { TABLE_HIGHLIGHT_GAP, TABLE_SNAP_GAP } from '../ui/consts';
16
- import { getTableWidth } from '../utils';
14
+ import { generateResizedPayload, generateResizeFrameRatePayloads, useMeasureFramerate } from '../utils/analytics';
17
15
  import { defaultGuidelines, defaultGuidelineWidths } from '../utils/guidelines';
18
16
  import { findClosestSnap } from '../utils/snapping';
19
17
  var handles = {
20
18
  right: true
21
19
  };
22
20
  var tableHandleMarginTop = 12;
23
- var generateResizedPayload = function generateResizedPayload(props) {
24
- var _props$originalNode$a;
25
- var tableMap = TableMap.get(props.resizedNode);
26
- return {
27
- action: TABLE_ACTION.RESIZED,
28
- actionSubject: ACTION_SUBJECT.TABLE,
29
- eventType: EVENT_TYPE.TRACK,
30
- attributes: {
31
- newWidth: props.resizedNode.attrs.width,
32
- prevWidth: (_props$originalNode$a = props.originalNode.attrs.width) !== null && _props$originalNode$a !== void 0 ? _props$originalNode$a : null,
33
- nodeSize: props.resizedNode.nodeSize,
34
- totalTableWidth: hasTableBeenResized(props.resizedNode) ? getTableWidth(props.resizedNode) : null,
35
- totalRowCount: tableMap.height,
36
- totalColumnCount: tableMap.width
37
- }
38
- };
39
- };
40
21
  var getResizerHandleHeight = function getResizerHandleHeight(tableRef) {
41
22
  var tableHeight = tableRef === null || tableRef === void 0 ? void 0 : tableRef.clientHeight;
42
23
  var handleHeightSize = 'small';
@@ -79,6 +60,10 @@ export var TableResizer = function TableResizer(_ref) {
79
60
  setSnappingEnabled = _useState2[1];
80
61
  var resizerMinWidth = getResizerMinWidth(node);
81
62
  var handleHeightSize = getResizerHandleHeight(tableRef);
63
+ var _useMeasureFramerate = useMeasureFramerate(),
64
+ startMeasure = _useMeasureFramerate.startMeasure,
65
+ endMeasure = _useMeasureFramerate.endMeasure,
66
+ countFrames = _useMeasureFramerate.countFrames;
82
67
  var updateActiveGuidelines = useCallback(function (_ref2) {
83
68
  var gap = _ref2.gap,
84
69
  keys = _ref2.keys;
@@ -93,13 +78,14 @@ export var TableResizer = function TableResizer(_ref) {
93
78
  } : undefined;
94
79
  }, [snappingEnabled]);
95
80
  var handleResizeStart = useCallback(function () {
81
+ startMeasure();
96
82
  var dispatch = editorView.dispatch,
97
83
  tr = editorView.state.tr;
98
84
  dispatch(tr.setMeta(tableWidthPluginKey, {
99
85
  resizing: true
100
86
  }));
101
87
  setSnappingEnabled(displayGuideline(defaultGuidelines));
102
- }, [displayGuideline, editorView]);
88
+ }, [displayGuideline, editorView, startMeasure]);
103
89
  var handleResizeStop = useCallback(function (originalState, delta) {
104
90
  var newWidth = originalState.width + delta.width;
105
91
  var state = editorView.state,
@@ -108,8 +94,20 @@ export var TableResizer = function TableResizer(_ref) {
108
94
  var tr = state.tr.setMeta(tableWidthPluginKey, {
109
95
  resizing: false
110
96
  });
97
+ var frameRateSamples = endMeasure();
98
+ if (frameRateSamples.length > 0) {
99
+ var resizeFrameRatePayloads = generateResizeFrameRatePayloads({
100
+ docSize: state.doc.nodeSize,
101
+ frameRateSamples: frameRateSamples,
102
+ originalNode: node
103
+ });
104
+ resizeFrameRatePayloads.forEach(function (payload) {
105
+ var _attachAnalyticsEvent;
106
+ (_attachAnalyticsEvent = attachAnalyticsEvent(payload)) === null || _attachAnalyticsEvent === void 0 ? void 0 : _attachAnalyticsEvent(tr);
107
+ });
108
+ }
111
109
  if (typeof pos === 'number') {
112
- var _attachAnalyticsEvent;
110
+ var _attachAnalyticsEvent2;
113
111
  tr = tr.setNodeMarkup(pos, undefined, _objectSpread(_objectSpread({}, node.attrs), {}, {
114
112
  width: newWidth
115
113
  }));
@@ -121,10 +119,10 @@ export var TableResizer = function TableResizer(_ref) {
121
119
  parentWidth: newWidth
122
120
  }, editorView.domAtPos.bind(editorView))(tr);
123
121
  var scaledNode = tr.doc.nodeAt(pos);
124
- (_attachAnalyticsEvent = attachAnalyticsEvent(generateResizedPayload({
122
+ (_attachAnalyticsEvent2 = attachAnalyticsEvent(generateResizedPayload({
125
123
  originalNode: node,
126
124
  resizedNode: scaledNode
127
- }))) === null || _attachAnalyticsEvent === void 0 ? void 0 : _attachAnalyticsEvent(tr);
125
+ }))) === null || _attachAnalyticsEvent2 === void 0 ? void 0 : _attachAnalyticsEvent2(tr);
128
126
  }
129
127
  dispatch(tr);
130
128
 
@@ -132,8 +130,9 @@ export var TableResizer = function TableResizer(_ref) {
132
130
  displayGuideline([]);
133
131
  updateWidth(newWidth);
134
132
  return newWidth;
135
- }, [updateWidth, editorView, getPos, node, tableRef, displayGuideline, attachAnalyticsEvent]);
133
+ }, [updateWidth, editorView, getPos, node, tableRef, displayGuideline, attachAnalyticsEvent, endMeasure]);
136
134
  var handleResize = useCallback(function (originalState, delta) {
135
+ countFrames();
137
136
  var newWidth = originalState.width + delta.width;
138
137
  var pos = getPos();
139
138
  if (typeof pos !== 'number') {
@@ -148,7 +147,7 @@ export var TableResizer = function TableResizer(_ref) {
148
147
  updateActiveGuidelines(findClosestSnap(newWidth, defaultGuidelineWidths, defaultGuidelines, TABLE_HIGHLIGHT_GAP));
149
148
  updateWidth(newWidth);
150
149
  return newWidth;
151
- }, [editorView, getPos, node, tableRef, updateWidth, updateActiveGuidelines]);
150
+ }, [editorView, getPos, node, tableRef, updateWidth, updateActiveGuidelines, countFrames]);
152
151
  var scheduleResize = useMemo(function () {
153
152
  return rafSchd(handleResize);
154
153
  }, [handleResize]);
@@ -299,10 +299,8 @@ export var getToolbarConfig = function getToolbarConfig(getEditorContainerWidth,
299
299
  if (tableObject && pluginState.editorHasFocus && !isWidthResizing) {
300
300
  var nodeType = state.schema.nodes.table;
301
301
  var menu = getToolbarMenuConfig(config, pluginState, intl, editorAnalyticsAPI);
302
- var _ref3 = getEditorFeatureFlags() || {},
303
- tableCellOptionsInFloatingToolbar = _ref3.tableCellOptionsInFloatingToolbar;
304
- var cellItems = getCellItems(config, state, getEditorView(), intl, getEditorContainerWidth, editorAnalyticsAPI, tableCellOptionsInFloatingToolbar);
305
- var colorPicker = getColorPicker(state, menu, intl, editorAnalyticsAPI, tableCellOptionsInFloatingToolbar);
302
+ var cellItems = getCellItems(config, state, getEditorView(), intl, getEditorContainerWidth, editorAnalyticsAPI);
303
+ var colorPicker = getColorPicker(state, menu, intl, editorAnalyticsAPI);
306
304
 
307
305
  // Check if we need to show confirm dialog for delete button
308
306
  var confirmDialog;
@@ -391,26 +389,24 @@ var separator = function separator(hidden) {
391
389
  hidden: hidden
392
390
  };
393
391
  };
394
- var getCellItems = function getCellItems(pluginConfig, state, view, _ref4, getEditorContainerWidth, editorAnalyticsAPI, tableCellOptionsInFloatingToolbar) {
395
- var formatMessage = _ref4.formatMessage;
396
- if (pluginConfig.allowCellOptionsInFloatingToolbar || tableCellOptionsInFloatingToolbar) {
397
- var initialSelectionRect = getClosestSelectionRect(state);
398
- if (initialSelectionRect) {
399
- var cellOptions = getToolbarCellOptionsConfig(state, view, initialSelectionRect, {
400
- formatMessage: formatMessage
401
- }, getEditorContainerWidth, editorAnalyticsAPI);
402
- return [cellOptions, separator(cellOptions.hidden)];
403
- }
392
+ var getCellItems = function getCellItems(pluginConfig, state, view, _ref3, getEditorContainerWidth, editorAnalyticsAPI) {
393
+ var formatMessage = _ref3.formatMessage;
394
+ var initialSelectionRect = getClosestSelectionRect(state);
395
+ if (initialSelectionRect) {
396
+ var cellOptions = getToolbarCellOptionsConfig(state, view, initialSelectionRect, {
397
+ formatMessage: formatMessage
398
+ }, getEditorContainerWidth, editorAnalyticsAPI);
399
+ return [cellOptions, separator(cellOptions.hidden)];
404
400
  }
405
401
  return [];
406
402
  };
407
- var getColorPicker = function getColorPicker(state, menu, _ref5, editorAnalyticsAPI, tableCellOptionsInFloatingToolbar) {
403
+ var getColorPicker = function getColorPicker(state, menu, _ref4, editorAnalyticsAPI) {
408
404
  var _node$attrs;
409
- var formatMessage = _ref5.formatMessage;
405
+ var formatMessage = _ref4.formatMessage;
410
406
  var _getPluginState2 = getPluginState(state),
411
407
  targetCellPosition = _getPluginState2.targetCellPosition,
412
408
  pluginConfig = _getPluginState2.pluginConfig;
413
- if (!pluginConfig.allowBackgroundColor || !tableCellOptionsInFloatingToolbar) {
409
+ if (!pluginConfig.allowBackgroundColor) {
414
410
  return [];
415
411
  }
416
412
  var node = targetCellPosition ? state.doc.nodeAt(targetCellPosition) : undefined;
@@ -1,5 +1,9 @@
1
+ import { useEffect, useRef } from 'react';
2
+ import { ACTION_SUBJECT, EVENT_TYPE, TABLE_ACTION } from '@atlaskit/editor-common/analytics';
1
3
  import { TableMap } from '@atlaskit/editor-tables/table-map';
2
4
  import { findTable, getSelectionRect } from '@atlaskit/editor-tables/utils';
5
+ import { hasTableBeenResized } from '../pm-plugins/table-resizing/utils';
6
+ import { getTableWidth } from '../utils';
3
7
  export function getSelectedTableInfo(selection) {
4
8
  var map;
5
9
  var totalRowCount = 0;
@@ -59,4 +63,139 @@ export var withEditorAnalyticsAPI = function withEditorAnalyticsAPI(payload) {
59
63
  };
60
64
  };
61
65
  };
66
+ };
67
+ export var generateResizedPayload = function generateResizedPayload(props) {
68
+ var _props$originalNode$a;
69
+ var tableMap = TableMap.get(props.resizedNode);
70
+ return {
71
+ action: TABLE_ACTION.RESIZED,
72
+ actionSubject: ACTION_SUBJECT.TABLE,
73
+ eventType: EVENT_TYPE.TRACK,
74
+ attributes: {
75
+ newWidth: props.resizedNode.attrs.width,
76
+ prevWidth: (_props$originalNode$a = props.originalNode.attrs.width) !== null && _props$originalNode$a !== void 0 ? _props$originalNode$a : null,
77
+ nodeSize: props.resizedNode.nodeSize,
78
+ totalTableWidth: hasTableBeenResized(props.resizedNode) ? getTableWidth(props.resizedNode) : null,
79
+ totalRowCount: tableMap.height,
80
+ totalColumnCount: tableMap.width
81
+ }
82
+ };
83
+ };
84
+ export var reduceResizeFrameRateSamples = function reduceResizeFrameRateSamples(frameRateSamples) {
85
+ if (frameRateSamples.length > 1) {
86
+ var frameRateSum = frameRateSamples.reduce(function (sum, frameRate, index) {
87
+ if (index === 0) {
88
+ return sum;
89
+ } else {
90
+ return sum + frameRate;
91
+ }
92
+ }, 0);
93
+ var averageFrameRate = Math.round(frameRateSum / (frameRateSamples.length - 1));
94
+ return [frameRateSamples[0], averageFrameRate];
95
+ } else {
96
+ return frameRateSamples;
97
+ }
98
+ };
99
+ export var generateResizeFrameRatePayloads = function generateResizeFrameRatePayloads(props) {
100
+ var reducedResizeFrameRateSamples = reduceResizeFrameRateSamples(props.frameRateSamples);
101
+ return reducedResizeFrameRateSamples.map(function (frameRateSample, index) {
102
+ return {
103
+ action: TABLE_ACTION.RESIZE_PERF_SAMPLING,
104
+ actionSubject: ACTION_SUBJECT.TABLE,
105
+ eventType: EVENT_TYPE.OPERATIONAL,
106
+ attributes: {
107
+ frameRate: frameRateSample,
108
+ nodeSize: props.originalNode.nodeSize,
109
+ docSize: props.docSize,
110
+ isInitialSample: index === 0
111
+ }
112
+ };
113
+ });
114
+ };
115
+
116
+ /**
117
+ * Measures the framerate of a component over a given time period.
118
+ */
119
+ export var useMeasureFramerate = function useMeasureFramerate() {
120
+ var config = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
121
+ var _config$maxSamples = config.maxSamples,
122
+ maxSamples = _config$maxSamples === void 0 ? 10 : _config$maxSamples,
123
+ _config$minFrames = config.minFrames,
124
+ minFrames = _config$minFrames === void 0 ? 5 : _config$minFrames,
125
+ _config$minTimeMs = config.minTimeMs,
126
+ minTimeMs = _config$minTimeMs === void 0 ? 500 : _config$minTimeMs,
127
+ _config$sampleRateMs = config.sampleRateMs,
128
+ sampleRateMs = _config$sampleRateMs === void 0 ? 1000 : _config$sampleRateMs,
129
+ _config$timeoutMs = config.timeoutMs,
130
+ timeoutMs = _config$timeoutMs === void 0 ? 200 : _config$timeoutMs;
131
+ var frameCount = useRef(0);
132
+ var lastTime = useRef(0);
133
+ var timeoutId = useRef();
134
+ var frameRateSamples = useRef([]);
135
+ useEffect(function () {
136
+ return function () {
137
+ if (timeoutId.current) {
138
+ clearTimeout(timeoutId.current);
139
+ }
140
+ };
141
+ }, []);
142
+ var startMeasure = function startMeasure() {
143
+ frameCount.current = 0;
144
+ lastTime.current = performance.now();
145
+ };
146
+
147
+ /**
148
+ * Returns an array of frame rate samples as integers.
149
+ */
150
+ var endMeasure = function endMeasure() {
151
+ var samples = frameRateSamples.current;
152
+ frameRateSamples.current = [];
153
+ return samples;
154
+ };
155
+ var sampleFrameRate = function sampleFrameRate() {
156
+ var delay = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
157
+ var currentTime = performance.now();
158
+ var deltaTime = currentTime - lastTime.current - delay;
159
+ var isValidSample = deltaTime > minTimeMs && frameCount.current >= minFrames;
160
+ if (isValidSample) {
161
+ var frameRate = Math.round(frameCount.current / (deltaTime / 1000));
162
+ frameRateSamples.current.push(frameRate);
163
+ }
164
+ frameCount.current = 0;
165
+ lastTime.current = 0;
166
+ };
167
+
168
+ /**
169
+ * Counts the number of frames that occur within a given time period. Intended to be called
170
+ * inside a `requestAnimationFrame` callback.
171
+ */
172
+ var countFrames = function countFrames() {
173
+ if (frameRateSamples.current.length >= maxSamples && timeoutId.current) {
174
+ clearTimeout(timeoutId.current);
175
+ return;
176
+ }
177
+
178
+ /**
179
+ * Allows us to keep counting frames even if `startMeasure` is not called
180
+ */
181
+ if (lastTime.current === 0) {
182
+ lastTime.current = performance.now();
183
+ }
184
+ frameCount.current++;
185
+ if (timeoutId.current) {
186
+ clearTimeout(timeoutId.current);
187
+ }
188
+ if (performance.now() - lastTime.current > sampleRateMs) {
189
+ sampleFrameRate();
190
+ } else {
191
+ timeoutId.current = setTimeout(function () {
192
+ return sampleFrameRate(timeoutMs);
193
+ }, timeoutMs);
194
+ }
195
+ };
196
+ return {
197
+ startMeasure: startMeasure,
198
+ endMeasure: endMeasure,
199
+ countFrames: countFrames
200
+ };
62
201
  };
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "@atlaskit/editor-plugin-table",
3
- "version": "2.7.1",
3
+ "version": "2.8.0",
4
4
  "sideEffects": false
5
5
  }
@@ -38,7 +38,6 @@ export interface PluginConfig {
38
38
  permittedLayouts?: PermittedLayoutsDescriptor;
39
39
  allowControls?: boolean;
40
40
  stickyHeaders?: boolean;
41
- allowCellOptionsInFloatingToolbar?: boolean;
42
41
  tableCellOptimization?: boolean;
43
42
  tableRenderOptimization?: boolean;
44
43
  stickyHeadersOptimization?: boolean;
@@ -1,5 +1,6 @@
1
- import type { AnalyticsEventPayload, AnalyticsEventPayloadCallback, EditorAnalyticsAPI } from '@atlaskit/editor-common/analytics';
1
+ import type { AnalyticsEventPayload, AnalyticsEventPayloadCallback, EditorAnalyticsAPI, TableEventPayload } from '@atlaskit/editor-common/analytics';
2
2
  import { HigherOrderCommand } from '@atlaskit/editor-common/types';
3
+ import type { Node as PMNode } from '@atlaskit/editor-prosemirror/model';
3
4
  import { Selection } from '@atlaskit/editor-prosemirror/state';
4
5
  import { TableMap } from '@atlaskit/editor-tables/table-map';
5
6
  export declare function getSelectedTableInfo(selection: Selection): {
@@ -16,3 +17,29 @@ export declare function getSelectedCellInfo(selection: Selection): {
16
17
  totalCells: number;
17
18
  };
18
19
  export declare const withEditorAnalyticsAPI: (payload: AnalyticsEventPayload | AnalyticsEventPayloadCallback) => (editorAnalyticsAPI: EditorAnalyticsAPI | undefined | null) => HigherOrderCommand;
20
+ interface UseMeasureFramerateConfig {
21
+ maxSamples?: number;
22
+ minFrames?: number;
23
+ minTimeMs?: number;
24
+ sampleRateMs?: number;
25
+ timeoutMs?: number;
26
+ }
27
+ export declare const generateResizedPayload: (props: {
28
+ originalNode: PMNode;
29
+ resizedNode: PMNode;
30
+ }) => TableEventPayload;
31
+ export declare const reduceResizeFrameRateSamples: (frameRateSamples: number[]) => number[];
32
+ export declare const generateResizeFrameRatePayloads: (props: {
33
+ docSize: number;
34
+ frameRateSamples: number[];
35
+ originalNode: PMNode;
36
+ }) => TableEventPayload[];
37
+ /**
38
+ * Measures the framerate of a component over a given time period.
39
+ */
40
+ export declare const useMeasureFramerate: (config?: UseMeasureFramerateConfig) => {
41
+ startMeasure: () => void;
42
+ endMeasure: () => number[];
43
+ countFrames: () => void;
44
+ };
45
+ export {};
@@ -38,7 +38,6 @@ export interface PluginConfig {
38
38
  permittedLayouts?: PermittedLayoutsDescriptor;
39
39
  allowControls?: boolean;
40
40
  stickyHeaders?: boolean;
41
- allowCellOptionsInFloatingToolbar?: boolean;
42
41
  tableCellOptimization?: boolean;
43
42
  tableRenderOptimization?: boolean;
44
43
  stickyHeadersOptimization?: boolean;
@@ -1,5 +1,6 @@
1
- import type { AnalyticsEventPayload, AnalyticsEventPayloadCallback, EditorAnalyticsAPI } from '@atlaskit/editor-common/analytics';
1
+ import type { AnalyticsEventPayload, AnalyticsEventPayloadCallback, EditorAnalyticsAPI, TableEventPayload } from '@atlaskit/editor-common/analytics';
2
2
  import { HigherOrderCommand } from '@atlaskit/editor-common/types';
3
+ import type { Node as PMNode } from '@atlaskit/editor-prosemirror/model';
3
4
  import { Selection } from '@atlaskit/editor-prosemirror/state';
4
5
  import { TableMap } from '@atlaskit/editor-tables/table-map';
5
6
  export declare function getSelectedTableInfo(selection: Selection): {
@@ -16,3 +17,29 @@ export declare function getSelectedCellInfo(selection: Selection): {
16
17
  totalCells: number;
17
18
  };
18
19
  export declare const withEditorAnalyticsAPI: (payload: AnalyticsEventPayload | AnalyticsEventPayloadCallback) => (editorAnalyticsAPI: EditorAnalyticsAPI | undefined | null) => HigherOrderCommand;
20
+ interface UseMeasureFramerateConfig {
21
+ maxSamples?: number;
22
+ minFrames?: number;
23
+ minTimeMs?: number;
24
+ sampleRateMs?: number;
25
+ timeoutMs?: number;
26
+ }
27
+ export declare const generateResizedPayload: (props: {
28
+ originalNode: PMNode;
29
+ resizedNode: PMNode;
30
+ }) => TableEventPayload;
31
+ export declare const reduceResizeFrameRateSamples: (frameRateSamples: number[]) => number[];
32
+ export declare const generateResizeFrameRatePayloads: (props: {
33
+ docSize: number;
34
+ frameRateSamples: number[];
35
+ originalNode: PMNode;
36
+ }) => TableEventPayload[];
37
+ /**
38
+ * Measures the framerate of a component over a given time period.
39
+ */
40
+ export declare const useMeasureFramerate: (config?: UseMeasureFramerateConfig) => {
41
+ startMeasure: () => void;
42
+ endMeasure: () => number[];
43
+ countFrames: () => void;
44
+ };
45
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/editor-plugin-table",
3
- "version": "2.7.1",
3
+ "version": "2.8.0",
4
4
  "description": "Table plugin for the @atlaskit/editor",
5
5
  "publishConfig": {
6
6
  "registry": "https://registry.npmjs.org/"
@@ -28,7 +28,7 @@
28
28
  },
29
29
  "dependencies": {
30
30
  "@atlaskit/adf-schema": "^28.0.0",
31
- "@atlaskit/editor-common": "^74.40.0",
31
+ "@atlaskit/editor-common": "^74.42.0",
32
32
  "@atlaskit/editor-palette": "1.5.1",
33
33
  "@atlaskit/editor-plugin-analytics": "^0.1.0",
34
34
  "@atlaskit/editor-plugin-content-insertion": "^0.0.7",
@@ -67,6 +67,7 @@
67
67
  "@atlassian/atlassian-frontend-prettier-config-1.0.1": "npm:@atlassian/atlassian-frontend-prettier-config@1.0.1",
68
68
  "@atlassian/feature-flags-test-utils": "^0.1.2",
69
69
  "@testing-library/react": "^12.1.5",
70
+ "@testing-library/react-hooks": "^8.0.1",
70
71
  "raf-stub": "^2.0.1",
71
72
  "typescript": "~4.9.5"
72
73
  },
package/report.api.md CHANGED
@@ -41,8 +41,6 @@ interface PluginConfig {
41
41
  // (undocumented)
42
42
  allowBackgroundColor?: boolean;
43
43
  // (undocumented)
44
- allowCellOptionsInFloatingToolbar?: boolean;
45
- // (undocumented)
46
44
  allowCollapse?: boolean;
47
45
  // (undocumented)
48
46
  allowColumnResizing?: boolean;
@@ -35,7 +35,6 @@ BrowserTestCase(
35
35
  advanced: true,
36
36
  allowColumnSorting: true,
37
37
  allowDistributeColumns: true,
38
- allowCellOptionsInFloatingToolbar: true,
39
38
  },
40
39
  defaultValue: basicTable,
41
40
  });
@@ -91,7 +90,6 @@ BrowserTestCase(
91
90
  advanced: true,
92
91
  allowColumnSorting: true,
93
92
  allowDistributeColumns: true,
94
- allowCellOptionsInFloatingToolbar: true,
95
93
  },
96
94
  defaultValue: basicTable,
97
95
  });
@@ -138,7 +136,6 @@ BrowserTestCase(
138
136
  allowTables: {
139
137
  allowColumnSorting: true,
140
138
  allowDistributeColumns: true,
141
- allowCellOptionsInFloatingToolbar: true,
142
139
  },
143
140
  defaultValue: basicTable,
144
141
  });
@@ -185,7 +182,6 @@ BrowserTestCase(
185
182
  allowTables: {
186
183
  allowColumnSorting: true,
187
184
  allowDistributeColumns: true,
188
- allowCellOptionsInFloatingToolbar: true,
189
185
  },
190
186
  defaultValue: documentWithMergedCells,
191
187
  });
@@ -247,7 +243,6 @@ BrowserTestCase(
247
243
  allowTables: {
248
244
  allowColumnSorting: true,
249
245
  allowDistributeColumns: true,
250
- allowCellOptionsInFloatingToolbar: true,
251
246
  },
252
247
  defaultValue: basicTableWithMergedCell,
253
248
  });
@@ -295,7 +290,6 @@ BrowserTestCase(
295
290
  allowTables: {
296
291
  allowColumnSorting: true,
297
292
  allowDistributeColumns: true,
298
- allowCellOptionsInFloatingToolbar: true,
299
293
  },
300
294
  defaultValue: basicTableWithMergedCell,
301
295
  });
@@ -343,7 +337,6 @@ BrowserTestCase(
343
337
  allowTables: {
344
338
  allowColumnSorting: true,
345
339
  allowDistributeColumns: true,
346
- allowCellOptionsInFloatingToolbar: true,
347
340
  },
348
341
  defaultValue: basicTable,
349
342
  });