import * as i0 from '@angular/core';
import { Component, Input, EventEmitter, ViewEncapsulation, Output, ViewChild, NgModule } from '@angular/core';
import { isNullOrUndefined } from '@seniorsistemas/angular-components/utils';
import moment from 'moment';
import { NgStyle } from '@angular/common';
import { TooltipDirective } from '@seniorsistemas/angular-components/tooltip';

var ViewMode;
(function (ViewMode) {
    ViewMode["QuarterHour"] = "quarterHour";
    ViewMode["Hour"] = "hour";
    ViewMode["QuarterDay"] = "quarterDay";
    ViewMode["HalfDay"] = "halfDay";
    ViewMode["Day"] = "day";
    ViewMode["Week"] = "week";
    ViewMode["Month"] = "month";
    ViewMode["Year"] = "year";
})(ViewMode || (ViewMode = {}));

const $ = (expr, con) => typeof expr === 'string'
    ? (con || document).querySelector(expr)
    : expr || null;
const createSVG = (tag, attrs) => {
    const elem = document.createElementNS('http://www.w3.org/2000/svg', tag);
    for (const attr in attrs) {
        if (attr === 'append_to') {
            const parent = attrs.append_to;
            parent.appendChild(elem);
        }
        else if (attr === 'innerHTML') {
            elem.innerHTML = attrs.innerHTML;
        }
        else {
            elem.setAttribute(attr, attrs[attr]);
        }
    }
    return elem;
};
const animateSVG = (svgElement, attr, from, to) => {
    const animatedSvgElement = getAnimationElement(svgElement, attr, from, to);
    if (animatedSvgElement === svgElement) {
        // triggered 2nd time programmatically
        // trigger artificial click event
        const event = new Event('click', { bubbles: true, cancelable: true });
        animatedSvgElement.dispatchEvent(event);
    }
};
const getAnimationElement = (svgElement, attr, from, to, dur = '0.4s', begin = '0.1s') => {
    const animEl = svgElement.querySelector('animate');
    if (animEl) {
        $.attr(animEl, {
            attributeName: attr,
            from,
            to,
            dur,
            begin: 'click + ' + begin, // artificial click
        }, null);
        return svgElement;
    }
    const animateElement = createSVG('animate', {
        attributeName: attr,
        from,
        to,
        dur,
        begin,
        calcMode: 'spline',
        values: from + ';' + to,
        keyTimes: '0; 1',
        keySplines: cubicBezier('ease-out'),
    });
    svgElement.appendChild(animateElement);
    return svgElement;
};
const cubicBezier = (name) => ({
    ease: '.25 .1 .25 1',
    linear: '0 0 1 1',
    'ease-in': '.42 0 1 1',
    'ease-out': '0 0 .58 1',
    'ease-in-out': '.42 0 .58 1',
}[name]);
$.on = (element, event, selector, callback) => {
    if (!callback) {
        callback = selector;
        $.bind(element, event, callback);
    }
    else {
        $.delegate(element, event, selector, callback);
    }
};
$.off = (element, event, handler) => {
    element.removeEventListener(event, handler);
};
$.bind = (element, event, callback) => {
    event.split(/\s+/).forEach(function (currentEvent) {
        element.addEventListener(currentEvent, callback);
    });
};
$.delegate = (element, event, selector, callback) => {
    element.addEventListener(event, function (e) {
        const delegatedTarget = e.target.closest(selector);
        if (delegatedTarget) {
            e.delegatedTarget = delegatedTarget;
            callback.call(this, e, delegatedTarget);
        }
    });
};
$.closest = (selector, element) => {
    if (!element) {
        return null;
    }
    if (element.matches(selector)) {
        return element;
    }
    return $.closest(selector, element.parentNode);
};
$.attr = (element, attr, value) => {
    if (!value && typeof attr === 'string') {
        return element.getAttribute(attr);
    }
    if (typeof attr === 'object') {
        for (const key in attr) {
            if (attr.hasOwnProperty(key)) {
                $.attr(element, key, attr[key]);
            }
        }
        return;
    }
    element.setAttribute(attr, value);
};

class Arrow {
    _gantt;
    _fromTask;
    _toTask;
    _path;
    _element;
    constructor(gantt, fromTask, toTask) {
        this._gantt = gantt;
        this._fromTask = fromTask;
        this._toTask = toTask;
        this.calculatePath();
        this.draw();
    }
    get fromTask() {
        return this._fromTask;
    }
    get toTask() {
        return this._toTask;
    }
    get element() {
        return this._element;
    }
    update() {
        this.calculatePath();
        this._element.setAttribute("d", this._path);
    }
    calculatePath() {
        let startX = this.fromTask.element.getX() + this.fromTask.element.getWidth() / 2;
        const condition = () => this.toTask.element.getX() < startX + this._gantt.options.padding &&
            startX > this.fromTask.element.getX() + this._gantt.options.padding;
        while (condition()) {
            startX -= 10;
        }
        const startY = this._gantt.options.headerHeight +
            this._gantt.options.barHeight +
            (this._gantt.options.padding + this._gantt.options.barHeight) *
                this.fromTask.task._index +
            this._gantt.options.padding;
        const endX = this.toTask.element.getX() - this._gantt.options.padding / 2;
        const endY = this._gantt.options.headerHeight +
            this._gantt.options.barHeight / 2 +
            (this._gantt.options.padding + this._gantt.options.barHeight) *
                this.toTask.task._index +
            this._gantt.options.padding;
        const fromIsBelowTo = this.fromTask.task._index > this.toTask.task._index;
        const curve = this._gantt.options.arrowCurve;
        const clockwise = fromIsBelowTo ? 1 : 0;
        const curveY = fromIsBelowTo ? -curve : curve;
        const offset = fromIsBelowTo
            ? endY + this._gantt.options.arrowCurve
            : endY - this._gantt.options.arrowCurve;
        this._path = `
            M ${startX} ${startY}
            V ${offset}
            a ${curve} ${curve} 0 0 ${clockwise} ${curve} ${curveY}
            L ${endX} ${endY}
            m -5 -5
            l 5 5
            l -5 5`;
        if (this.toTask.element.getX() < this.fromTask.element.getX() + this._gantt.options.padding) {
            const down1 = this._gantt.options.padding / 2 - curve;
            const down2 = this.toTask.element.getY() + this.toTask.element.getHeight() / 2 - curveY;
            const left = this.toTask.element.getX() - this._gantt.options.padding;
            this._path = `
                M ${startX} ${startY}
                v ${down1}
                a ${curve} ${curve} 0 0 1 -${curve} ${curve}
                H ${left}
                a ${curve} ${curve} 0 0 ${clockwise} -${curve} ${curveY}
                V ${down2}
                a ${curve} ${curve} 0 0 ${clockwise} ${curve} ${curveY}
                L ${endX} ${endY}
                m -5 -5
                l 5 5
                l -5 5`;
        }
    }
    draw() {
        this._element = createSVG("path", {
            d: this._path,
            "data-from": this.fromTask.task.id,
            "data-to": this.toTask.task.id,
        });
    }
}

const YEAR = 'year';
const MONTH = 'month';
const DAY = 'day';
const HOUR = 'hour';
const MINUTE = 'minute';
const SECOND = 'second';
const MILLISECOND = 'millisecond';
class DateUtils {
    static parse(date) {
        return moment(date).toDate();
    }
    static toString(date, with_time = false) {
        const result = with_time ? moment(date, 'YYYY-MM-DD hh:mm:ss.SSS') : moment(date, 'YYYY-MM-DD');
        return result.toString();
    }
    static format(date, formatString = 'YYYY-MM-DD HH:mm:ss.SSS', lang = 'en') {
        const monthName = moment(date).locale(lang).startOf('month').format('MMMM');
        const monthNameCapitalized = monthName.charAt(0).toUpperCase() + monthName.slice(1);
        const dateToFormat = moment(date).locale(lang);
        const formatMap = {
            YYYY: dateToFormat.format('YYYY'),
            MM: dateToFormat.format('MM'),
            DD: dateToFormat.format('DD'),
            // Removendo alterações nas traduções que acontecem nos diferentes idiomas
            ddd: dateToFormat.format('ddd').toUpperCase().replace('.', ''),
            HH: dateToFormat.format('HH'),
            mm: dateToFormat.format('mm'),
            ss: dateToFormat.format('ss'),
            SSS: dateToFormat.format('SSS'),
            D: dateToFormat.format('D'),
            MMMM: monthNameCapitalized,
            MMM: monthNameCapitalized,
        };
        let str = formatString;
        const formattedValues = [];
        Object.keys(formatMap)
            .sort((a, b) => b.length - a.length)
            .forEach((key) => {
            if (str.includes(key)) {
                str = str.replace(key, `$${formattedValues.length}`);
                formattedValues.push(formatMap[key]);
            }
        });
        formattedValues.forEach((value, i) => {
            str = str.replace(`$${i}`, value);
        });
        return str;
    }
    static diff(fistDate, secondDate, scale) {
        const milliseconds = moment(fistDate).diff(secondDate, MILLISECOND);
        const seconds = moment(fistDate).diff(secondDate, SECOND);
        const minutes = moment(fistDate).diff(secondDate, MINUTE);
        const hours = moment(fistDate).diff(secondDate, HOUR);
        const days = moment(fistDate).diff(secondDate, DAY);
        const months = moment(fistDate).diff(secondDate, MONTH);
        const years = moment(fistDate).diff(secondDate, YEAR);
        if (!scale.endsWith('s')) {
            scale += 's';
        }
        return Math.floor({ milliseconds, seconds, minutes, hours, days, months, years }[scale]);
    }
    static today() {
        const dateStr = moment().format('YYY-MM-DD');
        return new Date(dateStr);
    }
    static now() {
        return moment().toDate();
    }
    static add(date, quantity, scale) {
        return moment(date).add(quantity, scale).toDate();
    }
    static startOf(date, scale) {
        const scores = {
            [YEAR]: 6,
            [MONTH]: 5,
            [DAY]: 4,
            [HOUR]: 3,
            [MINUTE]: 2,
            [SECOND]: 1,
            [MILLISECOND]: 0,
        };
        function shouldReset(_scale) {
            const maxScore = scores[scale];
            return scores[_scale] <= maxScore;
        }
        const vals = [
            date.getFullYear(),
            shouldReset(YEAR) ? 0 : date.getMonth(),
            shouldReset(MONTH) ? 1 : date.getDate(),
            shouldReset(DAY) ? 0 : date.getHours(),
            shouldReset(HOUR) ? 0 : date.getMinutes(),
            shouldReset(MINUTE) ? 0 : date.getSeconds(),
            shouldReset(SECOND) ? 0 : date.getMilliseconds(),
        ];
        return new Date(vals[0], vals[1], vals[2], vals[3], vals[4], vals[5], vals[6]);
    }
    static clone(date) {
        return moment(date).toDate();
    }
    static getDateValues(date) {
        return [
            date.getFullYear(),
            date.getMonth(),
            date.getDate(),
            date.getHours(),
            date.getMinutes(),
            date.getSeconds(),
            date.getMilliseconds(),
        ];
    }
    static getDaysInMonth(date) {
        return moment(date, 'YYYY-MM').daysInMonth();
    }
}

