UNPKG

@atlaskit/editor-plugin-table

Version:

Table plugin for the @atlaskit/editor

100 lines (99 loc) 3.6 kB
import { tableCellBorderWidth, tableMarginTop } from '@atlaskit/editor-common/styles'; import { closestElement, containsClassName, parsePx } from '@atlaskit/editor-common/utils'; import { TableCssClassName as ClassName } from '../../../types'; import { getPluginState as getMainPluginState } from '../../plugin-factory'; import { colWidthsForRow } from '../../utils/column-controls'; import { getRowHeights } from '../../utils/row-controls'; export const updateControls = () => state => { const { tableRef } = getMainPluginState(state); if (!tableRef) { return; } const tr = tableRef.querySelector('tr'); if (!tr) { return; } const wrapper = tableRef.parentElement; if (!(wrapper && wrapper.parentElement)) { return; } const rowControls = wrapper.parentElement.querySelectorAll(`.${ClassName.ROW_CONTROLS_BUTTON_WRAP}`); const numberedRows = wrapper.parentElement.querySelectorAll(ClassName.NUMBERED_COLUMN_BUTTON); syncStickyRowToTable(tableRef); const rowHeights = getRowHeights(tableRef); // update rows controls height on resize for (let i = 0, count = rowControls.length; i < count; i++) { const height = rowHeights[i]; if (height) { rowControls[i].style.height = `${height}px`; if (numberedRows.length) { numberedRows[i].style.height = `${height}px`; } } } }; export const isClickNear = (event, click) => { const dx = click.x - event.clientX, dy = click.y - event.clientY; return dx * dx + dy * dy < 100; }; export const getResizeCellPos = (view, event) => { // Ignored via go/ees005 // eslint-disable-next-line @atlaskit/editor/no-as-casting const target = event.target; if (!containsClassName(target, ClassName.RESIZE_HANDLE_DECORATION)) { return null; } const tableCell = closestElement(target, 'td, th'); if (!tableCell) { return null; } const cellStartPosition = view.posAtDOM(tableCell, 0); return cellStartPosition - 1; }; export const updateStickyMargins = table => { const row = table.querySelector('tr.sticky'); if (!row) { table.style.marginTop = ''; return; } const paddingTop = parsePx(window.getComputedStyle(row).paddingTop || '') || 0; const firstRowHeight = row.getBoundingClientRect().height - paddingTop - tableCellBorderWidth; table.style.marginTop = `${tableMarginTop + firstRowHeight}px`; }; const applyColWidthsToStickyRow = (colGroup, headerRow) => { // sync column widths for the sticky row const newCols = colWidthsForRow(headerRow); if (newCols) { headerRow.style.gridTemplateColumns = newCols; } }; export const syncStickyRowToTable = tableRef => { if (!tableRef) { return; } const headerRow = tableRef.querySelector('tr[data-header-row]'); if (!headerRow) { return; } applyColWidthsToStickyRow(tableRef.querySelector('colgroup'), headerRow); applyTableWidthToStickyRow(tableRef, headerRow); }; const applyTableWidthToStickyRow = (tableRef, headerRow) => { // Ignored via go/ees005 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const tbody = tableRef.querySelector('tbody'); const wrapper = tableRef.parentElement; if (tbody && wrapper) { // when resizing in Chrome, clientWidth will give us 759px // but toggling the sticky class will reset it to 760px. // // both elements in the dom + inspector will // be the same width but at layout will be different.. const newWidth = Math.min(tbody.offsetWidth + 1, wrapper.offsetWidth); headerRow.style.width = `${newWidth}px`; headerRow.scrollLeft = wrapper.scrollLeft; } };