You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					368 lines
				
				10 KiB
			
		
		
			
		
	
	
					368 lines
				
				10 KiB
			| 
								 
											3 years ago
										 
									 | 
							
								import { EditorState, Plugin, PluginKey } from 'prosemirror-state';
							 | 
						||
| 
								 | 
							
								import {
							 | 
						||
| 
								 | 
							
								  Decoration,
							 | 
						||
| 
								 | 
							
								  DecorationSet,
							 | 
						||
| 
								 | 
							
								  EditorView,
							 | 
						||
| 
								 | 
							
								  NodeView,
							 | 
						||
| 
								 | 
							
								} from 'prosemirror-view';
							 | 
						||
| 
								 | 
							
								import { cellAround, pointsAtCell, _setAttr } from './util';
							 | 
						||
| 
								 | 
							
								import { TableMap } from './tablemap';
							 | 
						||
| 
								 | 
							
								import { TableView, updateColumnsOnResize } from './tableview';
							 | 
						||
| 
								 | 
							
								import { tableNodeTypes } from './schema';
							 | 
						||
| 
								 | 
							
								import { Attrs, Node as ProsemirrorNode } from 'prosemirror-model';
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * @public
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								export const columnResizingPluginKey = new PluginKey<ResizeState>(
							 | 
						||
| 
								 | 
							
								  'tableColumnResizing',
							 | 
						||
| 
								 | 
							
								);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * @public
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								export type ColumnResizingOptions = {
							 | 
						||
| 
								 | 
							
								  handleWidth?: number;
							 | 
						||
| 
								 | 
							
								  cellMinWidth?: number;
							 | 
						||
| 
								 | 
							
								  lastColumnResizable?: boolean;
							 | 
						||
| 
								 | 
							
								  View?: new (
							 | 
						||
| 
								 | 
							
								    node: ProsemirrorNode,
							 | 
						||
| 
								 | 
							
								    cellMinWidth: number,
							 | 
						||
| 
								 | 
							
								    view: EditorView,
							 | 
						||
| 
								 | 
							
								  ) => NodeView;
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * @public
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								export type Dragging = { startX: number; startWidth: number };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * @public
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								export function columnResizing({
							 | 
						||
| 
								 | 
							
								  handleWidth = 5,
							 | 
						||
| 
								 | 
							
								  cellMinWidth = 25,
							 | 
						||
| 
								 | 
							
								  View = TableView,
							 | 
						||
| 
								 | 
							
								  lastColumnResizable = true,
							 | 
						||
| 
								 | 
							
								}: ColumnResizingOptions = {}): Plugin {
							 | 
						||
| 
								 | 
							
								  const plugin = new Plugin({
							 | 
						||
| 
								 | 
							
								    key: columnResizingPluginKey,
							 | 
						||
| 
								 | 
							
								    state: {
							 | 
						||
| 
								 | 
							
								      init(_, state) {
							 | 
						||
| 
								 | 
							
								        this.spec.props.nodeViews[tableNodeTypes(state.schema).table.name] = (
							 | 
						||
| 
								 | 
							
								          node,
							 | 
						||
| 
								 | 
							
								          view,
							 | 
						||
| 
								 | 
							
								        ) => new View(node, cellMinWidth, view);
							 | 
						||
| 
								 | 
							
								        return new ResizeState(-1, false);
							 | 
						||
| 
								 | 
							
								      },
							 | 
						||
| 
								 | 
							
								      apply(tr, prev) {
							 | 
						||
| 
								 | 
							
								        return prev.apply(tr);
							 | 
						||
| 
								 | 
							
								      },
							 | 
						||
| 
								 | 
							
								    },
							 | 
						||
| 
								 | 
							
								    props: {
							 | 
						||
| 
								 | 
							
								      attributes(state) {
							 | 
						||
| 
								 | 
							
								        const pluginState = columnResizingPluginKey.getState(state);
							 | 
						||
| 
								 | 
							
								        return pluginState.activeHandle > -1
							 | 
						||
| 
								 | 
							
								          ? { class: 'resize-cursor' }
							 | 
						||
| 
								 | 
							
								          : null;
							 | 
						||
| 
								 | 
							
								      },
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      handleDOMEvents: {
							 | 
						||
| 
								 | 
							
								        mousemove(view, event) {
							 | 
						||
| 
								 | 
							
								          handleMouseMove(
							 | 
						||
| 
								 | 
							
								            view,
							 | 
						||
| 
								 | 
							
								            event,
							 | 
						||
| 
								 | 
							
								            handleWidth,
							 | 
						||
| 
								 | 
							
								            cellMinWidth,
							 | 
						||
| 
								 | 
							
								            lastColumnResizable,
							 | 
						||
| 
								 | 
							
								          );
							 | 
						||
| 
								 | 
							
								        },
							 | 
						||
| 
								 | 
							
								        mouseleave(view) {
							 | 
						||
| 
								 | 
							
								          handleMouseLeave(view);
							 | 
						||
| 
								 | 
							
								        },
							 | 
						||
| 
								 | 
							
								        mousedown(view, event) {
							 | 
						||
| 
								 | 
							
								          handleMouseDown(view, event, cellMinWidth);
							 | 
						||
| 
								 | 
							
								        },
							 | 
						||
| 
								 | 
							
								      },
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      decorations(state) {
							 | 
						||
| 
								 | 
							
								        const pluginState = columnResizingPluginKey.getState(state);
							 | 
						||
| 
								 | 
							
								        if (pluginState.activeHandle > -1)
							 | 
						||
| 
								 | 
							
								          return handleDecorations(state, pluginState.activeHandle);
							 | 
						||
| 
								 | 
							
								      },
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      nodeViews: {},
							 | 
						||
| 
								 | 
							
								    },
							 | 
						||
| 
								 | 
							
								  });
							 | 
						||
| 
								 | 
							
								  return plugin;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * @public
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								export class ResizeState {
							 | 
						||
| 
								 | 
							
								  constructor(public activeHandle: number, public dragging: Dragging | false) {}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  apply(tr) {
							 | 
						||
| 
								 | 
							
								    // eslint-disable-next-line @typescript-eslint/no-this-alias
							 | 
						||
| 
								 | 
							
								    let state = this;
							 | 
						||
| 
								 | 
							
								    const action = tr.getMeta(columnResizingPluginKey);
							 | 
						||
| 
								 | 
							
								    if (action && action.setHandle != null)
							 | 
						||
| 
								 | 
							
								      return new ResizeState(action.setHandle, null);
							 | 
						||
| 
								 | 
							
								    if (action && action.setDragging !== undefined)
							 | 
						||
| 
								 | 
							
								      return new ResizeState(state.activeHandle, action.setDragging);
							 | 
						||
| 
								 | 
							
								    if (state.activeHandle > -1 && tr.docChanged) {
							 | 
						||
| 
								 | 
							
								      let handle = tr.mapping.map(state.activeHandle, -1);
							 | 
						||
| 
								 | 
							
								      if (!pointsAtCell(tr.doc.resolve(handle))) handle = null;
							 | 
						||
| 
								 | 
							
								      state = new ResizeState(handle, state.dragging) as any;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    return state;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function handleMouseMove(
							 | 
						||
| 
								 | 
							
								  view: EditorView,
							 | 
						||
| 
								 | 
							
								  event: MouseEvent,
							 | 
						||
| 
								 | 
							
								  handleWidth: number,
							 | 
						||
| 
								 | 
							
								  cellMinWidth: number,
							 | 
						||
| 
								 | 
							
								  lastColumnResizable: boolean,
							 | 
						||
| 
								 | 
							
								): void {
							 | 
						||
| 
								 | 
							
								  const pluginState = columnResizingPluginKey.getState(view.state);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (!pluginState.dragging) {
							 | 
						||
| 
								 | 
							
								    const target = domCellAround(event.target as HTMLElement);
							 | 
						||
| 
								 | 
							
								    let cell = -1;
							 | 
						||
| 
								 | 
							
								    if (target) {
							 | 
						||
| 
								 | 
							
								      const { left, right } = target.getBoundingClientRect();
							 | 
						||
| 
								 | 
							
								      if (event.clientX - left <= handleWidth)
							 | 
						||
| 
								 | 
							
								        cell = edgeCell(view, event, 'left');
							 | 
						||
| 
								 | 
							
								      else if (right - event.clientX <= handleWidth)
							 | 
						||
| 
								 | 
							
								        cell = edgeCell(view, event, 'right');
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (cell != pluginState.activeHandle) {
							 | 
						||
| 
								 | 
							
								      if (!lastColumnResizable && cell !== -1) {
							 | 
						||
| 
								 | 
							
								        const $cell = view.state.doc.resolve(cell);
							 | 
						||
| 
								 | 
							
								        const table = $cell.node(-1),
							 | 
						||
| 
								 | 
							
								          map = TableMap.get(table),
							 | 
						||
| 
								 | 
							
								          start = $cell.start(-1);
							 | 
						||
| 
								 | 
							
								        const col =
							 | 
						||
| 
								 | 
							
								          map.colCount($cell.pos - start) + $cell.nodeAfter.attrs.colspan - 1;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if (col == map.width - 1) {
							 | 
						||
| 
								 | 
							
								          return;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      updateHandle(view, cell);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function handleMouseLeave(view: EditorView): void {
							 | 
						||
| 
								 | 
							
								  const pluginState = columnResizingPluginKey.getState(view.state);
							 | 
						||
| 
								 | 
							
								  if (pluginState.activeHandle > -1 && !pluginState.dragging)
							 | 
						||
| 
								 | 
							
								    updateHandle(view, -1);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function handleMouseDown(
							 | 
						||
| 
								 | 
							
								  view: EditorView,
							 | 
						||
| 
								 | 
							
								  event: MouseEvent,
							 | 
						||
| 
								 | 
							
								  cellMinWidth: number,
							 | 
						||
| 
								 | 
							
								): boolean {
							 | 
						||
| 
								 | 
							
								  const pluginState = columnResizingPluginKey.getState(view.state);
							 | 
						||
| 
								 | 
							
								  if (pluginState.activeHandle == -1 || pluginState.dragging) return false;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  const cell = view.state.doc.nodeAt(pluginState.activeHandle);
							 | 
						||
| 
								 | 
							
								  const width = currentColWidth(view, pluginState.activeHandle, cell.attrs);
							 | 
						||
| 
								 | 
							
								  view.dispatch(
							 | 
						||
| 
								 | 
							
								    view.state.tr.setMeta(columnResizingPluginKey, {
							 | 
						||
| 
								 | 
							
								      setDragging: { startX: event.clientX, startWidth: width },
							 | 
						||
| 
								 | 
							
								    }),
							 | 
						||
| 
								 | 
							
								  );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  function finish(event: MouseEvent) {
							 | 
						||
| 
								 | 
							
								    window.removeEventListener('mouseup', finish);
							 | 
						||
| 
								 | 
							
								    window.removeEventListener('mousemove', move);
							 | 
						||
| 
								 | 
							
								    const pluginState = columnResizingPluginKey.getState(view.state);
							 | 
						||
| 
								 | 
							
								    if (pluginState.dragging) {
							 | 
						||
| 
								 | 
							
								      updateColumnWidth(
							 | 
						||
| 
								 | 
							
								        view,
							 | 
						||
| 
								 | 
							
								        pluginState.activeHandle,
							 | 
						||
| 
								 | 
							
								        draggedWidth(pluginState.dragging, event, cellMinWidth),
							 | 
						||
| 
								 | 
							
								      );
							 | 
						||
| 
								 | 
							
								      view.dispatch(
							 | 
						||
| 
								 | 
							
								        view.state.tr.setMeta(columnResizingPluginKey, { setDragging: null }),
							 | 
						||
| 
								 | 
							
								      );
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  function move(event: MouseEvent): void {
							 | 
						||
| 
								 | 
							
								    if (!event.which) return finish(event);
							 | 
						||
| 
								 | 
							
								    const pluginState = columnResizingPluginKey.getState(view.state);
							 | 
						||
| 
								 | 
							
								    if (pluginState.dragging) {
							 | 
						||
| 
								 | 
							
								      const dragged = draggedWidth(pluginState.dragging, event, cellMinWidth);
							 | 
						||
| 
								 | 
							
								      displayColumnWidth(view, pluginState.activeHandle, dragged, cellMinWidth);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  window.addEventListener('mouseup', finish);
							 | 
						||
| 
								 | 
							
								  window.addEventListener('mousemove', move);
							 | 
						||
| 
								 | 
							
								  event.preventDefault();
							 | 
						||
| 
								 | 
							
								  return true;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function currentColWidth(
							 | 
						||
| 
								 | 
							
								  view: EditorView,
							 | 
						||
| 
								 | 
							
								  cellPos: number,
							 | 
						||
| 
								 | 
							
								  { colspan, colwidth }: Attrs,
							 | 
						||
| 
								 | 
							
								): number {
							 | 
						||
| 
								 | 
							
								  const width = colwidth && colwidth[colwidth.length - 1];
							 | 
						||
| 
								 | 
							
								  if (width) return width;
							 | 
						||
| 
								 | 
							
								  const dom = view.domAtPos(cellPos);
							 | 
						||
| 
								 | 
							
								  const node = dom.node.childNodes[dom.offset] as HTMLElement;
							 | 
						||
| 
								 | 
							
								  let domWidth = node.offsetWidth,
							 | 
						||
| 
								 | 
							
								    parts = colspan;
							 | 
						||
| 
								 | 
							
								  if (colwidth)
							 | 
						||
| 
								 | 
							
								    for (let i = 0; i < colspan; i++)
							 | 
						||
| 
								 | 
							
								      if (colwidth[i]) {
							 | 
						||
| 
								 | 
							
								        domWidth -= colwidth[i];
							 | 
						||
| 
								 | 
							
								        parts--;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								  return domWidth / parts;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function domCellAround(target: HTMLElement): HTMLElement | null {
							 | 
						||
| 
								 | 
							
								  while (target && target.nodeName != 'TD' && target.nodeName != 'TH')
							 | 
						||
| 
								 | 
							
								    target =
							 | 
						||
| 
								 | 
							
								      target.classList && target.classList.contains('ProseMirror')
							 | 
						||
| 
								 | 
							
								        ? null
							 | 
						||
| 
								 | 
							
								        : (target.parentNode as HTMLElement);
							 | 
						||
| 
								 | 
							
								  return target;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function edgeCell(
							 | 
						||
| 
								 | 
							
								  view: EditorView,
							 | 
						||
| 
								 | 
							
								  event: MouseEvent,
							 | 
						||
| 
								 | 
							
								  side: 'left' | 'right',
							 | 
						||
| 
								 | 
							
								): number {
							 | 
						||
| 
								 | 
							
								  const found = view.posAtCoords({ left: event.clientX, top: event.clientY });
							 | 
						||
| 
								 | 
							
								  if (!found) return -1;
							 | 
						||
| 
								 | 
							
								  const { pos } = found;
							 | 
						||
| 
								 | 
							
								  const $cell = cellAround(view.state.doc.resolve(pos));
							 | 
						||
| 
								 | 
							
								  if (!$cell) return -1;
							 | 
						||
| 
								 | 
							
								  if (side == 'right') return $cell.pos;
							 | 
						||
| 
								 | 
							
								  const map = TableMap.get($cell.node(-1)),
							 | 
						||
| 
								 | 
							
								    start = $cell.start(-1);
							 | 
						||
| 
								 | 
							
								  const index = map.map.indexOf($cell.pos - start);
							 | 
						||
| 
								 | 
							
								  return index % map.width == 0 ? -1 : start + map.map[index - 1];
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function draggedWidth(
							 | 
						||
| 
								 | 
							
								  dragging: Dragging,
							 | 
						||
| 
								 | 
							
								  event: MouseEvent,
							 | 
						||
| 
								 | 
							
								  cellMinWidth: number,
							 | 
						||
| 
								 | 
							
								): number {
							 | 
						||
| 
								 | 
							
								  const offset = event.clientX - dragging.startX;
							 | 
						||
| 
								 | 
							
								  return Math.max(cellMinWidth, dragging.startWidth + offset);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function updateHandle(view: EditorView, value: number): void {
							 | 
						||
| 
								 | 
							
								  view.dispatch(
							 | 
						||
| 
								 | 
							
								    view.state.tr.setMeta(columnResizingPluginKey, { setHandle: value }),
							 | 
						||
| 
								 | 
							
								  );
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function updateColumnWidth(
							 | 
						||
| 
								 | 
							
								  view: EditorView,
							 | 
						||
| 
								 | 
							
								  cell: number,
							 | 
						||
| 
								 | 
							
								  width: number,
							 | 
						||
| 
								 | 
							
								): void {
							 | 
						||
| 
								 | 
							
								  const $cell = view.state.doc.resolve(cell);
							 | 
						||
| 
								 | 
							
								  const table = $cell.node(-1),
							 | 
						||
| 
								 | 
							
								    map = TableMap.get(table),
							 | 
						||
| 
								 | 
							
								    start = $cell.start(-1);
							 | 
						||
| 
								 | 
							
								  const col =
							 | 
						||
| 
								 | 
							
								    map.colCount($cell.pos - start) + $cell.nodeAfter.attrs.colspan - 1;
							 | 
						||
| 
								 | 
							
								  const tr = view.state.tr;
							 | 
						||
| 
								 | 
							
								  for (let row = 0; row < map.height; row++) {
							 | 
						||
| 
								 | 
							
								    const mapIndex = row * map.width + col;
							 | 
						||
| 
								 | 
							
								    // Rowspanning cell that has already been handled
							 | 
						||
| 
								 | 
							
								    if (row && map.map[mapIndex] == map.map[mapIndex - map.width]) continue;
							 | 
						||
| 
								 | 
							
								    const pos = map.map[mapIndex],
							 | 
						||
| 
								 | 
							
								      { attrs } = table.nodeAt(pos);
							 | 
						||
| 
								 | 
							
								    const index = attrs.colspan == 1 ? 0 : col - map.colCount(pos);
							 | 
						||
| 
								 | 
							
								    if (attrs.colwidth && attrs.colwidth[index] == width) continue;
							 | 
						||
| 
								 | 
							
								    const colwidth = attrs.colwidth
							 | 
						||
| 
								 | 
							
								      ? attrs.colwidth.slice()
							 | 
						||
| 
								 | 
							
								      : zeroes(attrs.colspan);
							 | 
						||
| 
								 | 
							
								    colwidth[index] = width;
							 | 
						||
| 
								 | 
							
								    tr.setNodeMarkup(start + pos, null, _setAttr(attrs, 'colwidth', colwidth));
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  if (tr.docChanged) view.dispatch(tr);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function displayColumnWidth(
							 | 
						||
| 
								 | 
							
								  view: EditorView,
							 | 
						||
| 
								 | 
							
								  cell: number,
							 | 
						||
| 
								 | 
							
								  width: number,
							 | 
						||
| 
								 | 
							
								  cellMinWidth: number,
							 | 
						||
| 
								 | 
							
								): void {
							 | 
						||
| 
								 | 
							
								  const $cell = view.state.doc.resolve(cell);
							 | 
						||
| 
								 | 
							
								  const table = $cell.node(-1),
							 | 
						||
| 
								 | 
							
								    start = $cell.start(-1);
							 | 
						||
| 
								 | 
							
								  const col =
							 | 
						||
| 
								 | 
							
								    TableMap.get(table).colCount($cell.pos - start) +
							 | 
						||
| 
								 | 
							
								    $cell.nodeAfter.attrs.colspan -
							 | 
						||
| 
								 | 
							
								    1;
							 | 
						||
| 
								 | 
							
								  let dom = view.domAtPos($cell.start(-1)).node;
							 | 
						||
| 
								 | 
							
								  while (dom.nodeName != 'TABLE') dom = dom.parentNode;
							 | 
						||
| 
								 | 
							
								  updateColumnsOnResize(
							 | 
						||
| 
								 | 
							
								    table,
							 | 
						||
| 
								 | 
							
								    dom.firstChild as HTMLTableColElement,
							 | 
						||
| 
								 | 
							
								    dom as HTMLTableElement,
							 | 
						||
| 
								 | 
							
								    cellMinWidth,
							 | 
						||
| 
								 | 
							
								    col,
							 | 
						||
| 
								 | 
							
								    width,
							 | 
						||
| 
								 | 
							
								  );
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function zeroes(n: number): 0[] {
							 | 
						||
| 
								 | 
							
								  const result = [];
							 | 
						||
| 
								 | 
							
								  for (let i = 0; i < n; i++) result.push(0);
							 | 
						||
| 
								 | 
							
								  return result;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								export function handleDecorations(
							 | 
						||
| 
								 | 
							
								  state: EditorState,
							 | 
						||
| 
								 | 
							
								  cell: number,
							 | 
						||
| 
								 | 
							
								): DecorationSet {
							 | 
						||
| 
								 | 
							
								  const decorations = [];
							 | 
						||
| 
								 | 
							
								  const $cell = state.doc.resolve(cell);
							 | 
						||
| 
								 | 
							
								  const table = $cell.node(-1);
							 | 
						||
| 
								 | 
							
								  if (!table) {
							 | 
						||
| 
								 | 
							
								    return DecorationSet.empty;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  const map = TableMap.get(table);
							 | 
						||
| 
								 | 
							
								  const start = $cell.start(-1);
							 | 
						||
| 
								 | 
							
								  const col = map.colCount($cell.pos - start) + $cell.nodeAfter.attrs.colspan;
							 | 
						||
| 
								 | 
							
								  for (let row = 0; row < map.height; row++) {
							 | 
						||
| 
								 | 
							
								    const index = col + row * map.width - 1;
							 | 
						||
| 
								 | 
							
								    // For positions that are have either a different cell or the end
							 | 
						||
| 
								 | 
							
								    // of the table to their right, and either the top of the table or
							 | 
						||
| 
								 | 
							
								    // a different cell above them, add a decoration
							 | 
						||
| 
								 | 
							
								    if (
							 | 
						||
| 
								 | 
							
								      (col == map.width || map.map[index] != map.map[index + 1]) &&
							 | 
						||
| 
								 | 
							
								      (row == 0 || map.map[index - 1] != map.map[index - 1 - map.width])
							 | 
						||
| 
								 | 
							
								    ) {
							 | 
						||
| 
								 | 
							
								      const cellPos = map.map[index];
							 | 
						||
| 
								 | 
							
								      const pos = start + cellPos + table.nodeAt(cellPos).nodeSize - 1;
							 | 
						||
| 
								 | 
							
								      const dom = document.createElement('div');
							 | 
						||
| 
								 | 
							
								      dom.className = 'column-resize-handle';
							 | 
						||
| 
								 | 
							
								      decorations.push(Decoration.widget(pos, dom));
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  return DecorationSet.create(state.doc, decorations);
							 | 
						||
| 
								 | 
							
								}
							 |