class Bar {
    _actionCompleted;
    _gantt;
    _invalid;
    _height;
    _x;
    _y;
    _cornerRadius;
    _duration;
    _width;
    _barGroup;
    _arrows;
    _group;
    _task;
    _element;
    _isPopUpOpen = false;
    constructor(gantt, task) {
        this._setDefaults(gantt, task);
        this._prepare();
        this._draw();
        this._bind();
    }
    get arrows() {
        return this._arrows;
    }
    get task() {
        return this._task;
    }
    get element() {
        return this._element;
    }
    get group() {
        return this._group;
    }
    set arrows(arrows) {
        this._arrows = arrows;
    }
    updateBarPosition({ x, width }) {
        const bar = this.element;
        if (x) {
            // get all x values of parent task
            const xs = this.task?.dependencies?.map((dep) => this._gantt?.get_bar(dep)?.element.getX());
            // child task must not go before parent
            const validX = xs?.reduce((prev, curr) => x >= curr, x);
            if (!validX) {
                width = null;
                return;
            }
            this._updateAttr(bar, 'x', x);
        }
        if (width && width >= (this._gantt?.options?.columnWidth ?? 0)) {
            this._updateAttr(bar, 'width', width);
        }
        this._updateLabelPosition();
        this._updateArrowPosition();
    }
    dateChanged() {
        let changed = false;
        const computedStartEndDate = this._computeStartEndDate();
        if (isNullOrUndefined(computedStartEndDate))
            return;
        const { newStartDate, newEndDate } = computedStartEndDate;
        if (this.task?.start !== newStartDate) {
            changed = true;
            if (!isNullOrUndefined(this.task)) {
                this.task.start = newStartDate;
            }
        }
        if (this.task?.end !== newEndDate) {
            changed = true;
            if (!isNullOrUndefined(this.task)) {
                this.task.end = newEndDate;
            }
        }
        if (changed) {
            this._gantt?.trigger_event('onDateChange', [this.task, newStartDate, DateUtils.add(newEndDate, -1, 'second')]);
        }
    }
    setActionCompleted() {
        this._actionCompleted = true;
        setTimeout(() => {
            this._actionCompleted = false;
        }, 1000);
    }
    _setDefaults(gantt, task) {
        this._actionCompleted = false;
        this._gantt = gantt;
        this._task = task;
    }
    _prepare() {
        this._prepareValues();
        this._prepareHelpers();
    }
    _prepareValues() {
        if (isNullOrUndefined(this.task) ||
            isNullOrUndefined(this._gantt) ||
            isNullOrUndefined(this._gantt.options) ||
            isNullOrUndefined(this._gantt.options.step))
            return;
        this._invalid = this.task.invalid;
        this._height = this._gantt.options.barHeight;
        this._x = this._computeX();
        this._y = this._computeY();
        this._cornerRadius = this._gantt.options.barCornerRadius;
        this._duration = DateUtils.diff(this.task.end, this.task.start, 'minute') / this._gantt.options.step / 60.0;
        this._width = (this._gantt.options.columnWidth ?? 0) * this._duration;
        this._group = createSVG('g', {
            class: 'bar-wrapper ' + (this.task.custom_class || ''),
            'data-id': this.task.id,
        });
        this._barGroup = createSVG('g', {
            class: 'bar-group',
            append_to: this.group,
        });
    }
    _prepareHelpers() {
        SVGElement.prototype.getX = function () {
            return +this.getAttribute('x');
        };
        SVGElement.prototype.getY = function () {
            return +this.getAttribute('y');
        };
        SVGElement.prototype.getWidth = function () {
            return +this.getAttribute('width');
        };
        SVGElement.prototype.getHeight = function () {
            return +this.getAttribute('height');
        };
        SVGElement.prototype.getEndX = function () {
            return this.getX() + this.getWidth();
        };
    }
    _draw() {
        this._drawBar();
        this._drawLabel();
    }
    _drawBar() {
        this._element = createSVG('rect', {
            x: this._x,
            y: this._y,
            width: this._width,
            height: this._height,
            rx: this._cornerRadius,
            ry: this._cornerRadius,
            class: 'bar',
            append_to: this._barGroup,
            fill: this.task?.color,
        });
        animateSVG(this.element, 'width', 0, this._width);
        if (this._invalid) {
            this.element.classList.add('bar-invalid');
        }
    }
    _drawLabel() {
        createSVG('text', {
            x: (this._x ?? 0) + (this._width ?? 0) / 2,
            y: (this._y ?? 0) + (this._height ?? 0) / 2,
            innerHTML: this.task?.showTaskName ? this.task.name : '',
            class: 'bar-label',
            append_to: this._barGroup,
        });
        // labels get BBox in the next tick
        requestAnimationFrame(() => this._updateLabelPosition());
    }
    _bind() {
        if (!this._invalid) {
            this._setupClickEvent();
        }
    }
    _setupClickEvent() {
        if (this._gantt?.options?.hasPopup) {
            $.on(this.group, 'focus ' + this._gantt.options.popupTrigger, (e) => {
                // just finished a move action, wait for a few seconds
                if (!this._actionCompleted) {
                    this._showPopup();
                    this._gantt?.unselect_all();
                    this.group.classList.add('active');
                }
            }, null);
            $.on(this.group, 'dblclick', (e) => {
                // just finished a move action, wait for a few seconds
                if (!this._actionCompleted) {
                    this._gantt?.trigger_event('onClick', [this.task]);
                }
            }, null);
        }
        else {
            $.on(this.group, 'mouseenter', (e) => {
                if (!this._isPopUpOpen) {
                    this._showPopup({
                        x: e.clientX,
                        y: this.group.getBoundingClientRect().top + 30,
                        position: 'middle',
                    });
                    this._isPopUpOpen = true;
                }
            }, null);
            $.on(this.group, 'mouseleave', (e) => {
                this._gantt?.hide_popup();
                this._isPopUpOpen = false;
            }, null);
            $.on(this.group, 'focus click', (e) => {
                if (!this._actionCompleted) {
                    this._gantt?.unselect_all();
                    this.group.classList.add('active');
                    this._gantt?.trigger_event('onClick', [this.task]);
                }
            }, null);
        }
    }
    _showPopup(args) {
        if (this._gantt?.bar_being_dragged) {
            return;
        }
        const subtitle = {};
        if (!this._gantt?.options?.showOnlyHours) {
            subtitle.startDate = DateUtils.format(this.task?.start, 'DD/MM/YYYY', this._gantt?.options?.language);
            subtitle.endDate = DateUtils.format(this.task?.end, 'DD/MM/YYYY', this._gantt?.options?.language);
        }
        if (!this._gantt?.options?.showOnlyDays) {
            subtitle.startHour = DateUtils.format(this.task?.start, 'HH:mm:ss', this._gantt?.options?.language);
            subtitle.endHour = DateUtils.format(this.task?.end, 'HH:mm:ss', this._gantt?.options?.language);
        }
        this._gantt?.show_popup({
            target_element: this.element,
            title: this.task?.name,
            subtitle: subtitle,
            task: this.task,
            ...args,
        });
    }
    _computeStartEndDate() {
        if (isNullOrUndefined(this._gantt?.options?.columnWidth) || isNullOrUndefined(this._gantt.minDate))
            return null;
        const bar = this.element;
        const xInUnits = bar.getX() / this._gantt.options.columnWidth;
        const newStartDate = DateUtils.add(this._gantt.minDate, xInUnits * (this._gantt.options.step ?? 0), 'hour');
        const widthInUnits = bar.getWidth() / this._gantt.options.columnWidth;
        const newEndDate = DateUtils.add(newStartDate, widthInUnits * (this._gantt.options.step ?? 0), 'hour');
        return { newStartDate, newEndDate };
    }
    _computeX() {
        if (isNullOrUndefined(this._gantt))
            return undefined;
        const options = this._gantt.options;
        if (isNullOrUndefined(options))
            return undefined;
        const { step, columnWidth } = options;
        if (isNullOrUndefined(step) || isNullOrUndefined(columnWidth) || isNullOrUndefined(this.task) || isNullOrUndefined(this._gantt.minDate))
            return undefined;
        let x;
        if (this._gantt?.view_is([ViewMode.QuarterHour, ViewMode.Hour, ViewMode.QuarterDay, ViewMode.HalfDay, ViewMode.Day])) {
            const diff = DateUtils.diff(this.task.start, this._gantt.minDate, 'minutes');
            x = (diff / step) * (columnWidth / 60);
        }
        else {
            const diff = DateUtils.diff(this.task.start, this._gantt.minDate, 'hour');
            x = (diff / step) * columnWidth;
        }
        return x;
    }
    _computeY() {
        return (this._gantt?.options?.headerHeight ?? 0) + (this._gantt?.options?.padding ?? 0) + (this.task?._index ?? 0) * ((this._height ?? 0) + (this._gantt?.options?.padding ?? 0));
    }
    _updateAttr(element, attr, value) {
        value = +value;
        if (!isNaN(value)) {
            element.setAttribute(attr, value);
        }
        return element;
    }
    _updateLabelPosition() {
        const bar = this.element, label = this.group.querySelector('.bar-label');
        if (label.getBBox().width > bar.getWidth()) {
            label.classList.add('big');
            label.setAttribute('x', bar.getX() + bar.getWidth() + 5);
        }
        else {
            label.classList.remove('big');
            label.setAttribute('x', bar.getX() + bar.getWidth() / 2);
        }
    }
    _updateArrowPosition() {
        this._arrows = this._arrows || [];
        for (const arrow of this._arrows) {
            arrow.update();
        }
    }
}

