UNPKG

npx-calendar

Version:

A customizable and feature-rich calendar component for Angular applications.

481 lines 60.5 kB
import * as i0 from '@angular/core';
import { Injectable, Pipe, Input, ViewChild, Component } from '@angular/core';
import * as i1 from '@angular/common';
import { CommonModule } from '@angular/common';

class NpxCalendarService {
    constructor() { }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.0", ngImport: i0, type: NpxCalendarService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
    static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.0", ngImport: i0, type: NpxCalendarService, providedIn: 'root' });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.0", ngImport: i0, type: NpxCalendarService, decorators: [{
            type: Injectable,
            args: [{
                    providedIn: 'root'
                }]
        }], ctorParameters: () => [] });

class StyleObjectPipe {
    transform(value) {
        const styles = {};
        if (!value) {
            return styles;
        }
        const styleRules = value.split(';');
        styleRules.forEach(rule => {
            const [property, value2] = rule.split(':');
            if (property && value2) {
                styles[property.trim()] = value2.trim();
            }
        });
        return styles;
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.0", ngImport: i0, type: StyleObjectPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
    static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "19.2.0", ngImport: i0, type: StyleObjectPipe, isStandalone: true, name: "styleObject" });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.0", ngImport: i0, type: StyleObjectPipe, decorators: [{
            type: Pipe,
            args: [{
                    name: 'styleObject'
                }]
        }] });

class FilterEventsPipe {
    transform(events, targetTime) {
        return events.filter(event => event.time === targetTime);
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.0", ngImport: i0, type: FilterEventsPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
    static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "19.2.0", ngImport: i0, type: FilterEventsPipe, isStandalone: true, name: "filterEvents" });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.0", ngImport: i0, type: FilterEventsPipe, decorators: [{
            type: Pipe,
            args: [{ name: 'filterEvents' }]
        }] });

