UNPKG

@atlaskit/editor-plugin-table

Version:

Table plugin for the @atlaskit/editor

532 lines (526 loc) 28.3 kB
import React, { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react'; import rafSchd from 'raf-schd'; import { useIntl } from 'react-intl-next'; import { CHANGE_ALIGNMENT_REASON, INPUT_METHOD, TABLE_OVERFLOW_CHANGE_TRIGGER } from '@atlaskit/editor-common/analytics'; import { browser as browserLegacy, getBrowserInfo } from '@atlaskit/editor-common/browser'; import { getGuidelinesWithHighlights } from '@atlaskit/editor-common/guideline'; import { useSharedPluginStateWithSelector } from '@atlaskit/editor-common/hooks'; import { focusTableResizer, ToolTipContent } from '@atlaskit/editor-common/keymaps'; import { tableMessages as messages } from '@atlaskit/editor-common/messages'; import { logException } from '@atlaskit/editor-common/monitoring'; import { ResizerNext } from '@atlaskit/editor-common/resizer'; import { useSharedPluginStateSelector } from '@atlaskit/editor-common/use-shared-plugin-state-selector'; import { chainCommands } from '@atlaskit/editor-prosemirror/commands'; import { akEditorGutterPaddingDynamic, akEditorGutterPaddingReduced, akEditorFullPageNarrowBreakout } from '@atlaskit/editor-shared-styles'; import { findTable } from '@atlaskit/editor-tables/utils'; import { insm } from '@atlaskit/insm'; import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals'; import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments'; import { setTableAlignmentWithTableContentWithPosWithAnalytics } from '../pm-plugins/commands/commands-with-analytics'; import { updateWidthToWidest } from '../pm-plugins/commands/misc'; import { META_KEYS } from '../pm-plugins/table-analytics'; import { getColgroupChildrenLength } from '../pm-plugins/table-resizing/utils/colgroup'; import { COLUMN_MIN_WIDTH, TABLE_MAX_WIDTH, TABLE_FULL_WIDTH, TABLE_OFFSET_IN_COMMENT_EDITOR } from '../pm-plugins/table-resizing/utils/consts'; import { previewScaleTable, scaleTable } from '../pm-plugins/table-resizing/utils/scale-table'; import { pluginKey as tableWidthPluginKey } from '../pm-plugins/table-width'; import { ALIGN_CENTER, ALIGN_START, normaliseAlignment, shouldChangeAlignmentToCenterResized } from '../pm-plugins/utils/alignment'; import { generateResizedPayload, generateResizeFrameRatePayloads, useMeasureFramerate } from '../pm-plugins/utils/analytics'; import { defaultGuidelines, defaultGuidelinesForPreserveTable, PRESERVE_TABLE_GUIDELINES_LENGTH_OFFSET } from '../pm-plugins/utils/guidelines'; import { defaultSnappingWidths, defaultTablePreserveSnappingWidths, findClosestSnap, PRESERVE_TABLE_SNAPPING_LENGTH_OFFSET } from '../pm-plugins/utils/snapping'; import { TABLE_GUIDELINE_VISIBLE_ADJUSTMENT, TABLE_HIGHLIGHT_GAP, TABLE_HIGHLIGHT_TOLERANCE, TABLE_SNAP_GAP } from '../ui/consts'; const RESIZE_STEP_VALUE = 10; const handles = { right: true }; const handleStyles = { right: { // eslint-disable-next-line @atlaskit/design-system/ensure-design-token-usage/preview right: '-14px', marginTop: "var(--ds-space-150, 12px)" } }; const getResizerHandleHeight = tableRef => { var _tableRef$clientHeigh; const tableHeight = (_tableRef$clientHeigh = tableRef === null || tableRef === void 0 ? void 0 : tableRef.clientHeight) !== null && _tableRef$clientHeigh !== void 0 ? _tableRef$clientHeigh : 0; /* - One row table height (minimum possible table height) ~ 45px - Two row table height ~ 90px - Three row table height ~ 134px In the if below we need to use: - > 46 because the height of the table can be a float number like 45.44. - < 96 is the height of large resize handle. */ if (tableHeight >= 96) { return 'large'; } if (tableHeight > 46) { return 'medium'; } return 'small'; }; const getResizerMinWidth = node => { const currentColumnCount = getColgroupChildrenLength(node); const minColumnWidth = Math.min(3, currentColumnCount) * COLUMN_MIN_WIDTH; // add an extra pixel as the scale table logic will scale columns to be tableContainerWidth - 1 // the table can't scale past its min-width, so instead restrict table container min width to avoid that situation return minColumnWidth + 1; }; const getPadding = containerWidth => { return containerWidth <= akEditorFullPageNarrowBreakout && editorExperiment('platform_editor_preview_panel_responsiveness', true, { exposure: true }) ? akEditorGutterPaddingReduced : akEditorGutterPaddingDynamic(); }; /** * When guidelines are outside the viewport, filter them out, do not show * So the guideline container won't make the fabric-editor-popup-scroll-parent overflow * @param guidelines * @param containerWidth editorWidth * @param lineLength * @param isTableScalingEnabled * @param isFullWidthModeEnabled */ const getVisibleGuidelines = (guidelines, containerWidth, lineLength, isTableScalingEnabled, isFullWidthModeEnabled) => { let guidelineVisibleAdjustment = TABLE_GUIDELINE_VISIBLE_ADJUSTMENT; if (isTableScalingEnabled) { // Notes: // Example: containerWidth = 1244, lineLength = 1180 (used for when editor full width mode is enabled) // Full width/dynamic x coordinate can be float number. // Ex: guideline.position.x can be 590.5. So 590.5 * 2 = 1181 (not 1180). // For PTW we need to ensure that dynamic guideline never gets excluded: 1181 should be > width + guidelineVisibleAdjustment // guidelineVisibleAdjustment is set as a negative value, so we making it positive and adding + 1 const preserve_table_widths_adjustment = -1 * PRESERVE_TABLE_GUIDELINES_LENGTH_OFFSET + 1; const padding = getPadding(containerWidth); guidelineVisibleAdjustment = isFullWidthModeEnabled ? preserve_table_widths_adjustment // guidelineVisibleAdjustment = -2, if lineLength = 1180, 1181 < 1180 + 2 is true. : -2 * padding + preserve_table_widths_adjustment; // guidelineVisibleAdjustment = -62, if containerWidth is 1244, 1181 < 1244 - 62 = 1182 is true. } const width = isTableScalingEnabled && isFullWidthModeEnabled ? lineLength : containerWidth; return guidelines.filter(guideline => { return guideline.position && guideline.position.x !== undefined && typeof guideline.position.x === 'number' && Math.abs(guideline.position.x * 2) < width + guidelineVisibleAdjustment; }); }; const selector = states => { var _states$tableState; return { widthToWidest: (_states$tableState = states.tableState) === null || _states$tableState === void 0 ? void 0 : _states$tableState.widthToWidest }; }; export const TableResizer = ({ children, width, maxWidth, containerWidth, lineLength, updateWidth, onResizeStop, onResizeStart, editorView, getPos, node, tableRef, displayGuideline, attachAnalyticsEvent, displayGapCursor, isTableScalingEnabled, allowFixedColumnWidthOption, isTableAlignmentEnabled, isWholeTableInDanger, shouldUseIncreasedScalingPercent, pluginInjectionApi, isFullWidthModeEnabled, isCommentEditor, disabled }) => { var _editorView$state, _pluginInjectionApi$a2, _pluginInjectionApi$u2; const currentGap = useRef(0); // track resizing state - use ref over state to avoid re-render const isResizing = useRef(false); const areResizeMetaKeysPressed = useRef(false); const resizerRef = useRef(null); const interactionState = useSharedPluginStateSelector(pluginInjectionApi, 'interaction.interactionState'); const { widthToWidest } = useSharedPluginStateWithSelector(pluginInjectionApi, ['table'], selector); // used to reposition tooltip when table is resizing via keyboard const updateTooltip = React.useRef(); const [snappingEnabled, setSnappingEnabled] = useState(false); const { formatMessage } = useIntl(); const currentSelection = (_editorView$state = editorView.state) === null || _editorView$state === void 0 ? void 0 : _editorView$state.selection; const tableFromSelection = useMemo(() => { return findTable(currentSelection); }, [currentSelection]); const tableFromSelectionPosition = tableFromSelection === null || tableFromSelection === void 0 ? void 0 : tableFromSelection.pos; const isTableSelected = useMemo(() => { // Avoid call getPos if there is no table in the current selection, if (typeof tableFromSelectionPosition !== 'number') { return false; } if (interactionState === 'hasNotHadInteraction') { return false; } let currentNodePosition; try { // The React Table and the ProseMirror can endup out-of-sync // ProseMirror always assume the DOM is not managed by other framework currentNodePosition = getPos(); } catch (e) { logException(e, { location: 'editor-plugin-table/table-resizer' }); return false; } return tableFromSelectionPosition === currentNodePosition; }, [tableFromSelectionPosition, interactionState, getPos]); const resizerMinWidth = getResizerMinWidth(node); const handleSize = getResizerHandleHeight(tableRef); const { startMeasure, endMeasure, countFrames } = useMeasureFramerate(); const excludeGuidelineConfig = useMemo(() => ({ innerGuidelines: !!isTableAlignmentEnabled, breakoutPoints: !!(isTableAlignmentEnabled && isFullWidthModeEnabled) }), [isFullWidthModeEnabled, isTableAlignmentEnabled]); const updateActiveGuidelines = useCallback(({ gap, keys }) => { if (gap !== currentGap.current) { currentGap.current = gap; const visibleGuidelines = getVisibleGuidelines(isTableScalingEnabled ? defaultGuidelinesForPreserveTable(PRESERVE_TABLE_GUIDELINES_LENGTH_OFFSET, isFullWidthModeEnabled ? lineLength + 2 * getPadding(containerWidth) : containerWidth, excludeGuidelineConfig) : defaultGuidelines, containerWidth, lineLength, Boolean(isTableScalingEnabled), Boolean(isFullWidthModeEnabled)); displayGuideline(getGuidelinesWithHighlights(gap, TABLE_SNAP_GAP, keys, visibleGuidelines)); } }, [isTableScalingEnabled, excludeGuidelineConfig, containerWidth, displayGuideline, lineLength, isFullWidthModeEnabled]); const guidelineSnaps = useMemo(() => snappingEnabled ? { x: isTableScalingEnabled ? defaultTablePreserveSnappingWidths(PRESERVE_TABLE_SNAPPING_LENGTH_OFFSET, // was hardcoded to 0, using PRESERVE_TABLE_SNAPPING_LENGTH_OFFSET instead. isFullWidthModeEnabled ? lineLength + 2 * getPadding(containerWidth) : containerWidth, excludeGuidelineConfig) : defaultSnappingWidths } : undefined, [snappingEnabled, isTableScalingEnabled, excludeGuidelineConfig, containerWidth, lineLength, isFullWidthModeEnabled]); const switchToCenterAlignment = useCallback((pos, node, newWidth, state, dispatch) => { if (shouldChangeAlignmentToCenterResized(isTableAlignmentEnabled, node, lineLength, newWidth) && isResizing.current) { var _pluginInjectionApi$a; const tableNodeWithPos = { pos, node }; setTableAlignmentWithTableContentWithPosWithAnalytics(pluginInjectionApi === null || pluginInjectionApi === void 0 ? void 0 : (_pluginInjectionApi$a = pluginInjectionApi.analytics) === null || _pluginInjectionApi$a === void 0 ? void 0 : _pluginInjectionApi$a.actions)(ALIGN_CENTER, ALIGN_START, tableNodeWithPos, INPUT_METHOD.AUTO, CHANGE_ALIGNMENT_REASON.EDITOR_APPEARANCE_CHANGED)(state, dispatch); return true; } return false; }, [isTableAlignmentEnabled, lineLength, pluginInjectionApi === null || pluginInjectionApi === void 0 ? void 0 : (_pluginInjectionApi$a2 = pluginInjectionApi.analytics) === null || _pluginInjectionApi$a2 === void 0 ? void 0 : _pluginInjectionApi$a2.actions]); useEffect(() => { return () => { // only bring back the cursor if this table was deleted - i.e. if a user was resizing, then another // deleted this table if (isResizing.current) { const { dispatch, state: { tr } } = editorView; displayGapCursor(true); displayGuideline([]); tr.setMeta(tableWidthPluginKey, { resizing: false, tableLocalId: '', tableRef: null }); dispatch(tr); } }; }, [editorView, displayGuideline, displayGapCursor]); const handleResizeStart = useCallback(() => { var _pluginInjectionApi$u; if (expValEquals('cc_editor_interactivity_monitoring', 'isEnabled', true)) { var _insm$session; (_insm$session = insm.session) === null || _insm$session === void 0 ? void 0 : _insm$session.startFeature('tableResize'); } startMeasure(); isResizing.current = true; const { dispatch, state: { tr } } = editorView; displayGapCursor(false); tr.setMeta(tableWidthPluginKey, { resizing: true, tableLocalId: node.attrs.localId, tableRef: tableRef }); tr.setMeta('is-resizer-resizing', true); tr.setMeta(META_KEYS.OVERFLOW_TRIGGER, { name: TABLE_OVERFLOW_CHANGE_TRIGGER.RESIZED }); pluginInjectionApi === null || pluginInjectionApi === void 0 ? void 0 : (_pluginInjectionApi$u = pluginInjectionApi.userIntent) === null || _pluginInjectionApi$u === void 0 ? void 0 : _pluginInjectionApi$u.commands.setCurrentUserIntent('resizing')({ tr }); dispatch(tr); const visibleGuidelines = getVisibleGuidelines(isTableScalingEnabled ? defaultGuidelinesForPreserveTable(PRESERVE_TABLE_GUIDELINES_LENGTH_OFFSET, isFullWidthModeEnabled ? lineLength + 2 * getPadding(containerWidth) : containerWidth, excludeGuidelineConfig) : defaultGuidelines, containerWidth, lineLength, Boolean(isTableScalingEnabled), Boolean(isFullWidthModeEnabled)); setSnappingEnabled(displayGuideline(visibleGuidelines)); if (onResizeStart) { onResizeStart(); } }, [startMeasure, editorView, displayGapCursor, node.attrs.localId, tableRef, isTableScalingEnabled, isFullWidthModeEnabled, lineLength, containerWidth, excludeGuidelineConfig, displayGuideline, onResizeStart, pluginInjectionApi === null || pluginInjectionApi === void 0 ? void 0 : (_pluginInjectionApi$u2 = pluginInjectionApi.userIntent) === null || _pluginInjectionApi$u2 === void 0 ? void 0 : _pluginInjectionApi$u2.commands]); const handleResize = useCallback( // Ignored via go/ees005 // eslint-disable-next-line @typescript-eslint/no-explicit-any (originalState, delta) => { var _node$attrs$localId, _node$attrs; countFrames(); const newWidth = originalState.width + delta.width; let pos; try { pos = getPos(); } catch { return; } if (typeof pos !== 'number') { return; } const editorContainerWidth = isFullWidthModeEnabled ? lineLength + 2 * getPadding(containerWidth) : containerWidth; const closestSnap = !isCommentEditor && findClosestSnap(newWidth, isTableScalingEnabled ? defaultTablePreserveSnappingWidths(PRESERVE_TABLE_SNAPPING_LENGTH_OFFSET, editorContainerWidth, excludeGuidelineConfig) : defaultSnappingWidths, isTableScalingEnabled ? defaultGuidelinesForPreserveTable(PRESERVE_TABLE_GUIDELINES_LENGTH_OFFSET, editorContainerWidth, excludeGuidelineConfig) : defaultGuidelines, TABLE_HIGHLIGHT_GAP, TABLE_HIGHLIGHT_TOLERANCE); closestSnap && updateActiveGuidelines(closestSnap); // When snapping to the full width guideline, resize the table to be 1800px const { state, dispatch } = editorView; const currentTableNodeLocalId = (_node$attrs$localId = node === null || node === void 0 ? void 0 : (_node$attrs = node.attrs) === null || _node$attrs === void 0 ? void 0 : _node$attrs.localId) !== null && _node$attrs$localId !== void 0 ? _node$attrs$localId : ''; const fullWidthGuideline = defaultGuidelinesForPreserveTable(PRESERVE_TABLE_GUIDELINES_LENGTH_OFFSET, editorContainerWidth, excludeGuidelineConfig).filter(guideline => guideline.isFullWidth)[0]; const isFullWidthGuidelineActive = expValEquals('editor_tinymce_full_width_mode', 'isEnabled', true) || expValEquals('confluence_max_width_content_appearance', 'isEnabled', true) ? closestSnap && fullWidthGuideline && closestSnap.keys.includes(fullWidthGuideline.key) : closestSnap && closestSnap.keys.includes(fullWidthGuideline.key); const tableMaxWidth = isCommentEditor ? Math.floor(containerWidth - TABLE_OFFSET_IN_COMMENT_EDITOR) : expValEquals('editor_tinymce_full_width_mode', 'isEnabled', true) || expValEquals('confluence_max_width_content_appearance', 'isEnabled', true) ? TABLE_MAX_WIDTH : TABLE_FULL_WIDTH; const shouldUpdateWidthToWidest = isCommentEditor ? tableMaxWidth <= newWidth : !!isTableScalingEnabled && isFullWidthGuidelineActive; const previewParentWidth = isCommentEditor && shouldUpdateWidthToWidest ? tableMaxWidth : newWidth; previewScaleTable(tableRef, { node, prevNode: node, start: pos + 1, parentWidth: previewParentWidth }, editorView.domAtPos.bind(editorView), isTableScalingEnabled, allowFixedColumnWidthOption, isCommentEditor); chainCommands((state, dispatch) => { return switchToCenterAlignment(pos, node, newWidth, state, dispatch); }, updateWidthToWidest({ [currentTableNodeLocalId]: shouldUpdateWidthToWidest }))(state, dispatch); updateWidth(shouldUpdateWidthToWidest ? tableMaxWidth : newWidth); return newWidth; }, [countFrames, isCommentEditor, isTableScalingEnabled, allowFixedColumnWidthOption, isFullWidthModeEnabled, excludeGuidelineConfig, tableRef, node, editorView, updateActiveGuidelines, containerWidth, lineLength, updateWidth, getPos, switchToCenterAlignment]); const scheduleResize = useMemo(() => rafSchd(handleResize), [handleResize]); const handleResizeStop = useCallback((originalState, delta) => { var _node$attrs$localId2, _node$attrs2, _pluginInjectionApi$u3; isResizing.current = false; let newWidth = originalState.width + delta.width; const originalNewWidth = newWidth; const { state, dispatch } = editorView; const pos = getPos(); const currentTableNodeLocalId = (_node$attrs$localId2 = node === null || node === void 0 ? void 0 : (_node$attrs2 = node.attrs) === null || _node$attrs2 === void 0 ? void 0 : _node$attrs2.localId) !== null && _node$attrs$localId2 !== void 0 ? _node$attrs$localId2 : ''; const tableMaxWidth = isCommentEditor ? undefined // Table's full-width in comment appearance inherit the width of the Editor/Renderer : expValEquals('editor_tinymce_full_width_mode', 'isEnabled', true) || expValEquals('confluence_max_width_content_appearance', 'isEnabled', true) ? TABLE_MAX_WIDTH : TABLE_FULL_WIDTH; newWidth = widthToWidest && currentTableNodeLocalId && widthToWidest[currentTableNodeLocalId] ? tableMaxWidth : newWidth; let tr = state.tr.setMeta(tableWidthPluginKey, { resizing: false, tableLocalId: '', tableRef: null }); tr.setMeta('is-resizer-resizing', false); pluginInjectionApi === null || pluginInjectionApi === void 0 ? void 0 : (_pluginInjectionApi$u3 = pluginInjectionApi.userIntent) === null || _pluginInjectionApi$u3 === void 0 ? void 0 : _pluginInjectionApi$u3.commands.setCurrentUserIntent('default')({ tr }); const frameRateSamples = endMeasure(); if (frameRateSamples.length > 0) { const resizeFrameRatePayloads = generateResizeFrameRatePayloads({ docSize: state.doc.nodeSize, frameRateSamples, originalNode: node }); resizeFrameRatePayloads.forEach(payload => { var _attachAnalyticsEvent; (_attachAnalyticsEvent = attachAnalyticsEvent(payload)) === null || _attachAnalyticsEvent === void 0 ? void 0 : _attachAnalyticsEvent(tr); }); } if (typeof pos === 'number') { var _attachAnalyticsEvent2; tr = tr.setNodeMarkup(pos, undefined, { ...node.attrs, width: newWidth, layout: node.attrs.layout !== ALIGN_START && node.attrs.layout !== ALIGN_CENTER ? ALIGN_CENTER : node.attrs.layout }); // Ignored via go/ees005 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const newNode = tr.doc.nodeAt(pos); tr = scaleTable(tableRef, { node: newNode, prevNode: node, start: pos + 1, // We use originalNewWidth in comment editor, because in comment editor // newWidth can be underined when table is resized to 'full-width' // scaleTable function needs number value to work correctly. parentWidth: isCommentEditor ? originalNewWidth : newWidth }, editorView.domAtPos.bind(editorView), pluginInjectionApi, isTableScalingEnabled, shouldUseIncreasedScalingPercent || false, isCommentEditor)(tr); // Ignored via go/ees005 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const scaledNode = tr.doc.nodeAt(pos); (_attachAnalyticsEvent2 = attachAnalyticsEvent(generateResizedPayload({ originalNode: node, resizedNode: scaledNode }))) === null || _attachAnalyticsEvent2 === void 0 ? void 0 : _attachAnalyticsEvent2(tr); } displayGapCursor(true); dispatch(tr); if (delta.width < 0 && newWidth !== undefined) { var _pluginInjectionApi$a3; pluginInjectionApi === null || pluginInjectionApi === void 0 ? void 0 : (_pluginInjectionApi$a3 = pluginInjectionApi.accessibilityUtils) === null || _pluginInjectionApi$a3 === void 0 ? void 0 : _pluginInjectionApi$a3.actions.ariaNotify(formatMessage(messages.tableSizeDecreaseScreenReaderInformation, { newWidth: newWidth })); } else if (delta.width > 0 && newWidth !== undefined) { var _pluginInjectionApi$a4; pluginInjectionApi === null || pluginInjectionApi === void 0 ? void 0 : (_pluginInjectionApi$a4 = pluginInjectionApi.accessibilityUtils) === null || _pluginInjectionApi$a4 === void 0 ? void 0 : _pluginInjectionApi$a4.actions.ariaNotify(formatMessage(messages.tableSizeIncreaseScreenReaderInformation, { newWidth: newWidth })); } // Hide guidelines when resizing stops displayGuideline([]); newWidth !== undefined && updateWidth(newWidth); scheduleResize.cancel(); if (onResizeStop) { onResizeStop(); } if (expValEquals('cc_editor_interactivity_monitoring', 'isEnabled', true)) { var _insm$session2; (_insm$session2 = insm.session) === null || _insm$session2 === void 0 ? void 0 : _insm$session2.endFeature('tableResize'); } return newWidth; }, [editorView, getPos, node, isCommentEditor, widthToWidest, endMeasure, displayGapCursor, displayGuideline, updateWidth, scheduleResize, onResizeStop, pluginInjectionApi, attachAnalyticsEvent, tableRef, isTableScalingEnabled, shouldUseIncreasedScalingPercent, formatMessage]); const handleTableSizeChangeOnKeypress = useCallback(step => { const newWidth = width + step; if (newWidth < resizerMinWidth) { return; } handleResizeStop({ width: width, x: 0, y: 0, height: 0 }, { width: step, height: 0 }); }, [width, handleResizeStop, resizerMinWidth]); const handleEscape = useCallback(() => { editorView === null || editorView === void 0 ? void 0 : editorView.focus(); }, [editorView]); const handleKeyDown = useCallback(event => { const isBracketKey = event.code === 'BracketRight' || event.code === 'BracketLeft'; const browser = expValEquals('platform_editor_hydratable_ui', 'isEnabled', true) ? getBrowserInfo() : browserLegacy; const metaKey = browser.mac ? event.metaKey : event.ctrlKey; if (event.altKey || metaKey || event.shiftKey) { areResizeMetaKeysPressed.current = true; } if (event.altKey && metaKey) { if (isBracketKey) { event.preventDefault(); handleTableSizeChangeOnKeypress(event.code === 'BracketRight' ? RESIZE_STEP_VALUE : -RESIZE_STEP_VALUE); } } else if (!areResizeMetaKeysPressed.current) { handleEscape(); } }, [handleEscape, handleTableSizeChangeOnKeypress]); const handleKeyUp = useCallback(event => { if (event.altKey || event.metaKey) { areResizeMetaKeysPressed.current = false; } return; }, [areResizeMetaKeysPressed]); useLayoutEffect(() => { if (!resizerRef.current) { return; } const resizeHandleThumbEl = resizerRef.current.getResizerThumbEl(); const globalKeyDownHandler = event => { const browser = expValEquals('platform_editor_hydratable_ui', 'isEnabled', true) ? getBrowserInfo() : browserLegacy; const metaKey = browser.mac ? event.metaKey : event.ctrlKey; if (!isTableSelected) { return; } if (event.altKey && event.shiftKey && metaKey && event.code === 'KeyR') { event.preventDefault(); if (!resizeHandleThumbEl) { return; } resizeHandleThumbEl.focus(); resizeHandleThumbEl.scrollIntoView({ behavior: 'smooth', block: 'center', inline: 'nearest' }); } }; const editorViewDom = editorView === null || editorView === void 0 ? void 0 : editorView.dom; // Ignored via go/ees005 // eslint-disable-next-line @repo/internal/dom-events/no-unsafe-event-listeners editorViewDom === null || editorViewDom === void 0 ? void 0 : editorViewDom.addEventListener('keydown', globalKeyDownHandler); // Ignored via go/ees005 // eslint-disable-next-line @repo/internal/dom-events/no-unsafe-event-listeners resizeHandleThumbEl === null || resizeHandleThumbEl === void 0 ? void 0 : resizeHandleThumbEl.addEventListener('keydown', handleKeyDown); // Ignored via go/ees005 // eslint-disable-next-line @repo/internal/dom-events/no-unsafe-event-listeners resizeHandleThumbEl === null || resizeHandleThumbEl === void 0 ? void 0 : resizeHandleThumbEl.addEventListener('keyup', handleKeyUp); return () => { // Ignored via go/ees005 // eslint-disable-next-line @repo/internal/dom-events/no-unsafe-event-listeners editorViewDom === null || editorViewDom === void 0 ? void 0 : editorViewDom.removeEventListener('keydown', globalKeyDownHandler); // Ignored via go/ees005 // eslint-disable-next-line @repo/internal/dom-events/no-unsafe-event-listeners resizeHandleThumbEl === null || resizeHandleThumbEl === void 0 ? void 0 : resizeHandleThumbEl.removeEventListener('keydown', handleKeyDown); // Ignored via go/ees005 // eslint-disable-next-line @repo/internal/dom-events/no-unsafe-event-listeners resizeHandleThumbEl === null || resizeHandleThumbEl === void 0 ? void 0 : resizeHandleThumbEl.removeEventListener('keyup', handleKeyUp); }; }, [resizerRef, editorView, handleResizeStop, isTableSelected, handleKeyDown, handleKeyUp]); useLayoutEffect(() => { var _updateTooltip$curren; (_updateTooltip$curren = updateTooltip.current) === null || _updateTooltip$curren === void 0 ? void 0 : _updateTooltip$curren.call(updateTooltip); }, [width]); const resizeRatio = !isTableAlignmentEnabled || isTableAlignmentEnabled && normaliseAlignment(node.attrs.layout) === ALIGN_CENTER ? 2 : 1; return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(ResizerNext, { ref: resizerRef, enable: disabled ? {} : handles, width: width, handleAlignmentMethod: "sticky", handleSize: handleSize, handleStyles: handleStyles, handleResizeStart: handleResizeStart, handleResize: scheduleResize, handleResizeStop: handleResizeStop, resizeRatio: resizeRatio, minWidth: resizerMinWidth, maxWidth: maxWidth, snapGap: TABLE_SNAP_GAP, snap: guidelineSnaps, handlePositioning: "adjacent", isHandleVisible: isTableSelected, needExtendedResizeZone: expValEquals('platform_editor_table_resizer_extended_zone', 'isEnabled', true) ? true : !isTableSelected, appearance: isTableSelected && isWholeTableInDanger ? 'danger' : undefined, handleHighlight: "shadow" // eslint-disable-next-line @atlassian/perf-linting/no-unstable-inline-props -- Ignored via go/ees017 (to be fixed) , handleTooltipContent: ({ update }) => { updateTooltip.current = update; return /*#__PURE__*/React.createElement(ToolTipContent, { description: formatMessage(messages.resizeTable), keymap: focusTableResizer }); }, "data-vc-nvs": "true" }, children)); };