UNPKG

@obliczeniowo/elementary

Version:
377 lines (368 loc) 21.9 kB
import * as i1 from '@obliczeniowo/elementary/icons'; import { IconsModule } from '@obliczeniowo/elementary/icons'; import * as i0 from '@angular/core'; import { input, ViewChild, Component, ContentChildren, EventEmitter, LOCALE_ID, HostListener, Output, Input, Inject, model, NgModule } from '@angular/core'; import * as i2 from '@angular/common'; import { DatePipe, CommonModule } from '@angular/common'; import { ns, xlink } from '@obliczeniowo/elementary/svg'; import { SvgGroup, SvgRect, Style, SvgText, Rotate } from '@obliczeniowo/elementary/post-diagram'; class CalendarEventComponent { calendarEventComponent; calendarEventWindow; eventSettings = input.required(); constructor(calendarEventComponent) { this.calendarEventComponent = calendarEventComponent; } ngAfterViewInit() { this.calendarEventComponent.nativeElement.style.display = 'none'; this.calendarEventComponent.nativeElement.style.position = 'fixed'; this.calendarEventComponent.nativeElement.style.top = '0'; this.calendarEventComponent.nativeElement.style.left = '0'; this.calendarEventComponent.nativeElement.style.width = '100%'; this.calendarEventComponent.nativeElement.style.height = '100%'; this.calendarEventComponent.nativeElement.onclick = () => { this.calendarEventComponent.nativeElement.style.display = 'none'; }; this.calendarEventWindow.nativeElement.style.position = 'relative'; } displayWindow(x, y) { this.calendarEventWindow.nativeElement.style.left = x.toString() + 'px'; this.calendarEventWindow.nativeElement.style.top = y.toString() + 'px'; this.calendarEventComponent.nativeElement.style.display = 'block'; } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.4", ngImport: i0, type: CalendarEventComponent, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component }); static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "20.0.4", type: CalendarEventComponent, isStandalone: false, selector: "obl-calendar-event", inputs: { eventSettings: { classPropertyName: "eventSettings", publicName: "eventSettings", isSignal: true, isRequired: true, transformFunction: null } }, viewQueries: [{ propertyName: "calendarEventWindow", first: true, predicate: ["calendarEventWindow"], descendants: true }], ngImport: i0, template: "<div class=\"window\"\n [style.borderColor]=\"eventSettings().color\"\n [style.borderWidth.px]=\"1\"\n [style.borderStyle]=\"'solid'\"\n #calendarEventWindow>\n <ng-content select=\"title\"></ng-content>\n\n <ng-content select=\"body\"></ng-content>\n</div>", styles: [":host{background:#4285f400;color:#fff;position:fixed;top:0;left:0;width:100vw;height:100vh}.window{opacity:1;background-color:#000;max-width:300px;border-radius:5px;display:flex;flex-direction:column}ng-content{border-radius:5px}\n"] }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.4", ngImport: i0, type: CalendarEventComponent, decorators: [{ type: Component, args: [{ selector: 'obl-calendar-event', standalone: false, template: "<div class=\"window\"\n [style.borderColor]=\"eventSettings().color\"\n [style.borderWidth.px]=\"1\"\n [style.borderStyle]=\"'solid'\"\n #calendarEventWindow>\n <ng-content select=\"title\"></ng-content>\n\n <ng-content select=\"body\"></ng-content>\n</div>", styles: [":host{background:#4285f400;color:#fff;position:fixed;top:0;left:0;width:100vw;height:100vh}.window{opacity:1;background-color:#000;max-width:300px;border-radius:5px;display:flex;flex-direction:column}ng-content{border-radius:5px}\n"] }] }], ctorParameters: () => [{ type: i0.ElementRef }], propDecorators: { calendarEventWindow: [{ type: ViewChild, args: ['calendarEventWindow', { static: false }] }] } }); class EventsListComponent { eventsList; static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.4", ngImport: i0, type: EventsListComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.0.4", type: EventsListComponent, isStandalone: false, selector: "obl-events-list", queries: [{ propertyName: "eventsList", predicate: CalendarEventComponent }], ngImport: i0, template: "<ng-content select=\"eventslist\">\n</ng-content>", styles: [""] }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.4", ngImport: i0, type: EventsListComponent, decorators: [{ type: Component, args: [{ selector: 'obl-events-list', standalone: false, template: "<ng-content select=\"eventslist\">\n</ng-content>" }] }], propDecorators: { eventsList: [{ type: ContentChildren, args: [CalendarEventComponent] }] } }); class SvgDayElement { day; svgGroup; svgDayNumber; svgDayFrame; svgDayBackground; eventComponent; svgContainer; set event(eventListComponent) { if (eventListComponent) { this.eventComponent = eventListComponent.eventsList.find((event) => { return event.eventSettings().day.getDate() === this.day.getDate() && event.eventSettings().day.getMonth() === this.day.getMonth() && event.eventSettings().day.getFullYear() === this.day.getFullYear(); }); } const now = new Date(); const isNowDay = this.day.getDate() === now.getDate() && this.day.getMonth() === now.getMonth() && this.day.getFullYear() === now.getFullYear(); this.svgDayBackground.svg.style.fill = this.eventComponent ? this.eventComponent.eventSettings().color : (isNowDay ? '#0078d7' : '#3d3d3d'); } constructor(x, y, width, height, day, currentMonth, svgContainer, eventsListComponent, onClick) { this.day = day; this.svgGroup = new SvgGroup(this.id, 'cursor: pointer'); this.svgContainer = svgContainer; svgContainer.appendChild(this.svgGroup.svgGroupContainer); const now = new Date(); const isNowDay = this.day.getDate() === now.getDate() && this.day.getMonth() === now.getMonth() && this.day.getFullYear() === now.getFullYear(); this.svgDayFrame = new SvgRect(x, y, width, height, this.frameId, this.svgGroup, new Style({ fill: '#3d3d3d', stroke: isNowDay ? '#0078d7' : 'none' })); const dx = 3; this.svgDayBackground = new SvgRect(x + dx, y + dx, width - 2 * dx, height - 2 * dx, this.backgroundId, this.svgGroup, new Style({ fill: isNowDay ? '#0078d7' : '#3d3d3d' })); this.svgDayNumber = new SvgText(x + width / 2, y + height / 2 + 5, this.day.getDate().toString(), new Style({ 'text-anchor': 'middle', fill: this.day.getDay() ? '#ffffff' : '#ff4400', opacity: currentMonth.getMonth() === this.day.getMonth() ? '1' : '0.5' }), this.textId, new Rotate(0), this.svgGroup); this.event = eventsListComponent; this.onClick = onClick; this.svgGroup.svgGroupContainer.onclick = () => { if (this.eventComponent) { const rect = this.svgContainer.getBoundingClientRect(); this.eventComponent.displayWindow(x + rect.x, y + rect.y); } if (this.onClick) { this.onClick(this.day); } }; } onClick; setDay(day, currentMonth) { this.day = new Date(day); const now = new Date(); const isNowDay = this.day.getDate() === now.getDate() && this.day.getMonth() === now.getMonth() && this.day.getFullYear() === now.getFullYear(); this.svgDayBackground.svg.setAttribute('id', this.backgroundId); this.svgDayBackground.svg.setAttribute('style', new Style({ fill: !isNowDay ? '#3d3d3d' : '#0078d7' }).toString()); this.svgDayNumber.svg.setAttribute('id', this.textId); this.svgDayNumber.setText(day.getDate().toString()); this.svgDayNumber.svg.setAttribute('style', new Style({ 'text-anchor': 'middle', fill: this.day.getDay() ? '#ffffff' : '#ff4400', opacity: currentMonth.getMonth() === this.day.getMonth() ? '1' : '0.5' }).toString()); this.svgDayFrame.svg.setAttribute('id', this.frameId); this.svgDayFrame.svg.setAttribute('style', new Style({ fill: '#3d3d3d', stroke: !isNowDay ? 'none' : '#0078d7' }).toString()); } get id() { return 'day_' + this.day.getDate() + '_' + this.day.getMonth() + '_' + this.day.getFullYear(); } get frameId() { return 'frame_' + this.id; } get textId() { return 'day_' + this.id; } get backgroundId() { return 'background_' + this.id; } } class CalendarComponent { locale; calendarComponent; renderer; svgContainer; monthControl = input(null); // tslint:disable-next-line: variable-name _eventsList = null; set eventsList(eventList) { this._eventsList = eventList; this.setEvents(); } clicked = new EventEmitter(); width = 500; height = 500; rectWidth = 40; rectHeight = 40; dx = 5; framesGroup; defs; radialGradient; linearGradient; datePipe; currentDay = new Date(); currentMonth = new Date(); startDate; endDate; backgroundColor = '#3d3d3d'; svgRects = []; svgNumbers = []; svgHeaderGroup; svgHeaderDaysText = []; constructor(locale, calendarComponent, renderer) { this.locale = locale; this.calendarComponent = calendarComponent; this.renderer = renderer; // do not move outside of constructor as brings initialization problem in installing project this.datePipe = new DatePipe(this.locale || 'en-US'); this.defs = this.renderer.createElement('defs', ns); this.radialGradient = this.renderer.createElement('radialGradient', ns); this.linearGradient = this.renderer.createElement('linearGradient', ns); this.setStartEndDates(); } setStartEndDates() { this.startDate = new Date(this.currentMonth); this.startDate.setDate(1 - this.getFirstMonthDay(this.startDate)); this.endDate = new Date(this.startDate); this.endDate.setDate(this.startDate.getDate() + 7 * 6 - 1); } getFirstMonthDay(date) { const firstDay = new Date(date); firstDay.setDate(1); return firstDay.getDay() > 0 ? firstDay.getDay() - 1 : 6; } setXYGradientPost(x, y) { this.radialGradient.setAttribute('cx', x.toString()); this.radialGradient.setAttribute('cy', y.toString()); this.radialGradient.setAttribute('fx', x.toString()); this.radialGradient.setAttribute('fy', y.toString()); } mouseMove(event) { const rect = this.svgContainer.nativeElement.getBoundingClientRect(); this.setXYGradientPost(event.clientX - rect.left, event.clientY - rect.top); } setMonth(monthDate) { this.currentMonth = new Date(monthDate); this.setStartEndDates(); this.setEvents(); } setEvents() { this.svgNumbers.forEach((svgNumber, index) => { const day = new Date(this.startDate); day.setDate(day.getDate() + index); svgNumber.setDay(day, this.currentMonth); svgNumber.event = this._eventsList; }); } ngAfterViewInit() { this.calendarComponent.nativeElement.style.backgroundColor = this.backgroundColor; this.backgroundColor = '#3d3d3d'; this.width = (this.rectHeight + this.dx) * 7 + this.dx; this.height = (this.rectWidth + this.dx) * 7 + this.dx; this.svgContainer.nativeElement.setAttribute('width', this.width.toString()); this.svgContainer.nativeElement.setAttribute('height', this.height.toString()); this.svgContainer.nativeElement.style.backgroundColor = this.backgroundColor; this.linearGradient.id = 'frameLinearGradient'; const svgGradientStop = this.renderer.createElement('stop', ns); svgGradientStop.setAttribute('style', 'stop-color: white; stop-opacity: 1'); svgGradientStop.setAttribute('offset', '0'); const svgGradientStopEnd = this.renderer.createElement('stop', ns); svgGradientStopEnd.setAttribute('style', 'stop-color: white; stop-opacity: 0'); svgGradientStopEnd.setAttribute('offset', '1'); this.radialGradient.setAttributeNS(xlink, 'href', '#frameLinearGradient'); this.radialGradient.setAttribute('id', 'frameGradient'); this.radialGradient.setAttribute('cx', '1'); this.radialGradient.setAttribute('cy', '1'); this.radialGradient.setAttribute('fx', '1'); this.radialGradient.setAttribute('fy', '1'); this.radialGradient.setAttribute('r', '70'); this.radialGradient.setAttribute('gradientUnits', 'userSpaceOnUse'); this.linearGradient.appendChild(svgGradientStop); this.linearGradient.appendChild(svgGradientStopEnd); this.defs.appendChild(this.linearGradient); this.defs.appendChild(this.radialGradient); this.svgContainer.nativeElement.appendChild(this.defs); const monthControl = this.monthControl(); if (monthControl) { monthControl.triggerFunction = (date) => { this.setMonth(date); }; } this.framesGroup = new SvgGroup('framesGroup', 'stroke: url(#frameGradient); fill: none'); let day; const dx = 0; const dy = this.rectHeight; this.svgHeaderGroup = new SvgGroup('days_header'); const days = []; for (let offset = 0; offset < 7; offset++) { const date = new Date(this.startDate); date.setDate(date.getDate() + offset); days.push(this.datePipe.transform(date, 'E')); } days.forEach((dayT, index) => { this.svgHeaderDaysText.push(new SvgText(index * (this.rectWidth + this.dx) + 0.5 * this.rectWidth + this.dx, this.rectHeight - 12, dayT, new Style({ 'text-anchor': 'middle', fill: index !== 6 ? '#ffffff' : '#ff5500', 'font-size': '15px' }), 'day_header_' + index, new Rotate(0), this.svgHeaderGroup)); }); this.svgContainer.nativeElement.appendChild(this.svgHeaderGroup.svgGroupContainer); for (let y = 0; y < 6; y++) { for (let x = 0; x < 7; x++) { this.svgRects.push(new SvgRect((this.rectWidth + this.dx) * x + this.dx + dx, (this.rectHeight + this.dx) * y + this.dx + dy, this.rectWidth, this.rectHeight, '1', this.framesGroup, new Style({}))); day = new Date(this.startDate); day.setDate(day.getDate() + y * 7 + x); this.svgNumbers.push(new SvgDayElement((this.rectWidth + this.dx) * x + this.dx + dx, (this.rectHeight + this.dx) * y + this.dx + dy, this.rectWidth, this.rectHeight, day, this.currentDay, this.svgContainer.nativeElement, this._eventsList, (date) => this.clicked.emit(date))); } } this.svgContainer.nativeElement.appendChild(this.framesGroup.svgGroupContainer); } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.4", ngImport: i0, type: CalendarComponent, deps: [{ token: LOCALE_ID }, { token: i0.ElementRef }, { token: i0.Renderer2 }], target: i0.ɵɵFactoryTarget.Component }); static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "20.0.4", type: CalendarComponent, isStandalone: false, selector: "obl-calendar", inputs: { monthControl: { classPropertyName: "monthControl", publicName: "monthControl", isSignal: true, isRequired: false, transformFunction: null }, eventsList: { classPropertyName: "eventsList", publicName: "eventsList", isSignal: false, isRequired: false, transformFunction: null } }, outputs: { clicked: "clicked" }, host: { listeners: { "mousemove": "mouseMove($event)" } }, viewQueries: [{ propertyName: "svgContainer", first: true, predicate: ["svgContainer"], descendants: true }], ngImport: i0, template: "<svg #svgContainer></svg>\n", styles: [""] }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.4", ngImport: i0, type: CalendarComponent, decorators: [{ type: Component, args: [{ selector: 'obl-calendar', standalone: false, template: "<svg #svgContainer></svg>\n" }] }], ctorParameters: () => [{ type: undefined, decorators: [{ type: Inject, args: [LOCALE_ID] }] }, { type: i0.ElementRef }, { type: i0.Renderer2 }], propDecorators: { svgContainer: [{ type: ViewChild, args: ['svgContainer', { static: false }] }], eventsList: [{ type: Input }], clicked: [{ type: Output }], mouseMove: [{ type: HostListener, args: ['mousemove', ['$event']] }] } }); class MonthControlComponent { date = model(new Date()); triggerFunction = (date) => { }; nextMonth() { this.date.set(new Date(this.date().setMonth(this.date().getMonth() + 1))); this.triggerFunction(this.date()); } previousMonth() { this.date.set(new Date(this.date().setMonth(this.date().getMonth() - 1))); this.triggerFunction(this.date()); } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.4", ngImport: i0, type: MonthControlComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "20.0.4", type: MonthControlComponent, isStandalone: false, selector: "obl-month-control", inputs: { date: { classPropertyName: "date", publicName: "date", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { date: "dateChange" }, ngImport: i0, template: "<button (click)=\"previousMonth()\">\n <obl-icon [name]=\"'left'\"></obl-icon>\n</button>\n\n<div>{{ this.date() | date: 'LLLL - yyyy' }}</div>\n\n<button (click)=\"nextMonth()\">\n <obl-icon [name]=\"'right'\"></obl-icon>\n</button>\n", styles: [":host{color:#fff;background-color:#000;display:flex;justify-content:space-between;align-items:center}:host button{background:none;color:inherit;border:none;padding:0;font:inherit;cursor:pointer;outline:inherit;height:40px;width:40px;display:flex;align-items:center;justify-content:center}obl-icon{--obl-default-icon-color: white;width:30px!important}\n"], dependencies: [{ kind: "component", type: i1.IconComponent, selector: "obl-icon", inputs: ["name", "width"] }, { kind: "pipe", type: i2.DatePipe, name: "date" }] }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.4", ngImport: i0, type: MonthControlComponent, decorators: [{ type: Component, args: [{ selector: 'obl-month-control', standalone: false, template: "<button (click)=\"previousMonth()\">\n <obl-icon [name]=\"'left'\"></obl-icon>\n</button>\n\n<div>{{ this.date() | date: 'LLLL - yyyy' }}</div>\n\n<button (click)=\"nextMonth()\">\n <obl-icon [name]=\"'right'\"></obl-icon>\n</button>\n", styles: [":host{color:#fff;background-color:#000;display:flex;justify-content:space-between;align-items:center}:host button{background:none;color:inherit;border:none;padding:0;font:inherit;cursor:pointer;outline:inherit;height:40px;width:40px;display:flex;align-items:center;justify-content:center}obl-icon{--obl-default-icon-color: white;width:30px!important}\n"] }] }] }); class DateModule { static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.4", ngImport: i0, type: DateModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.0.4", ngImport: i0, type: DateModule, declarations: [EventsListComponent, CalendarComponent, MonthControlComponent, CalendarEventComponent], imports: [CommonModule, IconsModule], exports: [EventsListComponent, CalendarComponent, MonthControlComponent, CalendarEventComponent] }); static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.0.4", ngImport: i0, type: DateModule, imports: [CommonModule, IconsModule] }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.4", ngImport: i0, type: DateModule, decorators: [{ type: NgModule, args: [{ declarations: [ EventsListComponent, CalendarComponent, MonthControlComponent, CalendarEventComponent ], imports: [ CommonModule, IconsModule ], exports: [ EventsListComponent, CalendarComponent, MonthControlComponent, CalendarEventComponent ], providers: [] }] }] }); /** * Generated bundle index. Do not edit. */ export { CalendarComponent, CalendarEventComponent, DateModule, EventsListComponent, MonthControlComponent }; //# sourceMappingURL=obliczeniowo-elementary-date.mjs.map