UNPKG

reactronic-dom

Version:

Reactronic DOM - Transactional Reactive Front-End Development Framework

387 lines (386 loc) 14.8 kB
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var __metadata = (this && this.__metadata) || function (k, v) { if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); }; import { options, reaction, transaction, isnonreactive, Transaction, LoggingLevel } from 'reactronic'; import { findTargetElementData, SymDataForSensor } from './DataForSensor'; import { HtmlElementSensor } from './HtmlElementSensor'; import { extractModifierKeys, KeyboardModifiers } from './KeyboardSensor'; export class HtmlDragSensor extends HtmlElementSensor { constructor(focusSensor, windowSensor) { super(focusSensor, windowSensor); this.draggable = undefined; this.dragSource = undefined; this.dragTarget = undefined; this.dragTargetWindow = undefined; this.previousDragTarget = undefined; this.dragStarted = false; this.dragFinished = false; this.startX = Infinity; this.startY = Infinity; this.dataByFormat = new Map(); this.draggingImage = undefined; this.draggingImageX = Infinity; this.draggingImageY = Infinity; this.dropEffect = 'none'; this.dataTypesAllowed = []; this.effectAllowed = 'uninitialized'; this.dropAllowed = false; this.draggingOver = false; this.draggingDataTypes = []; this.positionX = Infinity; this.positionY = Infinity; this.modifiers = KeyboardModifiers.None; this.dropX = Infinity; this.dropY = Infinity; this.dropped = false; this.immediatePositionX = Infinity; this.immediatePositionY = Infinity; this.immediateModifiers = KeyboardModifiers.None; } getData(format) { return this.dataByFormat.get(format); } setData(format, value) { this.dataByFormat.set(format, value); } clearData(format) { if (format) this.dataByFormat.delete(format); else this.dataByFormat.clear(); } setDragImage(value, x, y) { this.draggingImage = value; this.draggingImageX = x; this.draggingImageY = y; } listen(element, enabled = true) { const existing = this.sourceElement; if (element !== existing) { if (existing) { existing.removeEventListener('dragstart', this.onDragStart.bind(this), { capture: true }); existing.removeEventListener('drag', this.onDrag.bind(this), { capture: true }); existing.removeEventListener('dragenter', this.onDragEnter.bind(this), { capture: false }); existing.removeEventListener('dragleave', this.onDragLeave.bind(this), { capture: false }); existing.removeEventListener('dragover', this.onDragOver.bind(this), { capture: true }); existing.removeEventListener('drop', this.onDrop.bind(this), { capture: true }); existing.removeEventListener('dragend', this.onDragEnd.bind(this), { capture: true }); } this.sourceElement = element; if (element && enabled) { element.addEventListener('dragstart', this.onDragStart.bind(this), { capture: true }); element.addEventListener('drag', this.onDrag.bind(this), { capture: true }); element.addEventListener('dragenter', this.onDragEnter.bind(this), { capture: false }); element.addEventListener('dragleave', this.onDragLeave.bind(this), { capture: false }); element.addEventListener('dragover', this.onDragOver.bind(this), { capture: true }); element.addEventListener('drop', this.onDrop.bind(this), { capture: true }); element.addEventListener('dragend', this.onDragEnd.bind(this), { capture: true }); } } } onDragStart(e) { this.startDragging(e); this.updateEventOnDragStart(e); } onDrag(e) { this.dragging(e); } onDragEnter(e) { this.enterTarget(e); this.updateEventOnDropAllowed(e); } onDragLeave(e) { this.leaveTarget(e); } onDragOver(e) { this.dragOver(e); this.updateEventOnDropAllowed(e); } onDrop(e) { this.drop(e); } onDragEnd(e) { this.finishDragging(e); this.reset(); } startDragging(e) { var _a; this.preventDefault = false; this.stopPropagation = false; const targetPath = e.composedPath(); const underPointer = document.elementsFromPoint(e.clientX, e.clientY); const { data, window } = findTargetElementData(targetPath, underPointer, SymDataForSensor, ['htmlDraggable']); this.draggable = data === null || data === void 0 ? void 0 : data.htmlDraggable; this.dragSource = (_a = findTargetElementData(targetPath, underPointer, SymDataForSensor, ['htmlDrag'], true).data) === null || _a === void 0 ? void 0 : _a.htmlDrag; this.dragStarted = true; this.dragFinished = false; this.startX = e.clientX; this.startY = e.clientY; this.modifiers = extractModifierKeys(e); this.positionX = e.clientX; this.positionY = e.clientY; this.dropped = false; this.dragTarget = undefined; this.dragTargetWindow = undefined; this.previousDragTarget = undefined; this.revision++; Transaction.standalone(() => { var _a; (_a = this.windowSensor) === null || _a === void 0 ? void 0 : _a.setActiveWindow(window, 'htmlDrag'); }); } dragging(e) { this.dragStarted = true; this.dragFinished = false; this.revision++; } finishDragging(e) { this.dragFinished = true; this.revision++; } enterTarget(e) { this.updateDragTarget(e); this.dropped = false; this.revision++; } leaveTarget(e) { } dragOver(e) { this.updateDragTarget(e); this.dropped = false; this.revision++; } drop(e) { this.updateDragTarget(e); this.modifiers = this.immediateModifiers; this.dropX = e.clientX; this.dropY = e.clientY; this.dropped = true; const dt = e.dataTransfer; if (dt) { let dataByFormat = this.dataByFormat; dt.types.forEach(type => { if (!dataByFormat.has(type)) { const data = dt.getData(type); if (data !== '') { this.dataByFormat = dataByFormat = dataByFormat.toMutable(); dataByFormat.set(type, data); } } }); } this.revision++; } updateEventOnDragStart(e) { const dt = e.dataTransfer; if (dt) { dt.dropEffect = this.dropEffect; dt.effectAllowed = this.effectAllowed; this.dataByFormat.forEach((data, format) => { if (typeof data === 'string') dt.setData(format, data); }); if (this.draggingImage) { dt.setDragImage(this.draggingImage, this.draggingImageX, this.draggingImageY); } } } updateEventOnDropAllowed(e) { if (this.dropAllowed) e.preventDefault(); } reset() { this.draggable = undefined; this.dragSource = undefined; this.dragTarget = undefined; this.dragTargetWindow = undefined; this.previousDragTarget = undefined; this.dragStarted = false; this.dragFinished = false; this.startX = Infinity; this.startY = Infinity; this.dataByFormat.clear(); this.draggingImage = undefined; this.draggingImageX = Infinity; this.draggingImageY = Infinity; this.dropEffect = 'none'; this.dataTypesAllowed = []; this.effectAllowed = 'uninitialized'; this.dropAllowed = false; this.draggingOver = false; this.draggingDataTypes = []; this.positionX = Infinity; this.positionY = Infinity; this.modifiers = KeyboardModifiers.None; this.dropX = Infinity; this.dropY = Infinity; this.dropped = false; this.immediatePositionX = Infinity; this.immediatePositionY = Infinity; this.immediateModifiers = KeyboardModifiers.None; this.revision++; } updateDragTarget(e) { var _a; const targetPath = e.composedPath(); const underPointer = document.elementsFromPoint(e.clientX, e.clientY); const { data, window } = findTargetElementData(targetPath, underPointer, SymDataForSensor, ['htmlDrag']); const dragTarget = data === null || data === void 0 ? void 0 : data.htmlDrag; if (dragTarget !== this.dragTarget) { this.previousDragTarget = this.dragTarget; this.dragTarget = dragTarget; this.dragTargetWindow = window; } const types = (_a = e.dataTransfer) === null || _a === void 0 ? void 0 : _a.types; if (types) { if (!areEqualArrays(types, this.draggingDataTypes)) { const draggingDataTypes = new Array(); for (let i = 0; i < types.length; i++) draggingDataTypes.push(types[i]); this.draggingDataTypes = draggingDataTypes; } } this.immediateModifiers = extractModifierKeys(e); this.immediatePositionX = e.clientX; this.immediatePositionY = e.clientY; this.draggingOver = true; } whenDragging() { if (this.draggingOver) { this.positionX = this.immediatePositionX; this.positionY = this.immediatePositionY; this.modifiers = this.immediateModifiers; } } } __decorate([ isnonreactive, __metadata("design:type", Map) ], HtmlDragSensor.prototype, "dataByFormat", void 0); __decorate([ isnonreactive, __metadata("design:type", Object) ], HtmlDragSensor.prototype, "draggingImage", void 0); __decorate([ isnonreactive, __metadata("design:type", Number) ], HtmlDragSensor.prototype, "draggingImageX", void 0); __decorate([ isnonreactive, __metadata("design:type", Number) ], HtmlDragSensor.prototype, "draggingImageY", void 0); __decorate([ isnonreactive, __metadata("design:type", String) ], HtmlDragSensor.prototype, "dropEffect", void 0); __decorate([ isnonreactive, __metadata("design:type", Array) ], HtmlDragSensor.prototype, "dataTypesAllowed", void 0); __decorate([ isnonreactive, __metadata("design:type", String) ], HtmlDragSensor.prototype, "effectAllowed", void 0); __decorate([ isnonreactive, __metadata("design:type", Boolean) ], HtmlDragSensor.prototype, "dropAllowed", void 0); __decorate([ transaction, __metadata("design:type", Function), __metadata("design:paramtypes", [Object, Boolean]), __metadata("design:returntype", void 0) ], HtmlDragSensor.prototype, "listen", null); __decorate([ transaction, options({ logging: LoggingLevel.Off }), __metadata("design:type", Function), __metadata("design:paramtypes", [DragEvent]), __metadata("design:returntype", void 0) ], HtmlDragSensor.prototype, "startDragging", null); __decorate([ transaction, options({ logging: LoggingLevel.Off }), __metadata("design:type", Function), __metadata("design:paramtypes", [DragEvent]), __metadata("design:returntype", void 0) ], HtmlDragSensor.prototype, "dragging", null); __decorate([ transaction, options({ logging: LoggingLevel.Off }), __metadata("design:type", Function), __metadata("design:paramtypes", [DragEvent]), __metadata("design:returntype", void 0) ], HtmlDragSensor.prototype, "finishDragging", null); __decorate([ transaction, options({ logging: LoggingLevel.Off }), __metadata("design:type", Function), __metadata("design:paramtypes", [DragEvent]), __metadata("design:returntype", void 0) ], HtmlDragSensor.prototype, "enterTarget", null); __decorate([ transaction, options({ logging: LoggingLevel.Off }), __metadata("design:type", Function), __metadata("design:paramtypes", [DragEvent]), __metadata("design:returntype", void 0) ], HtmlDragSensor.prototype, "leaveTarget", null); __decorate([ transaction, options({ logging: LoggingLevel.Off }), __metadata("design:type", Function), __metadata("design:paramtypes", [DragEvent]), __metadata("design:returntype", void 0) ], HtmlDragSensor.prototype, "dragOver", null); __decorate([ transaction, options({ logging: LoggingLevel.Off }), __metadata("design:type", Function), __metadata("design:paramtypes", [DragEvent]), __metadata("design:returntype", void 0) ], HtmlDragSensor.prototype, "drop", null); __decorate([ transaction, options({ logging: LoggingLevel.Off }), __metadata("design:type", Function), __metadata("design:paramtypes", [DragEvent]), __metadata("design:returntype", void 0) ], HtmlDragSensor.prototype, "updateEventOnDragStart", null); __decorate([ transaction, options({ logging: LoggingLevel.Off }), __metadata("design:type", Function), __metadata("design:paramtypes", [DragEvent]), __metadata("design:returntype", void 0) ], HtmlDragSensor.prototype, "updateEventOnDropAllowed", null); __decorate([ transaction, options({ logging: LoggingLevel.Off }), __metadata("design:type", Function), __metadata("design:paramtypes", []), __metadata("design:returntype", void 0) ], HtmlDragSensor.prototype, "reset", null); __decorate([ reaction, options({ throttling: 0 }), __metadata("design:type", Function), __metadata("design:paramtypes", []), __metadata("design:returntype", void 0) ], HtmlDragSensor.prototype, "whenDragging", null); function areEqualArrays(array1, array2) { let result = true; for (let i = 0; i < array1.length; i++) { if (array1[i] !== array2[i]) { result = false; break; } } return result; }