UNPKG

@progress/kendo-angular-pivotgrid

Version:
191 lines (190 loc) 10 kB
/**----------------------------------------------------------------------------------------- * Copyright © 2025 Progress Software Corporation. All rights reserved. * Licensed under commercial license. See LICENSE.md in the project root for more information *-------------------------------------------------------------------------------------------*/ import { Directive, ElementRef, Input, NgZone, Renderer2 } from "@angular/core"; import { PIVOT_CONFIGURATOR_ACTION } from "@progress/kendo-pivotgrid-common"; import { Subscription } from "rxjs"; import { ConfiguratorService } from "./configurator.service"; import { DropCueService } from "./drop-cue.service"; import { isPresent } from "../util"; import * as i0 from "@angular/core"; import * as i1 from "./configurator.service"; import * as i2 from "./drop-cue.service"; /** * @hidden */ export class DropTargetDirective { element; configuratorService; cue; renderer; zone; item; axes; elementType; elementSectionType; targetElement; nextChipOffset; subs = new Subscription(); constructor(element, configuratorService, cue, renderer, zone) { this.element = element; this.configuratorService = configuratorService; this.cue = cue; this.renderer = renderer; this.zone = zone; } ngOnInit() { const element = this.element.nativeElement; this.elementType = this.getElementType(element); this.elementSectionType = element.getAttribute('axes')?.split('Axes')[0]; this.subs.add(this.renderer.listen(element, 'mouseenter', this.handleMouseEnter.bind(this))); this.subs.add(this.renderer.listen(element, 'mousemove', this.handleMouseMove.bind(this))); this.subs.add(this.renderer.listen(element, 'mouseleave', this.handleMouseLeave.bind(this))); } ngOnDestroy() { this.subs.unsubscribe(); } handleMouseEnter(event) { this.zone.runOutsideAngular(() => { if (this.configuratorService.state.dragItem) { this.configuratorService.dropTargetElement = this.element.nativeElement; if (this.configuratorService.draggedElement && !this.isDropAllowed(this.configuratorService.draggedElement.fromSection)) { return; } this.configuratorService.parseConfiguratorState({ type: PIVOT_CONFIGURATOR_ACTION.setDropTarget, payload: this.item }); this.targetElement = this.elementType === 'header' ? event.target.nextElementSibling : event.target; // eslint-disable-next-line no-unused-expressions this.cue.dom && this.cue.remove(this.getCueContainer()); this.cue.create(); this.cue.attach(this.getCueContainer()); this.configuratorService.parseConfiguratorState({ type: PIVOT_CONFIGURATOR_ACTION.setDropZone, payload: this.axes }); } }); } handleMouseMove(event) { this.zone.runOutsideAngular(() => { event.stopImmediatePropagation(); if (this.configuratorService.state.dragItem) { if (this.configuratorService.draggedElement && !this.isDropAllowed(this.configuratorService.draggedElement.fromSection)) { this.renderer.setStyle(this.element.nativeElement, 'cursor', 'not-allowed'); return; } this.renderer.setStyle(this.element.nativeElement, 'cursor', 'pointer'); const singleOrNoChip = this.targetElement?.querySelectorAll('.k-chip').length < 2; const isInOwnContainer = this.elementSectionType === this.configuratorService.draggedElement.fromSection; if (!this.targetElement) { return; } switch (this.elementType) { case 'chip': { const rect = this.element.nativeElement.getBoundingClientRect(); const x = event.clientX - rect.left; const direction = x < rect.width / 2 ? 'before' : 'after'; this.cue.show(direction, this.configuratorService.cueContainer, this.targetElement); if (direction !== this.configuratorService.state.dropDirection) { this.configuratorService.parseConfiguratorState({ type: PIVOT_CONFIGURATOR_ACTION.setDropDirection, payload: direction }); } break; } case 'container': case 'header': if (singleOrNoChip && isInOwnContainer) { return; } if (isInOwnContainer) { const draggedElement = this.configuratorService.draggedElement.element; const nextChip = this.getNextChip(draggedElement); if (!nextChip) { this.cue.show('before', this.configuratorService.cueContainer, draggedElement); if (this.configuratorService.state.dropDirection !== 'before') { this.configuratorService.parseConfiguratorState({ type: PIVOT_CONFIGURATOR_ACTION.setDropDirection, payload: 'before' }); } return; } const isVertical = this.configuratorService.orientation === 'vertical'; if (!isPresent(this.nextChipOffset)) { this.nextChipOffset = isVertical ? nextChip.getBoundingClientRect().left : nextChip.getBoundingClientRect().top; } const isBefore = isVertical ? event.clientX < this.nextChipOffset : event.clientY < this.nextChipOffset; if (isBefore) { this.cue.show('after', this.configuratorService.cueContainer, draggedElement); return; } } if (this.configuratorService.state.dropDirection !== 'after') { this.configuratorService.parseConfiguratorState({ type: PIVOT_CONFIGURATOR_ACTION.setDropDirection, payload: 'after' }); } this.cue.show('after', this.configuratorService.cueContainer, this.targetElement); break; default: } } }); } handleMouseLeave(event) { this.renderer.removeStyle(this.element.nativeElement, 'cursor'); if (!this.configuratorService.draggedElement) { return; } this.zone.runOutsideAngular(() => { event.stopImmediatePropagation(); this.configuratorService.dropTargetElement = null; this.cue.remove(this.getCueContainer()); if (this.elementType === 'chip') { return; } if (this.configuratorService.state.dragItem) { this.configuratorService.parseConfiguratorState({ type: PIVOT_CONFIGURATOR_ACTION.setDropZone, payload: null }); } }); } isDropAllowed(fromSection) { const element = this.element.nativeElement; const fromRowsOrColsToMeasures = (fromSection === 'row' || fromSection === 'column') && element.closest('[axes=measureAxes]'); const fromMeasuresToRowsOrCols = fromSection === 'measure' && (element.closest('[axes=rowAxes]') || element.closest('[axes=columnAxes]')); return !(fromRowsOrColsToMeasures || fromMeasuresToRowsOrCols); } getElementType(element) { return { 'KENDO-CHIP': 'chip', 'KENDO-CHIPLIST': 'container', 'DIV': 'header' }[element.tagName]; } getCueContainer() { const element = this.element.nativeElement; const cueContainer = { chip: element.parentElement, container: element, header: element.classList.contains('k-settings-description') ? element : element.nextElementSibling }[this.elementType]; this.configuratorService.cueContainer = cueContainer; return cueContainer; } getNextChip(draggedElement) { let nextChip = draggedElement.nextElementSibling; if (nextChip && nextChip.matches('.k-chip')) { return nextChip; } while (nextChip) { nextChip = nextChip.nextElementSibling; if (nextChip === null || nextChip.matches('.k-chip')) { return nextChip; } } } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: DropTargetDirective, deps: [{ token: i0.ElementRef }, { token: i1.ConfiguratorService }, { token: i2.DropCueService }, { token: i0.Renderer2 }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Directive }); static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: DropTargetDirective, isStandalone: true, selector: "[kendoDropTarget]", inputs: { item: "item", axes: "axes" }, ngImport: i0 }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: DropTargetDirective, decorators: [{ type: Directive, args: [{ selector: '[kendoDropTarget]', standalone: true }] }], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: i1.ConfiguratorService }, { type: i2.DropCueService }, { type: i0.Renderer2 }, { type: i0.NgZone }]; }, propDecorators: { item: [{ type: Input }], axes: [{ type: Input }] } });