/* * This file is part of ORY Editor. * * ORY Editor is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * ORY Editor is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with ORY Editor. If not, see . * * @license LGPL-3.0 * @copyright 2016-2018 Aeneas Rekkas * @author Aeneas Rekkas * */ import throttle from 'lodash.throttle'; import * as React from 'react'; import { computeAndDispatchHover, computeAndDispatchInsert } from '../../../service/hover/input'; import { ComponetizedRow, ComponetizedCell } from '../../../types/editable'; import { delay } from '../../../helper/throttle'; import logger from '../../../service/logger'; import { isNativeHTMLElementDrag, createNativeCellReplacement } from '../../../helper/nativeDragHelpers'; import { DropTargetMonitor, DropTargetConnector } from 'dnd-core'; let last: { hover: string; drag: string } = { hover: '', drag: '', }; const clear = (hover: ComponetizedRow, drag: string) => { if (hover.id === last.hover && drag === last.drag) { return; } last = { hover: hover.id, drag }; hover.clearHover(drag); }; export const target = { hover: throttle( (hover: ComponetizedRow, monitor: DropTargetMonitor, component: React.ReactInstance) => { // tslint:disable-next-line:no-any let drag: any = monitor.getItem(); if (!drag) { // item undefined, happens when throttle triggers after drop return; } if (isNativeHTMLElementDrag(monitor)) { drag = createNativeCellReplacement(); } if (!drag) { return; } else if (drag.id === hover.id) { clear(hover, drag.id); return; } else if (!monitor.isOver({ shallow: true })) { return; } else if (hover.ancestors.indexOf(drag.id) > -1) { // If hovering over a child of itself clear(hover, drag.id); return; } else if (!hover.id) { // If hovering over something that isn't a cell or hasn't an id, do nothing. Should be an edge case logger.warn( 'Canceled cell.drop.target.hover: no id given.', hover, drag ); return; } computeAndDispatchHover( // tslint:disable-next-line:no-any hover as any, drag, monitor, component, '10x10-no-inline' ); }, delay, { leading: false } ), canDrop: ({ id, ancestors }: ComponetizedRow, monitor: DropTargetMonitor) => { const item = monitor.getItem(); return item.id !== id || ancestors.indexOf(item.id) === -1; }, // tslint:disable-next-line:no-any drop(hover: ComponetizedRow, monitor: DropTargetMonitor, component: any) { let drag: ComponetizedCell = monitor.getItem(); if (isNativeHTMLElementDrag(monitor)) { const { plugins } = component.props.config; drag = plugins.createNativePlugin(hover, monitor, component); } if (monitor.didDrop() || !monitor.isOver({ shallow: true })) { // If the item drop occurred deeper down the tree, don't do anything return; } else if (hover.ancestors.indexOf(drag.id) > -1) { // If hovering over a child of itself hover.cancelCellDrag(drag.id); return; } else if (drag.id === hover.id) { hover.cancelCellDrag(drag.id); return; } computeAndDispatchInsert( // tslint:disable-next-line:no-any hover as any, drag, monitor, component, '10x10-no-inline' ); }, }; export const connect = ( _connect: DropTargetConnector, monitor: DropTargetMonitor ) => ({ connectDropTarget: _connect.dropTarget(), isOverCurrent: monitor.isOver({ shallow: true }), });