const defaultOptions = {
    headerHeight: 94,
    columnWidth: 30,
    step: 24,
    barHeight: 20,
    barCornerRadius: 0,
    arrowCurve: 4,
    padding: 24,
    viewMode: ViewMode.Day,
    dateFormat: 'YYYY-MM-DD',
    popupTrigger: 'click',
    customPopupHtml: '',
    language: 'en',
    allowMovement: true,
    hasPopup: true,
    showOnlyHours: false,
    showOnlyDays: false,
};

class Popup {
    _parent;
    _customHtml;
    _title;
    _startDate;
    _startHour;
    _endDate;
    _endHour;
    _pointer;
    constructor(parent, customHtml) {
        this._parent = parent;
        this._customHtml = customHtml;
        this._make();
    }
    show(options) {
        if (!options.target_element) {
            throw new Error('target_element is required to show popup');
        }
        if (!options.position) {
            options.position = 'left';
        }
        const targetElement = options.target_element;
        this._parent.style.display = 'block';
        if (this._customHtml) {
            let html = this._customHtml(options.task);
            html += '<div class="pointer"></div>';
            this._parent.innerHTML = html;
            this._pointer = this._parent.querySelector('.pointer');
        }
        else {
            // set data
            this._title.innerHTML = options.title;
            this._startDate.innerHTML = options.subtitle.startDate ?? '';
            this._startHour.innerHTML = options.subtitle.startHour ?? '';
            this._endDate.innerHTML = options.subtitle.endDate ?? '';
            this._endHour.innerHTML = options.subtitle.endHour ?? '';
            this._parent.style.width = this._parent.clientWidth + 'px';
        }
        // set position
        let positionMeta;
        if (targetElement instanceof HTMLElement) {
            positionMeta = targetElement.getBoundingClientRect();
        }
        else if (targetElement instanceof SVGElement) {
            positionMeta = options.target_element.getBBox();
        }
        if (options.position === 'middle') {
            this._parent.style.position = 'fixed';
            this._parent.style.top = options.y + 'px';
            this._pointer.style.transform = 'rotateZ(180deg)';
            this._pointer.style.top = '-10px';
            if ((options.x - 17) + this._parent.offsetWidth > window.innerWidth) {
                this._parent.style.left = (options.x - this._parent.offsetWidth + 17) + 'px';
                this._pointer.style.right = '16px';
                this._pointer.style.left = 'auto';
            }
            else {
                this._parent.style.left = (options.x - 17) + 'px';
                this._pointer.style.left = '16px';
                this._pointer.style.right = 'auto';
            }
        }
        else if (options.position === 'left') {
            this._parent.style.left = positionMeta.x + (positionMeta.width + 10) + 'px';
            this._parent.style.top = positionMeta.y + 'px';
            this._pointer.style.transform = 'rotateZ(90deg)';
            this._pointer.style.left = '-7px';
            this._pointer.style.top = '2px';
        }
        // show
        this._parent.style.opacity = 1;
    }
    _make() {
        this._parent.innerHTML = `
        <div class="popup">
            <div class="wrp-title">
                <span class="title"></span>
            </div>
            <div class="wrp-subtitle">
                <span class="icon fas fa-calendar-alt"></span>
                <div style="margin-right: 15px">
                    <p class="startDate"></p>
                    <p class="startHour"></p>
                </div>
                <div>
                    <p class="endDate"></p>
                    <p class="endHour"></p>
                </div>
            </div>
            <div class="pointer"></div>
        </div>
        `;
        this._hide();
        this._title = this._parent.querySelector('.title');
        this._startDate = this._parent.querySelector('.startDate');
        this._startHour = this._parent.querySelector('.startHour');
        this._endDate = this._parent.querySelector('.endDate');
        this._endHour = this._parent.querySelector('.endHour');
        this._pointer = this._parent.querySelector('.pointer');
    }
    _hide() {
        this._parent.style.opacity = 0;
        this._parent.style.display = 'none';
        this._parent.style.left = 0;
    }
    hide() {
        this._hide();
    }
}