class CalendarComponent {
    elementRef;
    popover;
    isPopoverOpen = false;
    popoverDay = null;
    daysOfTheWeek = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
    monthsOfTheYear = [
        "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"
    ];
    hours = [];
    currentWeekDays = [];
    years = [];
    viewOptions = ["Month", "Work week", "Week"];
    daysInMonth = [];
    currentMonth = 0;
    currentYear = 0;
    currentDay = 0;
    currentMonthName = '';
    currentYearName = '';
    currentDate = '';
    firstDayOfWeek = 0;
    isOpen = false;
    isMonthPickerOpen = false;
    isFilterOpen = false;
    selectedView = 0;
    isOffCanvasOpen = false;
    weekDay = null;
    selectedDay = 0;
    selectedDayEvents = [];
    showYearPicker = false;
    selectedEventDetail = {
        title: '',
        time: '',
        description: '',
        start_time: '',
        end_time: '',
        style: '',
        attendees: [],
        location: '',
        locationLink: '',
        category: '',
        categoryColor: ''
    };
    calendar_events = [];
    calendar_themes = {
        show_header: true,
        show_arrow: true,
        show_month_picker: true,
        show_calendar_view_filter: true
    };
    constructor(elementRef) {
        this.elementRef = elementRef;
        this.selectedEventDetail.categoryColor = '#ff0000';
        this.years = [];
        for (let i = 2020; i <= new Date().getFullYear() + 10; i++) {
            this.years.push(i);
        }
    }
    /**
     * Initialize the component.
     *
     * Gets the current month and year, then calls
     * {@link generateCalender} to generate the calender.
     */
    ngOnInit() {
        this.currentMonth = new Date().getMonth();
        this.currentYear = new Date().getFullYear();
        this.generateCalender();
    }
    /**
     * Generate the calender.
     *
     * This method generates the days of the month and the first day of the week.
     * It also sets the current date.
     *
     * It is called on component initialization.
     */
    generateCalender() {
        this.currentDay = new Date().getDate();
        this.currentMonthName = this.monthsOfTheYear[this.currentMonth];
        this.currentYearName = this.currentYear.toString();
        this.currentDate = this.currentDay + ' ' + this.currentMonthName + ' ' + this.currentYearName;
        this.firstDayOfWeek = new Date(this.currentYear, this.currentMonth, 1).getDay();
        const daysInMonth = new Date(this.currentYear, this.currentMonth + 1, 0).getDate();
        this.daysInMonth = [];
        for (let i = 1; i <= daysInMonth; i++) {
            this.daysInMonth.push(i);
        }
    }
    handleCalenderEvent(day) {
        console.log(day);
    }
    /**
     * Handle the next month button click event.
     *
     * This will add one to the current month, taking into account the wrap-around
     * from December to January.
     *
     * If the current month is December (11), we should increment the current year.
     */
    handleNextMonth() {
        if (this.currentMonth === 11) {
            this.currentYear++;
            this.currentMonth = 0;
        }
        else {
            this.currentMonth++;
        }
        this.generateCalender();
    }
    /**
     * Handle the previous month button click event.
     *
     * This will subtract one from the current month, taking into account the wrap-around
     * from December to January.
     *
     * If the current month is January (0), we should decrement the current year.
     */
    handlePrevMonth() {
        this.currentMonth = (this.currentMonth - 1 + 12) % 12;
        if (this.currentMonth === 11)
            this.currentYear--;
        this.generateCalender();
    }
    /**
     * Toggle the date picker dropdown.
     *
     * This method is called when the current month button is clicked. It toggles the
     * {@link isOpen} property, which determines whether the date picker dropdown
     * is visible or not.
     */
    toggleDatePicker() {
        this.isOpen = !this.isOpen;
    }
    /**
     * Toggle the month picker dropdown.
     *
     * This method is called when the month button is clicked. It toggles the
     * {@link isMonthPickerOpen} property, which determines whether the month
     * picker dropdown is visible or not.
     */
    toggleMonthPicker() {
        this.isMonthPickerOpen = !this.isMonthPickerOpen;
    }
    /**
     * Toggle the filter dropdown.
     *
     * This method is called when the filter button is clicked. It toggles the
     * {@link isFilterOpen} property, which determines whether the filter dropdown
     * is visible or not.
     */
    toggleFilter() {
        this.isFilterOpen = !this.isFilterOpen;
    }
    /**
     * Handles the month change event.
     *
     * This method is called when a new month is selected from the month dropdown.
     * It is called automatically whenever the user selects a new month from the
     * month dropdown.
     *
     * The purpose of this method is to update the current month and regenerate
     * the calender. This is necessary because the calender is rendered based on the
     * current month and year, so if the user changes the month, we need to update
     * the calender to reflect the new month.
     *
     * The method takes a single argument, `month`, which is the new month to be
     * selected (0-11, January-December).
     *
     * The method does the following:
     *  1. It updates the current month by setting the `currentMonth` property to
     *     the new month.
     *  2. It closes the month dropdown by setting the `isOpen` property to false.
     *  3. It regenerates the calender by calling the `generateCalender()` method.
     *
     * @param month The new month (0-11, January-December).
     */
    onMonthChange(month) {
        this.currentMonth = month;
        this.isOpen = false;
        this.generateCalender();
    }
    /*************  ✨ Codeium Command 🌟  *************/
    /**
     * Handles the year change event.
     *
     * This method is called when a new year is selected from the year dropdown.
     * It updates the current year and regenerates the calender by calling
     * {@link generateCalender}.
     *
     * @param year The new year.
     */
    onYearChange(year) {
        this.currentYear = year;
        this.isOpen = false;
        this.generateCalender();
    }
    /******  a23a8126-489d-4240-8c98-4a4c397bedb5  *******/
    /**
     * Open the off-canvas menu.
     *
     * This method is called when a day is clicked in the calendar. It will open the
     * off-canvas menu and set the week day label to the name of the day of the week
     * of the selected date.
     *
     * @param day The day of the month that was clicked (1-31).
     * @param event The list of events associated with the day that was clicked.
     */
    openOffCanvas(day, event) {
        this.selectedDay = day;
        const date = new Date(this.currentYear, this.currentMonth, day);
        const dayOfWeek = date.getDay();
        this.weekDay = this.daysOfTheWeek[dayOfWeek];
        this.selectedDayEvents = event;
        this.isOffCanvasOpen = !this.isOffCanvasOpen;
        this.isPopoverOpen = false;
    }
    /**
     * Close the off-canvas menu.
     *
     * This method is called when the close button is clicked in the off-canvas
     * menu. It sets the {@link isOffCanvasOpen} property to false, which will
     * hide the off-canvas menu.
     */
    closeOffCanvas() {
        this.isOffCanvasOpen = false;
    }
    /**
     * Opens the popover that displays the events for the selected day.
     *
     * This method is called when a day is clicked in the calendar. It will open the
     * popover and position it at the location of the click event.
     *
     * @param event The mouse event that triggered this method.
     * @param day The day of the month that was clicked (1-31).
     */
    openPopover(event, day, eventDetail) {
        this.selectedEventDetail = eventDetail;
        this.selectedDay = day;
        const date = new Date(this.currentYear, this.currentMonth, day);
        const dayOfWeek = date.getDay();
        this.weekDay = this.daysOfTheWeek[dayOfWeek];
        this.isPopoverOpen = true;
        this.popoverDay = day;
        this.closeOffCanvas();
        this.positionPopover(event);
    }
    /**
     * Position the popover at the location of the click event.
     *
     * This function is called by the openPopover method, which is called when a day
     * is clicked in the calendar. It will position the popover at the location of the
     * click event.
     *
     * This function will wait for the popover to render before positioning it. This
     * is done with setTimeout and a 0ms delay. This ensures that the popover has
     * rendered and its width and height are available.
     *
     * It will check if the popover is too close to the edge of the screen and if so,
     * will reposition it so it doesn't go off the screen.
     *
     * @param event The mouse event that triggered this method.
     */
    positionPopover(event) {
        setTimeout(() => {
            const popoverEl = this.popover.nativeElement;
            const viewportWidth = window.innerWidth;
            const viewportHeight = window.innerHeight;
            const popoverRect = popoverEl.getBoundingClientRect();
            let left = event.clientX;
            let top = event.clientY + 10; // Default below cursor
            if (left + popoverRect.width > viewportWidth) {
                left = viewportWidth - popoverRect.width - 10;
            }
            if (top + popoverRect.height > viewportHeight) {
                top = event.clientY - popoverRect.height - 10;
            }
            popoverEl.style.left = `${left}px`;
            popoverEl.style.top = `${top + 5}px`;
        }, 0);
    }
    /**
     * Called when the user changes the calendar view.
     *
     * This function is called when the user changes the calendar view by clicking on
     * one of the view options in the top right corner of the calendar. The view
     * options are "Month", "Week", and "Day".
     *
     * When this function is called, it will update the selectedView property to the
     * index of the view that was selected.
     *
     * @param view The index of the view that was selected (0, 1, or 2).
     */
    onViewChange(view) {
        this.selectedView = view;
        this.getCurrentWeek(false);
    }
    /**
     * Toggle the year picker dropdown.
     *
     * This function is called when the year button is clicked. It will toggle the
     * {@link showYearPicker} property, which determines whether the year picker
     * dropdown is visible or not.
     *
     * Also, it will stop the event from propagating up the DOM tree, so that the
     * event doesn't bubble up and cause the calendar to be closed.
     *
     * @param event The mouse event that triggered this method.
     */
    toggleYearPicker(event) {
        this.showYearPicker = !this.showYearPicker;
        event.stopPropagation();
    }
    /**
     * Handles the previous year button click event.
     *
     * This method is called when the previous year button is clicked. It will
     * decrement the current year by one and regenerate the calender by calling
     * {@link generateCalender}.
     *
     * It will also stop the event from propagating up the DOM tree, so that the
     * event doesn't bubble up and cause the calendar to be closed.
     *
     * @param event The mouse event that triggered this method.
     */
    handlePrevYear(event) {
        event.stopPropagation();
        this.currentYear--;
        this.generateCalender();
    }
    /**
     * Handles the next year button click event.
     *
     * This method is called when the next year button is clicked. It will
     * increment the current year by one and regenerate the calender by calling
     * {@link generateCalender}.
     *
     * @param event The mouse event that triggered this method.
     */
    handleNextYear(event) {
        event.stopPropagation();
        this.currentYear++;
        this.generateCalender();
    }
    getCurrentWeek(startFromMonday = false) {
        this.hours = [];
        this.currentWeekDays = [];
        this.daysOfTheWeek = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
        const today = new Date();
        const dayOfWeek = today.getDay(); // 0 (Sunday) to 6 (Saturday)
        // Adjust for Monday as the start of the week if needed
        const weekStart = new Date(today);
        weekStart.setDate(today.getDate() - dayOfWeek + (startFromMonday ? (dayOfWeek === 0 ? -6 : 1) : 0));
        const weekDates = [];
        for (let i = 0; i < 7; i++) {
            const date = new Date(weekStart);
            date.setDate(weekStart.getDate() + i);
            weekDates.push(date.getDate()); // Day of the month as 1, 2, 3, etc.
        }
        this.hours = Array.from({ length: 24 }, (_, i) => {
            const suffix = i < 12 ? 'AM' : 'PM';
            const hour = i % 12 === 0 ? 12 : i % 12;
            return `${hour} ${suffix}`;
        });
        console.log("weekDates", weekDates);
        if (this.viewOptions[this.selectedView] === 'Work week') {
            this.currentWeekDays = weekDates.slice(1, weekDates.length - 1);
            this.daysOfTheWeek = this.daysOfTheWeek.slice(1, this.daysOfTheWeek.length - 1);
        }
        else {
            this.currentWeekDays = weekDates;
        }
        console.log(this.currentWeekDays, this.hours);
    }
    getEventHour(eventTime, extraMinutes) {
        return eventTime.split(" ")[0] + ":" + extraMinutes + ' ' + eventTime.split(" ")[1]; // Extract hour + AM/PM
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.0", ngImport: i0, type: CalendarComponent, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component });
    static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.0", type: CalendarComponent, isStandalone: true, selector: "lib-calendar", inputs: { calendar_events: "calendar_events", calendar_themes: "calendar_themes" }, viewQueries: [{ propertyName: "popover", first: true, predicate: ["popover"], descendants: true }], ngImport: i0, template: "<!-- Days of the week header (Sun, Mon, Tue, etc.) -->\n<div class=\"calendar-container\">\n  <div class=\"header\" *ngIf=\"calendar_themes.show_header\" [ngStyle]=\"calendar_themes.header_style ??  ''| styleObject\">\n    <div class=\"left-content\" style=\"display: flex; align-items: center;\">\n      <div *ngIf=\"calendar_themes.show_arrow\">\n        <span class=\"arrow-prev\" (click)=\"handlePrevMonth()\" [ngStyle]=\"calendar_themes.arrow_style ?? ''| styleObject\">&lt;</span>\n        <span class=\"arrow-next\" (click)=\"handleNextMonth()\" [ngStyle]=\"calendar_themes.arrow_style ?? ''| styleObject\">&gt;</span>\n      </div>\n\n      <div class=\"datepicker current-month\" (click)=\"toggleDatePicker()\" [ngClass]=\"{ 'active': isOpen }\">\n        <div class=\"datepicker-header\">\n          <span>{{ currentMonthName }} {{ currentYear }} &#9660;</span>\n        </div>\n\n        <div class=\"month-grid\" *ngIf=\"calendar_themes.show_month_picker\">\n          <div class=\"arrow\"></div>\n          <div class=\"year-container\">\n            <div class=\"year\" (click)=\"toggleYearPicker($event)\">{{ currentYear }}{{ showYearPicker ? '-' + years[years.length - 1] : '' }}</div>\n            <div class=\"year-filter-arrow\" style=\"margin: 8px;\">\n              <span class=\"year-arrow\" (click)=\"handlePrevYear($event)\">&uarr;</span>\n              <span class=\"year-arrow\" style=\"margin-left:2px ;\" (click)=\"handleNextYear($event)\">&darr;</span>\n            </div>\n          </div>\n          <div *ngFor=\"let month of monthsOfTheYear and let index = index\">\n            <div *ngIf=\"!showYearPicker\" class=\"month\" [ngClass]=\"{ 'selected': index === currentMonth }\" (click)=\"onMonthChange(index)\">\n              {{ month }}\n            </div>\n          </div>\n\n          <div *ngFor=\"let year of years and let index = index\" style=\"min-width: 120px;\">\n            <div *ngIf=\"showYearPicker\" class=\"month\" [ngClass]=\"{ 'selected': index === currentMonth }\" (click)=\"onYearChange(year)\">\n              {{ year }}\n            </div>\n          </div>\n\n        </div>\n      </div>\n    </div>\n\n    <div class=\"right-content\" style=\"display: flex; align-items: center;\" *ngIf=\"calendar_themes.show_calendar_view_filter\">\n      <div class=\"datepicker month-dropdown\" (click)=\"toggleMonthPicker()\" [ngClass]=\"{ 'active': isMonthPickerOpen }\">\n        <div class=\"datepicker-header\">\n          <span>{{viewOptions[selectedView]}} &#9660;</span>\n        </div>\n\n        <div class=\"view-options-grid\">\n          <div class=\"view-arrow\"></div>\n          <div *ngFor=\"let view of viewOptions and let index = index\" class=\"month\" [ngClass]=\"{ 'selected': index === selectedView }\" (click)=\"onViewChange(index)\">\n            {{ view }}\n          </div>\n        </div>\n      </div>\n    </div>\n  </div>\n\n  <!-- Calendar Weekdays -->\n  <div class=\"calendar-weekdays\" *ngIf=\"viewOptions[selectedView] === 'Month'\">\n    <span *ngFor=\"let day of daysOfTheWeek\" class=\"calendar-weekday\">{{ day }}</span>\n  </div>\n  <div [ngClass]=\"viewOptions[selectedView] === 'Work week' ? 'calendar-working-weekdays' : 'calendar-weekdays'\" *ngIf=\"viewOptions[selectedView] === 'Work week' || viewOptions[selectedView] === 'Week'\">\n    <span *ngFor=\"let day of daysOfTheWeek and let index = index\" class=\"calendar-weekday\" [class.current-day-in-weekdays]=\"currentWeekDays[index] === currentDay\">\n      <div>\n        {{ day }}\n      </div>\n      {{currentWeekDays[index]}}\n    </span>\n  </div>\n\n  <!-- Calendar Days -->\n  <div class=\"calendar-days\" *ngIf=\"viewOptions[selectedView] === 'Month'\">\n    <!-- Blank spaces before 1st day -->\n    <div *ngFor=\"let blank of [].constructor(firstDayOfWeek)\">\n      <div></div>\n    </div>\n\n    <!-- Calendar Days -->\n    <div *ngFor=\"let day of daysInMonth\" class=\"calendar-day\" [class.current-day]=\"day === currentDay\" (click)=\"handleCalenderEvent(day)\">\n      <div style=\"font-weight: bolder;\">\n        {{ day }}\n      </div>\n      <div *ngFor=\"let eventDetails of calendar_events\">\n        <div *ngIf=\"eventDetails.month - 1 === currentMonth\">\n          <div *ngFor=\"let list of eventDetails.list\">\n            <div *ngIf=\"list.day === day\">\n              <div *ngFor=\"let event of list.events and let index = index\">\n                <span class=\"events\" [ngStyle]=\"event.style | styleObject\" *ngIf=\"index < 2\" #trigger (click)=\"openPopover($event, day, event)()\">\n                  {{ event.title }} - {{ event.time }}\n                </span>\n                <div class=\"extra-events\" *ngIf=\"index===2\" (click)=\"openOffCanvas(day, list.events)\">+{{ list.events.length - 2 }}</div>\n              </div>\n            </div>\n          </div>\n        </div>\n      </div>\n    </div>\n  </div>\n\n  <div class=\"calendar-days\" style=\"display: flex; margin: 0;\" *ngIf=\"viewOptions[selectedView] === 'Work week' || viewOptions[selectedView] === 'Week'\">\n    <div [ngClass]=\"viewOptions[selectedView] === 'Work week' ? 'calendar-week-days' : 'calendar-weekend-days'\" style=\"border: 1px solid #000;\">\n      <div class=\"calendar-week-day\" *ngFor=\"let day of currentWeekDays; let index = index\" [class.current-day-in-weekdays]=\"currentWeekDays[index] === currentDay\">\n        <div class=\"time-slot\" *ngFor=\"let hour of hours\">\n          <div style=\"height: 100%;\" *ngFor=\"let eventDetails of calendar_events\">\n\n\n            <ng-container *ngIf=\"eventDetails.month - 1 === currentMonth\">\n              <div style=\"height: 50%; padding: 5px 0 2px 4px; width: 100%; overflow-y: auto;\">\n                <div *ngIf=\"index === 0\">\n                  {{ hour }}\n                </div>\n\n                <div *ngFor=\"let list of eventDetails.list\">\n                  <ng-container *ngIf=\"list.day === day\">\n                    <ng-container *ngIf=\"(list.events | filterEvents:getEventHour(hour, '00')) as filteredEvents\">\n                      <ng-container *ngFor=\"let event of filteredEvents.slice(0, 2)\">\n                        <span class=\"week-events\" [ngStyle]=\"event.style | styleObject\" #trigger (click)=\"openPopover($event, day, event)\">\n                          {{ event.title }} - {{ event.time }}\n                        </span>\n                      </ng-container>\n                      <div *ngIf=\"filteredEvents.length > 2\" (click)=\"openOffCanvas(day, list.events)\" class=\"extra-week-events\">+{{ filteredEvents.length - 2 }}</div>\n                    </ng-container>\n                  </ng-container>\n                </div>\n\n              </div>\n              <div style=\"border-top: 1px solid rgba(128, 128, 128, 0.486); min-height: 50%; padding: 5px 0 2px 4px; width: 100%; overflow-y: auto;\">\n\n                <div *ngFor=\"let list of eventDetails.list\">\n                  <ng-container *ngIf=\"list.day === day\">\n                    <ng-container *ngIf=\"(list.events | filterEvents:getEventHour(hour, '30')) as filteredEvents\">\n                      <ng-container *ngFor=\"let event of filteredEvents.slice(0, 2)\">\n                        <span class=\"week-events\" [ngStyle]=\"event.style | styleObject\" #trigger (click)=\"openPopover($event, day, event)\">\n                          {{ event.title }} - {{ event.time }}\n                        </span>\n                      </ng-container>\n                      <div *ngIf=\"filteredEvents.length > 2\" (click)=\"openOffCanvas(day, list.events)\" class=\"extra-week-events\">+{{ filteredEvents.length - 2 }}</div>\n                    </ng-container>\n                  </ng-container>\n                </div>\n\n              </div>\n            </ng-container>\n\n          </div>\n        </div>\n\n      </div>\n    </div>\n  </div>\n\n\n</div>\n\n<div class=\"off-canvas\" [class.open]=\"isOffCanvasOpen\">\n  <div class=\"off-canvas-header\">\n    <h3>{{ weekDay?.slice(0, 3) }}, {{ currentMonthName.slice(0, 3) }} {{ selectedDay }}</h3>\n    <button class=\"close-btn\" (click)=\"closeOffCanvas()\">\u00D7</button>\n  </div>\n\n  <div class=\"off-canvas-content\">\n    <div *ngIf=\"selectedDayEvents.length; else noEvents\">\n      <div *ngFor=\"let event of selectedDayEvents\" class=\"event-card\" [ngStyle]=\"event.style | styleObject\">\n        <div class=\"event-header\">\n          <h3 class=\"event-title\">{{ event.title }}</h3>\n        </div>\n\n        <div class=\"event-category\" [ngStyle]=\"{'background': event.categoryColor}\">\n          {{ event.category || 'General' }}\n        </div>\n\n        <div class=\"popover-section\">\n          <i class=\"icon-calendar\"></i>\n          <p>{{ selectedDay }} {{ currentMonthName }} {{ weekDay?.slice(0, 3) }},\n            {{ selectedEventDetail.start_time }} - {{ selectedEventDetail.end_time }}</p>\n        </div>\n\n        <div class=\"event-section\">\n          <i class=\"icon-location\"></i>\n          <p>\n            {{ selectedEventDetail.location}}\n          </p>\n        </div>\n\n        <div class=\"event-section attendees\" *ngIf=\"event.attendees?.length\">\n          <i class=\"icon-users\"></i>\n          <div class=\"attendees-list\">\n            <div class=\"attendee\" *ngFor=\"let attendee of event.attendees.slice(0, 3)\">\n              <img [src]=\"attendee.image\" [alt]=\"attendee.name\">\n              <span class=\"attendee-name\">{{ attendee.name }}</span>\n            </div>\n            <span *ngIf=\"event.attendees.length > 3\" class=\"more-attendees\">\n              +{{ event.attendees.length - 3 }} more\n            </span>\n          </div>\n        </div>\n\n        <div class=\"event-section\">\n          <i class=\"icon-info\"></i>\n          <p>{{ event.description }}</p>\n        </div>\n      </div>\n    </div>\n\n    <ng-template #noEvents>\n      <p class=\"no-events\">No events scheduled for this day.</p>\n    </ng-template>\n  </div>\n</div>\n\n\n\n\n\n<div #popover class=\"popover-container\" [ngClass]=\"{ 'show': isPopoverOpen }\" [ngStyle]=\"selectedEventDetail.style | styleObject\">\n  <div class=\"popover-content\">\n    <h3 class=\"popover-title\">\n      {{ selectedEventDetail.title }}\n    </h3>\n\n    <div class=\"event-category\" [ngStyle]=\"{'background': selectedEventDetail.categoryColor}\">\n      {{ selectedEventDetail.category || 'General' }}\n    </div>\n\n    <div class=\"popover-section\">\n      <i class=\"icon-calendar\"></i>\n      <p>{{ selectedDay }} {{ currentMonthName }} {{ weekDay?.slice(0, 3) }},\n        {{ selectedEventDetail.start_time }} - {{ selectedEventDetail.end_time }}</p>\n    </div>\n\n    <div class=\"event-section\" *ngIf=\"selectedEventDetail.location\">\n      <i class=\"icon-location\"></i>\n      <p>\n        {{ selectedEventDetail.location }}\n      </p>\n    </div>\n\n    <div class=\"event-section attendees\" *ngIf=\"selectedEventDetail.attendees?.length\">\n      <i class=\"icon-users\"></i>\n      <div class=\"attendees-list\">\n        <div class=\"attendee\" *ngFor=\"let attendee of selectedEventDetail.attendees.slice(0, 3)\">\n          <img [src]=\"attendee.image\" [alt]=\"attendee.name\">\n          <span class=\"attendee-name\">{{ attendee.name }}</span>\n        </div>\n        <span *ngIf=\"selectedEventDetail.attendees.length > 3\" class=\"more-attendees\">\n          +{{ selectedEventDetail.attendees.length - 3 }} more\n        </span>\n      </div>\n    </div>\n\n    <div class=\"popover-section\">\n      <i class=\"icon-info\"></i>\n      <p>{{ selectedEventDetail.description }}</p>\n    </div>\n\n    <button class=\"close-btn\" (click)=\"isPopoverOpen = false\">\u2716</button>\n  </div>\n</div>\n", styles: [".calendar-container{display:flex;flex-direction:column;align-items:center;width:100%;margin:auto;padding:0 10px;box-sizing:border-box;min-height:100vh}.calendar-weekdays,.calendar-days{display:grid;grid-template-columns:repeat(7,minmax(50px,1fr));gap:5px;padding:10px;border:1px solid #000;width:100%}.calendar-working-weekdays{display:grid;grid-template-columns:repeat(5,minmax(50px,1fr));gap:5px;padding:10px;border:1px solid #000;width:100%}.calendar-weekday,.calendar-day{text-align:center;padding:8px;border-radius:5px;min-height:20px;cursor:pointer;border:1px solid #000;font-weight:bolder;font-size:14px}@media (max-width: 1024px){.calendar-weekdays,.calendar-days{grid-template-columns:repeat(7,minmax(40px,1fr))}.calendar-weekday,.calendar-day{font-size:12px;padding:5px}}@media (max-width: 768px){.calendar-weekdays,.calendar-days{grid-template-columns:repeat(7,minmax(35px,1fr))}.calendar-weekday,.calendar-day{font-size:11px;padding:4px}}@media (max-width: 480px){.calendar-weekdays,.calendar-days{grid-template-columns:repeat(7,minmax(30px,1fr))}.calendar-weekday,.calendar-day{font-size:10px;padding:3px}}.calendar-day{text-align:left;padding:10px;background-color:transparent;border-radius:5px;min-height:95px;align-content:flex-start;cursor:pointer;border:1px solid #000}.time-slot{height:50px;border-bottom:1px solid #333}.blank{background-color:transparent}.current-day{background-color:#0000008e;color:#fff;font-weight:700;border-radius:5px;align-content:center;cursor:pointer;border:1px solid #000;align-content:flex-start}.current-day-in-weekdays{background-color:#00000029;color:#fff;font-weight:700;align-content:center;cursor:pointer;align-content:flex-start}.header{padding:10px;border:1px solid #000;display:flex;justify-content:space-between;width:100%}.left-content,.right-content{padding:10px}.arrow-prev,.arrow-next,.current-month{font-weight:700;border:2px solid #000;padding:10px;border-radius:5px;cursor:pointer;background-color:#000;color:#fff}.arrow-prev,.month-dropdown,.arrow-next{margin-right:2px}.current-month{font-weight:700;padding:10px}.month-dropdown,.filter-dropdown{font-weight:700;border:2px solid #000;padding:10px;border-radius:5px;cursor:pointer;background-color:#000;color:#fff}.datepicker{background:#000;padding:10px;border-radius:8px;max-width:200px;position:relative}.datepicker-header{display:flex;justify-content:space-between;align-items:center;cursor:pointer;border-radius:6px}.datepicker-header span{font-size:14px}.month-grid{display:none;grid-template-columns:repeat(3,1fr);gap:3px 5px;padding:10px 5px;position:absolute;top:50px;left:0;background:#000;border-radius:8px;width:100%;box-shadow:0 4px 6px #0000004d;z-index:1}.year-container{grid-column-start:1;grid-column-end:4;padding:5px;display:grid;grid-template-columns:repeat(2,60%)}.year{text-align:center;padding:5px;border-radius:6px;cursor:pointer;color:#fff;border:1px solid #fff}.year-filter-arrow{text-align:center}.year-arrow{padding:5px;border:1px solid #fff;border-radius:6px;cursor:pointer;color:#fff;background:#000}.view-options-grid{display:none;grid-template-columns:repeat(1,1fr);gap:8px;padding:10px 5px;position:absolute;top:50px;left:0;background:#000;border-radius:8px;width:100%;z-index:1}.month{text-align:center;padding:5px;border-radius:6px;cursor:pointer;color:#fff;border:1px solid #fff}.month:hover,.selected{background:#fff;color:#000}.datepicker.active .month-grid,.datepicker.active .view-options-grid{display:grid;width:-webkit-max-content}.arrow{position:absolute;top:-8px;left:10%;transform:translate(-50%);width:0;height:0;border-left:8px solid transparent;border-right:8px solid transparent;border-bottom:8px solid #0d0d0d}.view-arrow,.view-arrow-popover{position:absolute;top:-8px;left:30%;transform:translate(-50%);width:0;height:0;border-left:8px solid transparent;border-right:8px solid transparent;border-bottom:8px solid #0d0d0d}.view-arrow-popover{border-bottom:8px solid #fff!important}.events{border:1px dotted #000;padding:2px;border-radius:5px;margin:5px 0;font-size:small;overflow:hidden;min-height:fit-content;white-space:nowrap;text-overflow:ellipsis;display:block;width:100%}.extra-events{background-color:#000;color:#fff;text-align:center;border-radius:5px;padding:2px;margin:5px 0;font-size:small;width:100%}.off-canvas{display:none;position:fixed;top:0;right:-320px;width:300px;height:100vh;background:#000c;-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);color:#fff;padding:20px;transition:right .3s ease-in-out;box-shadow:-5px 0 10px #0000004d;overflow-y:auto}.off-canvas.open{display:block;right:0}.off-canvas-header{display:flex;justify-content:space-between;align-items:center;border-bottom:2px solid rgba(255,255,255,.2);padding-bottom:10px}.off-canvas-header h3{font-size:18px;font-weight:700}.close-btn{background:none;border:none;color:#fff;font-size:20px;cursor:pointer;opacity:.8;transition:opacity .2s ease}.off-canvas-content{margin-top:10px}.event-card{background:#ffffff1a;border-radius:8px;padding:12px;margin-bottom:10px;transition:transform .2s ease-in-out}.event-card:hover{transform:scale(1.05)}.event-header{display:flex;align-items:center;gap:12px}.event-icon img{width:40px;height:40px;border-radius:50%}.event-icon i{font-size:24px;color:#fff}.event-title{font-size:16px;font-weight:700}.event-category{padding:4px 10px;border-radius:5px;font-size:12px;text-align:center;color:#fff;margin:8px 0}.event-section{display:flex;align-items:center;gap:8px;font-size:14px}.icon-calendar:before{content:\"\\1f4c5\"}.icon-location:before{content:\"\\1f4cd\"}.icon-users:before{content:\"\\1f465\"}.icon-timer:before{content:\"\\23f3\"}.event-actions{display:flex;justify-content:space-between;margin-top:10px}.btn{border:none;padding:8px 10px;border-radius:5px;cursor:pointer;font-size:12px}.btn-primary{background:#4caf50;color:#fff}.btn-secondary{background:#2196f3;color:#fff}.btn-edit{background:#ffc107;color:#fff}.btn-delete{background:#f44336;color:#fff}.btn:hover{opacity:.8}.no-events{text-align:center;font-style:italic;opacity:.7}.attendees{display:flex;align-items:center;gap:8px}.attendees-list{display:flex;flex-wrap:wrap;gap:8px}.attendee{display:flex;align-items:center;gap:6px;background:#ffffff1a;padding:4px 8px;border-radius:5px}.attendee img{width:28px;height:28px;border-radius:50%;border:2px solid white}.attendee-name{font-size:14px;color:#fff}.more-attendees{font-size:14px;color:#ddd;background:#fff3;padding:4px 8px;border-radius:5px}.popover-container{display:none;position:absolute;background:#ffffff1a;-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);border:1px solid rgba(255,255,255,.2);border-radius:12px;padding:16px;width:250px;box-shadow:0 8px 16px #0003;opacity:0;transform:scale(.95);pointer-events:none;transition:opacity .3s ease-in-out,visibility .3s ease-in-out}.popover-container.show{visibility:visible;display:block;opacity:1;transform:scale(1);pointer-events:auto}.popover-content{display:flex;flex-direction:column;gap:10px;color:#fff}.popover-title{font-size:18px;font-weight:700;padding-bottom:8px;border-bottom:2px solid rgba(255,255,255,.3);text-align:center}.popover-section{display:flex;align-items:center;gap:8px;font-size:14px}.icon-calendar:before,.icon-info:before{content:\"\\1f4c5\";font-size:16px}.icon-info:before{content:\"\\2139\\fe0f\"}.close-btn{position:absolute;top:8px;left:88%;background:none;border:none;color:#fff;font-size:16px;cursor:pointer;opacity:.7;transition:opacity .2s ease}.close-btn:hover{opacity:1}.time-column{display:flex;flex-direction:column;align-items:flex-end;text-align:right;font-weight:700}.calendar-week-days{display:grid;grid-template-columns:repeat(5,1fr);border-left:1px solid #444;height:78vh;overflow-y:scroll;overflow-x:auto;width:100%}.calendar-weekend-days{display:grid;grid-template-columns:repeat(7,1fr);border-left:1px solid #444;height:78vh;overflow-y:scroll;overflow-x:auto;width:100%}.calendar-week-day{display:grid;grid-template-rows:repeat(24,120px);border-right:1px solid #444;width:100%}.time-slot{border-bottom:1px solid #333;height:120px;padding:5px 0;width:100%;box-sizing:border-box;position:relative}.time-divider{position:absolute;width:100%;border-bottom:1px solid #333;left:0}.week-events{border:1px dotted #000;border-radius:5px;margin:5px 0;font-size:small;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;display:block;width:92%;cursor:pointer}.extra-week-events{background-color:#000;color:#fff;text-align:center;border-radius:5px;padding:2px;margin:5px 0;font-size:small;width:92%;cursor:pointer}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "pipe", type: StyleObjectPipe, name: "styleObject" }, { kind: "pipe", type: FilterEventsPipe, name: "filterEvents" }] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.0", ngImport: i0, type: CalendarComponent, decorators: [{
            type: Component,
            args: [{ selector: 'lib-calendar', imports: [CommonModule, StyleObjectPipe, FilterEventsPipe], template: "<!-- Days of the week header (Sun, Mon, Tue, etc.) -->\n<div class=\"calendar-container\">\n  <div class=\"header\" *ngIf=\"calendar_themes.show_header\" [ngStyle]=\"calendar_themes.header_style ??  ''| styleObject\">\n    <div class=\"left-content\" style=\"display: flex; align-items: center;\">\n      <div *ngIf=\"calendar_themes.show_arrow\">\n        <span class=\"arrow-prev\" (click)=\"handlePrevMonth()\" [ngStyle]=\"calendar_themes.arrow_style ?? ''| styleObject\">&lt;</span>\n        <span class=\"arrow-next\" (click)=\"handleNextMonth()\" [ngStyle]=\"calendar_themes.arrow_style ?? ''| styleObject\">&gt;</span>\n      </div>\n\n      <div class=\"datepicker current-month\" (click)=\"toggleDatePicker()\" [ngClass]=\"{ 'active': isOpen }\">\n        <div class=\"datepicker-header\">\n          <span>{{ currentMonthName }} {{ currentYear }} &#9660;</span>\n        </div>\n\n        <div class=\"month-grid\" *ngIf=\"calendar_themes.show_month_picker\">\n          <div class=\"arrow\"></div>\n          <div class=\"year-container\">\n            <div class=\"year\" (click)=\"toggleYearPicker($event)\">{{ currentYear }}{{ showYearPicker ? '-' + years[years.length - 1] : '' }}</div>\n            <div class=\"year-filter-arrow\" style=\"margin: 8px;\">\n              <span class=\"year-arrow\" (click)=\"handlePrevYear($event)\">&uarr;</span>\n              <span class=\"year-arrow\" style=\"margin-left:2px ;\" (click)=\"handleNextYear($event)\">&darr;</span>\n            </div>\n          </div>\n          <div *ngFor=\"let month of monthsOfTheYear and let index = index\">\n            <div *ngIf=\"!showYearPicker\" class=\"month\" [ngClass]=\"{ 'selected': index === currentMonth }\" (click)=\"onMonthChange(index)\">\n              {{ month }}\n            </div>\n          </div>\n\n          <div *ngFor=\"let year of years and let index = index\" style=\"min-width: 120px;\">\n            <div *ngIf=\"showYearPicker\" class=\"month\" [ngClass]=\"{ 'selected': index === currentMonth }\" (click)=\"onYearChange(year)\">\n              {{ year }}\n            </div>\n          </div>\n\n        </div>\n      </div>\n    </div>\n\n    <div class=\"right-content\" style=\"display: flex; align-items: center;\" *ngIf=\"calendar_themes.show_calendar_view_filter\">\n      <div class=\"datepicker month-dropdown\" (click)=\"toggleMonthPicker()\" [ngClass]=\"{ 'active': isMonthPickerOpen }\">\n        <div class=\"datepicker-header\">\n          <span>{{viewOptions[selectedView]}} &#9660;</span>\n        </div>\n\n        <div class=\"view-options-grid\">\n          <div class=\"view-arrow\"></div>\n          <div *ngFor=\"let view of viewOptions and let index = index\" class=\"month\" [ngClass]=\"{ 'selected': index === selectedView }\" (click)=\"onViewChange(index)\">\n            {{ view }}\n          </div>\n        </div>\n      </div>\n    </div>\n  </div>\n\n  <!-- Calendar Weekdays -->\n  <div class=\"calendar-weekdays\" *ngIf=\"viewOptions[selectedView] === 'Month'\">\n    <span *ngFor=\"let day of daysOfTheWeek\" class=\"calendar-weekday\">{{ day }}</span>\n  </div>\n  <div [ngClass]=\"viewOptions[selectedView] === 'Work week' ? 'calendar-working-weekdays' : 'calendar-weekdays'\" *ngIf=\"viewOptions[selectedView] === 'Work week' || viewOptions[selectedView] === 'Week'\">\n    <span *ngFor=\"let day of daysOfTheWeek and let index = index\" class=\"calendar-weekday\" [class.current-day-in-weekdays]=\"currentWeekDays[index] === currentDay\">\n      <div>\n        {{ day }}\n      </div>\n      {{currentWeekDays[index]}}\n    </span>\n  </div>\n\n  <!-- Calendar Days -->\n  <div class=\"calendar-days\" *ngIf=\"viewOptions[selectedView] === 'Month'\">\n    <!-- Blank spaces before 1st day -->\n    <div *ngFor=\"let blank of [].constructor(firstDayOfWeek)\">\n      <div></div>\n    </div>\n\n    <!-- Calendar Days -->\n    <div *ngFor=\"let day of daysInMonth\" class=\"calendar-day\" [class.current-day]=\"day === currentDay\" (click)=\"handleCalenderEvent(day)\">\n      <div style=\"font-weight: bolder;\">\n        {{ day }}\n      </div>\n      <div *ngFor=\"let eventDetails of calendar_events\">\n        <div *ngIf=\"eventDetails.month - 1 === currentMonth\">\n          <div *ngFor=\"let list of eventDetails.list\">\n            <div *ngIf=\"list.day === day\">\n              <div *ngFor=\"let event of list.events and let index = index\">\n                <span class=\"events\" [ngStyle]=\"event.style | styleObject\" *ngIf=\"index < 2\" #trigger (click)=\"openPopover($event, day, event)()\">\n                  {{ event.title }} - {{ event.time }}\n                </span>\n                <div class=\"extra-events\" *ngIf=\"index===2\" (click)=\"openOffCanvas(day, list.events)\">+{{ list.events.length - 2 }}</div>\n              </div>\n            </div>\n          </div>\n        </div>\n      </div>\n    </div>\n  </div>\n\n  <div class=\"calendar-days\" style=\"display: flex; margin: 0;\" *ngIf=\"viewOptions[selectedView] === 'Work week' || viewOptions[selectedView] === 'Week'\">\n    <div [ngClass]=\"viewOptions[selectedView] === 'Work week' ? 'calendar-week-days' : 'calendar-weekend-days'\" style=\"border: 1px solid #000;\">\n      <div class=\"calendar-week-day\" *ngFor=\"let day of currentWeekDays; let index = index\" [class.current-day-in-weekdays]=\"currentWeekDays[index] === currentDay\">\n        <div class=\"time-slot\" *ngFor=\"let hour of hours\">\n          <div style=\"height: 100%;\" *ngFor=\"let eventDetails of calendar_events\">\n\n\n            <ng-container *ngIf=\"eventDetails.month - 1 === currentMonth\">\n              <div style=\"height: 50%; padding: 5px 0 2px 4px; width: 100%; overflow-y: auto;\">\n                <div *ngIf=\"index === 0\">\n                  {{ hour }}\n                </div>\n\n                <div *ngFor=\"let list of eventDetails.list\">\n                  <ng-container *ngIf=\"list.day === day\">\n                    <ng-container *ngIf=\"(list.events | filterEvents:getEventHour(hour, '00')) as filteredEvents\">\n                      <ng-container *ngFor=\"let event of filteredEvents.slice(0, 2)\">\n                        <span class=\"week-events\" [ngStyle]=\"event.style | styleObject\" #trigger (click)=\"openPopover($event, day, event)\">\n                          {{ event.title }} - {{ event.time }}\n                        </span>\n                      </ng-container>\n                      <div *ngIf=\"filteredEvents.length > 2\" (click)=\"openOffCanvas(day, list.events)\" class=\"extra-week-events\">+{{ filteredEvents.length - 2 }}</div>\n                    </ng-container>\n                  </ng-container>\n                </div>\n\n              </div>\n              <div style=\"border-top: 1px solid rgba(128, 128, 128, 0.486); min-height: 50%; padding: 5px 0 2px 4px; width: 100%; overflow-y: auto;\">\n\n                <div *ngFor=\"let list of eventDetails.list\">\n                  <ng-container *ngIf=\"list.day === day\">\n                    <ng-container *ngIf=\"(list.events | filterEvents:getEventHour(hour, '30')) as filteredEvents\">\n                      <ng-container *ngFor=\"let event of filteredEvents.slice(0, 2)\">\n                        <span class=\"week-events\" [ngStyle]=\"event.style | styleObject\" #trigger (click)=\"openPopover($event, day, event)\">\n                          {{ event.title }} - {{ event.time }}\n                        </span>\n                      </ng-container>\n                      <div *ngIf=\"filteredEvents.length > 2\" (click)=\"openOffCanvas(day, list.events)\" class=\"extra-week-events\">+{{ filteredEvents.length - 2 }}</div>\n                    </ng-container>\n                  </ng-container>\n                </div>\n\n              </div>\n            </ng-container>\n\n          </div>\n        </div>\n\n      </div>\n    </div>\n  </div>\n\n\n</div>\n\n<div class=\"off-canvas\" [class.open]=\"isOffCanvasOpen\">\n  <div class=\"off-canvas-header\">\n    <h3>{{ weekDay?.slice(0, 3) }}, {{ currentMonthName.slice(0, 3) }} {{ selectedDay }}</h3>\n    <button class=\"close-btn\" (click)=\"closeOffCanvas()\">\u00D7</button>\n  </div>\n\n  <div class=\"off-canvas-content\">\n    <div *ngIf=\"selectedDayEvents.length; else noEvents\">\n      <div *ngFor=\"let event of selectedDayEvents\" class=\"event-card\" [ngStyle]=\"event.style | styleObject\">\n        <div class=\"event-header\">\n          <h3 class=\"event-title\">{{ event.title }}</h3>\n        </div>\n\n        <div class=\"event-category\" [ngStyle]=\"{'background': event.categoryColor}\">\n          {{ event.category || 'General' }}\n        </div>\n\n        <div class=\"popover-section\">\n          <i class=\"icon-calendar\"></i>\n          <p>{{ selectedDay }} {{ currentMonthName }} {{ weekDay?.slice(0, 3) }},\n            {{ selectedEventDetail.start_time }} - {{ selectedEventDetail.end_time }}</p>\n        </div>\n\n        <div class=\"event-section\">\n          <i class=\"icon-location\"></i>\n          <p>\n            {{ selectedEventDetail.location}}\n          </p>\n        </div>\n\n        <div class=\"event-section attendees\" *ngIf=\"event.attendees?.length\">\n          <i class=\"icon-users\"></i>\n          <div class=\"attendees-list\">\n            <div class=\"attendee\" *ngFor=\"let attendee of event.attendees.slice(0, 3)\">\n              <img [src]=\"attendee.image\" [alt]=\"attendee.name\">\n              <span class=\"attendee-name\">{{ attendee.name }}</span>\n            </div>\n            <span *ngIf=\"event.attendees.length > 3\" class=\"more-attendees\">\n              +{{ event.attendees.length - 3 }} more\n            </span>\n          </div>\n        </div>\n\n        <div class=\"event-section\">\n          <i class=\"icon-info\"></i>\n          <p>{{ event.description }}</p>\n        </div>\n      </div>\n    </div>\n\n    <ng-template #noEvents>\n      <p class=\"no-events\">No events scheduled for this day.</p>\n    </ng-template>\n  </div>\n</div>\n\n\n\n\n\n<div #popover class=\"popover-container\" [ngClass]=\"{ 'show': isPopoverOpen }\" [ngStyle]=\"selectedEventDetail.style | styleObject\">\n  <div class=\"popover-content\">\n    <h3 class=\"popover-title\">\n      {{ selectedEventDetail.title }}\n    </h3>\n\n    <div class=\"event-category\" [ngStyle]=\"{'background': selectedEventDetail.categoryColor}\">\n      {{ selectedEventDetail.category || 'General' }}\n    </div>\n\n    <div class=\"popover-section\">\n      <i class=\"icon-calendar\"></i>\n      <p>{{ selectedDay }} {{ currentMonthName }} {{ weekDay?.slice(0, 3) }},\n        {{ selectedEventDetail.start_time }} - {{ selectedEventDetail.end_time }}</p>\n    </div>\n\n    <div class=\"event-section\" *ngIf=\"selectedEventDetail.location\">\n      <i class=\"icon-location\"></i>\n      <p>\n        {{ selectedEventDetail.location }}\n      </p>\n    </div>\n\n    <div class=\"event-section attendees\" *ngIf=\"selectedEventDetail.attendees?.length\">\n      <i class=\"icon-users\"></i>\n      <div class=\"attendees-list\">\n        <div class=\"attendee\" *ngFor=\"let attendee of selectedEventDetail.attendees.slice(0, 3)\">\n          <img [src]=\"attendee.image\" [alt]=\"attendee.name\">\n          <span class=\"attendee-name\">{{ attendee.name }}</span>\n        </div>\n        <span *ngIf=\"selectedEventDetail.attendees.length > 3\" class=\"more-attendees\">\n          +{{ selectedEventDetail.attendees.length - 3 }} more\n        </span>\n      </div>\n    </div>\n\n    <div class=\"popover-section\">\n      <i class=\"icon-info\"></i>\n      <p>{{ selectedEventDetail.description }}</p>\n    </div>\n\n    <button class=\"close-btn\" (click)=\"isPopoverOpen = false\">\u2716</button>\n  </div>\n</div>\n", styles: [".calendar-container{display:flex;flex-direction:column;align-items:center;width:100%;margin:auto;padding:0 10px;box-sizing:border-box;min-height:100vh}.calendar-weekdays,.calendar-days{display:grid;grid-template-columns:repeat(7,minmax(50px,1fr));gap:5px;padding:10px;border:1px solid #000;width:100%}.calendar-working-weekdays{display:grid;grid-template-columns:repeat(5,minmax(50px,1fr));gap:5px;padding:10px;border:1px solid #000;width:100%}.calendar-weekday,.calendar-day{text-align:center;padding:8px;border-radius:5px;min-height:20px;cursor:pointer;border:1px solid #000;font-weight:bolder;font-size:14px}@media (max-width: 1024px){.calendar-weekdays,.calendar-days{grid-template-columns:repeat(7,minmax(40px,1fr))}.calendar-weekday,.calendar-day{font-size:12px;padding:5px}}@media (max-width: 768px){.calendar-weekdays,.calendar-days{grid-template-columns:repeat(7,minmax(35px,1fr))}.calendar-weekday,.calendar-day{font-size:11px;padding:4px}}@media (max-width: 480px){.calendar-weekdays,.calendar-days{grid-template-columns:repeat(7,minmax(30px,1fr))}.calendar-weekday,.calendar-day{font-size:10px;padding:3px}}.calendar-day{text-align:left;padding:10px;background-color:transparent;border-radius:5px;min-height:95px;align-content:flex-start;cursor:pointer;border:1px solid #000}.time-slot{height:50px;border-bottom:1px solid #333}.blank{background-color:transparent}.current-day{background-color:#0000008e;color:#fff;font-weight:700;border-radius:5px;align-content:center;cursor:pointer;border:1px solid #000;align-content:flex-start}.current-day-in-weekdays{background-color:#00000029;color:#fff;font-weight:700;align-content:center;cursor:pointer;align-content:flex-start}.header{padding:10px;border:1px solid #000;display:flex;justify-content:space-between;width:100%}.left-content,.right-content{padding:10px}.arrow-prev,.arrow-next,.current-month{font-weight:700;border:2px solid #000;padding:10px;border-radius:5px;cursor:pointer;background-color:#000;color:#fff}.arrow-prev,.month-dropdown,.arrow-next{margin-right:2px}.current-month{font-weight:700;padding:10px}.month-dropdown,.filter-dropdown{font-weight:700;border:2px solid #000;padding:10px;border-radius:5px;cursor:pointer;background-color:#000;color:#fff}.datepicker{background:#000;padding:10px;border-radius:8px;max-width:200px;position:relative}.datepicker-header{display:flex;justify-content:space-between;align-items:center;cursor:pointer;border-radius:6px}.datepicker-header span{font-size:14px}.month-grid{display:none;grid-template-columns:repeat(3,1fr);gap:3px 5px;padding:10px 5px;position:absolute;top:50px;left:0;background:#000;border-radius:8px;width:100%;box-shadow:0 4px 6px #0000004d;z-index:1}.year-container{grid-column-start:1;grid-column-end:4;padding:5px;display:grid;grid-template-columns:repeat(2,60%)}.year{text-align:center;padding:5px;border-radius:6px;cursor:pointer;color:#fff;border:1px solid #fff}.year-filter-arrow{text-align:center}.year-arrow{padding:5px;border:1px solid #fff;border-radius:6px;cursor:pointer;color:#fff;background:#000}.view-options-grid{display:none;grid-template-columns:repeat(1,1fr);gap:8px;padding:10px 5px;position:absolute;top:50px;left:0;background:#000;border-radius:8px;width:100%;z-index:1}.month{text-align:center;padding:5px;border-radius:6px;cursor:pointer;color:#fff;border:1px solid #fff}.month:hover,.selected{background:#fff;color:#000}.datepicker.active .month-grid,.datepicker.active .view-options-grid{display:grid;width:-webkit-max-content}.arrow{position:absolute;top:-8px;left:10%;transform:translate(-50%);width:0;height:0;border-left:8px solid transparent;border-right:8px solid transparent;border-bottom:8px solid #0d0d0d}.view-arrow,.view-arrow-popover{position:absolute;top:-8px;left:30%;transform:translate(-50%);width:0;height:0;border-left:8px solid transparent;border-right:8px solid transparent;border-bottom:8px solid #0d0d0d}.view-arrow-popover{border-bottom:8px solid #fff!important}.events{border:1px dotted #000;padding:2px;border-radius:5px;margin:5px 0;font-size:small;overflow:hidden;min-height:fit-content;white-space:nowrap;text-overflow:ellipsis;display:block;width:100%}.extra-events{background-color:#000;color:#fff;text-align:center;border-radius:5px;padding:2px;margin:5px 0;font-size:small;width:100%}.off-canvas{display:none;position:fixed;top:0;right:-320px;width:300px;height:100vh;background:#000c;-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);color:#fff;padding:20px;transition:right .3s ease-in-out;box-shadow:-5px 0 10px #0000004d;overflow-y:auto}.off-canvas.open{display:block;right:0}.off-canvas-header{display:flex;justify-content:space-between;align-items:center;border-bottom:2px solid rgba(255,255,255,.2);padding-bottom:10px}.off-canvas-header h3{font-size:18px;font-weight:700}.close-btn{background:none;border:none;color:#fff;font-size:20px;cursor:pointer;opacity:.8;transition:opacity .2s ease}.off-canvas-content{margin-top:10px}.event-card{background:#ffffff1a;border-radius:8px;padding:12px;margin-bottom:10px;transition:transform .2s ease-in-out}.event-card:hover{transform:scale(1.05)}.event-header{display:flex;align-items:center;gap:12px}.event-icon img{width:40px;height:40px;border-radius:50%}.event-icon i{font-size:24px;color:#fff}.event-title{font-size:16px;font-weight:700}.event-category{padding:4px 10px;border-radius:5px;font-size:12px;text-align:center;color:#fff;margin:8px 0}.event-section{display:flex;align-items:center;gap:8px;font-size:14px}.icon-calendar:before{content:\"\\1f4c5\"}.icon-location:before{content:\"\\1f4cd\"}.icon-users:before{content:\"\\1f465\"}.icon-timer:before{content:\"\\23f3\"}.event-actions{display:flex;justify-content:space-between;margin-top:10px}.btn{border:none;padding:8px 10px;border-radius:5px;cursor:pointer;font-size:12px}.btn-primary{background:#4caf50;color:#fff}.btn-secondary{background:#2196f3;color:#fff}.btn-edit{background:#ffc107;color:#fff}.btn-delete{background:#f44336;color:#fff}.btn:hover{opacity:.8}.no-events{text-align:center;font-style:italic;opacity:.7}.attendees{display:flex;align-items:center;gap:8px}.attendees-list{display:flex;flex-wrap:wrap;gap:8px}.attendee{display:flex;align-items:center;gap:6px;background:#ffffff1a;padding:4px 8px;border-radius:5px}.attendee img{width:28px;height:28px;border-radius:50%;border:2px solid white}.attendee-name{font-size:14px;color:#fff}.more-attendees{font-size:14px;color:#ddd;background:#fff3;padding:4px 8px;border-radius:5px}.popover-container{display:none;position:absolute;background:#ffffff1a;-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);border:1px solid rgba(255,255,255,.2);border-radius:12px;padding:16px;width:250px;box-shadow:0 8px 16px #0003;opacity:0;transform:scale(.95);pointer-events:none;transition:opacity .3s ease-in-out,visibility .3s ease-in-out}.popover-container.show{visibility:visible;display:block;opacity:1;transform:scale(1);pointer-events:auto}.popover-content{display:flex;flex-direction:column;gap:10px;color:#fff}.popover-title{font-size:18px;font-weight:700;padding-bottom:8px;border-bottom:2px solid rgba(255,255,255,.3);text-align:center}.popover-section{display:flex;align-items:center;gap:8px;font-size:14px}.icon-calendar:before,.icon-info:before{content:\"\\1f4c5\";font-size:16px}.icon-info:before{content:\"\\2139\\fe0f\"}.close-btn{position:absolute;top:8px;left:88%;background:none;border:none;color:#fff;font-size:16px;cursor:pointer;opacity:.7;transition:opacity .2s ease}.close-btn:hover{opacity:1}.time-column{display:flex;flex-direction:column;align-items:flex-end;text-align:right;font-weight:700}.calendar-week-days{display:grid;grid-template-columns:repeat(5,1fr);border-left:1px solid #444;height:78vh;overflow-y:scroll;overflow-x:auto;width:100%}.calendar-weekend-days{display:grid;grid-template-columns:repeat(7,1fr);border-left:1px solid #444;height:78vh;overflow-y:scroll;overflow-x:auto;width:100%}.calendar-week-day{display:grid;grid-template-rows:repeat(24,120px);border-right:1px solid #444;width:100%}.time-slot{border-bottom:1px solid #333;height:120px;padding:5px 0;width:100%;box-sizing:border-box;position:relative}.time-divider{position:absolute;width:100%;border-bottom:1px solid #333;left:0}.week-events{border:1px dotted #000;border-radius:5px;margin:5px 0;font-size:small;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;display:block;width:92%;cursor:pointer}.extra-week-events{background-color:#000;color:#fff;text-align:center;border-radius:5px;padding:2px;margin:5px 0;font-size:small;width:92%;cursor:pointer}\n"] }]
        }], ctorParameters: () => [{ type: i0.ElementRef }], propDecorators: { popover: [{
                type: ViewChild,
                args: ['popover']
            }], calendar_events: [{
                type: Input
            }], calendar_themes: [{
                type: Input
            }] } });

class NpxCalendarComponent {
    events = [];
    options = {
        show_header: true,
        show_arrow: true,
        show_month_picker: true,
        show_calendar_view_filter: true
    };
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.0", ngImport: i0, type: NpxCalendarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
    static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.0", type: NpxCalendarComponent, isStandalone: true, selector: "npx-calendar", inputs: { events: "events", options: "options" }, ngImport: i0, template: `
   <lib-calendar [calendar_events]="events" [calendar_themes]="options"></lib-calendar>
  `, isInline: true, styles: [""], dependencies: [{ kind: "component", type: CalendarComponent, selector: "lib-calendar", inputs: ["calendar_events", "calendar_themes"] }] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.0", ngImport: i0, type: NpxCalendarComponent, decorators: [{
            type: Component,
            args: [{ selector: 'npx-calendar', imports: [CalendarComponent], template: `
   <lib-calendar [calendar_events]="events" [calendar_themes]="options"></lib-calendar>
  ` }]
        }], propDecorators: { events: [{
                type: Input
            }], options: [{
                type: Input
            }] } });

/*
 * Public API Surface of npx-calendar
 */

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

export { NpxCalendarComponent, NpxCalendarService };
//# sourceMappingURL=npx-calendar.mjs.map