UNPKG

@atlaskit/editor-plugin-table

Version:

Table plugin for the @atlaskit/editor

306 lines (298 loc) 12.2 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.getHeightInfoPayload = exports.generateResizedPayload = exports.generateResizeFrameRatePayloads = void 0; exports.getSelectedCellInfo = getSelectedCellInfo; exports.getSelectedTableInfo = getSelectedTableInfo; exports.withEditorAnalyticsAPI = exports.useMeasureFramerate = exports.reduceResizeFrameRateSamples = exports.getWidthInfoPayload = void 0; var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray")); var _react = require("react"); var _analytics = require("@atlaskit/editor-common/analytics"); var _analytics2 = require("@atlaskit/editor-common/utils/analytics"); var _tableMap = require("@atlaskit/editor-tables/table-map"); var _utils = require("@atlaskit/editor-tables/utils"); var _colgroup = require("../table-resizing/utils/colgroup"); var _nodes = require("./nodes"); function getSelectedTableInfo(selection) { var map; var totalRowCount = 0; var totalColumnCount = 0; var table = (0, _utils.findTable)(selection); if (table) { map = _tableMap.TableMap.get(table.node); totalRowCount = map.height; totalColumnCount = map.width; } return { table: table, map: map, totalRowCount: totalRowCount, totalColumnCount: totalColumnCount }; } function getSelectedCellInfo(selection) { var horizontalCells = 1; var verticalCells = 1; var totalCells = 1; var _getSelectedTableInfo = getSelectedTableInfo(selection), table = _getSelectedTableInfo.table, map = _getSelectedTableInfo.map, totalRowCount = _getSelectedTableInfo.totalRowCount, totalColumnCount = _getSelectedTableInfo.totalColumnCount; if (table && map) { var rect = (0, _utils.getSelectionRect)(selection); if (rect) { totalCells = map.cellsInRect(rect).length; horizontalCells = rect.right - rect.left; verticalCells = rect.bottom - rect.top; } } return { totalRowCount: totalRowCount, totalColumnCount: totalColumnCount, horizontalCells: horizontalCells, verticalCells: verticalCells, totalCells: totalCells }; } var withEditorAnalyticsAPI = exports.withEditorAnalyticsAPI = function withEditorAnalyticsAPI(payload) { return function (editorAnalyticsAPI) { return function (command) { return function (state, dispatch, view) { return command(state, function (tr) { var dynamicPayload = payload instanceof Function ? payload(state) : payload; if (dynamicPayload) { editorAnalyticsAPI === null || editorAnalyticsAPI === void 0 || editorAnalyticsAPI.attachAnalyticsEvent(dynamicPayload)(tr); } if (dispatch) { dispatch(tr); } return true; }, view); }; }; }; }; var generateResizedPayload = exports.generateResizedPayload = function generateResizedPayload(props) { var _props$originalNode$a; var tableMap = _tableMap.TableMap.get(props.resizedNode); return { action: _analytics.TABLE_ACTION.RESIZED, actionSubject: _analytics.ACTION_SUBJECT.TABLE, eventType: _analytics.EVENT_TYPE.TRACK, attributes: { newWidth: props.resizedNode.attrs.width, prevWidth: (_props$originalNode$a = props.originalNode.attrs.width) !== null && _props$originalNode$a !== void 0 ? _props$originalNode$a : null, nodeSize: props.resizedNode.nodeSize, totalTableWidth: (0, _colgroup.hasTableBeenResized)(props.resizedNode) ? (0, _nodes.getTableWidth)(props.resizedNode) : null, totalRowCount: tableMap.height, totalColumnCount: tableMap.width } }; }; var reduceResizeFrameRateSamples = exports.reduceResizeFrameRateSamples = function reduceResizeFrameRateSamples(frameRateSamples) { if (frameRateSamples.length > 1) { var frameRateSum = frameRateSamples.reduce(function (sum, frameRate, index) { if (index === 0) { return sum; } else { return sum + frameRate; } }, 0); var averageFrameRate = Math.round(frameRateSum / (frameRateSamples.length - 1)); return [frameRateSamples[0], averageFrameRate]; } else { return frameRateSamples; } }; var generateResizeFrameRatePayloads = exports.generateResizeFrameRatePayloads = function generateResizeFrameRatePayloads(props) { var reducedResizeFrameRateSamples = reduceResizeFrameRateSamples(props.frameRateSamples); return reducedResizeFrameRateSamples.map(function (frameRateSample, index) { return { action: _analytics.TABLE_ACTION.RESIZE_PERF_SAMPLING, actionSubject: _analytics.ACTION_SUBJECT.TABLE, eventType: _analytics.EVENT_TYPE.OPERATIONAL, attributes: { frameRate: frameRateSample, nodeSize: props.originalNode.nodeSize, docSize: props.docSize, isInitialSample: index === 0 } }; }); }; /** * Measures the framerate of a component over a given time period. */ var useMeasureFramerate = exports.useMeasureFramerate = function useMeasureFramerate() { var config = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; var _config$maxSamples = config.maxSamples, maxSamples = _config$maxSamples === void 0 ? 10 : _config$maxSamples, _config$minFrames = config.minFrames, minFrames = _config$minFrames === void 0 ? 5 : _config$minFrames, _config$minTimeMs = config.minTimeMs, minTimeMs = _config$minTimeMs === void 0 ? 500 : _config$minTimeMs, _config$sampleRateMs = config.sampleRateMs, sampleRateMs = _config$sampleRateMs === void 0 ? 1000 : _config$sampleRateMs, _config$timeoutMs = config.timeoutMs, timeoutMs = _config$timeoutMs === void 0 ? 200 : _config$timeoutMs; var frameCount = (0, _react.useRef)(0); var lastTime = (0, _react.useRef)(0); var timeoutId = (0, _react.useRef)(); var frameRateSamples = (0, _react.useRef)([]); (0, _react.useEffect)(function () { return function () { if (timeoutId.current) { clearTimeout(timeoutId.current); } }; }, []); var startMeasure = function startMeasure() { frameCount.current = 0; lastTime.current = performance.now(); }; /** * Returns an array of frame rate samples as integers. */ var endMeasure = function endMeasure() { var samples = frameRateSamples.current; frameRateSamples.current = []; return samples; }; var sampleFrameRate = function sampleFrameRate() { var delay = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0; var currentTime = performance.now(); var deltaTime = currentTime - lastTime.current - delay; var isValidSample = deltaTime > minTimeMs && frameCount.current >= minFrames; if (isValidSample) { var frameRate = Math.round(frameCount.current / (deltaTime / 1000)); frameRateSamples.current.push(frameRate); } frameCount.current = 0; lastTime.current = 0; }; /** * Counts the number of frames that occur within a given time period. Intended to be called * inside a `requestAnimationFrame` callback. */ var countFrames = function countFrames() { if (frameRateSamples.current.length >= maxSamples && timeoutId.current) { clearTimeout(timeoutId.current); return; } /** * Allows us to keep counting frames even if `startMeasure` is not called */ if (lastTime.current === 0) { lastTime.current = performance.now(); } frameCount.current++; if (timeoutId.current) { clearTimeout(timeoutId.current); } if (performance.now() - lastTime.current > sampleRateMs) { sampleFrameRate(); } else { timeoutId.current = setTimeout(function () { return sampleFrameRate(timeoutMs); }, timeoutMs); } }; return { startMeasure: startMeasure, endMeasure: endMeasure, countFrames: countFrames }; }; var tableContainerNodes = new Set(['layoutSection', 'layoutColumn', 'expand', 'nestedExpand', 'extension', 'bodiedExtension', 'multiBodiedExtension', 'extensionFrame', 'table', 'tableCell', 'tableHeader', 'tableRow']); var getWidthInfoPayload = exports.getWidthInfoPayload = function getWidthInfoPayload(editorView, editorWidth) { var tablesInfo = []; editorView.state.doc.nodesBetween(0, editorView.state.doc.content.size, function (node, pos, parent) { if (!tableContainerNodes.has(node.type.name)) { return false; } if (node.type.name === 'table') { var _domAtPos$node; var domAtPos = editorView.domAtPos(pos + 1); var table = (_domAtPos$node = domAtPos.node) === null || _domAtPos$node === void 0 ? void 0 : _domAtPos$node.parentElement; var isNestedTable = (parent === null || parent === void 0 ? void 0 : parent.type.name) === 'tableCell' || (parent === null || parent === void 0 ? void 0 : parent.type.name) === 'tableHeader'; if (table instanceof HTMLTableElement) { tablesInfo.push({ tableWidth: table.scrollWidth, isNestedTable: isNestedTable, hasScrollbar: table.parentElement ? (table === null || table === void 0 ? void 0 : table.parentElement.clientWidth) < table.scrollWidth : false }); } } }); // only send the event if there are tables on the page if (tablesInfo.length === 0) { return undefined; } var maxTableWidth = Math.max.apply(Math, (0, _toConsumableArray2.default)(tablesInfo.map(function (table) { return table.tableWidth; }))); return { action: _analytics.TABLE_ACTION.TABLE_WIDTH_INFO, actionSubject: _analytics.ACTION_SUBJECT.TABLE, attributes: { editorWidth: editorWidth, editorWidthBreakpoint: (0, _analytics2.getBreakpointKey)(editorWidth), hasTableWithScrollbar: tablesInfo.some(function (table) { return table.hasScrollbar; }), hasTableWiderThanEditor: maxTableWidth > editorWidth, maxTableWidthBreakpoint: (0, _analytics2.getBreakpointKey)(maxTableWidth), tableWidthInfo: tablesInfo, mode: 'editor' }, eventType: _analytics.EVENT_TYPE.OPERATIONAL }; }; var getHeightInfoPayload = exports.getHeightInfoPayload = function getHeightInfoPayload(editorView) { var tablesInfo = []; var editorPopupScrollParent = editorView.dom.closest('.fabric-editor-popup-scroll-parent'); // don't send the event if the editor scroll parent is not available if (!editorPopupScrollParent) { return undefined; } var editorScrollParentClientHeight = editorPopupScrollParent.clientHeight; var isEditorScrollable = editorPopupScrollParent.scrollHeight > editorScrollParentClientHeight; editorView.state.doc.nodesBetween(0, editorView.state.doc.content.size, function (node, pos, parent) { if (!tableContainerNodes.has(node.type.name)) { return false; } if (node.type.name === 'table') { var _domAtPos$node2; var domAtPos = editorView.domAtPos(pos + 1); var table = (_domAtPos$node2 = domAtPos.node) === null || _domAtPos$node2 === void 0 ? void 0 : _domAtPos$node2.parentElement; var isNestedTable = (parent === null || parent === void 0 ? void 0 : parent.type.name) === 'tableCell' || (parent === null || parent === void 0 ? void 0 : parent.type.name) === 'tableHeader'; if (table instanceof HTMLTableElement) { tablesInfo.push({ isNestedTable: isNestedTable, tableHeight: table.scrollHeight }); } } }); // only send the event if there are tables on the page if (tablesInfo.length === 0) { return undefined; } var maxTableHeight = Math.max.apply(Math, (0, _toConsumableArray2.default)(tablesInfo.map(function (table) { return table.tableHeight; }))); return { action: _analytics.TABLE_ACTION.TABLE_EDITOR_HEIGHT_INFO, actionSubject: _analytics.ACTION_SUBJECT.TABLE, attributes: { editorScrollParentClientHeight: editorScrollParentClientHeight, isEditorScrollable: isEditorScrollable, maxTableToEditorHeightRatio: maxTableHeight / editorScrollParentClientHeight, tableHeightInfo: tablesInfo }, eventType: _analytics.EVENT_TYPE.OPERATIONAL }; };