Skip to content
Snippets Groups Projects
CreateTable.js 2.31 KiB
Newer Older
chris's avatar
chris committed
/* eslint react/prop-types: 0 */

chris's avatar
chris committed
import React, { useState, useContext, useMemo, useEffect, useRef } from 'react';
chris's avatar
chris committed
import { WaxContext } from 'wax-prosemirror-core';
chris's avatar
chris committed
import styled from 'styled-components';
import { grid } from '@pubsweet/ui-toolkit';
chris's avatar
chris committed
import MenuButton from '../../ui/buttons/MenuButton';
chris's avatar
chris committed
import InsertTableTool from '../../ui/tables/InsertTableTool';

chris's avatar
chris committed
const Wrapper = styled.div`
  font-size: 0;
  position: relative;
  z-index: 2;
`;

const DropWrapper = styled.div`
  margin-top: ${grid(1)};
  position: absolute;
  background: white;
`;

chris's avatar
chris committed
const CreateTable = ({ view = {}, item }) => {
  const {
    view: { main },
    activeViewId,
chris's avatar
chris committed
  } = useContext(WaxContext);
  if (item.onlyOnMain) {
    view = main;
  }

chris's avatar
chris committed
  const { state } = view;
  const { enable, icon, run, select, title } = item;
chris's avatar
chris committed
  const ref = useRef();
chris's avatar
chris committed
  const [isOpen, setIsOpen] = useState(false);

  const dropComponent = (
    <InsertTableTool
chris's avatar
chris committed
      onGridSelect={colRows => handleSelect(colRows, view.state, view.dispatch)}
chris's avatar
chris committed

chris's avatar
chris committed
  const handleSelect = (colRows, editorState, editorDispatch) => {
    run(colRows, editorState, editorDispatch);
    setIsOpen(!isOpen);
  };

  const isDisabled =
    enable && !enable(state) && !(select && select(state, activeViewId));
chris's avatar
chris committed
  useOnClickOutside(ref, () => setIsOpen(false));

chris's avatar
chris committed
  const MemorizedDropdown = useMemo(
    () => (
chris's avatar
chris committed
      <Wrapper ref={ref}>
chris's avatar
chris committed
        <MenuButton
          active={isOpen}
          disabled={isDisabled}
          iconName={icon}
          onMouseDown={() => {
            setIsOpen(!isOpen);
          }}
          title={title}
        />

        {isOpen && <DropWrapper>{dropComponent}</DropWrapper>}
      </Wrapper>
    ),
    [isDisabled, isOpen],
chris's avatar
chris committed
  );
chris's avatar
chris committed

  return MemorizedDropdown;
chris's avatar
chris committed
};

chris's avatar
chris committed
// Hook
const useOnClickOutside = (ref, handler) => {
  useEffect(() => {
    const listener = event => {
      /* Do nothing if clicking ref's element or descendent elements */
      if (!ref.current || ref.current.contains(event.target)) {
        return;
      }

      handler(event);
    };

    document.addEventListener('mousedown', listener);
    document.addEventListener('touchstart', listener);

    return () => {
      document.removeEventListener('mousedown', listener);
      document.removeEventListener('touchstart', listener);
    };
  }, [ref, handler]);
};
chris's avatar
chris committed
export default CreateTable;