123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172 |
- import React, { useEffect, useState, useCallback } from 'react';
- import Icon from '../components/Icon';
- import Button from '../components/Button';
- import ExpansionPanel from '../components/ExpansionPanel';
- import HighlightOption from '../components/HighlightOption';
- import useActions from '../actions';
- import useStore from '../store';
- import { getMarkupWithSelection } from '../helpers/markup';
- type Props = {
- title: string;
- isActive: boolean;
- onClick: () => void;
- };
- let timer = 0;
- let textLayer: HTMLElement | null = null;
- const HighlightTools: React.FC<Props> = ({
- title,
- isActive,
- onClick,
- }: Props) => {
- const [currentId, setCurrentId] = useState('');
- const [data, setData] = useState({
- type: 'highlight',
- color: '#FBB705',
- opacity: 35,
- });
- const [{ scale, annotations }, dispatch] = useStore();
- const { addAnnots, updateAnnots } = useActions(dispatch);
- const setDataState = (obj: OptionPropsType): void => {
- setData((prev) => ({
- ...prev,
- ...obj,
- }));
- };
- const handleDown = () => {
- timer = setTimeout(() => {
- setCurrentId('');
- }, 1500);
- };
- const handleMove = () => {
- if (timer) {
- clearTimeout(timer);
- }
- };
- const handleUp = useCallback(
- (e: MouseEvent | TouchEvent): void => {
- const selection = document.getSelection();
- if (!selection?.isCollapsed && !currentId) {
- if (e.target) {
- textLayer = (e.target as HTMLElement).parentNode as HTMLElement;
- if (textLayer.getAttribute('data-id') !== 'text-layer') {
- textLayer = textLayer.querySelector(
- '[data-id="text-layer"]',
- ) as HTMLElement;
- }
- if (textLayer) {
- textLayer.style.zIndex = '10';
- const newMarkup = getMarkupWithSelection({
- ...data,
- scale,
- textLayer,
- });
- if (newMarkup) {
- setCurrentId(newMarkup.id as string);
- addAnnots([newMarkup]);
- }
- }
- }
- }
- if (selection?.isCollapsed) {
- if (textLayer) {
- textLayer.style.zIndex = '0';
- }
- setCurrentId('');
- }
- },
- [data, scale, currentId],
- );
- const handleSelectStart = () => {
- setCurrentId('');
- };
- const handleSelectChange = useCallback(() => {
- const selection = document.getSelection();
- if (!selection?.isCollapsed && currentId) {
- if (textLayer) {
- const newMarkup = getMarkupWithSelection({
- ...data,
- scale,
- textLayer,
- });
- if (newMarkup) {
- const array: AnnotationType[] = [];
- annotations.forEach((ele) => {
- if (ele.id === currentId) {
- // eslint-disable-next-line no-param-reassign
- ele.obj_attr.position = newMarkup.obj_attr.position;
- }
- array.push(ele);
- });
- updateAnnots(array);
- }
- }
- }
- }, [annotations, data, scale, currentId]);
- useEffect(() => {
- if (isActive) {
- document.addEventListener('mousedown', handleDown);
- document.addEventListener('mousemove', handleMove);
- document.addEventListener('mouseup', handleUp);
- document.addEventListener('selectstart', handleSelectStart);
- document.addEventListener('touchstart', handleDown);
- document.addEventListener('touchmove', handleMove);
- document.addEventListener('touchend', handleUp);
- document.addEventListener('selectionchange', handleSelectChange);
- } else if (textLayer) {
- textLayer.style.zIndex = '0';
- }
- return (): void => {
- document.removeEventListener('mousedown', handleDown);
- document.removeEventListener('mousemove', handleMove);
- document.removeEventListener('mouseup', handleUp);
- document.removeEventListener('selectstart', handleSelectStart);
- document.removeEventListener('touchstart', handleDown);
- document.removeEventListener('touchmove', handleMove);
- document.removeEventListener('touchend', handleUp);
- document.removeEventListener('selectionchange', handleSelectChange);
- };
- }, [isActive, handleUp, handleSelectChange]);
- const Label = (
- <Button
- shouldFitContainer
- align="left"
- onClick={onClick}
- isActive={isActive}
- >
- <Icon glyph="highlight" style={{ marginRight: '10px' }} />
- {title}
- </Button>
- );
- return (
- <ExpansionPanel label={Label} isActive={isActive} showBottomBorder>
- <HighlightOption {...data} setDataState={setDataState} />
- </ExpansionPanel>
- );
- };
- export default HighlightTools;
|