shdr-calendar 0.0.2 → 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Component, signal, computed, inject, input } from '@angular/core';
|
|
2
|
-
import { NgFor } from '@angular/common';
|
|
2
|
+
import { NgFor, NgIf } from '@angular/common';
|
|
3
3
|
import { CalendarService } from './calendar.service';
|
|
4
4
|
import * as i0 from "@angular/core";
|
|
5
5
|
export class CalendarComponent {
|
|
@@ -55,10 +55,10 @@ export class CalendarComponent {
|
|
|
55
55
|
this.selectedDate.set(today);
|
|
56
56
|
}
|
|
57
57
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: CalendarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
58
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.12", type: CalendarComponent, isStandalone: true, selector: "shdr-calendar", inputs: { calendarStates: { classPropertyName: "calendarStates", publicName: "calendarStates", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div class=\"calendar\">\n <header class=\"calendar-header\">\n <button type=\"button\" class=\"nav-btn\" (click)=\"prevMonth()\" aria-label=\"\u4E0A\u4E00\u6708\">\n \u2039\n </button>\n <h2 class=\"month-year\">{{ monthYearLabel() }}</h2>\n <button type=\"button\" class=\"nav-btn\" (click)=\"nextMonth()\" aria-label=\"\u4E0B\u4E00\u6708\">\n \u203A\n </button>\n </header>\n\n <button type=\"button\" class=\"today-btn\" (click)=\"goToToday()\">\u4ECA\u5929</button>\n\n <div class=\"weekdays\">\n @for (label of weekDays; track label) {\n <span class=\"weekday\">{{ label }}</span>\n }\n </div>\n\n <div class=\"days-grid\">\n @for (day of days(); track day.date.getTime()) {\n <button\n type=\"button\"\n class=\"day-cell\"\n [class.other-month]=\"!day.isCurrentMonth\"\n [class.today]=\"day.isToday\"\n [class.selected]=\"day.isSelected\"\n [class.status-available]=\"day.status === 'AVAILABLE'\"\n [class.status-purchased]=\"day.status === 'PURCHASED'\"\n (click)=\"selectDay(day)\"\n >\n {{ day.day }}\n </button>\n }\n </div>\n</div>\n", styles: [":host{display:block}.calendar{--cal-bg: #fff;--cal-border: #e2e8f0;--cal-text: #1e293b;--cal-text-muted: #64748b;--cal-today: #3b82f6;--cal-selected: #2563eb;--cal-selected-text: #fff;--cal-hover: #f1f5f9;max-width:360px;padding:1rem;background:var(--cal-bg);border:1px solid var(--cal-border);border-radius:12px;font-family:system-ui,-apple-system,sans-serif}.calendar-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:.75rem}.month-year{margin:0;font-size:1.125rem;font-weight:600;color:var(--cal-text)}.nav-btn{width:2rem;height:2rem;display:flex;align-items:center;justify-content:center;border:none;background:var(--cal-hover);color:var(--cal-text);border-radius:8px;cursor:pointer;font-size:1.25rem;line-height:1}.nav-btn:hover{background:var(--cal-border)}.today-btn{display:block;width:100%;margin-bottom:1rem;padding:.5rem;border:1px solid var(--cal-border);background:transparent;color:var(--cal-text);border-radius:8px;cursor:pointer;font-size:.875rem}.today-btn:hover{background:var(--cal-hover)}.weekdays{display:grid;grid-template-columns:repeat(7,1fr);gap:2px;margin-bottom:4px}.weekday{text-align:center;font-size:.75rem;font-weight:600;color:var(--cal-text-muted)}.days-grid{display:grid;grid-template-columns:repeat(7,1fr);gap:2px}.day-cell{position:relative;aspect-ratio:1;display:flex;align-items:center;justify-content:center;border:none;background:transparent;color:var(--cal-text);font-size:.875rem;border-radius:8px;cursor:pointer}.day-cell:hover{background:var(--cal-hover)}.day-cell.other-month{color:var(--cal-text-muted)}.day-cell.today{font-weight:700;color:var(--cal-today)}.day-cell.selected{background:var(--cal-selected);color:var(--cal-selected-text)}.day-cell.selected:hover{background:var(--cal-selected);filter:brightness(1.05)}.day-cell.status-available{--cal-
|
|
58
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.12", type: CalendarComponent, isStandalone: true, selector: "shdr-calendar", inputs: { calendarStates: { classPropertyName: "calendarStates", publicName: "calendarStates", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div class=\"calendar\">\n <header class=\"calendar-header\">\n <button type=\"button\" class=\"nav-btn\" (click)=\"prevMonth()\" aria-label=\"\u4E0A\u4E00\u6708\">\n \u2039\n </button>\n <h2 class=\"month-year\">{{ monthYearLabel() }}</h2>\n <button type=\"button\" class=\"nav-btn\" (click)=\"nextMonth()\" aria-label=\"\u4E0B\u4E00\u6708\">\n \u203A\n </button>\n </header>\n\n <button type=\"button\" class=\"today-btn\" (click)=\"goToToday()\">\u4ECA\u5929</button>\n\n <div class=\"weekdays\">\n @for (label of weekDays; track label) {\n <span class=\"weekday\">{{ label }}</span>\n }\n </div>\n\n <div class=\"days-grid\">\n @for (day of days(); track day.date.getTime()) {\n <button\n type=\"button\"\n class=\"day-cell\"\n [class.other-month]=\"!day.isCurrentMonth\"\n [class.today]=\"day.isToday\"\n [class.selected]=\"day.isSelected\"\n [class.status-available]=\"day.status === 'AVAILABLE'\"\n [class.status-purchased]=\"day.status === 'PURCHASED'\"\n [attr.disabled]=\"day.status === 'PURCHASED' ? true : null\"\n (click)=\"day.status !== 'PURCHASED' && selectDay(day)\"\n >\n <span class=\"day-num\">{{ day.day }}</span>\n <span class=\"day-label\" *ngIf=\"day.status === 'PURCHASED'\">\u5DF2\u9884\u7EA6</span>\n <span class=\"day-label\" *ngIf=\"day.status !== 'PURCHASED' && day.isToday\">\u4ECA\u5929</span>\n </button>\n }\n </div>\n</div>\n", styles: [":host{display:block}.calendar{--cal-bg: #fff;--cal-border: #e2e8f0;--cal-text: #1e293b;--cal-text-muted: #64748b;--cal-today: #3b82f6;--cal-selected: #2563eb;--cal-selected-text: #fff;--cal-hover: #f1f5f9;max-width:360px;padding:1rem;background:var(--cal-bg);border:1px solid var(--cal-border);border-radius:12px;font-family:system-ui,-apple-system,sans-serif}.calendar-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:.75rem}.month-year{margin:0;font-size:1.125rem;font-weight:600;color:var(--cal-text)}.nav-btn{width:2rem;height:2rem;display:flex;align-items:center;justify-content:center;border:none;background:var(--cal-hover);color:var(--cal-text);border-radius:8px;cursor:pointer;font-size:1.25rem;line-height:1}.nav-btn:hover{background:var(--cal-border)}.today-btn{display:block;width:100%;margin-bottom:1rem;padding:.5rem;border:1px solid var(--cal-border);background:transparent;color:var(--cal-text);border-radius:8px;cursor:pointer;font-size:.875rem}.today-btn:hover{background:var(--cal-hover)}.weekdays{display:grid;grid-template-columns:repeat(7,1fr);gap:2px;margin-bottom:4px}.weekday{text-align:center;font-size:.75rem;font-weight:600;color:var(--cal-text-muted)}.days-grid{display:grid;grid-template-columns:repeat(7,1fr);gap:2px}.day-cell{position:relative;aspect-ratio:1;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:2px;border:none;background:transparent;color:var(--cal-text);font-size:.875rem;border-radius:8px;cursor:pointer}.day-cell:hover:not(:disabled){background:var(--cal-hover)}.day-cell:disabled{cursor:not-allowed}.day-cell.other-month{color:var(--cal-text-muted)}.day-cell .day-num{font-weight:500;line-height:1.2}.day-cell .day-label{font-size:.625rem;line-height:1.2;color:var(--cal-text-muted)}.day-cell.today .day-num{font-weight:700;color:var(--cal-today)}.day-cell.today .day-label{color:var(--cal-today)}.day-cell.today:not(.status-purchased){outline:2px solid var(--cal-today);outline-offset:1px}.day-cell.selected{background:var(--cal-selected);color:var(--cal-selected-text)}.day-cell.selected .day-label{color:var(--cal-selected-text);opacity:.9}.day-cell.selected:hover{background:var(--cal-selected);filter:brightness(1.05)}.day-cell.status-available .day-label{color:var(--cal-text-muted)}.day-cell.status-purchased{background:#f1f5f9;color:var(--cal-text-muted)}.day-cell.status-purchased .day-num{font-weight:600;color:var(--cal-text)}.day-cell.status-purchased .day-label{font-size:.625rem;color:var(--cal-text-muted)}.day-cell.status-purchased:hover{background:#f1f5f9}\n"], dependencies: [{ kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] }); }
|
|
59
59
|
}
|
|
60
60
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: CalendarComponent, decorators: [{
|
|
61
61
|
type: Component,
|
|
62
|
-
args: [{ selector: 'shdr-calendar', standalone: true, imports: [NgFor], template: "<div class=\"calendar\">\n <header class=\"calendar-header\">\n <button type=\"button\" class=\"nav-btn\" (click)=\"prevMonth()\" aria-label=\"\u4E0A\u4E00\u6708\">\n \u2039\n </button>\n <h2 class=\"month-year\">{{ monthYearLabel() }}</h2>\n <button type=\"button\" class=\"nav-btn\" (click)=\"nextMonth()\" aria-label=\"\u4E0B\u4E00\u6708\">\n \u203A\n </button>\n </header>\n\n <button type=\"button\" class=\"today-btn\" (click)=\"goToToday()\">\u4ECA\u5929</button>\n\n <div class=\"weekdays\">\n @for (label of weekDays; track label) {\n <span class=\"weekday\">{{ label }}</span>\n }\n </div>\n\n <div class=\"days-grid\">\n @for (day of days(); track day.date.getTime()) {\n <button\n type=\"button\"\n class=\"day-cell\"\n [class.other-month]=\"!day.isCurrentMonth\"\n [class.today]=\"day.isToday\"\n [class.selected]=\"day.isSelected\"\n [class.status-available]=\"day.status === 'AVAILABLE'\"\n [class.status-purchased]=\"day.status === 'PURCHASED'\"\n (click)=\"selectDay(day)\"\n >\n {{ day.day }}\n </button>\n }\n </div>\n</div>\n", styles: [":host{display:block}.calendar{--cal-bg: #fff;--cal-border: #e2e8f0;--cal-text: #1e293b;--cal-text-muted: #64748b;--cal-today: #3b82f6;--cal-selected: #2563eb;--cal-selected-text: #fff;--cal-hover: #f1f5f9;max-width:360px;padding:1rem;background:var(--cal-bg);border:1px solid var(--cal-border);border-radius:12px;font-family:system-ui,-apple-system,sans-serif}.calendar-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:.75rem}.month-year{margin:0;font-size:1.125rem;font-weight:600;color:var(--cal-text)}.nav-btn{width:2rem;height:2rem;display:flex;align-items:center;justify-content:center;border:none;background:var(--cal-hover);color:var(--cal-text);border-radius:8px;cursor:pointer;font-size:1.25rem;line-height:1}.nav-btn:hover{background:var(--cal-border)}.today-btn{display:block;width:100%;margin-bottom:1rem;padding:.5rem;border:1px solid var(--cal-border);background:transparent;color:var(--cal-text);border-radius:8px;cursor:pointer;font-size:.875rem}.today-btn:hover{background:var(--cal-hover)}.weekdays{display:grid;grid-template-columns:repeat(7,1fr);gap:2px;margin-bottom:4px}.weekday{text-align:center;font-size:.75rem;font-weight:600;color:var(--cal-text-muted)}.days-grid{display:grid;grid-template-columns:repeat(7,1fr);gap:2px}.day-cell{position:relative;aspect-ratio:1;display:flex;align-items:center;justify-content:center;border:none;background:transparent;color:var(--cal-text);font-size:.875rem;border-radius:8px;cursor:pointer}.day-cell:hover{background:var(--cal-hover)}.day-cell.other-month{color:var(--cal-text-muted)}.day-cell.today{font-weight:700;color:var(--cal-today)}.day-cell.selected{background:var(--cal-selected);color:var(--cal-selected-text)}.day-cell.selected:hover{background:var(--cal-selected);filter:brightness(1.05)}.day-cell.status-available{--cal-
|
|
62
|
+
args: [{ selector: 'shdr-calendar', standalone: true, imports: [NgFor, NgIf], template: "<div class=\"calendar\">\n <header class=\"calendar-header\">\n <button type=\"button\" class=\"nav-btn\" (click)=\"prevMonth()\" aria-label=\"\u4E0A\u4E00\u6708\">\n \u2039\n </button>\n <h2 class=\"month-year\">{{ monthYearLabel() }}</h2>\n <button type=\"button\" class=\"nav-btn\" (click)=\"nextMonth()\" aria-label=\"\u4E0B\u4E00\u6708\">\n \u203A\n </button>\n </header>\n\n <button type=\"button\" class=\"today-btn\" (click)=\"goToToday()\">\u4ECA\u5929</button>\n\n <div class=\"weekdays\">\n @for (label of weekDays; track label) {\n <span class=\"weekday\">{{ label }}</span>\n }\n </div>\n\n <div class=\"days-grid\">\n @for (day of days(); track day.date.getTime()) {\n <button\n type=\"button\"\n class=\"day-cell\"\n [class.other-month]=\"!day.isCurrentMonth\"\n [class.today]=\"day.isToday\"\n [class.selected]=\"day.isSelected\"\n [class.status-available]=\"day.status === 'AVAILABLE'\"\n [class.status-purchased]=\"day.status === 'PURCHASED'\"\n [attr.disabled]=\"day.status === 'PURCHASED' ? true : null\"\n (click)=\"day.status !== 'PURCHASED' && selectDay(day)\"\n >\n <span class=\"day-num\">{{ day.day }}</span>\n <span class=\"day-label\" *ngIf=\"day.status === 'PURCHASED'\">\u5DF2\u9884\u7EA6</span>\n <span class=\"day-label\" *ngIf=\"day.status !== 'PURCHASED' && day.isToday\">\u4ECA\u5929</span>\n </button>\n }\n </div>\n</div>\n", styles: [":host{display:block}.calendar{--cal-bg: #fff;--cal-border: #e2e8f0;--cal-text: #1e293b;--cal-text-muted: #64748b;--cal-today: #3b82f6;--cal-selected: #2563eb;--cal-selected-text: #fff;--cal-hover: #f1f5f9;max-width:360px;padding:1rem;background:var(--cal-bg);border:1px solid var(--cal-border);border-radius:12px;font-family:system-ui,-apple-system,sans-serif}.calendar-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:.75rem}.month-year{margin:0;font-size:1.125rem;font-weight:600;color:var(--cal-text)}.nav-btn{width:2rem;height:2rem;display:flex;align-items:center;justify-content:center;border:none;background:var(--cal-hover);color:var(--cal-text);border-radius:8px;cursor:pointer;font-size:1.25rem;line-height:1}.nav-btn:hover{background:var(--cal-border)}.today-btn{display:block;width:100%;margin-bottom:1rem;padding:.5rem;border:1px solid var(--cal-border);background:transparent;color:var(--cal-text);border-radius:8px;cursor:pointer;font-size:.875rem}.today-btn:hover{background:var(--cal-hover)}.weekdays{display:grid;grid-template-columns:repeat(7,1fr);gap:2px;margin-bottom:4px}.weekday{text-align:center;font-size:.75rem;font-weight:600;color:var(--cal-text-muted)}.days-grid{display:grid;grid-template-columns:repeat(7,1fr);gap:2px}.day-cell{position:relative;aspect-ratio:1;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:2px;border:none;background:transparent;color:var(--cal-text);font-size:.875rem;border-radius:8px;cursor:pointer}.day-cell:hover:not(:disabled){background:var(--cal-hover)}.day-cell:disabled{cursor:not-allowed}.day-cell.other-month{color:var(--cal-text-muted)}.day-cell .day-num{font-weight:500;line-height:1.2}.day-cell .day-label{font-size:.625rem;line-height:1.2;color:var(--cal-text-muted)}.day-cell.today .day-num{font-weight:700;color:var(--cal-today)}.day-cell.today .day-label{color:var(--cal-today)}.day-cell.today:not(.status-purchased){outline:2px solid var(--cal-today);outline-offset:1px}.day-cell.selected{background:var(--cal-selected);color:var(--cal-selected-text)}.day-cell.selected .day-label{color:var(--cal-selected-text);opacity:.9}.day-cell.selected:hover{background:var(--cal-selected);filter:brightness(1.05)}.day-cell.status-available .day-label{color:var(--cal-text-muted)}.day-cell.status-purchased{background:#f1f5f9;color:var(--cal-text-muted)}.day-cell.status-purchased .day-num{font-weight:600;color:var(--cal-text)}.day-cell.status-purchased .day-label{font-size:.625rem;color:var(--cal-text-muted)}.day-cell.status-purchased:hover{background:#f1f5f9}\n"] }]
|
|
63
63
|
}] });
|
|
64
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
64
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2FsZW5kYXIuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vcHJvamVjdHMvc2hkci1jYWxlbmRhci9zcmMvbGliL2NhbGVuZGFyLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uL3Byb2plY3RzL3NoZHItY2FsZW5kYXIvc3JjL2xpYi9jYWxlbmRhci5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sRUFBRSxRQUFRLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUMzRSxPQUFPLEVBQUUsS0FBSyxFQUFFLElBQUksRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQzlDLE9BQU8sRUFBRSxlQUFlLEVBQTJDLE1BQU0sb0JBQW9CLENBQUM7O0FBUzlGLE1BQU0sT0FBTyxpQkFBaUI7SUFQOUI7UUFRVSxvQkFBZSxHQUFHLE1BQU0sQ0FBQyxlQUFlLENBQUMsQ0FBQztRQUVsRCxxRUFBcUU7UUFDckUsbUJBQWMsR0FBRyxLQUFLLENBQXFCLEVBQUUsQ0FBQyxDQUFDO1FBRS9DLGdCQUFXLEdBQUcsTUFBTSxDQUFDLElBQUksSUFBSSxFQUFFLENBQUMsQ0FBQztRQUNqQyxpQkFBWSxHQUFHLE1BQU0sQ0FBYyxJQUFJLENBQUMsQ0FBQztRQUV6QyxhQUFRLEdBQUcsSUFBSSxDQUFDLGVBQWUsQ0FBQyxnQkFBZ0IsRUFBRSxDQUFDO1FBRW5ELG1CQUFjLEdBQUcsUUFBUSxDQUFDLEdBQUcsRUFBRTtZQUM3QixNQUFNLENBQUMsR0FBRyxJQUFJLENBQUMsV0FBVyxFQUFFLENBQUM7WUFDN0IsT0FBTyxJQUFJLENBQUMsZUFBZSxDQUFDLGlCQUFpQixDQUFDLENBQUMsQ0FBQyxXQUFXLEVBQUUsRUFBRSxDQUFDLENBQUMsUUFBUSxFQUFFLENBQUMsQ0FBQztRQUMvRSxDQUFDLENBQUMsQ0FBQztRQUVILFNBQUksR0FBRyxR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QUk7OzRGQUlWLGlCQUFpQjtrQkFQN0IsU0FBUzsrQkFDRSxlQUFlLGNBQ2IsSUFBSSxXQUNQLENBQUMsS0FBSyxFQUFFLElBQUksQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENvbXBvbmVudCwgc2lnbmFsLCBjb21wdXRlZCwgaW5qZWN0LCBpbnB1dCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgTmdGb3IsIE5nSWYgfSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xuaW1wb3J0IHsgQ2FsZW5kYXJTZXJ2aWNlLCB0eXBlIENhbGVuZGFyRGF5LCB0eXBlIENhbGVuZGFyRGF5U3RhdGUgfSBmcm9tICcuL2NhbGVuZGFyLnNlcnZpY2UnO1xuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdzaGRyLWNhbGVuZGFyJyxcbiAgc3RhbmRhbG9uZTogdHJ1ZSxcbiAgaW1wb3J0czogW05nRm9yLCBOZ0lmXSxcbiAgdGVtcGxhdGVVcmw6ICcuL2NhbGVuZGFyLmNvbXBvbmVudC5odG1sJyxcbiAgc3R5bGVVcmw6ICcuL2NhbGVuZGFyLmNvbXBvbmVudC5zY3NzJyxcbn0pXG5leHBvcnQgY2xhc3MgQ2FsZW5kYXJDb21wb25lbnQge1xuICBwcml2YXRlIGNhbGVuZGFyU2VydmljZSA9IGluamVjdChDYWxlbmRhclNlcnZpY2UpO1xuXG4gIC8qKiDlj6/pgInjgILkuI7mjqXlj6MgZGF0YS5jYWxlbmRhckxpc3Qg5LiA6Ie077yM55So5LqO5oyJ5pel5pyf5pi+56S654q25oCB77yI5aaCIEFWQUlMQUJMRSAvIFBVUkNIQVNFRO+8iSAqL1xuICBjYWxlbmRhclN0YXRlcyA9IGlucHV0PENhbGVuZGFyRGF5U3RhdGVbXT4oW10pO1xuXG4gIGN1cnJlbnREYXRlID0gc2lnbmFsKG5ldyBEYXRlKCkpO1xuICBzZWxlY3RlZERhdGUgPSBzaWduYWw8RGF0ZSB8IG51bGw+KG51bGwpO1xuXG4gIHdlZWtEYXlzID0gdGhpcy5jYWxlbmRhclNlcnZpY2UuZ2V0V2Vla0RheUxhYmVscygpO1xuXG4gIG1vbnRoWWVhckxhYmVsID0gY29tcHV0ZWQoKCkgPT4ge1xuICAgIGNvbnN0IGQgPSB0aGlzLmN1cnJlbnREYXRlKCk7XG4gICAgcmV0dXJuIHRoaXMuY2FsZW5kYXJTZXJ2aWNlLmdldE1vbnRoWWVhckxhYmVsKGQuZ2V0RnVsbFllYXIoKSwgZC5nZXRNb250aCgpKTtcbiAgfSk7XG5cbiAgZGF5cyA9IGNvbXB1dGVkKCgpID0+IHtcbiAgICBjb25zdCBkID0gdGhpcy5jdXJyZW50RGF0ZSgpO1xuICAgIGNvbnN0IHNlbGVjdGVkID0gdGhpcy5zZWxlY3RlZERhdGUoKTtcbiAgICBjb25zdCBzdGF0ZXMgPSB0aGlzLmNhbGVuZGFyU3RhdGVzKCk7XG4gICAgY29uc3Qgc3RhdGVNYXAgPSBuZXcgTWFwKHN0YXRlcy5tYXAoKHMpID0+IFtzLmRhdGUsIHNdKSk7XG4gICAgY29uc3QgZGF5cyA9IHRoaXMuY2FsZW5kYXJTZXJ2aWNlLmdldERheXNJbk1vbnRoKFxuICAgICAgZC5nZXRGdWxsWWVhcigpLFxuICAgICAgZC5nZXRNb250aCgpXG4gICAgKTtcbiAgICByZXR1cm4gZGF5cy5tYXAoKGRheSkgPT4ge1xuICAgICAgY29uc3Qga2V5ID0gdGhpcy5mb3JtYXREYXRlS2V5KGRheS5kYXRlKTtcbiAgICAgIGNvbnN0IHN0YXRlID0gc3RhdGVNYXAuZ2V0KGtleSk7XG4gICAgICByZXR1cm4ge1xuICAgICAgICAuLi5kYXksXG4gICAgICAgIGlzU2VsZWN0ZWQ6XG4gICAgICAgICAgc2VsZWN0ZWQgIT09IG51bGwgJiZcbiAgICAgICAgICB0aGlzLmNhbGVuZGFyU2VydmljZS5pc1NhbWVEYXkoZGF5LmRhdGUsIHNlbGVjdGVkKSxcbiAgICAgICAgc3RhdHVzOiBzdGF0ZT8uc3RhdHVzLFxuICAgICAgfTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgcHJpdmF0ZSBmb3JtYXREYXRlS2V5KGRhdGU6IERhdGUpOiBzdHJpbmcge1xuICAgIGNvbnN0IHkgPSBkYXRlLmdldEZ1bGxZZWFyKCk7XG4gICAgY29uc3QgbSA9IFN0cmluZyhkYXRlLmdldE1vbnRoKCkgKyAxKS5wYWRTdGFydCgyLCAnMCcpO1xuICAgIGNvbnN0IGRheSA9IFN0cmluZyhkYXRlLmdldERhdGUoKSkucGFkU3RhcnQoMiwgJzAnKTtcbiAgICByZXR1cm4gYCR7eX0tJHttfS0ke2RheX1gO1xuICB9XG5cbiAgcHJldk1vbnRoKCk6IHZvaWQge1xuICAgIGNvbnN0IGQgPSB0aGlzLmN1cnJlbnREYXRlKCk7XG4gICAgdGhpcy5jdXJyZW50RGF0ZS5zZXQobmV3IERhdGUoZC5nZXRGdWxsWWVhcigpLCBkLmdldE1vbnRoKCkgLSAxKSk7XG4gIH1cblxuICBuZXh0TW9udGgoKTogdm9pZCB7XG4gICAgY29uc3QgZCA9IHRoaXMuY3VycmVudERhdGUoKTtcbiAgICB0aGlzLmN1cnJlbnREYXRlLnNldChuZXcgRGF0ZShkLmdldEZ1bGxZZWFyKCksIGQuZ2V0TW9udGgoKSArIDEpKTtcbiAgfVxuXG4gIHNlbGVjdERheShkYXk6IENhbGVuZGFyRGF5KTogdm9pZCB7XG4gICAgdGhpcy5zZWxlY3RlZERhdGUuc2V0KGRheS5kYXRlKTtcbiAgfVxuXG4gIGdvVG9Ub2RheSgpOiB2b2lkIHtcbiAgICBjb25zdCB0b2RheSA9IG5ldyBEYXRlKCk7XG4gICAgdGhpcy5jdXJyZW50RGF0ZS5zZXQodG9kYXkpO1xuICAgIHRoaXMuc2VsZWN0ZWREYXRlLnNldCh0b2RheSk7XG4gIH1cbn1cbiIsIjxkaXYgY2xhc3M9XCJjYWxlbmRhclwiPlxuICA8aGVhZGVyIGNsYXNzPVwiY2FsZW5kYXItaGVhZGVyXCI+XG4gICAgPGJ1dHRvbiB0eXBlPVwiYnV0dG9uXCIgY2xhc3M9XCJuYXYtYnRuXCIgKGNsaWNrKT1cInByZXZNb250aCgpXCIgYXJpYS1sYWJlbD1cIuS4iuS4gOaciFwiPlxuICAgICAg4oC5XG4gICAgPC9idXR0b24+XG4gICAgPGgyIGNsYXNzPVwibW9udGgteWVhclwiPnt7IG1vbnRoWWVhckxhYmVsKCkgfX08L2gyPlxuICAgIDxidXR0b24gdHlwZT1cImJ1dHRvblwiIGNsYXNzPVwibmF2LWJ0blwiIChjbGljayk9XCJuZXh0TW9udGgoKVwiIGFyaWEtbGFiZWw9XCLkuIvkuIDmnIhcIj5cbiAgICAgIOKAulxuICAgIDwvYnV0dG9uPlxuICA8L2hlYWRlcj5cblxuICA8YnV0dG9uIHR5cGU9XCJidXR0b25cIiBjbGFzcz1cInRvZGF5LWJ0blwiIChjbGljayk9XCJnb1RvVG9kYXkoKVwiPuS7iuWkqTwvYnV0dG9uPlxuXG4gIDxkaXYgY2xhc3M9XCJ3ZWVrZGF5c1wiPlxuICAgIEBmb3IgKGxhYmVsIG9mIHdlZWtEYXlzOyB0cmFjayBsYWJlbCkge1xuICAgICAgPHNwYW4gY2xhc3M9XCJ3ZWVrZGF5XCI+e3sgbGFiZWwgfX08L3NwYW4+XG4gICAgfVxuICA8L2Rpdj5cblxuICA8ZGl2IGNsYXNzPVwiZGF5cy1ncmlkXCI+XG4gICAgQGZvciAoZGF5IG9mIGRheXMoKTsgdHJhY2sgZGF5LmRhdGUuZ2V0VGltZSgpKSB7XG4gICAgICA8YnV0dG9uXG4gICAgICAgIHR5cGU9XCJidXR0b25cIlxuICAgICAgICBjbGFzcz1cImRheS1jZWxsXCJcbiAgICAgICAgW2NsYXNzLm90aGVyLW1vbnRoXT1cIiFkYXkuaXNDdXJyZW50TW9udGhcIlxuICAgICAgICBbY2xhc3MudG9kYXldPVwiZGF5LmlzVG9kYXlcIlxuICAgICAgICBbY2xhc3Muc2VsZWN0ZWRdPVwiZGF5LmlzU2VsZWN0ZWRcIlxuICAgICAgICBbY2xhc3Muc3RhdHVzLWF2YWlsYWJsZV09XCJkYXkuc3RhdHVzID09PSAnQVZBSUxBQkxFJ1wiXG4gICAgICAgIFtjbGFzcy5zdGF0dXMtcHVyY2hhc2VkXT1cImRheS5zdGF0dXMgPT09ICdQVVJDSEFTRUQnXCJcbiAgICAgICAgW2F0dHIuZGlzYWJsZWRdPVwiZGF5LnN0YXR1cyA9PT0gJ1BVUkNIQVNFRCcgPyB0cnVlIDogbnVsbFwiXG4gICAgICAgIChjbGljayk9XCJkYXkuc3RhdHVzICE9PSAnUFVSQ0hBU0VEJyAmJiBzZWxlY3REYXkoZGF5KVwiXG4gICAgICA+XG4gICAgICAgIDxzcGFuIGNsYXNzPVwiZGF5LW51bVwiPnt7IGRheS5kYXkgfX08L3NwYW4+XG4gICAgICAgIDxzcGFuIGNsYXNzPVwiZGF5LWxhYmVsXCIgKm5nSWY9XCJkYXkuc3RhdHVzID09PSAnUFVSQ0hBU0VEJ1wiPuW3sumihOe6pjwvc3Bhbj5cbiAgICAgICAgPHNwYW4gY2xhc3M9XCJkYXktbGFiZWxcIiAqbmdJZj1cImRheS5zdGF0dXMgIT09ICdQVVJDSEFTRUQnICYmIGRheS5pc1RvZGF5XCI+5LuK5aSpPC9zcGFuPlxuICAgICAgPC9idXR0b24+XG4gICAgfVxuICA8L2Rpdj5cbjwvZGl2PlxuIl19
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
2
|
import { Injectable, inject, input, signal, computed, Component } from '@angular/core';
|
|
3
|
-
import { NgFor } from '@angular/common';
|
|
3
|
+
import { NgIf, NgFor } from '@angular/common';
|
|
4
4
|
|
|
5
5
|
class CalendarService {
|
|
6
6
|
constructor() {
|
|
@@ -125,11 +125,11 @@ class CalendarComponent {
|
|
|
125
125
|
this.selectedDate.set(today);
|
|
126
126
|
}
|
|
127
127
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: CalendarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
128
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.12", type: CalendarComponent, isStandalone: true, selector: "shdr-calendar", inputs: { calendarStates: { classPropertyName: "calendarStates", publicName: "calendarStates", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div class=\"calendar\">\n <header class=\"calendar-header\">\n <button type=\"button\" class=\"nav-btn\" (click)=\"prevMonth()\" aria-label=\"\u4E0A\u4E00\u6708\">\n \u2039\n </button>\n <h2 class=\"month-year\">{{ monthYearLabel() }}</h2>\n <button type=\"button\" class=\"nav-btn\" (click)=\"nextMonth()\" aria-label=\"\u4E0B\u4E00\u6708\">\n \u203A\n </button>\n </header>\n\n <button type=\"button\" class=\"today-btn\" (click)=\"goToToday()\">\u4ECA\u5929</button>\n\n <div class=\"weekdays\">\n @for (label of weekDays; track label) {\n <span class=\"weekday\">{{ label }}</span>\n }\n </div>\n\n <div class=\"days-grid\">\n @for (day of days(); track day.date.getTime()) {\n <button\n type=\"button\"\n class=\"day-cell\"\n [class.other-month]=\"!day.isCurrentMonth\"\n [class.today]=\"day.isToday\"\n [class.selected]=\"day.isSelected\"\n [class.status-available]=\"day.status === 'AVAILABLE'\"\n [class.status-purchased]=\"day.status === 'PURCHASED'\"\n (click)=\"selectDay(day)\"\n >\n {{ day.day }}\n </button>\n }\n </div>\n</div>\n", styles: [":host{display:block}.calendar{--cal-bg: #fff;--cal-border: #e2e8f0;--cal-text: #1e293b;--cal-text-muted: #64748b;--cal-today: #3b82f6;--cal-selected: #2563eb;--cal-selected-text: #fff;--cal-hover: #f1f5f9;max-width:360px;padding:1rem;background:var(--cal-bg);border:1px solid var(--cal-border);border-radius:12px;font-family:system-ui,-apple-system,sans-serif}.calendar-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:.75rem}.month-year{margin:0;font-size:1.125rem;font-weight:600;color:var(--cal-text)}.nav-btn{width:2rem;height:2rem;display:flex;align-items:center;justify-content:center;border:none;background:var(--cal-hover);color:var(--cal-text);border-radius:8px;cursor:pointer;font-size:1.25rem;line-height:1}.nav-btn:hover{background:var(--cal-border)}.today-btn{display:block;width:100%;margin-bottom:1rem;padding:.5rem;border:1px solid var(--cal-border);background:transparent;color:var(--cal-text);border-radius:8px;cursor:pointer;font-size:.875rem}.today-btn:hover{background:var(--cal-hover)}.weekdays{display:grid;grid-template-columns:repeat(7,1fr);gap:2px;margin-bottom:4px}.weekday{text-align:center;font-size:.75rem;font-weight:600;color:var(--cal-text-muted)}.days-grid{display:grid;grid-template-columns:repeat(7,1fr);gap:2px}.day-cell{position:relative;aspect-ratio:1;display:flex;align-items:center;justify-content:center;border:none;background:transparent;color:var(--cal-text);font-size:.875rem;border-radius:8px;cursor:pointer}.day-cell:hover{background:var(--cal-hover)}.day-cell.other-month{color:var(--cal-text-muted)}.day-cell.today{font-weight:700;color:var(--cal-today)}.day-cell.selected{background:var(--cal-selected);color:var(--cal-selected-text)}.day-cell.selected:hover{background:var(--cal-selected);filter:brightness(1.05)}.day-cell.status-available{--cal-
|
|
128
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.12", type: CalendarComponent, isStandalone: true, selector: "shdr-calendar", inputs: { calendarStates: { classPropertyName: "calendarStates", publicName: "calendarStates", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div class=\"calendar\">\n <header class=\"calendar-header\">\n <button type=\"button\" class=\"nav-btn\" (click)=\"prevMonth()\" aria-label=\"\u4E0A\u4E00\u6708\">\n \u2039\n </button>\n <h2 class=\"month-year\">{{ monthYearLabel() }}</h2>\n <button type=\"button\" class=\"nav-btn\" (click)=\"nextMonth()\" aria-label=\"\u4E0B\u4E00\u6708\">\n \u203A\n </button>\n </header>\n\n <button type=\"button\" class=\"today-btn\" (click)=\"goToToday()\">\u4ECA\u5929</button>\n\n <div class=\"weekdays\">\n @for (label of weekDays; track label) {\n <span class=\"weekday\">{{ label }}</span>\n }\n </div>\n\n <div class=\"days-grid\">\n @for (day of days(); track day.date.getTime()) {\n <button\n type=\"button\"\n class=\"day-cell\"\n [class.other-month]=\"!day.isCurrentMonth\"\n [class.today]=\"day.isToday\"\n [class.selected]=\"day.isSelected\"\n [class.status-available]=\"day.status === 'AVAILABLE'\"\n [class.status-purchased]=\"day.status === 'PURCHASED'\"\n [attr.disabled]=\"day.status === 'PURCHASED' ? true : null\"\n (click)=\"day.status !== 'PURCHASED' && selectDay(day)\"\n >\n <span class=\"day-num\">{{ day.day }}</span>\n <span class=\"day-label\" *ngIf=\"day.status === 'PURCHASED'\">\u5DF2\u9884\u7EA6</span>\n <span class=\"day-label\" *ngIf=\"day.status !== 'PURCHASED' && day.isToday\">\u4ECA\u5929</span>\n </button>\n }\n </div>\n</div>\n", styles: [":host{display:block}.calendar{--cal-bg: #fff;--cal-border: #e2e8f0;--cal-text: #1e293b;--cal-text-muted: #64748b;--cal-today: #3b82f6;--cal-selected: #2563eb;--cal-selected-text: #fff;--cal-hover: #f1f5f9;max-width:360px;padding:1rem;background:var(--cal-bg);border:1px solid var(--cal-border);border-radius:12px;font-family:system-ui,-apple-system,sans-serif}.calendar-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:.75rem}.month-year{margin:0;font-size:1.125rem;font-weight:600;color:var(--cal-text)}.nav-btn{width:2rem;height:2rem;display:flex;align-items:center;justify-content:center;border:none;background:var(--cal-hover);color:var(--cal-text);border-radius:8px;cursor:pointer;font-size:1.25rem;line-height:1}.nav-btn:hover{background:var(--cal-border)}.today-btn{display:block;width:100%;margin-bottom:1rem;padding:.5rem;border:1px solid var(--cal-border);background:transparent;color:var(--cal-text);border-radius:8px;cursor:pointer;font-size:.875rem}.today-btn:hover{background:var(--cal-hover)}.weekdays{display:grid;grid-template-columns:repeat(7,1fr);gap:2px;margin-bottom:4px}.weekday{text-align:center;font-size:.75rem;font-weight:600;color:var(--cal-text-muted)}.days-grid{display:grid;grid-template-columns:repeat(7,1fr);gap:2px}.day-cell{position:relative;aspect-ratio:1;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:2px;border:none;background:transparent;color:var(--cal-text);font-size:.875rem;border-radius:8px;cursor:pointer}.day-cell:hover:not(:disabled){background:var(--cal-hover)}.day-cell:disabled{cursor:not-allowed}.day-cell.other-month{color:var(--cal-text-muted)}.day-cell .day-num{font-weight:500;line-height:1.2}.day-cell .day-label{font-size:.625rem;line-height:1.2;color:var(--cal-text-muted)}.day-cell.today .day-num{font-weight:700;color:var(--cal-today)}.day-cell.today .day-label{color:var(--cal-today)}.day-cell.today:not(.status-purchased){outline:2px solid var(--cal-today);outline-offset:1px}.day-cell.selected{background:var(--cal-selected);color:var(--cal-selected-text)}.day-cell.selected .day-label{color:var(--cal-selected-text);opacity:.9}.day-cell.selected:hover{background:var(--cal-selected);filter:brightness(1.05)}.day-cell.status-available .day-label{color:var(--cal-text-muted)}.day-cell.status-purchased{background:#f1f5f9;color:var(--cal-text-muted)}.day-cell.status-purchased .day-num{font-weight:600;color:var(--cal-text)}.day-cell.status-purchased .day-label{font-size:.625rem;color:var(--cal-text-muted)}.day-cell.status-purchased:hover{background:#f1f5f9}\n"], dependencies: [{ kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] }); }
|
|
129
129
|
}
|
|
130
130
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: CalendarComponent, decorators: [{
|
|
131
131
|
type: Component,
|
|
132
|
-
args: [{ selector: 'shdr-calendar', standalone: true, imports: [NgFor], template: "<div class=\"calendar\">\n <header class=\"calendar-header\">\n <button type=\"button\" class=\"nav-btn\" (click)=\"prevMonth()\" aria-label=\"\u4E0A\u4E00\u6708\">\n \u2039\n </button>\n <h2 class=\"month-year\">{{ monthYearLabel() }}</h2>\n <button type=\"button\" class=\"nav-btn\" (click)=\"nextMonth()\" aria-label=\"\u4E0B\u4E00\u6708\">\n \u203A\n </button>\n </header>\n\n <button type=\"button\" class=\"today-btn\" (click)=\"goToToday()\">\u4ECA\u5929</button>\n\n <div class=\"weekdays\">\n @for (label of weekDays; track label) {\n <span class=\"weekday\">{{ label }}</span>\n }\n </div>\n\n <div class=\"days-grid\">\n @for (day of days(); track day.date.getTime()) {\n <button\n type=\"button\"\n class=\"day-cell\"\n [class.other-month]=\"!day.isCurrentMonth\"\n [class.today]=\"day.isToday\"\n [class.selected]=\"day.isSelected\"\n [class.status-available]=\"day.status === 'AVAILABLE'\"\n [class.status-purchased]=\"day.status === 'PURCHASED'\"\n (click)=\"selectDay(day)\"\n >\n {{ day.day }}\n </button>\n }\n </div>\n</div>\n", styles: [":host{display:block}.calendar{--cal-bg: #fff;--cal-border: #e2e8f0;--cal-text: #1e293b;--cal-text-muted: #64748b;--cal-today: #3b82f6;--cal-selected: #2563eb;--cal-selected-text: #fff;--cal-hover: #f1f5f9;max-width:360px;padding:1rem;background:var(--cal-bg);border:1px solid var(--cal-border);border-radius:12px;font-family:system-ui,-apple-system,sans-serif}.calendar-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:.75rem}.month-year{margin:0;font-size:1.125rem;font-weight:600;color:var(--cal-text)}.nav-btn{width:2rem;height:2rem;display:flex;align-items:center;justify-content:center;border:none;background:var(--cal-hover);color:var(--cal-text);border-radius:8px;cursor:pointer;font-size:1.25rem;line-height:1}.nav-btn:hover{background:var(--cal-border)}.today-btn{display:block;width:100%;margin-bottom:1rem;padding:.5rem;border:1px solid var(--cal-border);background:transparent;color:var(--cal-text);border-radius:8px;cursor:pointer;font-size:.875rem}.today-btn:hover{background:var(--cal-hover)}.weekdays{display:grid;grid-template-columns:repeat(7,1fr);gap:2px;margin-bottom:4px}.weekday{text-align:center;font-size:.75rem;font-weight:600;color:var(--cal-text-muted)}.days-grid{display:grid;grid-template-columns:repeat(7,1fr);gap:2px}.day-cell{position:relative;aspect-ratio:1;display:flex;align-items:center;justify-content:center;border:none;background:transparent;color:var(--cal-text);font-size:.875rem;border-radius:8px;cursor:pointer}.day-cell:hover{background:var(--cal-hover)}.day-cell.other-month{color:var(--cal-text-muted)}.day-cell.today{font-weight:700;color:var(--cal-today)}.day-cell.selected{background:var(--cal-selected);color:var(--cal-selected-text)}.day-cell.selected:hover{background:var(--cal-selected);filter:brightness(1.05)}.day-cell.status-available{--cal-
|
|
132
|
+
args: [{ selector: 'shdr-calendar', standalone: true, imports: [NgFor, NgIf], template: "<div class=\"calendar\">\n <header class=\"calendar-header\">\n <button type=\"button\" class=\"nav-btn\" (click)=\"prevMonth()\" aria-label=\"\u4E0A\u4E00\u6708\">\n \u2039\n </button>\n <h2 class=\"month-year\">{{ monthYearLabel() }}</h2>\n <button type=\"button\" class=\"nav-btn\" (click)=\"nextMonth()\" aria-label=\"\u4E0B\u4E00\u6708\">\n \u203A\n </button>\n </header>\n\n <button type=\"button\" class=\"today-btn\" (click)=\"goToToday()\">\u4ECA\u5929</button>\n\n <div class=\"weekdays\">\n @for (label of weekDays; track label) {\n <span class=\"weekday\">{{ label }}</span>\n }\n </div>\n\n <div class=\"days-grid\">\n @for (day of days(); track day.date.getTime()) {\n <button\n type=\"button\"\n class=\"day-cell\"\n [class.other-month]=\"!day.isCurrentMonth\"\n [class.today]=\"day.isToday\"\n [class.selected]=\"day.isSelected\"\n [class.status-available]=\"day.status === 'AVAILABLE'\"\n [class.status-purchased]=\"day.status === 'PURCHASED'\"\n [attr.disabled]=\"day.status === 'PURCHASED' ? true : null\"\n (click)=\"day.status !== 'PURCHASED' && selectDay(day)\"\n >\n <span class=\"day-num\">{{ day.day }}</span>\n <span class=\"day-label\" *ngIf=\"day.status === 'PURCHASED'\">\u5DF2\u9884\u7EA6</span>\n <span class=\"day-label\" *ngIf=\"day.status !== 'PURCHASED' && day.isToday\">\u4ECA\u5929</span>\n </button>\n }\n </div>\n</div>\n", styles: [":host{display:block}.calendar{--cal-bg: #fff;--cal-border: #e2e8f0;--cal-text: #1e293b;--cal-text-muted: #64748b;--cal-today: #3b82f6;--cal-selected: #2563eb;--cal-selected-text: #fff;--cal-hover: #f1f5f9;max-width:360px;padding:1rem;background:var(--cal-bg);border:1px solid var(--cal-border);border-radius:12px;font-family:system-ui,-apple-system,sans-serif}.calendar-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:.75rem}.month-year{margin:0;font-size:1.125rem;font-weight:600;color:var(--cal-text)}.nav-btn{width:2rem;height:2rem;display:flex;align-items:center;justify-content:center;border:none;background:var(--cal-hover);color:var(--cal-text);border-radius:8px;cursor:pointer;font-size:1.25rem;line-height:1}.nav-btn:hover{background:var(--cal-border)}.today-btn{display:block;width:100%;margin-bottom:1rem;padding:.5rem;border:1px solid var(--cal-border);background:transparent;color:var(--cal-text);border-radius:8px;cursor:pointer;font-size:.875rem}.today-btn:hover{background:var(--cal-hover)}.weekdays{display:grid;grid-template-columns:repeat(7,1fr);gap:2px;margin-bottom:4px}.weekday{text-align:center;font-size:.75rem;font-weight:600;color:var(--cal-text-muted)}.days-grid{display:grid;grid-template-columns:repeat(7,1fr);gap:2px}.day-cell{position:relative;aspect-ratio:1;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:2px;border:none;background:transparent;color:var(--cal-text);font-size:.875rem;border-radius:8px;cursor:pointer}.day-cell:hover:not(:disabled){background:var(--cal-hover)}.day-cell:disabled{cursor:not-allowed}.day-cell.other-month{color:var(--cal-text-muted)}.day-cell .day-num{font-weight:500;line-height:1.2}.day-cell .day-label{font-size:.625rem;line-height:1.2;color:var(--cal-text-muted)}.day-cell.today .day-num{font-weight:700;color:var(--cal-today)}.day-cell.today .day-label{color:var(--cal-today)}.day-cell.today:not(.status-purchased){outline:2px solid var(--cal-today);outline-offset:1px}.day-cell.selected{background:var(--cal-selected);color:var(--cal-selected-text)}.day-cell.selected .day-label{color:var(--cal-selected-text);opacity:.9}.day-cell.selected:hover{background:var(--cal-selected);filter:brightness(1.05)}.day-cell.status-available .day-label{color:var(--cal-text-muted)}.day-cell.status-purchased{background:#f1f5f9;color:var(--cal-text-muted)}.day-cell.status-purchased .day-num{font-weight:600;color:var(--cal-text)}.day-cell.status-purchased .day-label{font-size:.625rem;color:var(--cal-text-muted)}.day-cell.status-purchased:hover{background:#f1f5f9}\n"] }]
|
|
133
133
|
}] });
|
|
134
134
|
|
|
135
135
|
/*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shdr-calendar.mjs","sources":["../../../projects/shdr-calendar/src/lib/calendar.service.ts","../../../projects/shdr-calendar/src/lib/calendar.component.ts","../../../projects/shdr-calendar/src/lib/calendar.component.html","../../../projects/shdr-calendar/src/public-api.ts","../../../projects/shdr-calendar/src/shdr-calendar.ts"],"sourcesContent":["import { Injectable } from '@angular/core';\n\nexport interface CalendarDay {\n date: Date;\n day: number;\n isCurrentMonth: boolean;\n isToday: boolean;\n isSelected?: boolean;\n}\n\n/** 与接口 data.calendarList 项一致,用于按日期显示状态(如 AVAILABLE / PURCHASED) */\nexport interface CalendarDayState {\n date: string; // 'YYYY-MM-DD'\n status: string; // e.g. 'AVAILABLE' | 'PURCHASED'\n plu?: string;\n}\n\n@Injectable({\n providedIn: 'root',\n})\nexport class CalendarService {\n private readonly weekDays = ['日', '一', '二', '三', '四', '五', '六'];\n\n getWeekDayLabels(): string[] {\n return this.weekDays;\n }\n\n getDaysInMonth(year: number, month: number): CalendarDay[] {\n const first = new Date(year, month, 1);\n const last = new Date(year, month + 1, 0);\n const firstDayOfWeek = first.getDay();\n const daysInMonth = last.getDate();\n const today = new Date();\n today.setHours(0, 0, 0, 0);\n\n const days: CalendarDay[] = [];\n const startPadding = firstDayOfWeek;\n const prevMonth = month === 0 ? 11 : month - 1;\n const prevYear = month === 0 ? year - 1 : year;\n const prevMonthDays = new Date(prevYear, prevMonth + 1, 0).getDate();\n\n for (let i = 0; i < startPadding; i++) {\n const day = prevMonthDays - startPadding + i + 1;\n const date = new Date(prevYear, prevMonth, day);\n days.push({\n date,\n day,\n isCurrentMonth: false,\n isToday: this.isSameDay(date, today),\n });\n }\n\n for (let d = 1; d <= daysInMonth; d++) {\n const date = new Date(year, month, d);\n days.push({\n date,\n day: d,\n isCurrentMonth: true,\n isToday: this.isSameDay(date, today),\n });\n }\n\n const remaining = 42 - days.length;\n const nextMonth = month === 11 ? 0 : month + 1;\n const nextYear = month === 11 ? year + 1 : year;\n for (let d = 1; d <= remaining; d++) {\n const date = new Date(nextYear, nextMonth, d);\n days.push({\n date,\n day: d,\n isCurrentMonth: false,\n isToday: this.isSameDay(date, today),\n });\n }\n\n return days;\n }\n\n isSameDay(a: Date, b: Date): boolean {\n return (\n a.getFullYear() === b.getFullYear() &&\n a.getMonth() === b.getMonth() &&\n a.getDate() === b.getDate()\n );\n }\n\n getMonthYearLabel(year: number, month: number): string {\n return `${year}年${month + 1}月`;\n }\n}\n","import { Component, signal, computed, inject, input } from '@angular/core';\nimport { NgFor } from '@angular/common';\nimport { CalendarService, type CalendarDay, type CalendarDayState } from './calendar.service';\n\n@Component({\n selector: 'shdr-calendar',\n standalone: true,\n imports: [NgFor],\n templateUrl: './calendar.component.html',\n styleUrl: './calendar.component.scss',\n})\nexport class CalendarComponent {\n private calendarService = inject(CalendarService);\n\n /** 可选。与接口 data.calendarList 一致,用于按日期显示状态(如 AVAILABLE / PURCHASED) */\n calendarStates = input<CalendarDayState[]>([]);\n\n currentDate = signal(new Date());\n selectedDate = signal<Date | null>(null);\n\n weekDays = this.calendarService.getWeekDayLabels();\n\n monthYearLabel = computed(() => {\n const d = this.currentDate();\n return this.calendarService.getMonthYearLabel(d.getFullYear(), d.getMonth());\n });\n\n days = computed(() => {\n const d = this.currentDate();\n const selected = this.selectedDate();\n const states = this.calendarStates();\n const stateMap = new Map(states.map((s) => [s.date, s]));\n const days = this.calendarService.getDaysInMonth(\n d.getFullYear(),\n d.getMonth()\n );\n return days.map((day) => {\n const key = this.formatDateKey(day.date);\n const state = stateMap.get(key);\n return {\n ...day,\n isSelected:\n selected !== null &&\n this.calendarService.isSameDay(day.date, selected),\n status: state?.status,\n };\n });\n });\n\n private formatDateKey(date: Date): string {\n const y = date.getFullYear();\n const m = String(date.getMonth() + 1).padStart(2, '0');\n const day = String(date.getDate()).padStart(2, '0');\n return `${y}-${m}-${day}`;\n }\n\n prevMonth(): void {\n const d = this.currentDate();\n this.currentDate.set(new Date(d.getFullYear(), d.getMonth() - 1));\n }\n\n nextMonth(): void {\n const d = this.currentDate();\n this.currentDate.set(new Date(d.getFullYear(), d.getMonth() + 1));\n }\n\n selectDay(day: CalendarDay): void {\n this.selectedDate.set(day.date);\n }\n\n goToToday(): void {\n const today = new Date();\n this.currentDate.set(today);\n this.selectedDate.set(today);\n }\n}\n","<div class=\"calendar\">\n <header class=\"calendar-header\">\n <button type=\"button\" class=\"nav-btn\" (click)=\"prevMonth()\" aria-label=\"上一月\">\n ‹\n </button>\n <h2 class=\"month-year\">{{ monthYearLabel() }}</h2>\n <button type=\"button\" class=\"nav-btn\" (click)=\"nextMonth()\" aria-label=\"下一月\">\n ›\n </button>\n </header>\n\n <button type=\"button\" class=\"today-btn\" (click)=\"goToToday()\">今天</button>\n\n <div class=\"weekdays\">\n @for (label of weekDays; track label) {\n <span class=\"weekday\">{{ label }}</span>\n }\n </div>\n\n <div class=\"days-grid\">\n @for (day of days(); track day.date.getTime()) {\n <button\n type=\"button\"\n class=\"day-cell\"\n [class.other-month]=\"!day.isCurrentMonth\"\n [class.today]=\"day.isToday\"\n [class.selected]=\"day.isSelected\"\n [class.status-available]=\"day.status === 'AVAILABLE'\"\n [class.status-purchased]=\"day.status === 'PURCHASED'\"\n (click)=\"selectDay(day)\"\n >\n {{ day.day }}\n </button>\n }\n </div>\n</div>\n","/*\n * Public API Surface of shdr-calendar\n */\n\nexport * from './lib/calendar.service';\nexport * from './lib/calendar.component';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"shdr-calendar.mjs","sources":["../../../projects/shdr-calendar/src/lib/calendar.service.ts","../../../projects/shdr-calendar/src/lib/calendar.component.ts","../../../projects/shdr-calendar/src/lib/calendar.component.html","../../../projects/shdr-calendar/src/public-api.ts","../../../projects/shdr-calendar/src/shdr-calendar.ts"],"sourcesContent":["import { Injectable } from '@angular/core';\n\nexport interface CalendarDay {\n date: Date;\n day: number;\n isCurrentMonth: boolean;\n isToday: boolean;\n isSelected?: boolean;\n}\n\n/** 与接口 data.calendarList 项一致,用于按日期显示状态(如 AVAILABLE / PURCHASED) */\nexport interface CalendarDayState {\n date: string; // 'YYYY-MM-DD'\n status: string; // e.g. 'AVAILABLE' | 'PURCHASED'\n plu?: string;\n}\n\n@Injectable({\n providedIn: 'root',\n})\nexport class CalendarService {\n private readonly weekDays = ['日', '一', '二', '三', '四', '五', '六'];\n\n getWeekDayLabels(): string[] {\n return this.weekDays;\n }\n\n getDaysInMonth(year: number, month: number): CalendarDay[] {\n const first = new Date(year, month, 1);\n const last = new Date(year, month + 1, 0);\n const firstDayOfWeek = first.getDay();\n const daysInMonth = last.getDate();\n const today = new Date();\n today.setHours(0, 0, 0, 0);\n\n const days: CalendarDay[] = [];\n const startPadding = firstDayOfWeek;\n const prevMonth = month === 0 ? 11 : month - 1;\n const prevYear = month === 0 ? year - 1 : year;\n const prevMonthDays = new Date(prevYear, prevMonth + 1, 0).getDate();\n\n for (let i = 0; i < startPadding; i++) {\n const day = prevMonthDays - startPadding + i + 1;\n const date = new Date(prevYear, prevMonth, day);\n days.push({\n date,\n day,\n isCurrentMonth: false,\n isToday: this.isSameDay(date, today),\n });\n }\n\n for (let d = 1; d <= daysInMonth; d++) {\n const date = new Date(year, month, d);\n days.push({\n date,\n day: d,\n isCurrentMonth: true,\n isToday: this.isSameDay(date, today),\n });\n }\n\n const remaining = 42 - days.length;\n const nextMonth = month === 11 ? 0 : month + 1;\n const nextYear = month === 11 ? year + 1 : year;\n for (let d = 1; d <= remaining; d++) {\n const date = new Date(nextYear, nextMonth, d);\n days.push({\n date,\n day: d,\n isCurrentMonth: false,\n isToday: this.isSameDay(date, today),\n });\n }\n\n return days;\n }\n\n isSameDay(a: Date, b: Date): boolean {\n return (\n a.getFullYear() === b.getFullYear() &&\n a.getMonth() === b.getMonth() &&\n a.getDate() === b.getDate()\n );\n }\n\n getMonthYearLabel(year: number, month: number): string {\n return `${year}年${month + 1}月`;\n }\n}\n","import { Component, signal, computed, inject, input } from '@angular/core';\nimport { NgFor, NgIf } from '@angular/common';\nimport { CalendarService, type CalendarDay, type CalendarDayState } from './calendar.service';\n\n@Component({\n selector: 'shdr-calendar',\n standalone: true,\n imports: [NgFor, NgIf],\n templateUrl: './calendar.component.html',\n styleUrl: './calendar.component.scss',\n})\nexport class CalendarComponent {\n private calendarService = inject(CalendarService);\n\n /** 可选。与接口 data.calendarList 一致,用于按日期显示状态(如 AVAILABLE / PURCHASED) */\n calendarStates = input<CalendarDayState[]>([]);\n\n currentDate = signal(new Date());\n selectedDate = signal<Date | null>(null);\n\n weekDays = this.calendarService.getWeekDayLabels();\n\n monthYearLabel = computed(() => {\n const d = this.currentDate();\n return this.calendarService.getMonthYearLabel(d.getFullYear(), d.getMonth());\n });\n\n days = computed(() => {\n const d = this.currentDate();\n const selected = this.selectedDate();\n const states = this.calendarStates();\n const stateMap = new Map(states.map((s) => [s.date, s]));\n const days = this.calendarService.getDaysInMonth(\n d.getFullYear(),\n d.getMonth()\n );\n return days.map((day) => {\n const key = this.formatDateKey(day.date);\n const state = stateMap.get(key);\n return {\n ...day,\n isSelected:\n selected !== null &&\n this.calendarService.isSameDay(day.date, selected),\n status: state?.status,\n };\n });\n });\n\n private formatDateKey(date: Date): string {\n const y = date.getFullYear();\n const m = String(date.getMonth() + 1).padStart(2, '0');\n const day = String(date.getDate()).padStart(2, '0');\n return `${y}-${m}-${day}`;\n }\n\n prevMonth(): void {\n const d = this.currentDate();\n this.currentDate.set(new Date(d.getFullYear(), d.getMonth() - 1));\n }\n\n nextMonth(): void {\n const d = this.currentDate();\n this.currentDate.set(new Date(d.getFullYear(), d.getMonth() + 1));\n }\n\n selectDay(day: CalendarDay): void {\n this.selectedDate.set(day.date);\n }\n\n goToToday(): void {\n const today = new Date();\n this.currentDate.set(today);\n this.selectedDate.set(today);\n }\n}\n","<div class=\"calendar\">\n <header class=\"calendar-header\">\n <button type=\"button\" class=\"nav-btn\" (click)=\"prevMonth()\" aria-label=\"上一月\">\n ‹\n </button>\n <h2 class=\"month-year\">{{ monthYearLabel() }}</h2>\n <button type=\"button\" class=\"nav-btn\" (click)=\"nextMonth()\" aria-label=\"下一月\">\n ›\n </button>\n </header>\n\n <button type=\"button\" class=\"today-btn\" (click)=\"goToToday()\">今天</button>\n\n <div class=\"weekdays\">\n @for (label of weekDays; track label) {\n <span class=\"weekday\">{{ label }}</span>\n }\n </div>\n\n <div class=\"days-grid\">\n @for (day of days(); track day.date.getTime()) {\n <button\n type=\"button\"\n class=\"day-cell\"\n [class.other-month]=\"!day.isCurrentMonth\"\n [class.today]=\"day.isToday\"\n [class.selected]=\"day.isSelected\"\n [class.status-available]=\"day.status === 'AVAILABLE'\"\n [class.status-purchased]=\"day.status === 'PURCHASED'\"\n [attr.disabled]=\"day.status === 'PURCHASED' ? true : null\"\n (click)=\"day.status !== 'PURCHASED' && selectDay(day)\"\n >\n <span class=\"day-num\">{{ day.day }}</span>\n <span class=\"day-label\" *ngIf=\"day.status === 'PURCHASED'\">已预约</span>\n <span class=\"day-label\" *ngIf=\"day.status !== 'PURCHASED' && day.isToday\">今天</span>\n </button>\n }\n </div>\n</div>\n","/*\n * Public API Surface of shdr-calendar\n */\n\nexport * from './lib/calendar.service';\nexport * from './lib/calendar.component';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|