UNPKG

azure-devops-ui

Version:

React components for building web UI in Azure DevOps

202 lines (201 loc) 9.92 kB
import "../../CommonImports"; import "../../Core/core.css"; import "./Table.css"; import * as React from "react"; import { ListDropIndicatorPosition } from '../../Components/List/ListDropIndicator.Props'; import { cellFromEvent } from '../../List'; import { getPointByEventType } from '../../Util'; import { beginDragOperation, DragDropEffect, DragImage } from '../../Utilities/DragDrop'; import { ListDropIndicator } from "../List/ListDropIndicator"; import { ColumnFillId } from "./Table"; /** * A behavior for dragging & dropping columns */ export class ColumnDragDropBehavior { constructor(options) { this.initialize = (props, dragDroppableUI, eventDispatch) => { this.dragDroppableUI = dragDroppableUI; this.eventDispatch = eventDispatch; this.eventDispatch.addEventListener("pointerdown", this.onPointerDown); this.eventDispatch.addEventListener("dragstart", this.onDragStart); this.eventDispatch.addEventListener("dragend", this.onDragEnd); this.eventDispatch.addEventListener("dragenter", this.onDragEnter); this.eventDispatch.addEventListener("dragexit", this.onDragExit); this.eventDispatch.addEventListener("dragover", this.onDragOver); this.eventDispatch.addEventListener("drop", this.onDrop); this.indicatorName = "drop-indicator"; }; this.onDragEnd = (event) => { const index = eventIsOnHeader(event); if (index && index >= 0 && this.options.onDragEnd) { this.options.onDragEnd(event); } this.dragDroppableUI.removeOverlay("drag-source-item"); this.dragImageData = undefined; }; this.onDragStart = (event) => { if (event.detail.dataTransfer && !event.defaultPrevented) { const index = eventIsOnHeader(event); if (index !== null && index >= 0) { if (this.options.onDragStart) { this.options.onDragStart(event); } if (event.detail.dataTransfer.effectAllowed !== DragDropEffect.none) { this.dragDroppableUI.addOverlay("drag-source-item", -1, this.renderDragSourceItemOverlay, /** z-index */ 0, /** columnIndex */ index); if (this.dragImageData === undefined) { this.dragImageData = { image: this.options.renderDragImage(event) }; } } } } }; this.onPointerDown = (event) => { if (event.button === 0) { this.beginDrag(event); } }; this.renderDragSourceItemOverlay = (props) => { return (React.createElement(React.Fragment, null, React.createElement("div", { className: "bolt-list-drag-source-item flex-grow" }), this.operation && this.dragImageData && React.createElement(DragImage, { operation: this.operation }, this.dragImageData.image))); }; this.setDragImage = (image, xOffset, yOffset) => { this.dragImageData = { image: image, xOffset: xOffset, yOffset: yOffset }; }; this.onDragEnter = (event) => { if (!this.handlesType(event)) { return; } if (this.options.onDragEnter) { this.options.onDragEnter(event); } else { event.detail.dataTransfer.dropEffect = DragDropEffect.move; } }; this.onDragExit = (event) => { if (!this.handlesType(event)) { return; } if (this.options.onDragExit) { this.options.onDragExit(event); } this.dragDroppableUI.removeOverlay(this.indicatorName); }; this.onDragOver = (event) => { if (!this.handlesType(event)) { return; } const index = this.calculateIndex(event); const dragIndex = event.detail.dataTransfer.secondaryData.index; const listId = event.detail.dataTransfer.secondaryData.sourceId; if (index >= 0 && (index !== dragIndex || listId !== this.options.id) && this.options.columns[index].id !== ColumnFillId) { if (this.options.onDragOver) { this.options.onDragOver(event, { index: this.listIndicatorPosition === ListDropIndicatorPosition.right ? index + 1 : index }); } else { event.detail.dataTransfer.dropEffect = DragDropEffect.move; } } else { event.detail.dataTransfer.dropEffect = DragDropEffect.none; } if (event.detail.dataTransfer.dropEffect === DragDropEffect.none) { this.dragDroppableUI.removeOverlay(this.indicatorName); } else { this.dragDroppableUI.addOverlay(this.indicatorName, -1, this.renderDropIndicator, /** z-index */ 0, /** columnIndex */ index); } }; this.onDrop = (event) => { if (!this.handlesType(event)) { return; } const index = this.calculateIndex(event); const dragIndex = event.detail.dataTransfer.secondaryData.index; const listId = event.detail.dataTransfer.secondaryData.sourceId; if (index >= 0 && (index !== dragIndex || listId !== this.options.id) && this.options.onDrop) { event.persist(); this.options.onDrop(event, { index: this.listIndicatorPosition === ListDropIndicatorPosition.right ? index + 1 : index }); } this.dragDroppableUI.removeOverlay(this.indicatorName); }; this.renderDropIndicator = (props) => { const xOffset = this.listIndicatorPosition === ListDropIndicatorPosition.right ? props.rowElement.offsetWidth : 0; return React.createElement(ListDropIndicator, { position: this.listIndicatorPosition, xOffset: xOffset - 3, lineOffset: xOffset }); }; this.options = options; this.contextMenuIndex = options.columns.findIndex(col => col.id === "_more"); } componentWillUnmount() { var _a, _b, _c, _d, _e, _f, _g; (_a = this.eventDispatch) === null || _a === void 0 ? void 0 : _a.removeEventListener("pointerdown", this.onPointerDown); (_b = this.eventDispatch) === null || _b === void 0 ? void 0 : _b.removeEventListener("dragstart", this.onDragStart); (_c = this.eventDispatch) === null || _c === void 0 ? void 0 : _c.removeEventListener("dragend", this.onDragEnd); (_d = this.eventDispatch) === null || _d === void 0 ? void 0 : _d.removeEventListener("dragenter", this.onDragEnter); (_e = this.eventDispatch) === null || _e === void 0 ? void 0 : _e.removeEventListener("dragexit", this.onDragExit); (_f = this.eventDispatch) === null || _f === void 0 ? void 0 : _f.removeEventListener("dragover", this.onDragOver); (_g = this.eventDispatch) === null || _g === void 0 ? void 0 : _g.removeEventListener("drop", this.onDrop); } updateBehaviorOptions(options) { this.options = options; } beginDrag(event) { var _a; const index = eventIsOnHeader(event); if (index !== null && ((_a = this.options) === null || _a === void 0 ? void 0 : _a.columns) && index >= 0) { const item = this.options.columns[index]; this.operation = beginDragOperation(event, { data: item, dropEffect: DragDropEffect.none, secondaryData: { index: index, sourceId: this.options.id }, setDragImage: this.setDragImage, type: this.options.type }); } } handlesType(event) { var _a; const type = ((_a = event.detail.dataTransfer) === null || _a === void 0 ? void 0 : _a.type) || ""; return this.options.allowedTypes.indexOf(type) !== -1; } calculateIndex(event) { const cell = cellFromEvent(event); let index = cell.cellIndex; if (cell.cellElement && event.detail.dataTransfer.secondaryData) { const dragIndex = event.detail.dataTransfer.secondaryData.index; const nativeEvent = event.detail.nativeEvent; const columnRect = cell.cellElement.getBoundingClientRect(); const point = getPointByEventType(nativeEvent); const leftOfColumn = point ? point.x < columnRect.width / 2 + columnRect.left : index < dragIndex; if (index < dragIndex) { this.listIndicatorPosition = ListDropIndicatorPosition.left; if (!leftOfColumn) { index++; } if (index === this.contextMenuIndex) { index--; } } else if (index > dragIndex) { this.listIndicatorPosition = ListDropIndicatorPosition.right; if (leftOfColumn) { index--; } if (index + 1 < this.options.columns.length && index + 1 == this.contextMenuIndex) { index++; } } // No-op if index === dragIndex } return index; } } function eventIsOnHeader(event) { const cell = cellFromEvent(event); return cell.rowIndex === -1 ? cell.cellIndex : null; }