class Gantt {
    options = { ...defaultOptions };
    tasks;
    dependency_map;
    dates;
    layers;
    bars;
    arrows;
    bar_being_dragged;
    $svg;
    $container;
    popup_wrapper;
    popup = null;
    _minDate;
    _maxDate;
    constructor(wrapper, tasks, options) {
        this._setupOptions(options);
        this._setupWrapper(wrapper);
        this.setup_tasks(tasks);
        // initialize with default view mode
        this.change_view_mode();
        this._bindEvents();
    }
    get minDate() {
        return this._minDate;
    }
    get maxDate() {
        return this._maxDate;
    }
    setup_tasks(tasks) {
        // prepare tasks
        this.tasks = tasks.map((task, i) => {
            // standard colors if needed
            task.color = task.color || '#7892A1';
            // convert to Date objects
            task._start = DateUtils.parse(task.start);
            task._end = DateUtils.parse(task.end);
            // make task invalid if duration too large
            if (DateUtils.diff(task._end, task._start, 'year') > 10) {
                task.end = null;
            }
            // cache index
            task._index = i;
            if (typeof task._row_id === 'number') {
                task._index = task._row_id;
            }
            // invalid dates
            if (!task.start && !task.end) {
                const today = DateUtils.today();
                task._start = today;
                task._end = DateUtils.add(today, 2, 'day');
            }
            if (!task.start && task.end) {
                task._start = DateUtils.add(task._end, -2, 'day');
            }
            if (task.start && !task.end) {
                task._end = DateUtils.add(task._start, 2, 'day');
            }
            // if hours is not set, assume the last day is full day
            // e.g: 2018-09-09 becomes 2018-09-09 23:59:59
            const taskEndValues = DateUtils.getDateValues(task._end);
            if (taskEndValues.slice(3).every((d) => d === 0)) {
                task._end = DateUtils.add(task._end, 24, 'hour');
            }
            // invalid flag
            if (!task.start || !task.end) {
                task.invalid = true;
            }
            // dependencies
            if (typeof task.dependencies === 'string' || !task.dependencies) {
                let deps = [];
                if (task.dependencies) {
                    deps = task.dependencies
                        .split(',')
                        .map((d) => d.trim())
                        .filter((d) => d);
                }
                task.dependencies = deps;
            }
            // uids
            if (!task.id) {
                task.id = generate_id(task);
            }
            return task;
        });
        this._setupDependencies();
    }
    refresh(tasks) {
        this.setup_tasks(tasks);
        this.change_view_mode();
    }
    change_view_mode(mode = this.options?.viewMode) {
        this._setupGanttDates();
        this._updateViewScale(mode);
        this._setupDates();
        this._render();
        // fire viewmode_change event
        this.trigger_event('onViewChange', [mode]);
    }
    make_grid_highlights() {
        if (this.view_is(ViewMode.Day)) {
            const width = this.options?.columnWidth;
            const height = ((this.options?.barHeight ?? 0) + (this.options?.padding ?? 0)) * (this.tasks?.length ?? 0) +
                (this.options?.headerHeight ?? 0) +
                (this.options?.padding ?? 0) / 2;
            let x = 0;
            if (isNullOrUndefined(this.dates))
                return;
            for (const date of this.dates) {
                let y = ((this.options?.headerHeight ?? 0) + (this.options?.padding ?? 0)) / 2;
                const isToday = date === DateUtils.today();
                const isWeekend = date.getDay() === 0 || date.getDay() === 6;
                let className;
                if (isToday) {
                    className = 'today-highlight';
                    y = ((this.options?.headerHeight ?? 0) + (this.options?.padding ?? 0)) / 2;
                }
                else if (isWeekend) {
                    className = 'weekend-highlight';
                }
                const rx = 3;
                const ry = 3;
                if (isToday || isWeekend) {
                    createSVG('rect', {
                        x,
                        y,
                        rx,
                        ry,
                        width,
                        height,
                        class: className,
                        append_to: this.layers.grid,
                    });
                }
                x += this.options?.columnWidth ?? 0;
            }
        }
    }
    unselect_all() {
        [...this.$svg.querySelectorAll('.bar-wrapper')].forEach((el) => {
            el.classList.remove('active');
        });
    }
    view_is(modes) {
        if (Array.isArray(modes)) {
            return modes.some((mode) => this.options?.viewMode === mode);
        }
        return this.options?.viewMode === modes;
    }
    get_bar(id) {
        return this.bars?.find((bar) => bar.task.id === id);
    }
    show_popup(options) {
        if (!this.popup) {
            this.popup = new Popup(this.popup_wrapper, this.options?.customPopupHtml);
        }
        this.popup.show(options);
    }
    hide_popup() {
        this.popup?.hide();
    }
    trigger_event(event, args) {
        if (this.options?.[event]) {
            this.options[event].apply(null, args);
        }
    }
    _setupWrapper(element) {
        let svgElement, wrapperElement;
        // CSS Selector is passed
        if (typeof element === 'string') {
            element = document.querySelector(element);
        }
        else if (element instanceof SVGElement) {
            // Se já for SVGElement direto, usar como tal
            svgElement = element;
        }
        // get the SVGElement
        if (!svgElement && element instanceof HTMLElement) {
            wrapperElement = element;
            svgElement = element.querySelector('svg');
        }
        else if (element instanceof SVGElement) {
            svgElement = element;
        }
        else {
            throw new TypeError(
            // eslint-disable-next-line max-len
            "Frappé Gantt only supports usage of a string CSS selector, HTML DOM element or SVG DOM element for the 'element' parameter");
        }
        // svg element
        if (!svgElement) {
            // create it
            this.$svg = createSVG('svg', {
                append_to: wrapperElement,
                class: 'gantt',
            });
        }
        else {
            this.$svg = svgElement;
            this.$svg.classList.add('gantt');
        }
        // wrapper element
        this.$container = document.createElement('div');
        this.$container.classList.add('gantt-container');
        if (this.options?.containerWidth) {
            this.$container.style.width = this.options.containerWidth + 'px';
        }
        const parentElement = this.$svg.parentElement;
        parentElement.appendChild(this.$container);
        this.$container.appendChild(this.$svg);
        // popup wrapper
        this.popup_wrapper = document.createElement('div');
        this.popup_wrapper.classList.add('popup-wrapper');
        this.$container.appendChild(this.popup_wrapper);
    }
    _setupOptions(options) {
        this.options = Object.assign({}, defaultOptions, options);
    }
    _setupDependencies() {
        this.dependency_map = {};
        if (isNullOrUndefined(this.tasks))
            return;
        for (const t of this.tasks) {
            if (isNullOrUndefined(t.dependencies))
                continue;
            for (const d of t.dependencies) {
                this.dependency_map[d] = this.dependency_map[d] || [];
                this.dependency_map[d].push(t.id);
            }
        }
    }
    _updateViewScale(view_mode) {
        if (isNullOrUndefined(this.options))
            return;
        this.options.viewMode = view_mode;
        if (view_mode === ViewMode.QuarterHour) {
            this.options.step = 24 / 24 / 4;
            this.options.columnWidth = 50;
        }
        else if (view_mode === ViewMode.Hour) {
            this.options.step = 24 / 24;
            this.options.columnWidth = 50;
        }
        else if (view_mode === ViewMode.Day) {
            this.options.step = 24;
            this.options.columnWidth = 50;
        }
        else if (view_mode === ViewMode.HalfDay) {
            this.options.step = 24 / 2;
            this.options.columnWidth = 50;
        }
        else if (view_mode === ViewMode.QuarterDay) {
            this.options.step = 24 / 4;
            this.options.columnWidth = 50;
        }
        else if (view_mode === ViewMode.Week) {
            this.options.step = 24 * 7;
            this.options.columnWidth = 140;
        }
        else if (view_mode === ViewMode.Month) {
            this.options.step = 24 * 30;
            this.options.columnWidth = 120;
        }
        else if (view_mode === ViewMode.Year) {
            this.options.step = 24 * 365;
            this.options.columnWidth = 120;
        }
    }
    _setupDates() {
        this._setupDateValues();
    }
    _setupGanttDates() {
        this._minDate = undefined;
        this._maxDate = undefined;
        if (!isNullOrUndefined(this.tasks)) {
            for (const task of this.tasks) {
                // set global start and end date
                if (!this.minDate || task.start < this.minDate) {
                    this._minDate = DateUtils.startOf(task.start, 'day');
                }
                if (!this.maxDate || task.end > this.maxDate) {
                    this._maxDate = task.end;
                }
            }
        }
        if (isNullOrUndefined(this.minDate) || isNullOrUndefined(this.maxDate))
            return;
        switch (this.options?.viewMode) {
            case ViewMode.QuarterHour:
                this._minDate = DateUtils.add(this.minDate, -(this.options.marginBeforeStart ?? 15), 'minutes');
                this._maxDate = DateUtils.add(this.maxDate, this.options.marginAfterEnd ?? 15, 'minutes');
                break;
            case ViewMode.Hour:
                this._minDate = DateUtils.add(this.minDate, -(this.options.marginBeforeStart ?? 1), 'hour');
                this._maxDate = DateUtils.add(this.maxDate, this.options.marginAfterEnd ?? 1, 'hour');
                break;
            case ViewMode.QuarterDay:
                this._minDate = DateUtils.add(this.minDate, -(this.options.marginBeforeStart ?? 6), 'hour');
                this._maxDate = DateUtils.add(this.maxDate, this.options.marginAfterEnd ?? 6, 'hour');
                break;
            case ViewMode.HalfDay:
                this._minDate = DateUtils.add(this.minDate, -(this.options.marginBeforeStart ?? 12), 'hour');
                this._maxDate = DateUtils.add(this.maxDate, this.options.marginAfterEnd ?? 12, 'hour');
                break;
            case ViewMode.Day:
                this._minDate = DateUtils.add(this.minDate, -(this.options.marginBeforeStart ?? 1), 'day');
                this._maxDate = DateUtils.add(this.maxDate, this.options.marginAfterEnd ?? 1, 'day');
                break;
            case ViewMode.Week:
                this._minDate = DateUtils.add(this.minDate, -(this.options.marginBeforeStart ?? 1), 'week');
                this._maxDate = DateUtils.add(this.maxDate, this.options.marginAfterEnd ?? 1, 'week');
                break;
            case ViewMode.Month:
                this._minDate = DateUtils.add(this.minDate, -(this.options.marginBeforeStart ?? 1), 'month');
                this._maxDate = DateUtils.add(this.maxDate, this.options.marginAfterEnd ?? 1, 'month');
                break;
            case ViewMode.Year:
                this._minDate = DateUtils.add(this.minDate, -(this.options.marginBeforeStart ?? 1), 'year');
                this._maxDate = DateUtils.add(this.maxDate, this.options.marginAfterEnd ?? 1, 'year');
                break;
        }
    }
    _setupDateValues() {
        this.dates = [];
        let curDate = null;
        if (!isNullOrUndefined(this.minDate) && !isNullOrUndefined(this.maxDate)) {
            while (curDate === null || curDate < this.maxDate) {
                if (!curDate) {
                    curDate = DateUtils.clone(this.minDate);
                }
                else {
                    if (this.view_is(ViewMode.Year)) {
                        curDate = DateUtils.add(curDate, 1, 'year');
                    }
                    else if (this.view_is(ViewMode.Month)) {
                        curDate = DateUtils.add(curDate, 1, 'month');
                    }
                    else {
                        curDate = DateUtils.add(curDate, this.options?.step, 'hour');
                    }
                }
                this.dates.push(curDate);
            }
        }
        if (this.options?.containerWidth) {
            const columnWidth = (this.options.containerWidth - 1) / this.dates.length;
            this.options.columnWidth = columnWidth < 45 ? 45 : columnWidth;
        }
    }
    _bindEvents() {
        this._bindGridClick();
        this._bindBarEvents();
    }
    _render() {
        this._clear();
        this._setupLayers();
        this._makeGrid();
        this._makeDates();
        this._makeBars();
        this._makeArrows();
        this._mapArrowsOnBars();
        this._setWidth();
        this._setScrollPosition();
    }
    _setupLayers() {
        this.layers = {};
        const layers = ['grid', 'date', 'arrow', 'progress', 'bar', 'details'];
        // make group layers
        for (const layer of layers) {
            this.layers[layer] = createSVG('g', {
                class: layer,
                append_to: this.$svg,
            });
        }
    }
    _makeGrid() {
        this._makeGridBackground();
        this._makeGridRows();
        this._makeGridHeader();
        this.make_grid_highlights();
        this._makeGridTicks();
    }
    _makeGridBackground() {
        let gridWidth = (this.dates?.length ?? 0) * (this.options?.columnWidth ?? 0);
        if (this.options?.containerWidth) {
            gridWidth = this.options.containerWidth;
        }
        const distinctRows = [...new Set(this.tasks?.map((x) => x._row_id))];
        const gridHeight = (this.options?.headerHeight ?? 0) +
            (this.options?.padding ?? 0) / 2 +
            ((this.options?.barHeight ?? 0) + (this.options?.padding ?? 0)) * distinctRows.length;
        createSVG('rect', {
            x: 0,
            y: 0,
            width: gridWidth,
            height: gridHeight,
            class: 'grid-background',
            append_to: this.layers.grid,
        });
        $.attr(this.$svg, {
            height: gridHeight,
            width: '100%',
        }, null);
    }
    _makeGridRows() {
        const rowsLayer = createSVG('g', { append_to: this.layers.grid });
        const linesLayer = createSVG('g', { append_to: this.layers.grid });
        const rowWidth = (this.dates?.length ?? 0) * (this.options?.columnWidth ?? 0);
        const rowHeight = (this.options?.barHeight ?? 0) + (this.options?.padding ?? 0);
        let rowY = (this.options?.headerHeight ?? 0) + (this.options?.padding ?? 0) / 2;
        this.tasks?.forEach((_) => {
            createSVG('rect', {
                x: 0,
                y: rowY,
                width: rowWidth,
                height: rowHeight,
                class: 'grid-row',
                append_to: rowsLayer,
            });
            createSVG('line', {
                x1: 0,
                y1: rowY + rowHeight,
                x2: rowWidth,
                y2: rowY + rowHeight,
                class: 'row-line',
                append_to: linesLayer,
            });
            rowY += (this.options?.barHeight ?? 0) + (this.options?.padding ?? 0);
        });
    }
    _makeGridHeader() {
        // const addIsHourView = this.isHourView ? 25 : 10
        const headerWidth = (this.dates?.length ?? 0) * (this.options?.columnWidth ?? 0);
        const headerHeight = (this.options?.headerHeight ?? 0) + 10;
        createSVG('rect', {
            x: 0,
            y: 0,
            width: headerWidth,
            height: headerHeight,
            class: 'grid-header',
            append_to: this.layers.grid,
        });
    }
    _makeGridTicks() {
        let tickX = 0;
        const tickY = (this.options?.headerHeight ?? 0) + (this.options?.padding ?? 0) / 2;
        const tickHeight = ((this.options?.barHeight ?? 0) + (this.options?.padding ?? 0)) * (this.tasks?.length ?? 0);
        if (isNullOrUndefined(this.dates))
            return;
        for (const date of this.dates) {
            let tickClass = 'tick';
            if (this.view_is(ViewMode.QuarterHour) && date.getHours() === 0 && date.getMinutes() === 0) {
                // thick tick for first hour of day.
                tickClass += ' thick';
            }
            else if (this.view_is([ViewMode.Hour, ViewMode.QuarterDay, ViewMode.HalfDay]) && date.getHours() === 0) {
                // thick tick for first hour of day.
                tickClass += ' thick';
            }
            else if (this.view_is(ViewMode.Day) && date.getDate() === 1) {
                // thick tick for monday
                tickClass += ' thick';
            }
            else if (this.view_is(ViewMode.Week) && date.getDate() >= 1 && date.getDate() < 8) {
                // thick tick for first week
                tickClass += ' thick';
            }
            else if (this.view_is(ViewMode.Month) && date.getMonth() % 3 === 0) {
                // thick ticks for quarters
                tickClass += ' thick';
            }
            createSVG('path', {
                d: `M ${tickX} ${tickY} v ${tickHeight}`,
                class: tickClass,
                append_to: this.layers.grid,
            });
            if (this.view_is(ViewMode.Month)) {
                tickX += (DateUtils.getDaysInMonth(date) * (this.options?.columnWidth ?? 0)) / 30;
            }
            else {
                tickX += this.options?.columnWidth ?? 0;
            }
        }
    }
    _makeDates() {
        const dates = this._getDatesToDraw();
        if (isNullOrUndefined(dates))
            return;
        for (let i = 0; i < dates.length; i++) {
            const date = dates[i];
            createSVG('text', {
                x: date.lower_x,
                y: date.lower_y + 20,
                innerHTML: date.lower_text,
                class: 'title-2',
                append_to: this.layers.date,
            });
            if (date.middle_text) {
                createSVG('text', {
                    x: date.middle_x,
                    y: date.middle_y,
                    innerHTML: date.middle_text,
                    class: 'middle-text',
                    append_to: this.layers.date,
                });
            }
            if (date.upper_text) {
                const $upperText = createSVG('text', {
                    x: date.upper_x,
                    y: date.upper_y,
                    innerHTML: date.upper_text,
                    class: 'upper-text',
                    append_to: this.layers.date,
                });
                // remove out-of-bound dates
                if ($upperText.getBBox().x2 > this.layers.grid.getBBox().width) {
                    $upperText.remove();
                }
            }
        }
    }
    _getDatesToDraw() {
        let lastDate = null;
        const dates = this.dates?.map((date, i) => {
            const d = this._getDateInfo(date, lastDate, i);
            lastDate = date;
            return d;
        });
        return dates;
    }
    _getDateInfo(date, last_date, i) {
        if (!last_date) {
            last_date = DateUtils.add(date, 1, 'year');
        }
        const dateText = {
            // quarter hour
            quarterHourUpper: date.getDate() !== last_date.getDate() ? DateUtils.format(date, 'D MMM', this.options?.language) : '',
            quarterHourLower: DateUtils.format(date, 'HH:mm', this.options?.language),
            // hour
            hourUpper: date.getDate() !== last_date.getDate() ? DateUtils.format(date, 'D MMM', this.options?.language) : '',
            hourLower: DateUtils.format(date, 'HH:mm', this.options?.language),
            // quarter day
            quarterDayUpper: date.getDate() !== last_date.getDate() ? DateUtils.format(date, 'D MMM', this.options?.language) : '',
            quarterDayLower: DateUtils.format(date, 'HH:mm', this.options?.language),
            // half day
            halfDayUpper: date.getDate() !== last_date.getDate()
                ? date.getMonth() !== last_date.getMonth() || i < 2
                    ? DateUtils.format(date, 'D MMM', this.options?.language)
                    : DateUtils.format(date, 'D', this.options?.language)
                : '',
            halfDayLower: DateUtils.format(date, 'HH:mm', this.options?.language),
            // day
            dayUpper: date.getMonth() !== last_date.getMonth() || i === 0 ? DateUtils.format(date, 'MMMM', this.options?.language) : '',
            dayMiddle: DateUtils.format(date, 'ddd', this.options?.language),
            dayLower: DateUtils.format(date, 'D', this.options?.language),
            // week
            weekUpper: date.getMonth() !== last_date.getMonth() ? DateUtils.format(date, 'MMMM', this.options?.language) : '',
            weekLower: date.getMonth() !== last_date.getMonth()
                ? DateUtils.format(date, 'D MMM', this.options?.language)
                : DateUtils.format(date, 'D', this.options?.language),
            // month
            monthUpper: date.getFullYear() !== last_date.getFullYear() ? DateUtils.format(date, 'YYYY', this.options?.language) : '',
            monthLower: DateUtils.format(date, 'MMMM', this.options?.language),
            // year
            yearUpper: date.getFullYear() !== last_date.getFullYear() ? DateUtils.format(date, 'YYYY', this.options?.language) : '',
            yearLower: DateUtils.format(date, 'YYYY', this.options?.language),
        };
        // Descontando 20 para adcionar uma segunda linha de informação no cabeçalho
        const basePos = {
            x: i * (this.options?.columnWidth ?? 0),
            upper_y: (this.options?.headerHeight ?? 0) - 20 - 25,
            middle_y: (this.options?.headerHeight ?? 0) - 20,
            lower_y: (this.options?.headerHeight ?? 0) - 20,
        };
        const xPos = {
            quarterHourUpper: (this.dates?.length ?? 0) < 14 ? (this.options?.columnWidth ?? 0) : ((this.options?.columnWidth ?? 0) * 24) / 2,
            quarterHourMiddle: (this.options?.columnWidth ?? 0) / 2,
            quarterHourLower: (this.options?.columnWidth ?? 0) / 2,
            hourUpper: (this.dates?.length ?? 0) < 14 ? (this.options?.columnWidth ?? 0) : ((this.options?.columnWidth ?? 0) * 24) / 2,
            hourMiddle: (this.options?.columnWidth ?? 0) / 2,
            hourLower: (this.options?.columnWidth ?? 0) / 2,
            quarterDayUpper: ((this.options?.columnWidth ?? 0) * 4) / 2,
            quarterDayMiddle: (this.options?.columnWidth ?? 0) / 2,
            quarterDayLower: (this.options?.columnWidth ?? 0) / 2,
            halfDayUpper: ((this.options?.columnWidth ?? 0) * 2) / 2,
            halfDayMiddle: (this.options?.columnWidth ?? 0) / 2,
            halfDayLower: (this.options?.columnWidth ?? 0) / 2,
            dayUpper: (this.dates?.length ?? 0) < 15 ? (this.options?.columnWidth ?? 0) : ((this.options?.columnWidth ?? 0) * 30) / 2,
            dayMiddle: (this.options?.columnWidth ?? 0) / 2 - 12,
            dayLower: (this.options?.columnWidth ?? 0) / 2,
            weekUpper: ((this.options?.columnWidth ?? 0) * 4) / 2,
            weekMiddle: 0,
            weekLower: 0,
            monthUpper: (this.dates?.length ?? 0) < 15 ? (this.options?.columnWidth ?? 0) : ((this.options?.columnWidth ?? 0) * 12) / 2,
            monthMiddle: 0,
            monthLower: (this.options?.columnWidth ?? 0) / 2,
            yearUpper: ((this.options?.columnWidth ?? 0) * 30) / 2,
            yearMiddle: (this.options?.columnWidth ?? 0) / 2,
            yearLower: (this.options?.columnWidth ?? 0) / 2,
        };
        return {
            upper_text: dateText[`${this.options?.viewMode ?? 'day'}Upper`],
            middle_text: dateText[`${this.options?.viewMode ?? 'day'}Middle`],
            lower_text: dateText[`${this.options?.viewMode ?? 'day'}Lower`],
            upper_x: basePos.x + xPos[`${this.options?.viewMode ?? 'day'}Upper`],
            upper_y: basePos.upper_y,
            middle_x: basePos.x + xPos[`${this.options?.viewMode ?? 'day'}Middle`],
            middle_y: basePos.middle_y,
            lower_x: basePos.x + xPos[`${this.options?.viewMode ?? 'day'}Lower`],
            lower_y: basePos.lower_y,
            date,
        };
    }
    _makeBars() {
        this.bars = this.tasks?.map((task) => {
            const bar = new Bar(this, task);
            this.layers.bar.appendChild(bar.group);
            return bar;
        });
    }
    _makeArrows() {
        this.arrows = [];
        if (isNullOrUndefined(this.tasks))
            return;
        for (const task of this.tasks) {
            if (isNullOrUndefined(task.dependencies))
                continue;
            let arrows = [];
            arrows = task.dependencies
                .map((task_id) => {
                const dependency = this._getTask(task_id);
                if (!dependency || !this.bars)
                    return undefined;
                const arrow = new Arrow(this, this.bars[dependency._index], // from_task
                this.bars[task._index]);
                this.layers.arrow.appendChild(arrow.element);
                return arrow;
            })
                .filter((arrow) => arrow !== undefined); // filter undefined values
            this.arrows = this.arrows.concat(arrows);
        }
    }
    _mapArrowsOnBars() {
        if (isNullOrUndefined(this.bars))
            return;
        for (const bar of this.bars) {
            bar.arrows = this.arrows?.filter((arrow) => arrow.fromTask.task?.id === bar.task?.id || arrow.toTask.task?.id === bar.task?.id) ?? [];
        }
    }
    _setWidth() {
        const curWidth = this.$svg.getBoundingClientRect().width;
        const actualWidth = this.$svg.querySelector('.grid .grid-row').getAttribute('width');
        if (curWidth < actualWidth) {
            this.$svg.setAttribute('width', actualWidth);
        }
    }
    _setScrollPosition() {
        const parentElement = this.$svg.parentElement;
        if (!parentElement || !this.minDate)
            return;
        const hoursBeforeFirstTask = DateUtils.diff(this._getOldestStartingDate(), this.minDate, 'hour');
        const scrollPos = (hoursBeforeFirstTask / (this.options?.step ?? 0)) * (this.options?.columnWidth ?? 0) - (this.options?.columnWidth ?? 0);
        parentElement.scrollLeft = scrollPos;
    }
    _bindGridClick() {
        $.on(this.$svg, this.options?.popupTrigger, '.grid-row, .grid-header', () => {
            this.unselect_all();
            this.hide_popup();
        });
    }
    _bindBarEvents() {
        let isDragging = false;
        let xOnStart = 0;
        let isResizingLeft = false;
        let isResizingRight = false;
        let parentBarId = null;
        let bars = [];
        this.bar_being_dragged = null;
        function action_in_progress() {
            return isDragging || isResizingLeft || isResizingRight;
        }
        $.on(this.$svg, 'mousedown', '.bar-wrapper, .handle', (e, element) => {
            const barWrapper = $.closest('.bar-wrapper', element);
            if (element.classList.contains('left')) {
                isResizingLeft = true;
            }
            else if (element.classList.contains('right')) {
                isResizingRight = true;
            }
            else if (element.classList.contains('bar-wrapper') && this.options?.allowMovement) {
                isDragging = true;
            }
            barWrapper?.classList.add('active');
            xOnStart = e.offsetX;
            parentBarId = barWrapper?.getAttribute('data-id');
            const ids = [parentBarId, ...this._getAllDependentTasks(parentBarId)];
            bars = ids.map((id) => this.get_bar(id)).filter((bar) => bar !== undefined);
            this.bar_being_dragged = parentBarId;
            bars.forEach((bar) => {
                const $bar = bar.element;
                $bar.ox = $bar.getX();
                $bar.oy = $bar.getY();
                $bar.owidth = $bar.getWidth();
                $bar.finaldx = 0;
            });
        });
        $.on(this.$svg, 'mousemove', (e) => {
            if (!action_in_progress()) {
                return;
            }
            const dx = e.offsetX - xOnStart;
            bars.forEach((bar) => {
                const $bar = bar.element;
                $bar.finaldx = this._getSnapPosition(dx);
                this.hide_popup();
                if (isResizingLeft) {
                    if (parentBarId === bar.task?.id) {
                        bar.updateBarPosition({
                            x: $bar.ox + $bar.finaldx,
                            width: $bar.owidth - $bar.finaldx,
                        });
                    }
                    else {
                        bar.updateBarPosition({
                            x: $bar.ox + $bar.finaldx,
                        });
                    }
                }
                else if (isResizingRight) {
                    if (parentBarId === bar.task?.id) {
                        bar.updateBarPosition({
                            width: $bar.owidth + $bar.finaldx,
                        });
                    }
                }
                else if (isDragging) {
                    bar.updateBarPosition({ x: $bar.ox + $bar.finaldx });
                }
            });
        }, null);
        document.addEventListener('mouseup', (e) => {
            if (isDragging || isResizingLeft || isResizingRight || !this.options?.allowMovement) {
                bars.forEach((bar) => bar.group.classList.remove('active'));
            }
            isDragging = false;
            isResizingLeft = false;
            isResizingRight = false;
        });
        $.on(this.$svg, 'mouseup', (e) => {
            this.bar_being_dragged = null;
            bars.forEach((bar) => {
                const $bar = bar.element;
                if (!$bar.finaldx)
                    return;
                bar.dateChanged();
                bar.setActionCompleted();
            });
        }, null);
    }
    _getAllDependentTasks(task_id) {
        let out = [];
        let toProcess = [task_id];
        while (toProcess.length) {
            const deps = toProcess.reduce((acc, curr) => {
                acc = acc.concat(this.dependency_map[curr]);
                return acc;
            }, []);
            out = out.concat(deps);
            toProcess = deps.filter((d) => !toProcess.includes(d));
        }
        return out.filter(Boolean);
    }
    _getSnapPosition(dx) {
        const odx = dx;
        let rem;
        let position;
        if (this.view_is(ViewMode.Hour)) {
            rem = dx % ((this.options?.columnWidth ?? 0) / 6);
            position = odx - rem + (rem < (this.options?.columnWidth ?? 0) / 12 ? 0 : (this.options?.columnWidth ?? 0) / 6);
        }
        else if (this.view_is(ViewMode.Week)) {
            rem = dx % ((this.options?.columnWidth ?? 0) / 7);
            position = odx - rem + (rem < (this.options?.columnWidth ?? 0) / 14 ? 0 : (this.options?.columnWidth ?? 0) / 7);
        }
        else if (this.view_is(ViewMode.Month)) {
            rem = dx % ((this.options?.columnWidth ?? 0) / 30);
            position = odx - rem + (rem < (this.options?.columnWidth ?? 0) / 60 ? 0 : (this.options?.columnWidth ?? 0) / 30);
        }
        else {
            rem = dx % (this.options?.columnWidth ?? 0);
            position = odx - rem + (rem < (this.options?.columnWidth ?? 0) / 2 ? 0 : (this.options?.columnWidth ?? 0));
        }
        return position;
    }
    _getTask(id) {
        return this.tasks?.find((task) => task.id === id);
    }
    _getOldestStartingDate() {
        return this.tasks?.map((task) => task._start).reduce((prev_date, cur_date) => (cur_date <= prev_date ? cur_date : prev_date));
    }
    _clear() {
        this.$svg.innerHTML = '';
    }
}
function generate_id(task) {
    return task.name + '_' + Math.random().toString(36).slice(2, 12);
}

