import * as i0 from '@angular/core';
import { inject, TemplateRef, Directive, contentChild, viewChild, ElementRef, Renderer2, DestroyRef, input, signal, output, Component } from '@angular/core';
import { moveItemInArray, transferArrayItem, CdkDrag, CdkDropList, CdkDropListGroup } from '@angular/cdk/drag-drop';
import { Icon } from '@ngstarter-ui/components/icon';
import { Ripple } from '@ngstarter-ui/components/core';
import { NgTemplateOutlet } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { Menu, MenuItem, MenuTrigger } from '@ngstarter-ui/components/menu';
import { PanelContent, Panel, PanelHeader } from '@ngstarter-ui/components/panel';
import { fromEvent } from 'rxjs';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { Button } from '@ngstarter-ui/components/button';

class KanbanItemDefDirective {
    templateRef = inject(TemplateRef);
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: KanbanItemDefDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
    static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.4", type: KanbanItemDefDirective, isStandalone: true, selector: "[ngsKanbanItemDef]", ngImport: i0 });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: KanbanItemDefDirective, decorators: [{
            type: Directive,
            args: [{
                    selector: '[ngsKanbanItemDef]'
                }]
        }] });

class KanbanBoard {
    _itemTplDef = contentChild.required(KanbanItemDefDirective);
    _headerContainer = viewChild.required('headerContainer', { read: ElementRef });
    _scrollContainer = viewChild.required('scrollContainer', { read: ElementRef });
    _renderer = inject(Renderer2);
    _destroyRef = inject(DestroyRef);
    columns = input([], ...(ngDevMode ? [{ debugName: "columns" }] : /* istanbul ignore next */ []));
    colors = input([], ...(ngDevMode ? [{ debugName: "colors" }] : /* istanbul ignore next */ []));
    _hasVerticalScroll = signal(false, ...(ngDevMode ? [{ debugName: "_hasVerticalScroll" }] : /* istanbul ignore next */ []));
    columnEdit = output();
    columnDelete = output();
    itemAdd = output();
    itemClick = output();
    itemDropped = output();
    itemSorted = output();
    itemTransferred = output();
    _startContainerXOffset = 0;
    _itemXOffset = 0;
    _itemWidth = 0;
    isDraggingActive = false;
    _autoScrollStarted = false;
    ngOnInit() {
        fromEvent(this._scrollContainer().nativeElement, 'scroll')
            .pipe(takeUntilDestroyed(this._destroyRef))
            .subscribe((event) => {
            this.onScroll(event);
        });
    }
    onDropped(event) {
        this.itemDropped.emit(event);
        if (event.previousContainer === event.container) {
            this.itemSorted.emit({
                previousIndex: event.previousIndex,
                currentIndex: event.currentIndex
            });
            moveItemInArray(event.container.data, event.previousIndex, event.currentIndex);
        }
        else {
            this.itemTransferred.emit({
                previousContainerData: event.previousContainer.data,
                currentContainerData: event.container.data,
                previousIndex: event.previousIndex,
                currentIndex: event.currentIndex
            });
            transferArrayItem(event.previousContainer.data, event.container.data, event.previousIndex, event.currentIndex);
        }
    }
    onScroll(event) {
        const target = event.target;
        const headerContainerElement = this._headerContainer().nativeElement;
        this._renderer.setStyle(headerContainerElement, 'transform', `translate(-${target.scrollLeft}px, 0)`);
        this._hasVerticalScroll.set(target.scrollTop > 0);
    }
    onDragStarted(event, element) {
        this.isDraggingActive = true;
    }
    onDragMoved(event) {
        const space = 100;
        const scrollContainer = this._scrollContainer().nativeElement;
        const scrollContainerWidth = scrollContainer.getBoundingClientRect().width;
        const itemOffsetXStart = this._startContainerXOffset + event.distance.x;
        const itemOffsetXEnd = this._startContainerXOffset + event.distance.x + this._itemWidth;
        if (!this._autoScrollStarted) {
            if (itemOffsetXEnd + space >= scrollContainerWidth) {
                this._autoScrollStarted = true;
                scrollContainer.scroll({
                    left: scrollContainer.scrollLeft + this._itemWidth * 2,
                    behavior: 'smooth'
                });
                setTimeout(() => {
                    this._autoScrollStarted = false;
                }, 500);
            }
            else if (itemOffsetXStart <= space && scrollContainer.scrollLeft > 0) {
                this._autoScrollStarted = true;
                scrollContainer.scroll({
                    left: scrollContainer.scrollLeft - this._itemWidth * 2,
                    behavior: 'smooth'
                });
                setTimeout(() => {
                    this._autoScrollStarted = false;
                }, 500);
            }
        }
    }
    onDragEnded(event) {
        this.isDraggingActive = false;
    }
    itemMousedown(event) {
        const scrollContainerElement = this._scrollContainer().nativeElement;
        let targetElement = event.target;
        if (!targetElement.classList.contains('kanban-item')) {
            targetElement = targetElement.closest('.kanban-item');
        }
        const targetRect = targetElement.getBoundingClientRect();
        this._startContainerXOffset = targetRect.x - scrollContainerElement.getBoundingClientRect().x;
        this._itemXOffset = event.clientX - targetRect.x;
        this._itemWidth = targetRect.width;
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: KanbanBoard, deps: [], target: i0.ɵɵFactoryTarget.Component });
    static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.4", type: KanbanBoard, isStandalone: true, selector: "ngs-kanban-board", inputs: { columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: false, transformFunction: null }, colors: { classPropertyName: "colors", publicName: "colors", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { columnEdit: "columnEdit", columnDelete: "columnDelete", itemAdd: "itemAdd", itemClick: "itemClick", itemDropped: "itemDropped", itemSorted: "itemSorted", itemTransferred: "itemTransferred" }, host: { properties: { "class.is-dragging-active": "isDraggingActive" }, classAttribute: "ngs-kanban-board" }, queries: [{ propertyName: "_itemTplDef", first: true, predicate: KanbanItemDefDirective, descendants: true, isSignal: true }], viewQueries: [{ propertyName: "_headerContainer", first: true, predicate: ["headerContainer"], descendants: true, read: ElementRef, isSignal: true }, { propertyName: "_scrollContainer", first: true, predicate: ["scrollContainer"], descendants: true, read: ElementRef, isSignal: true }], exportAs: ["ngsKanbanBoard"], ngImport: i0, template: "<ngs-panel class=\"h-full\">\n  <ngs-panel-header class=\"header\">\n    <div class=\"flex flex-nowrap h-full items-center header-container\" #headerContainer>\n      @for (column of columns(); track column; let index = $index) {\n        <div class=\"h-full header-column relative flex gap-2 items-center justify-between flex-none\">\n          <div class=\"flex gap-2 items-center uppercase text-sm\">\n            @if (column.color) {\n              <div class=\"size-3 rounded-full\" [style.background-color]=\"column.color\"></div>\n            }\n            {{ column.name }} ({{ column.items.length }})\n          </div>\n          <div class=\"flex gap-0.5 items-center\">\n            <button ngsIconButton (click)=\"itemAdd.emit()\">\n              <ngs-icon name=\"fluent:add-24-regular\"/>\n            </button>\n            <button ngsIconButton [ngsMenuTriggerFor]=\"columnMenu\">\n              <ngs-icon name=\"fluent:more-horizontal-24-regular\"/>\n            </button>\n          </div>\n\n          @if (_hasVerticalScroll()) {\n            <div class=\"h-px bg-surface-container absolute bottom-0 start-0 end-0\"></div>\n          }\n\n          <ngs-menu #columnMenu=\"ngsMenu\">\n            <button ngs-menu-item (click)=\"columnEdit.emit(column)\">\n              <ngs-icon name=\"fluent:share-24-regular\"/>\n              <span>Edit</span>\n            </button>\n            <button ngs-menu-item (click)=\"columnDelete.emit({ column, index })\">\n              <ngs-icon name=\"fluent:delete-24-regular\"/>\n              <span>Delete</span>\n            </button>\n          </ngs-menu>\n        </div>\n      }\n    </div>\n  </ngs-panel-header>\n  <ngs-panel-content class=\"relative overflow-hidden\">\n    <div #scrollContainer\n         class=\"scroll-container h-full absolute overflow-auto inset-0 flex body items-baseline\">\n      <div #scrollContainerContent\n           class=\"flex min-h-full flex-nowrap column\" cdkDropListGroup>\n        @for (column of columns(); track column) {\n          <div class=\"column-container bg-surface-container-low flex-none rounded-2xl p-3 min-h-full flex flex-col gap-3\"\n               cdkDropList\n               [cdkDropListData]=\"column.items\"\n               (cdkDropListDropped)=\"onDropped($event)\">\n            @for (item of column.items; track item) {\n              <div #element\n                   class=\"kanban-item bg-surface-container-lowest flex-none rounded-2xl\n                          p-3 shadow-sm cursor-pointer hover:outline-2 hover:outline-primary\"\n                   cdkDrag [cdkDragData]=\"item\" ngsRipple\n                   (mousedown)=\"itemMousedown($event)\"\n                   (click)=\"itemClick.emit(item)\"\n                   (cdkDragStarted)=\"onDragStarted($event, element)\"\n                   (cdkDragMoved)=\"onDragMoved($event)\"\n                   (cdkDragEnded)=\"onDragEnded($event)\">\n                <ng-container [ngTemplateOutlet]=\"_itemTplDef().templateRef\"\n                              [ngTemplateOutletContext]=\"{ $implicit: item, column }\"/>\n              </div>\n            }\n          </div>\n        }\n      </div>\n    </div>\n  </ngs-panel-content>\n</ngs-panel>\n", styles: [":host{--ngs-kanban-board-col-width: calc(var(--spacing, .25rem) * 72);--ngs-kanban-board-padding-x: calc(var(--spacing, .25rem) * 10);--ngs-kanban-board-column-gap: calc(var(--spacing, .25rem) * 5);height:100%}:host .header{padding:0 var(--ngs-kanban-board-padding-x);overflow:hidden}:host .header-container{gap:var(--ngs-kanban-board-column-gap)}:host .header-column{width:var(--ngs-kanban-board-col-width);flex:none}:host .body{gap:var(--ngs-kanban-board-column-gap);padding:0 var(--ngs-kanban-board-padding-x)}:host .column{padding-bottom:var(--ngs-kanban-board-column-gap);gap:var(--ngs-kanban-board-column-gap)}:host .column-container{width:var(--ngs-kanban-board-col-width);flex:none}:host .cdk-drag-placeholder{opacity:60%}:host.is-dragging-active .scroll-container{transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}:host.is-dragging-active .kanban-item:hover{outline:none}.kanban-item.cdk-drag-preview{background:var(--ngs-color-surface-container-lowest);padding:calc(var(--spacing, .25rem) * 3);cursor:pointer;flex:none;box-shadow:var(--ngs-shadow-sm);border-radius:var(--ngs-radius-xl)}\n/*! tailwindcss v4.2.2 | MIT License | https://tailwindcss.com */\n"], dependencies: [{ kind: "directive", type: CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "directive", type: CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep", "cdkDropListElementContainer", "cdkDropListHasAnchor"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "directive", type: CdkDropListGroup, selector: "[cdkDropListGroup]", inputs: ["cdkDropListGroupDisabled"], exportAs: ["cdkDropListGroup"] }, { kind: "component", type: Icon, selector: "ngs-icon", inputs: ["name"], exportAs: ["ngsIcon"] }, { kind: "directive", type: Ripple, selector: "[ngsRipple]", inputs: ["ngsRippleColor", "ngsRippleUnbounded", "ngsRippleCentered", "ngsRippleRadius", "ngsRippleAnimation", "ngsRippleDisabled", "ngsRippleTrigger"], outputs: ["ngsRippleCenteredChange", "ngsRippleDisabledChange", "ngsRippleTriggerChange"], exportAs: ["ngsRipple"] }, { kind: "component", type: PanelContent, selector: "ngs-panel-content", exportAs: ["ngsPanelContent"] }, { kind: "component", type: Panel, selector: "ngs-panel", inputs: ["absolute"], exportAs: ["ngsPanel"] }, { kind: "component", type: PanelHeader, selector: "ngs-panel-header", inputs: ["flex", "autoHeight"], exportAs: ["ngsPanelHeader"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: FormsModule }, { kind: "component", type: Menu, selector: "ngs-menu", inputs: ["role", "classList", "xPosition", "yPosition"], outputs: ["closed"], exportAs: ["ngsMenu"] }, { kind: "component", type: MenuItem, selector: "ngs-menu-item, [ngs-menu-item]", inputs: ["disabled", "role", "selected"], outputs: ["_triggered"], exportAs: ["ngsMenuItem"] }, { kind: "directive", type: MenuTrigger, selector: "[ngsMenuTriggerFor]", inputs: ["ngsMenuTriggerFor", "ngsMenuTriggerData", "ngsMenuDisabled", "xPosition", "yPosition", "ngsMenuTriggerRestoreFocus"], outputs: ["menuOpened", "menuClosed"], exportAs: ["ngsMenuTrigger"] }, { kind: "component", type: Button, selector: "    button[ngsButton], button[ngsIconButton],    a[ngsButton], a[ngsIconButton]  ", inputs: ["ngsButton", "ngsIconButton", "loading", "disabled", "disabledInteractive", "disableRipple", "reverse", "fullWidth", "hideTextOnMobile"], exportAs: ["ngsButton"] }] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: KanbanBoard, decorators: [{
            type: Component,
            args: [{ selector: 'ngs-kanban-board', exportAs: 'ngsKanbanBoard', imports: [
                        CdkDrag,
                        CdkDropList,
                        CdkDropListGroup,
                        Icon,
                        Ripple,
                        PanelContent,
                        Panel,
                        PanelHeader,
                        NgTemplateOutlet,
                        FormsModule,
                        Menu,
                        MenuItem,
                        MenuTrigger,
                        Button
                    ], host: {
                        'class': 'ngs-kanban-board',
                        '[class.is-dragging-active]': 'isDraggingActive'
                    }, template: "<ngs-panel class=\"h-full\">\n  <ngs-panel-header class=\"header\">\n    <div class=\"flex flex-nowrap h-full items-center header-container\" #headerContainer>\n      @for (column of columns(); track column; let index = $index) {\n        <div class=\"h-full header-column relative flex gap-2 items-center justify-between flex-none\">\n          <div class=\"flex gap-2 items-center uppercase text-sm\">\n            @if (column.color) {\n              <div class=\"size-3 rounded-full\" [style.background-color]=\"column.color\"></div>\n            }\n            {{ column.name }} ({{ column.items.length }})\n          </div>\n          <div class=\"flex gap-0.5 items-center\">\n            <button ngsIconButton (click)=\"itemAdd.emit()\">\n              <ngs-icon name=\"fluent:add-24-regular\"/>\n            </button>\n            <button ngsIconButton [ngsMenuTriggerFor]=\"columnMenu\">\n              <ngs-icon name=\"fluent:more-horizontal-24-regular\"/>\n            </button>\n          </div>\n\n          @if (_hasVerticalScroll()) {\n            <div class=\"h-px bg-surface-container absolute bottom-0 start-0 end-0\"></div>\n          }\n\n          <ngs-menu #columnMenu=\"ngsMenu\">\n            <button ngs-menu-item (click)=\"columnEdit.emit(column)\">\n              <ngs-icon name=\"fluent:share-24-regular\"/>\n              <span>Edit</span>\n            </button>\n            <button ngs-menu-item (click)=\"columnDelete.emit({ column, index })\">\n              <ngs-icon name=\"fluent:delete-24-regular\"/>\n              <span>Delete</span>\n            </button>\n          </ngs-menu>\n        </div>\n      }\n    </div>\n  </ngs-panel-header>\n  <ngs-panel-content class=\"relative overflow-hidden\">\n    <div #scrollContainer\n         class=\"scroll-container h-full absolute overflow-auto inset-0 flex body items-baseline\">\n      <div #scrollContainerContent\n           class=\"flex min-h-full flex-nowrap column\" cdkDropListGroup>\n        @for (column of columns(); track column) {\n          <div class=\"column-container bg-surface-container-low flex-none rounded-2xl p-3 min-h-full flex flex-col gap-3\"\n               cdkDropList\n               [cdkDropListData]=\"column.items\"\n               (cdkDropListDropped)=\"onDropped($event)\">\n            @for (item of column.items; track item) {\n              <div #element\n                   class=\"kanban-item bg-surface-container-lowest flex-none rounded-2xl\n                          p-3 shadow-sm cursor-pointer hover:outline-2 hover:outline-primary\"\n                   cdkDrag [cdkDragData]=\"item\" ngsRipple\n                   (mousedown)=\"itemMousedown($event)\"\n                   (click)=\"itemClick.emit(item)\"\n                   (cdkDragStarted)=\"onDragStarted($event, element)\"\n                   (cdkDragMoved)=\"onDragMoved($event)\"\n                   (cdkDragEnded)=\"onDragEnded($event)\">\n                <ng-container [ngTemplateOutlet]=\"_itemTplDef().templateRef\"\n                              [ngTemplateOutletContext]=\"{ $implicit: item, column }\"/>\n              </div>\n            }\n          </div>\n        }\n      </div>\n    </div>\n  </ngs-panel-content>\n</ngs-panel>\n", styles: [":host{--ngs-kanban-board-col-width: calc(var(--spacing, .25rem) * 72);--ngs-kanban-board-padding-x: calc(var(--spacing, .25rem) * 10);--ngs-kanban-board-column-gap: calc(var(--spacing, .25rem) * 5);height:100%}:host .header{padding:0 var(--ngs-kanban-board-padding-x);overflow:hidden}:host .header-container{gap:var(--ngs-kanban-board-column-gap)}:host .header-column{width:var(--ngs-kanban-board-col-width);flex:none}:host .body{gap:var(--ngs-kanban-board-column-gap);padding:0 var(--ngs-kanban-board-padding-x)}:host .column{padding-bottom:var(--ngs-kanban-board-column-gap);gap:var(--ngs-kanban-board-column-gap)}:host .column-container{width:var(--ngs-kanban-board-col-width);flex:none}:host .cdk-drag-placeholder{opacity:60%}:host.is-dragging-active .scroll-container{transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}:host.is-dragging-active .kanban-item:hover{outline:none}.kanban-item.cdk-drag-preview{background:var(--ngs-color-surface-container-lowest);padding:calc(var(--spacing, .25rem) * 3);cursor:pointer;flex:none;box-shadow:var(--ngs-shadow-sm);border-radius:var(--ngs-radius-xl)}\n/*! tailwindcss v4.2.2 | MIT License | https://tailwindcss.com */\n"] }]
        }], propDecorators: { _itemTplDef: [{ type: i0.ContentChild, args: [i0.forwardRef(() => KanbanItemDefDirective), { isSignal: true }] }], _headerContainer: [{ type: i0.ViewChild, args: ['headerContainer', { ...{ read: ElementRef }, isSignal: true }] }], _scrollContainer: [{ type: i0.ViewChild, args: ['scrollContainer', { ...{ read: ElementRef }, isSignal: true }] }], columns: [{ type: i0.Input, args: [{ isSignal: true, alias: "columns", required: false }] }], colors: [{ type: i0.Input, args: [{ isSignal: true, alias: "colors", required: false }] }], columnEdit: [{ type: i0.Output, args: ["columnEdit"] }], columnDelete: [{ type: i0.Output, args: ["columnDelete"] }], itemAdd: [{ type: i0.Output, args: ["itemAdd"] }], itemClick: [{ type: i0.Output, args: ["itemClick"] }], itemDropped: [{ type: i0.Output, args: ["itemDropped"] }], itemSorted: [{ type: i0.Output, args: ["itemSorted"] }], itemTransferred: [{ type: i0.Output, args: ["itemTransferred"] }] } });

/**
 * Generated bundle index. Do not edit.
 */

export { KanbanBoard, KanbanItemDefDirective };
//# sourceMappingURL=ngstarter-ui-components-kanban-board.mjs.map
