Skip to content
Snippets Groups Projects
TextHighlightingTool.js 3.93 KiB
Newer Older
import React, { useMemo, useState, useRef, useContext } from 'react';
import styled from 'styled-components';
chris's avatar
chris committed
import { grid, override } from '@pubsweet/ui-toolkit';
chris's avatar
chris committed
import {
  WaxContext,
  useOnClickOutside,
  MenuButton,
} from 'wax-prosemirror-core';

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

chris's avatar
chris committed
  button,
chris's avatar
chris committed
  button:hover {
    background: transparent;
  }
chris's avatar
chris committed
  background: white;
  margin-top: ${grid(1)};
  position: absolute;
  top: 32px;
  width: max-content;
chris's avatar
chris committed

  ${override('Wax.HighlightToolWrapper')}
`;
const TextHighlightComponent = styled.div`
chris's avatar
chris committed
  background: white;
  border: 1px solid gray;
  display: flex;
  flex-direction: column;
`;
const Highlighter = styled.div`
chris's avatar
chris committed
  border: 1px solid gray;
  cursor: pointer;
  display: inline-grid;
chris's avatar
chris committed
  margin: 5px;
chris's avatar
chris committed
  min-width: 25px;
`;

const TextHighlightingTool = ({ view: { dispatch, state }, item }) => {
  const { icon, title, select } = item;
  const [isOpen, setIsOpen] = useState(false);
chris's avatar
chris committed

chris's avatar
chris committed
  const highlightDropDownOptions = [
    { name: 'red', value: 'red' },
    { name: 'Light blue', value: '#add8e6' },
    { name: 'yellow', value: 'yellow' },
    { name: 'green', value: '#90EE90' },
    { name: 'gray', value: '#d3d3d3' },
    { name: 'orange', value: 'orange' },
    { name: 'brown', value: 'brown' },
    { name: 'aquamarine', value: 'aquamarine' },
    { name: 'remove highlight', value: 'transparent' },
  ];

chris's avatar
chris committed
  const {
    activeViewId,
    activeView,
    pmViews: { main },
  } = useContext(WaxContext);

  const isEditable = main.props.editable(editable => {
chris's avatar
chris committed
    return editable;
  });

  useOnClickOutside(ref, () => setIsOpen(false));

  const renderList = () => {
    const lists = [];

chris's avatar
chris committed
    Object.keys(highlightDropDownOptions).forEach(key => {
chris's avatar
chris committed
        <Highlighter
chris's avatar
chris committed
          data-style={highlightDropDownOptions[key].value}
          key={uuidv4()}
chris's avatar
chris committed
          onMouseDown={e =>
            handleMouseDown(e, highlightDropDownOptions[key].value)
          }
          style={{ backgroundColor: highlightDropDownOptions[key].value }}
chris's avatar
chris committed
          title={highlightDropDownOptions[key].name}
chris's avatar
chris committed
        />,
chris's avatar
chris committed

chris's avatar
chris committed
  const handleMouseDown = (e, color) => {
chris's avatar
chris committed
    item.run(activeView.state, activeView.dispatch, color);
    if (color !== 'transparent') localStorage.setItem('lastBgColor', color);
chris's avatar
chris committed
  };
chris's avatar
chris committed

chris's avatar
chris committed
  const handleDblClk = () => {
chris's avatar
chris committed
    const color = localStorage.getItem('lastBgColor')
      ? localStorage.getItem('lastBgColor')
      : highlightDropDownOptions[0].value;

chris's avatar
chris committed
    item.run(state, dispatch, color);
chris's avatar
chris committed
  };
chris's avatar
chris committed
  let isDisabled = !select(state, activeViewId, activeView);
  if (!isEditable) isDisabled = true;
chris's avatar
chris committed
      <Wrapper onDoubleClick={handleDblClk} ref={ref}>
chris's avatar
chris committed
        <div
chris's avatar
chris committed
          disabled={isDisabled}
chris's avatar
chris committed
          style={{
            backgroundColor:
chris's avatar
chris committed
              localStorage.getItem('lastBgColor') !== null
chris's avatar
chris committed
                ? localStorage.getItem('lastBgColor')
                : highlightDropDownOptions[0].name,
chris's avatar
chris committed
            opacity: isDisabled ? '0.6' : '1',
chris's avatar
chris committed
          }}
        >
          <MenuButton
            active={isOpen}
            disabled={isDisabled}
            iconName={icon}
            onMouseDown={() => {
              setIsOpen(!isOpen);
            }}
            title={title}
          />
chris's avatar
chris committed
            <TextHighlightComponent
chris's avatar
chris committed
              }}
chris's avatar
chris committed
              item={item}
              key={uuidv4()}
              view={(dispatch, state)}
chris's avatar
chris committed
            >
              {renderList()}
            </TextHighlightComponent>
chris's avatar
chris committed
    [isOpen, isDisabled],
  );

  return MenuButtonComponent;
};

export default TextHighlightingTool;