/* eslint-disable @angular-eslint/component-selector */
class SideTableComponent {
    columnTitle;
    tasks;
    multipleTaskPerLine = false;
    ROW_HEIGHT = 44;
    ngOnInit() {
        this._removeEmptyTasks();
    }
    _removeEmptyTasks() {
        this.tasks = this.tasks.filter((task) => task.tasks.length);
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: SideTableComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
    static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: SideTableComponent, isStandalone: true, selector: "gantt-side-table", inputs: { columnTitle: "columnTitle", tasks: "tasks", multipleTaskPerLine: "multipleTaskPerLine" }, ngImport: i0, template: "<div class=\"side-table\">\n    <div class=\"column-title\">\n        <span>{{ columnTitle }}</span>\n    </div>\n    <div class=\"tasks\" >\n        @for(task of tasks; track task.id; let i = $index) {\n            <div\n                class=\"task\"\n                [ngStyle]=\"{'height.px': multipleTaskPerLine\n                        ? ROW_HEIGHT\n                        : ROW_HEIGHT * task.tasks.length}\"\n                [sTooltip]=\"task.title.length > 20 || task.subtitle.length > 20 ? '<span><strong>' + task.title + ' </strong></br><span> ' + task.subtitle + ' </span></span>' : '' \"\n                [escape]=\"false\">\n                    <div class=\"title\">\n                        {{ task.title }}\n                    </div>\n                    <div class=\"subtitle\">\n                        {{ task.subtitle }}\n                    </div>\n            </div>\n        }\n    </div>\n</div>\n", styles: [".side-table{background:#fff;height:100%;min-width:175px}.side-table .column-title{height:106px;border:solid 1px #e0e0e0;box-sizing:border-box;display:flex;align-items:flex-end;justify-content:center;padding:8px}.side-table .column-title span{font-family:\"Open Sans\" sans-serif;font-size:14px;font-weight:700;line-height:150%}.side-table .task{align-items:center;background-color:#fff;border:solid 1px #e0e0e0;display:flex;flex-direction:column;font-family:Open Sans,sans-serif;font-weight:400;justify-content:center;line-height:150%;padding:0 5px}.side-table .task .title{color:#333;font-size:14px;max-width:300px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.side-table .task .subtitle{color:#999;font-size:12px;max-width:300px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n"], dependencies: [{ kind: "directive", type: NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: TooltipDirective, selector: "[sTooltip]", inputs: ["sTooltip", "tooltipPosition", "showDelay", "displayTime", "tooltipEvent", "escape", "visible", "mobileBehavior", "focusedInputRef", "checkTruncatedText"] }] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: SideTableComponent, decorators: [{
            type: Component,
            args: [{ selector: 'gantt-side-table', standalone: true, imports: [NgStyle, TooltipDirective], template: "<div class=\"side-table\">\n    <div class=\"column-title\">\n        <span>{{ columnTitle }}</span>\n    </div>\n    <div class=\"tasks\" >\n        @for(task of tasks; track task.id; let i = $index) {\n            <div\n                class=\"task\"\n                [ngStyle]=\"{'height.px': multipleTaskPerLine\n                        ? ROW_HEIGHT\n                        : ROW_HEIGHT * task.tasks.length}\"\n                [sTooltip]=\"task.title.length > 20 || task.subtitle.length > 20 ? '<span><strong>' + task.title + ' </strong></br><span> ' + task.subtitle + ' </span></span>' : '' \"\n                [escape]=\"false\">\n                    <div class=\"title\">\n                        {{ task.title }}\n                    </div>\n                    <div class=\"subtitle\">\n                        {{ task.subtitle }}\n                    </div>\n            </div>\n        }\n    </div>\n</div>\n", styles: [".side-table{background:#fff;height:100%;min-width:175px}.side-table .column-title{height:106px;border:solid 1px #e0e0e0;box-sizing:border-box;display:flex;align-items:flex-end;justify-content:center;padding:8px}.side-table .column-title span{font-family:\"Open Sans\" sans-serif;font-size:14px;font-weight:700;line-height:150%}.side-table .task{align-items:center;background-color:#fff;border:solid 1px #e0e0e0;display:flex;flex-direction:column;font-family:Open Sans,sans-serif;font-weight:400;justify-content:center;line-height:150%;padding:0 5px}.side-table .task .title{color:#333;font-size:14px;max-width:300px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.side-table .task .subtitle{color:#999;font-size:12px;max-width:300px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n"] }]
        }], propDecorators: { columnTitle: [{
                type: Input,
                args: [{ required: true }]
            }], tasks: [{
                type: Input,
                args: [{ required: true }]
            }], multipleTaskPerLine: [{
                type: Input
            }] } });

/**
 * @description Componente de diagrama de Gantt para visualização e manipulação de tarefas
 * em linha do tempo. Suporta diferentes modos de visualização (dia, semana, mês),
 * movimentação de tarefas via drag e popup de detalhes ao clicar.
 *
 * @example
 * ```html
 * <s-gantt
 *   [tasks]="gruposDeTarefas"
 *   [viewMode]="viewMode"
 *   (taskClicked)="onTaskClicada($event)" />
 * ```
 *
 * @category Data
 */
class GanttComponent {
    /** @description Título da coluna lateral de identificação das tarefas. */
    columnTitle;
    /** @description Permite renderizar múltiplas tarefas na mesma linha. @default false */
    multipleTaskPerLine = false;
    /** @description Exibe a tabela lateral com os nomes das tarefas. @default true */
    showSideTable = true;
    /** @description Modo de visualização do gantt (dia, semana, mês, etc.). @default ViewMode.Day */
    viewMode = ViewMode.Day;
    /** @description Lista de grupos de tarefas a serem renderizados. Campo obrigatório. */
    tasks;
    /** @description Margem em dias antes do início da primeira tarefa. */
    marginBeforeStart;
    /** @description Margem em dias após o fim da última tarefa. */
    marginAfterEnd;
    /** @description Habilita o arrastar de tarefas para alterar datas. @default true */
    allowMovement = true;
    /** @description Exibe popup com detalhes ao clicar em uma tarefa. @default true */
    hasPopup = true;
    /** @description Largura do container em pixels. Se omitido, usa a largura natural. */
    containerWidth;
    /** @description Faz o gantt ocupar 100% da largura disponível. @default false */
    fullWidth = false;
    /** @description Exibe apenas horas na linha do tempo (ignora dias). @default false */
    showOnlyHours = false;
    /** @description Exibe apenas dias na linha do tempo (ignora horas). @default false */
    showOnlyDays = false;
    /** @description Emitido quando o usuário clica em uma tarefa. */
    taskClicked = new EventEmitter();
    /** @description Emitido quando o usuário arrasta e modifica as datas de uma tarefa. */
    taskDateChanged = new EventEmitter();
    /** @description Emitido quando o modo de visualização é alterado. */
    viewChanged = new EventEmitter();
    outer = null;
    side = null;
    ganttSvg = null;
    _gantt;
    ngOnInit() {
        this._validateViewMode();
        this._validateTasks();
    }
    ngAfterViewInit() {
        if (this.fullWidth) {
            this.containerWidth = this.outer?.nativeElement.offsetWidth - this.side?.nativeElement.offsetWidth;
        }
        this._gantt = new Gantt(this.ganttSvg.nativeElement, this._filterTask(this.tasks), {
            viewMode: this.viewMode,
            marginBeforeStart: this.marginBeforeStart,
            marginAfterEnd: this.marginAfterEnd,
            language: 'pt-br',
            allowMovement: this.allowMovement,
            hasPopup: this.hasPopup,
            containerWidth: this.containerWidth,
            showOnlyHours: this.showOnlyHours,
            showOnlyDays: this.showOnlyDays,
            onClick: (task) => this.taskClicked.emit(task),
            onDateChange: (task, start, end) => this.taskDateChanged.emit({ task, start, end }),
            onViewChange: (viewMode) => this.viewChanged.emit(viewMode),
        });
    }
    ngOnChanges(changes) {
        if (!this._gantt) {
            return;
        }
        if (changes['viewMode'] && !isNullOrUndefined(this._gantt.options?.viewMode)) {
            this._gantt.options.viewMode = changes['viewMode'].currentValue;
            this._gantt.change_view_mode();
        }
        if (changes['tasks']) {
            this._gantt.refresh(this._filterTask(changes['tasks'].currentValue));
        }
    }
    _filterTask(tasksGroups) {
        const tasks = [];
        if (this.multipleTaskPerLine) {
            tasksGroups.forEach((group, index) => {
                tasks.push(...group.tasks.map((task) => ({ ...task, _row_id: index })));
            }, []);
        }
        else {
            let i = 0;
            tasksGroups.forEach((group) => {
                tasks.push(...group.tasks.map((task) => ({ ...task, _row_id: i++ })));
            }, []);
        }
        return tasks;
    }
    _validateViewMode() {
        if (![
            ViewMode.QuarterHour,
            ViewMode.Hour,
            ViewMode.QuarterDay,
            ViewMode.HalfDay,
            ViewMode.Day,
            ViewMode.Week,
            ViewMode.Month,
            ViewMode.Year,
        ].includes(this.viewMode)) {
            throw new Error('Invalid gantt view mode');
        }
    }
    _validateTasks() {
        this.tasks.forEach((group) => {
            group.tasks.forEach((task) => {
                if (task.start > task.end) {
                    throw new Error('invalid task. The start date must be less than the end date.');
                }
            });
        });
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: GanttComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
    static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: GanttComponent, isStandalone: true, selector: "s-gantt", inputs: { columnTitle: "columnTitle", multipleTaskPerLine: "multipleTaskPerLine", showSideTable: "showSideTable", viewMode: "viewMode", tasks: "tasks", marginBeforeStart: "marginBeforeStart", marginAfterEnd: "marginAfterEnd", allowMovement: "allowMovement", hasPopup: "hasPopup", containerWidth: "containerWidth", fullWidth: "fullWidth", showOnlyHours: "showOnlyHours", showOnlyDays: "showOnlyDays" }, outputs: { taskClicked: "taskClicked", taskDateChanged: "taskDateChanged", viewChanged: "viewChanged" }, viewQueries: [{ propertyName: "outer", first: true, predicate: ["outer"], descendants: true }, { propertyName: "side", first: true, predicate: ["side"], descendants: true }, { propertyName: "ganttSvg", first: true, predicate: ["ganttSvg"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div class=\"outer\" #outer>\n    <div #side>\n        @if(showSideTable) {\n            <gantt-side-table\n                [tasks]=\"tasks\"\n                [columnTitle]=\"columnTitle ?? ''\"\n                [multipleTaskPerLine]=\"multipleTaskPerLine\">\n            </gantt-side-table>\n        }\n    </div>\n    <svg #ganttSvg></svg>\n</div>\n", styles: [".outer{display:flex;justify-content:center;align-items:flex-start;align-content:center;flex-wrap:nowrap;flex-direction:row}\n", ".gantt{border:1px solid #e0e0e0}.gantt .weekend-highlight{fill:#b8c2cc;opacity:.5;stroke:#ebeff2;stroke-width:1}.gantt .grid-background{fill:none}.gantt .grid-header,.gantt .grid-row{fill:#fff}.gantt .grid-row:nth-child(2n){fill:#f5f5f5}.gantt .row-line{stroke:#ebeff2}.gantt .tick{stroke:#e0e0e0;stroke-width:.4}.gantt .tick.thick{stroke:#428bca;stroke-width:2}.gantt .today-highlight{fill:#ffe979;opacity:.5}.gantt .arrow{fill:none;stroke:#666;stroke-width:1.4}.gantt .bar{opacity:.8;stroke:#8d99a6;stroke-width:0;transition:stroke-width .3s ease;-webkit-user-select:none;user-select:none}.gantt .bar-invalid{fill:transparent;stroke:#8d99a6;stroke-dasharray:5;stroke-width:1}.gantt .bar-invalid~.bar-label{fill:#555}.gantt .bar-label{fill:#fff;text-anchor:middle;font-size:12px;font-weight:lighter}.gantt .bar-label.big{fill:#555;text-anchor:start}.gantt .bar-wrapper{cursor:pointer;outline:none}.gantt .bar-wrapper:hover .bar,.gantt .bar-wrapper.active .bar{opacity:1}.gantt .bar-wrapper.active .bar{stroke:#212533;stroke-width:2}.gantt .lower-text,.gantt .upper-text{font-size:12px;text-anchor:middle}.gantt .upper-text{fill:#555}.gantt .lower-text{fill:#333}.gantt .hide{display:none}.gantt-container{border-left:1px solid #e0e0e0;font-size:12px;overflow:auto;position:relative}.gantt-container .title-1{fill:#999;font-size:12px;font-weight:400;line-height:150%;text-anchor:middle}.gantt-container .title-2{fill:#333;font-size:14px;font-weight:400;line-height:150%;text-anchor:middle}.gantt-container .popup-wrapper{left:0;position:absolute;top:0}.gantt-container .popup-wrapper .popup{background:#0e1119;border-radius:2px;color:#fff;padding:8px;font-family:\"Open Sans\" sans-serif;line-height:150%;font-weight:400}.gantt-container .popup-wrapper .popup .wrp-title{border-bottom:1px solid #525966;padding-bottom:10px}.gantt-container .popup-wrapper .popup .wrp-title .title{font-size:14px}.gantt-container .popup-wrapper .popup .wrp-subtitle{color:#dfe2e5;padding-top:10px;display:flex;align-items:center}.gantt-container .popup-wrapper .popup .wrp-subtitle .icon{margin-right:10px}.gantt-container .popup-wrapper .popup .wrp-subtitle .subtitle{font-size:12px}.gantt-container .popup-wrapper .popup .pointer{border:6px solid transparent;border-top-color:#0e1119;height:6px;margin-left:-4px;position:absolute}\n"], dependencies: [{ kind: "component", type: SideTableComponent, selector: "gantt-side-table", inputs: ["columnTitle", "tasks", "multipleTaskPerLine"] }], encapsulation: i0.ViewEncapsulation.None });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: GanttComponent, decorators: [{
            type: Component,
            args: [{ selector: 's-gantt', encapsulation: ViewEncapsulation.None, standalone: true, imports: [SideTableComponent], template: "<div class=\"outer\" #outer>\n    <div #side>\n        @if(showSideTable) {\n            <gantt-side-table\n                [tasks]=\"tasks\"\n                [columnTitle]=\"columnTitle ?? ''\"\n                [multipleTaskPerLine]=\"multipleTaskPerLine\">\n            </gantt-side-table>\n        }\n    </div>\n    <svg #ganttSvg></svg>\n</div>\n", styles: [".outer{display:flex;justify-content:center;align-items:flex-start;align-content:center;flex-wrap:nowrap;flex-direction:row}\n", ".gantt{border:1px solid #e0e0e0}.gantt .weekend-highlight{fill:#b8c2cc;opacity:.5;stroke:#ebeff2;stroke-width:1}.gantt .grid-background{fill:none}.gantt .grid-header,.gantt .grid-row{fill:#fff}.gantt .grid-row:nth-child(2n){fill:#f5f5f5}.gantt .row-line{stroke:#ebeff2}.gantt .tick{stroke:#e0e0e0;stroke-width:.4}.gantt .tick.thick{stroke:#428bca;stroke-width:2}.gantt .today-highlight{fill:#ffe979;opacity:.5}.gantt .arrow{fill:none;stroke:#666;stroke-width:1.4}.gantt .bar{opacity:.8;stroke:#8d99a6;stroke-width:0;transition:stroke-width .3s ease;-webkit-user-select:none;user-select:none}.gantt .bar-invalid{fill:transparent;stroke:#8d99a6;stroke-dasharray:5;stroke-width:1}.gantt .bar-invalid~.bar-label{fill:#555}.gantt .bar-label{fill:#fff;text-anchor:middle;font-size:12px;font-weight:lighter}.gantt .bar-label.big{fill:#555;text-anchor:start}.gantt .bar-wrapper{cursor:pointer;outline:none}.gantt .bar-wrapper:hover .bar,.gantt .bar-wrapper.active .bar{opacity:1}.gantt .bar-wrapper.active .bar{stroke:#212533;stroke-width:2}.gantt .lower-text,.gantt .upper-text{font-size:12px;text-anchor:middle}.gantt .upper-text{fill:#555}.gantt .lower-text{fill:#333}.gantt .hide{display:none}.gantt-container{border-left:1px solid #e0e0e0;font-size:12px;overflow:auto;position:relative}.gantt-container .title-1{fill:#999;font-size:12px;font-weight:400;line-height:150%;text-anchor:middle}.gantt-container .title-2{fill:#333;font-size:14px;font-weight:400;line-height:150%;text-anchor:middle}.gantt-container .popup-wrapper{left:0;position:absolute;top:0}.gantt-container .popup-wrapper .popup{background:#0e1119;border-radius:2px;color:#fff;padding:8px;font-family:\"Open Sans\" sans-serif;line-height:150%;font-weight:400}.gantt-container .popup-wrapper .popup .wrp-title{border-bottom:1px solid #525966;padding-bottom:10px}.gantt-container .popup-wrapper .popup .wrp-title .title{font-size:14px}.gantt-container .popup-wrapper .popup .wrp-subtitle{color:#dfe2e5;padding-top:10px;display:flex;align-items:center}.gantt-container .popup-wrapper .popup .wrp-subtitle .icon{margin-right:10px}.gantt-container .popup-wrapper .popup .wrp-subtitle .subtitle{font-size:12px}.gantt-container .popup-wrapper .popup .pointer{border:6px solid transparent;border-top-color:#0e1119;height:6px;margin-left:-4px;position:absolute}\n"] }]
        }], propDecorators: { columnTitle: [{
                type: Input
            }], multipleTaskPerLine: [{
                type: Input
            }], showSideTable: [{
                type: Input
            }], viewMode: [{
                type: Input
            }], tasks: [{
                type: Input,
                args: [{ required: true }]
            }], marginBeforeStart: [{
                type: Input
            }], marginAfterEnd: [{
                type: Input
            }], allowMovement: [{
                type: Input
            }], hasPopup: [{
                type: Input
            }], containerWidth: [{
                type: Input
            }], fullWidth: [{
                type: Input
            }], showOnlyHours: [{
                type: Input
            }], showOnlyDays: [{
                type: Input
            }], taskClicked: [{
                type: Output
            }], taskDateChanged: [{
                type: Output
            }], viewChanged: [{
                type: Output
            }], outer: [{
                type: ViewChild,
                args: ['outer']
            }], side: [{
                type: ViewChild,
                args: ['side']
            }], ganttSvg: [{
                type: ViewChild,
                args: ['ganttSvg']
            }] } });

class GanttModule {
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: GanttModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
    static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "18.2.14", ngImport: i0, type: GanttModule, imports: [GanttComponent], exports: [GanttComponent] });
    static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: GanttModule });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: GanttModule, decorators: [{
            type: NgModule,
            args: [{
                    imports: [GanttComponent],
                    exports: [GanttComponent],
                }]
        }] });

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

export { GanttComponent, GanttModule, ViewMode };
//# sourceMappingURL=seniorsistemas-angular-components-gantt.mjs.map
