shdr-calendar 0.0.1
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.
- package/README.md +24 -0
- package/esm2022/lib/calendar.component.mjs +49 -0
- package/esm2022/lib/calendar.service.mjs +72 -0
- package/esm2022/public-api.mjs +6 -0
- package/esm2022/shdr-calendar.mjs +5 -0
- package/fesm2022/shdr-calendar.mjs +129 -0
- package/fesm2022/shdr-calendar.mjs.map +1 -0
- package/index.d.ts +5 -0
- package/lib/calendar.component.d.ts +22 -0
- package/lib/calendar.service.d.ts +17 -0
- package/package.json +38 -0
- package/public-api.d.ts +2 -0
package/README.md
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# ShdrCalendar
|
|
2
|
+
|
|
3
|
+
This library was generated with [Angular CLI](https://github.com/angular/angular-cli) version 17.3.0.
|
|
4
|
+
|
|
5
|
+
## Code scaffolding
|
|
6
|
+
|
|
7
|
+
Run `ng generate component component-name --project shdr-calendar` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module --project shdr-calendar`.
|
|
8
|
+
> Note: Don't forget to add `--project shdr-calendar` or else it will be added to the default project in your `angular.json` file.
|
|
9
|
+
|
|
10
|
+
## Build
|
|
11
|
+
|
|
12
|
+
Run `ng build shdr-calendar` to build the project. The build artifacts will be stored in the `dist/` directory.
|
|
13
|
+
|
|
14
|
+
## Publishing
|
|
15
|
+
|
|
16
|
+
After building your library with `ng build shdr-calendar`, go to the dist folder `cd dist/shdr-calendar` and run `npm publish`.
|
|
17
|
+
|
|
18
|
+
## Running unit tests
|
|
19
|
+
|
|
20
|
+
Run `ng test shdr-calendar` to execute the unit tests via [Karma](https://karma-runner.github.io).
|
|
21
|
+
|
|
22
|
+
## Further help
|
|
23
|
+
|
|
24
|
+
To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI Overview and Command Reference](https://angular.io/cli) page.
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { Component, signal, computed, inject } from '@angular/core';
|
|
2
|
+
import { NgFor } from '@angular/common';
|
|
3
|
+
import { CalendarService } from './calendar.service';
|
|
4
|
+
import * as i0 from "@angular/core";
|
|
5
|
+
export class CalendarComponent {
|
|
6
|
+
constructor() {
|
|
7
|
+
this.calendarService = inject(CalendarService);
|
|
8
|
+
this.currentDate = signal(new Date());
|
|
9
|
+
this.selectedDate = signal(null);
|
|
10
|
+
this.weekDays = this.calendarService.getWeekDayLabels();
|
|
11
|
+
this.monthYearLabel = computed(() => {
|
|
12
|
+
const d = this.currentDate();
|
|
13
|
+
return this.calendarService.getMonthYearLabel(d.getFullYear(), d.getMonth());
|
|
14
|
+
});
|
|
15
|
+
this.days = computed(() => {
|
|
16
|
+
const d = this.currentDate();
|
|
17
|
+
const selected = this.selectedDate();
|
|
18
|
+
const days = this.calendarService.getDaysInMonth(d.getFullYear(), d.getMonth());
|
|
19
|
+
return days.map((day) => ({
|
|
20
|
+
...day,
|
|
21
|
+
isSelected: selected !== null &&
|
|
22
|
+
this.calendarService.isSameDay(day.date, selected),
|
|
23
|
+
}));
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
prevMonth() {
|
|
27
|
+
const d = this.currentDate();
|
|
28
|
+
this.currentDate.set(new Date(d.getFullYear(), d.getMonth() - 1));
|
|
29
|
+
}
|
|
30
|
+
nextMonth() {
|
|
31
|
+
const d = this.currentDate();
|
|
32
|
+
this.currentDate.set(new Date(d.getFullYear(), d.getMonth() + 1));
|
|
33
|
+
}
|
|
34
|
+
selectDay(day) {
|
|
35
|
+
this.selectedDate.set(day.date);
|
|
36
|
+
}
|
|
37
|
+
goToToday() {
|
|
38
|
+
const today = new Date();
|
|
39
|
+
this.currentDate.set(today);
|
|
40
|
+
this.selectedDate.set(today);
|
|
41
|
+
}
|
|
42
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: CalendarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
43
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.12", type: CalendarComponent, isStandalone: true, selector: "shdr-calendar", 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 (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{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)}\n"] }); }
|
|
44
|
+
}
|
|
45
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: CalendarComponent, decorators: [{
|
|
46
|
+
type: Component,
|
|
47
|
+
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 (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{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)}\n"] }]
|
|
48
|
+
}] });
|
|
49
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2FsZW5kYXIuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vcHJvamVjdHMvc2hkci1jYWxlbmRhci9zcmMvbGliL2NhbGVuZGFyLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uL3Byb2plY3RzL3NoZHItY2FsZW5kYXIvc3JjL2xpYi9jYWxlbmRhci5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sRUFBRSxRQUFRLEVBQUUsTUFBTSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ3BFLE9BQU8sRUFBRSxLQUFLLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUN4QyxPQUFPLEVBQUUsZUFBZSxFQUFvQixNQUFNLG9CQUFvQixDQUFDOztBQVN2RSxNQUFNLE9BQU8saUJBQWlCO0lBUDlCO1FBUVUsb0JBQWUsR0FBRyxNQUFNLENBQUMsZUFBZSxDQUFDLENBQUM7UUFFbEQsZ0JBQVcsR0FBRyxNQUFNLENBQUMsSUFBSSxJQUFJLEVBQUUsQ0FBQyxDQUFDO1FBQ2pDLGlCQUFZLEdBQUcsTUFBTSxDQUFjLElBQUksQ0FBQyxDQUFDO1FBRXpDLGFBQVEsR0FBRyxJQUFJLENBQUMsZUFBZSxDQUFDLGdCQUFnQixFQUFFLENBQUM7UUFFbkQsbUJBQWMsR0FBRyxRQUFRLENBQUMsR0FBRyxFQUFFO1lBQzdCLE1BQU0sQ0FBQyxHQUFHLElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQztZQUM3QixPQUFPLElBQUksQ0FBQyxlQUFlLENBQUMsaUJBQWlCLENBQUMsQ0FBQyxDQUFDLFdBQVcsRUFBRSxFQUFFLENBQUMsQ0FBQyxRQUFRLEVBQUUsQ0FBQyxDQUFDO1FBQy9FLENBQUMsQ0FBQyxDQUFDO1FBRUgsU0FBSSxHQUFHLFFBQVEsQ0FBQyxHQUFHLEVBQUU7WUFDbkIsTUFBTSxDQUFDLEdBQUcsSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDO1lBQzdCLE1BQU0sUUFBUSxHQUFHLElBQUksQ0FBQyxZQUFZLEVBQUUsQ0FBQztZQUNyQyxNQUFNLElBQUksR0FBRyxJQUFJLENBQUMsZUFBZSxDQUFDLGNBQWMsQ0FDOUMsQ0FBQyxDQUFDLFdBQVcsRUFBRSxFQUNmLENBQUMsQ0FBQyxRQUFRLEVBQUUsQ0FDYixDQUFDO1lBQ0YsT0FBTyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsR0FBRyxFQUFFLEVBQUUsQ0FBQyxDQUFDO2dCQUN4QixHQUFHLEdBQUc7Z0JBQ04sVUFBVSxFQUNSLFFBQVEsS0FBSyxJQUFJO29CQUNqQixJQUFJLENBQUMsZUFBZSxDQUFDLFNBQVMsQ0FBQyxHQUFHLENBQUMsSUFBSSxFQUFFLFFBQVEsQ0FBQzthQUNyRCxDQUFDLENBQUMsQ0FBQztRQUNOLENBQUMsQ0FBQyxDQUFDO0tBcUJKO0lBbkJDLFNBQVM7UUFDUCxNQUFNLENBQUMsR0FBRyxJQUFJLENBQUMsV0FBVyxFQUFFLENBQUM7UUFDN0IsSUFBSSxDQUFDLFdBQVcsQ0FBQyxHQUFHLENBQUMsSUFBSSxJQUFJLENBQUMsQ0FBQyxDQUFDLFdBQVcsRUFBRSxFQUFFLENBQUMsQ0FBQyxRQUFRLEVBQUUsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3BFLENBQUM7SUFFRCxTQUFTO1FBQ1AsTUFBTSxDQUFDLEdBQUcsSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDO1FBQzdCLElBQUksQ0FBQyxXQUFXLENBQUMsR0FBRyxDQUFDLElBQUksSUFBSSxDQUFDLENBQUMsQ0FBQyxXQUFXLEVBQUUsRUFBRSxDQUFDLENBQUMsUUFBUSxFQUFFLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUNwRSxDQUFDO0lBRUQsU0FBUyxDQUFDLEdBQWdCO1FBQ3hCLElBQUksQ0FBQyxZQUFZLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUNsQyxDQUFDO0lBRUQsU0FBUztRQUNQLE1BQU0sS0FBSyxHQUFHLElBQUksSUFBSSxFQUFFLENBQUM7UUFDekIsSUFBSSxDQUFDLFdBQVcsQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDNUIsSUFBSSxDQUFDLFlBQVksQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDL0IsQ0FBQzsrR0E5Q1UsaUJBQWlCO21HQUFqQixpQkFBaUIseUVDWDlCLG9oQ0FrQ0E7OzRGRHZCYSxpQkFBaUI7a0JBUDdCLFNBQVM7K0JBQ0UsZUFBZSxjQUNiLElBQUksV0FDUCxDQUFDLEtBQUssQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENvbXBvbmVudCwgc2lnbmFsLCBjb21wdXRlZCwgaW5qZWN0IH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBOZ0ZvciB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbic7XG5pbXBvcnQgeyBDYWxlbmRhclNlcnZpY2UsIHR5cGUgQ2FsZW5kYXJEYXkgfSBmcm9tICcuL2NhbGVuZGFyLnNlcnZpY2UnO1xuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdzaGRyLWNhbGVuZGFyJyxcbiAgc3RhbmRhbG9uZTogdHJ1ZSxcbiAgaW1wb3J0czogW05nRm9yXSxcbiAgdGVtcGxhdGVVcmw6ICcuL2NhbGVuZGFyLmNvbXBvbmVudC5odG1sJyxcbiAgc3R5bGVVcmw6ICcuL2NhbGVuZGFyLmNvbXBvbmVudC5zY3NzJyxcbn0pXG5leHBvcnQgY2xhc3MgQ2FsZW5kYXJDb21wb25lbnQge1xuICBwcml2YXRlIGNhbGVuZGFyU2VydmljZSA9IGluamVjdChDYWxlbmRhclNlcnZpY2UpO1xuXG4gIGN1cnJlbnREYXRlID0gc2lnbmFsKG5ldyBEYXRlKCkpO1xuICBzZWxlY3RlZERhdGUgPSBzaWduYWw8RGF0ZSB8IG51bGw+KG51bGwpO1xuXG4gIHdlZWtEYXlzID0gdGhpcy5jYWxlbmRhclNlcnZpY2UuZ2V0V2Vla0RheUxhYmVscygpO1xuXG4gIG1vbnRoWWVhckxhYmVsID0gY29tcHV0ZWQoKCkgPT4ge1xuICAgIGNvbnN0IGQgPSB0aGlzLmN1cnJlbnREYXRlKCk7XG4gICAgcmV0dXJuIHRoaXMuY2FsZW5kYXJTZXJ2aWNlLmdldE1vbnRoWWVhckxhYmVsKGQuZ2V0RnVsbFllYXIoKSwgZC5nZXRNb250aCgpKTtcbiAgfSk7XG5cbiAgZGF5cyA9IGNvbXB1dGVkKCgpID0+IHtcbiAgICBjb25zdCBkID0gdGhpcy5jdXJyZW50RGF0ZSgpO1xuICAgIGNvbnN0IHNlbGVjdGVkID0gdGhpcy5zZWxlY3RlZERhdGUoKTtcbiAgICBjb25zdCBkYXlzID0gdGhpcy5jYWxlbmRhclNlcnZpY2UuZ2V0RGF5c0luTW9udGgoXG4gICAgICBkLmdldEZ1bGxZZWFyKCksXG4gICAgICBkLmdldE1vbnRoKClcbiAgICApO1xuICAgIHJldHVybiBkYXlzLm1hcCgoZGF5KSA9PiAoe1xuICAgICAgLi4uZGF5LFxuICAgICAgaXNTZWxlY3RlZDpcbiAgICAgICAgc2VsZWN0ZWQgIT09IG51bGwgJiZcbiAgICAgICAgdGhpcy5jYWxlbmRhclNlcnZpY2UuaXNTYW1lRGF5KGRheS5kYXRlLCBzZWxlY3RlZCksXG4gICAgfSkpO1xuICB9KTtcblxuICBwcmV2TW9udGgoKTogdm9pZCB7XG4gICAgY29uc3QgZCA9IHRoaXMuY3VycmVudERhdGUoKTtcbiAgICB0aGlzLmN1cnJlbnREYXRlLnNldChuZXcgRGF0ZShkLmdldEZ1bGxZZWFyKCksIGQuZ2V0TW9udGgoKSAtIDEpKTtcbiAgfVxuXG4gIG5leHRNb250aCgpOiB2b2lkIHtcbiAgICBjb25zdCBkID0gdGhpcy5jdXJyZW50RGF0ZSgpO1xuICAgIHRoaXMuY3VycmVudERhdGUuc2V0KG5ldyBEYXRlKGQuZ2V0RnVsbFllYXIoKSwgZC5nZXRNb250aCgpICsgMSkpO1xuICB9XG5cbiAgc2VsZWN0RGF5KGRheTogQ2FsZW5kYXJEYXkpOiB2b2lkIHtcbiAgICB0aGlzLnNlbGVjdGVkRGF0ZS5zZXQoZGF5LmRhdGUpO1xuICB9XG5cbiAgZ29Ub1RvZGF5KCk6IHZvaWQge1xuICAgIGNvbnN0IHRvZGF5ID0gbmV3IERhdGUoKTtcbiAgICB0aGlzLmN1cnJlbnREYXRlLnNldCh0b2RheSk7XG4gICAgdGhpcy5zZWxlY3RlZERhdGUuc2V0KHRvZGF5KTtcbiAgfVxufVxuIiwiPGRpdiBjbGFzcz1cImNhbGVuZGFyXCI+XG4gIDxoZWFkZXIgY2xhc3M9XCJjYWxlbmRhci1oZWFkZXJcIj5cbiAgICA8YnV0dG9uIHR5cGU9XCJidXR0b25cIiBjbGFzcz1cIm5hdi1idG5cIiAoY2xpY2spPVwicHJldk1vbnRoKClcIiBhcmlhLWxhYmVsPVwi5LiK5LiA5pyIXCI+XG4gICAgICDigLlcbiAgICA8L2J1dHRvbj5cbiAgICA8aDIgY2xhc3M9XCJtb250aC15ZWFyXCI+e3sgbW9udGhZZWFyTGFiZWwoKSB9fTwvaDI+XG4gICAgPGJ1dHRvbiB0eXBlPVwiYnV0dG9uXCIgY2xhc3M9XCJuYXYtYnRuXCIgKGNsaWNrKT1cIm5leHRNb250aCgpXCIgYXJpYS1sYWJlbD1cIuS4i+S4gOaciFwiPlxuICAgICAg4oC6XG4gICAgPC9idXR0b24+XG4gIDwvaGVhZGVyPlxuXG4gIDxidXR0b24gdHlwZT1cImJ1dHRvblwiIGNsYXNzPVwidG9kYXktYnRuXCIgKGNsaWNrKT1cImdvVG9Ub2RheSgpXCI+5LuK5aSpPC9idXR0b24+XG5cbiAgPGRpdiBjbGFzcz1cIndlZWtkYXlzXCI+XG4gICAgQGZvciAobGFiZWwgb2Ygd2Vla0RheXM7IHRyYWNrIGxhYmVsKSB7XG4gICAgICA8c3BhbiBjbGFzcz1cIndlZWtkYXlcIj57eyBsYWJlbCB9fTwvc3Bhbj5cbiAgICB9XG4gIDwvZGl2PlxuXG4gIDxkaXYgY2xhc3M9XCJkYXlzLWdyaWRcIj5cbiAgICBAZm9yIChkYXkgb2YgZGF5cygpOyB0cmFjayBkYXkuZGF0ZS5nZXRUaW1lKCkpIHtcbiAgICAgIDxidXR0b25cbiAgICAgICAgdHlwZT1cImJ1dHRvblwiXG4gICAgICAgIGNsYXNzPVwiZGF5LWNlbGxcIlxuICAgICAgICBbY2xhc3Mub3RoZXItbW9udGhdPVwiIWRheS5pc0N1cnJlbnRNb250aFwiXG4gICAgICAgIFtjbGFzcy50b2RheV09XCJkYXkuaXNUb2RheVwiXG4gICAgICAgIFtjbGFzcy5zZWxlY3RlZF09XCJkYXkuaXNTZWxlY3RlZFwiXG4gICAgICAgIChjbGljayk9XCJzZWxlY3REYXkoZGF5KVwiXG4gICAgICA+XG4gICAgICAgIHt7IGRheS5kYXkgfX1cbiAgICAgIDwvYnV0dG9uPlxuICAgIH1cbiAgPC9kaXY+XG48L2Rpdj5cbiJdfQ==
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { Injectable } from '@angular/core';
|
|
2
|
+
import * as i0 from "@angular/core";
|
|
3
|
+
export class CalendarService {
|
|
4
|
+
constructor() {
|
|
5
|
+
this.weekDays = ['日', '一', '二', '三', '四', '五', '六'];
|
|
6
|
+
}
|
|
7
|
+
getWeekDayLabels() {
|
|
8
|
+
return this.weekDays;
|
|
9
|
+
}
|
|
10
|
+
getDaysInMonth(year, month) {
|
|
11
|
+
const first = new Date(year, month, 1);
|
|
12
|
+
const last = new Date(year, month + 1, 0);
|
|
13
|
+
const firstDayOfWeek = first.getDay();
|
|
14
|
+
const daysInMonth = last.getDate();
|
|
15
|
+
const today = new Date();
|
|
16
|
+
today.setHours(0, 0, 0, 0);
|
|
17
|
+
const days = [];
|
|
18
|
+
const startPadding = firstDayOfWeek;
|
|
19
|
+
const prevMonth = month === 0 ? 11 : month - 1;
|
|
20
|
+
const prevYear = month === 0 ? year - 1 : year;
|
|
21
|
+
const prevMonthDays = new Date(prevYear, prevMonth + 1, 0).getDate();
|
|
22
|
+
for (let i = 0; i < startPadding; i++) {
|
|
23
|
+
const day = prevMonthDays - startPadding + i + 1;
|
|
24
|
+
const date = new Date(prevYear, prevMonth, day);
|
|
25
|
+
days.push({
|
|
26
|
+
date,
|
|
27
|
+
day,
|
|
28
|
+
isCurrentMonth: false,
|
|
29
|
+
isToday: this.isSameDay(date, today),
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
for (let d = 1; d <= daysInMonth; d++) {
|
|
33
|
+
const date = new Date(year, month, d);
|
|
34
|
+
days.push({
|
|
35
|
+
date,
|
|
36
|
+
day: d,
|
|
37
|
+
isCurrentMonth: true,
|
|
38
|
+
isToday: this.isSameDay(date, today),
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
const remaining = 42 - days.length;
|
|
42
|
+
const nextMonth = month === 11 ? 0 : month + 1;
|
|
43
|
+
const nextYear = month === 11 ? year + 1 : year;
|
|
44
|
+
for (let d = 1; d <= remaining; d++) {
|
|
45
|
+
const date = new Date(nextYear, nextMonth, d);
|
|
46
|
+
days.push({
|
|
47
|
+
date,
|
|
48
|
+
day: d,
|
|
49
|
+
isCurrentMonth: false,
|
|
50
|
+
isToday: this.isSameDay(date, today),
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
return days;
|
|
54
|
+
}
|
|
55
|
+
isSameDay(a, b) {
|
|
56
|
+
return (a.getFullYear() === b.getFullYear() &&
|
|
57
|
+
a.getMonth() === b.getMonth() &&
|
|
58
|
+
a.getDate() === b.getDate());
|
|
59
|
+
}
|
|
60
|
+
getMonthYearLabel(year, month) {
|
|
61
|
+
return `${year}年${month + 1}月`;
|
|
62
|
+
}
|
|
63
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: CalendarService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
64
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: CalendarService, providedIn: 'root' }); }
|
|
65
|
+
}
|
|
66
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: CalendarService, decorators: [{
|
|
67
|
+
type: Injectable,
|
|
68
|
+
args: [{
|
|
69
|
+
providedIn: 'root',
|
|
70
|
+
}]
|
|
71
|
+
}] });
|
|
72
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2FsZW5kYXIuc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3Byb2plY3RzL3NoZHItY2FsZW5kYXIvc3JjL2xpYi9jYWxlbmRhci5zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxlQUFlLENBQUM7O0FBYTNDLE1BQU0sT0FBTyxlQUFlO0lBSDVCO1FBSW1CLGFBQVEsR0FBRyxDQUFDLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLEdBQUcsQ0FBQyxDQUFDO0tBb0VqRTtJQWxFQyxnQkFBZ0I7UUFDZCxPQUFPLElBQUksQ0FBQyxRQUFRLENBQUM7SUFDdkIsQ0FBQztJQUVELGNBQWMsQ0FBQyxJQUFZLEVBQUUsS0FBYTtRQUN4QyxNQUFNLEtBQUssR0FBRyxJQUFJLElBQUksQ0FBQyxJQUFJLEVBQUUsS0FBSyxFQUFFLENBQUMsQ0FBQyxDQUFDO1FBQ3ZDLE1BQU0sSUFBSSxHQUFHLElBQUksSUFBSSxDQUFDLElBQUksRUFBRSxLQUFLLEdBQUcsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO1FBQzFDLE1BQU0sY0FBYyxHQUFHLEtBQUssQ0FBQyxNQUFNLEVBQUUsQ0FBQztRQUN0QyxNQUFNLFdBQVcsR0FBRyxJQUFJLENBQUMsT0FBTyxFQUFFLENBQUM7UUFDbkMsTUFBTSxLQUFLLEdBQUcsSUFBSSxJQUFJLEVBQUUsQ0FBQztRQUN6QixLQUFLLENBQUMsUUFBUSxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO1FBRTNCLE1BQU0sSUFBSSxHQUFrQixFQUFFLENBQUM7UUFDL0IsTUFBTSxZQUFZLEdBQUcsY0FBYyxDQUFDO1FBQ3BDLE1BQU0sU0FBUyxHQUFHLEtBQUssS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsS0FBSyxHQUFHLENBQUMsQ0FBQztRQUMvQyxNQUFNLFFBQVEsR0FBRyxLQUFLLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUM7UUFDL0MsTUFBTSxhQUFhLEdBQUcsSUFBSSxJQUFJLENBQUMsUUFBUSxFQUFFLFNBQVMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsT0FBTyxFQUFFLENBQUM7UUFFckUsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLFlBQVksRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDO1lBQ3RDLE1BQU0sR0FBRyxHQUFHLGFBQWEsR0FBRyxZQUFZLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQztZQUNqRCxNQUFNLElBQUksR0FBRyxJQUFJLElBQUksQ0FBQyxRQUFRLEVBQUUsU0FBUyxFQUFFLEdBQUcsQ0FBQyxDQUFDO1lBQ2hELElBQUksQ0FBQyxJQUFJLENBQUM7Z0JBQ1IsSUFBSTtnQkFDSixHQUFHO2dCQUNILGNBQWMsRUFBRSxLQUFLO2dCQUNyQixPQUFPLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLEVBQUUsS0FBSyxDQUFDO2FBQ3JDLENBQUMsQ0FBQztRQUNMLENBQUM7UUFFRCxLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLElBQUksV0FBVyxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUM7WUFDdEMsTUFBTSxJQUFJLEdBQUcsSUFBSSxJQUFJLENBQUMsSUFBSSxFQUFFLEtBQUssRUFBRSxDQUFDLENBQUMsQ0FBQztZQUN0QyxJQUFJLENBQUMsSUFBSSxDQUFDO2dCQUNSLElBQUk7Z0JBQ0osR0FBRyxFQUFFLENBQUM7Z0JBQ04sY0FBYyxFQUFFLElBQUk7Z0JBQ3BCLE9BQU8sRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksRUFBRSxLQUFLLENBQUM7YUFDckMsQ0FBQyxDQUFDO1FBQ0wsQ0FBQztRQUVELE1BQU0sU0FBUyxHQUFHLEVBQUUsR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDO1FBQ25DLE1BQU0sU0FBUyxHQUFHLEtBQUssS0FBSyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsS0FBSyxHQUFHLENBQUMsQ0FBQztRQUMvQyxNQUFNLFFBQVEsR0FBRyxLQUFLLEtBQUssRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUM7UUFDaEQsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxJQUFJLFNBQVMsRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDO1lBQ3BDLE1BQU0sSUFBSSxHQUFHLElBQUksSUFBSSxDQUFDLFFBQVEsRUFBRSxTQUFTLEVBQUUsQ0FBQyxDQUFDLENBQUM7WUFDOUMsSUFBSSxDQUFDLElBQUksQ0FBQztnQkFDUixJQUFJO2dCQUNKLEdBQUcsRUFBRSxDQUFDO2dCQUNOLGNBQWMsRUFBRSxLQUFLO2dCQUNyQixPQUFPLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLEVBQUUsS0FBSyxDQUFDO2FBQ3JDLENBQUMsQ0FBQztRQUNMLENBQUM7UUFFRCxPQUFPLElBQUksQ0FBQztJQUNkLENBQUM7SUFFRCxTQUFTLENBQUMsQ0FBTyxFQUFFLENBQU87UUFDeEIsT0FBTyxDQUNMLENBQUMsQ0FBQyxXQUFXLEVBQUUsS0FBSyxDQUFDLENBQUMsV0FBVyxFQUFFO1lBQ25DLENBQUMsQ0FBQyxRQUFRLEVBQUUsS0FBSyxDQUFDLENBQUMsUUFBUSxFQUFFO1lBQzdCLENBQUMsQ0FBQyxPQUFPLEVBQUUsS0FBSyxDQUFDLENBQUMsT0FBTyxFQUFFLENBQzVCLENBQUM7SUFDSixDQUFDO0lBRUQsaUJBQWlCLENBQUMsSUFBWSxFQUFFLEtBQWE7UUFDM0MsT0FBTyxHQUFHLElBQUksSUFBSSxLQUFLLEdBQUcsQ0FBQyxHQUFHLENBQUM7SUFDakMsQ0FBQzsrR0FwRVUsZUFBZTttSEFBZixlQUFlLGNBRmQsTUFBTTs7NEZBRVAsZUFBZTtrQkFIM0IsVUFBVTttQkFBQztvQkFDVixVQUFVLEVBQUUsTUFBTTtpQkFDbkIiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBJbmplY3RhYmxlIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgQ2FsZW5kYXJEYXkge1xuICBkYXRlOiBEYXRlO1xuICBkYXk6IG51bWJlcjtcbiAgaXNDdXJyZW50TW9udGg6IGJvb2xlYW47XG4gIGlzVG9kYXk6IGJvb2xlYW47XG4gIGlzU2VsZWN0ZWQ/OiBib29sZWFuO1xufVxuXG5ASW5qZWN0YWJsZSh7XG4gIHByb3ZpZGVkSW46ICdyb290Jyxcbn0pXG5leHBvcnQgY2xhc3MgQ2FsZW5kYXJTZXJ2aWNlIHtcbiAgcHJpdmF0ZSByZWFkb25seSB3ZWVrRGF5cyA9IFsn5pelJywgJ+S4gCcsICfkuownLCAn5LiJJywgJ+WbmycsICfkupQnLCAn5YWtJ107XG5cbiAgZ2V0V2Vla0RheUxhYmVscygpOiBzdHJpbmdbXSB7XG4gICAgcmV0dXJuIHRoaXMud2Vla0RheXM7XG4gIH1cblxuICBnZXREYXlzSW5Nb250aCh5ZWFyOiBudW1iZXIsIG1vbnRoOiBudW1iZXIpOiBDYWxlbmRhckRheVtdIHtcbiAgICBjb25zdCBmaXJzdCA9IG5ldyBEYXRlKHllYXIsIG1vbnRoLCAxKTtcbiAgICBjb25zdCBsYXN0ID0gbmV3IERhdGUoeWVhciwgbW9udGggKyAxLCAwKTtcbiAgICBjb25zdCBmaXJzdERheU9mV2VlayA9IGZpcnN0LmdldERheSgpO1xuICAgIGNvbnN0IGRheXNJbk1vbnRoID0gbGFzdC5nZXREYXRlKCk7XG4gICAgY29uc3QgdG9kYXkgPSBuZXcgRGF0ZSgpO1xuICAgIHRvZGF5LnNldEhvdXJzKDAsIDAsIDAsIDApO1xuXG4gICAgY29uc3QgZGF5czogQ2FsZW5kYXJEYXlbXSA9IFtdO1xuICAgIGNvbnN0IHN0YXJ0UGFkZGluZyA9IGZpcnN0RGF5T2ZXZWVrO1xuICAgIGNvbnN0IHByZXZNb250aCA9IG1vbnRoID09PSAwID8gMTEgOiBtb250aCAtIDE7XG4gICAgY29uc3QgcHJldlllYXIgPSBtb250aCA9PT0gMCA/IHllYXIgLSAxIDogeWVhcjtcbiAgICBjb25zdCBwcmV2TW9udGhEYXlzID0gbmV3IERhdGUocHJldlllYXIsIHByZXZNb250aCArIDEsIDApLmdldERhdGUoKTtcblxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgc3RhcnRQYWRkaW5nOyBpKyspIHtcbiAgICAgIGNvbnN0IGRheSA9IHByZXZNb250aERheXMgLSBzdGFydFBhZGRpbmcgKyBpICsgMTtcbiAgICAgIGNvbnN0IGRhdGUgPSBuZXcgRGF0ZShwcmV2WWVhciwgcHJldk1vbnRoLCBkYXkpO1xuICAgICAgZGF5cy5wdXNoKHtcbiAgICAgICAgZGF0ZSxcbiAgICAgICAgZGF5LFxuICAgICAgICBpc0N1cnJlbnRNb250aDogZmFsc2UsXG4gICAgICAgIGlzVG9kYXk6IHRoaXMuaXNTYW1lRGF5KGRhdGUsIHRvZGF5KSxcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIGZvciAobGV0IGQgPSAxOyBkIDw9IGRheXNJbk1vbnRoOyBkKyspIHtcbiAgICAgIGNvbnN0IGRhdGUgPSBuZXcgRGF0ZSh5ZWFyLCBtb250aCwgZCk7XG4gICAgICBkYXlzLnB1c2goe1xuICAgICAgICBkYXRlLFxuICAgICAgICBkYXk6IGQsXG4gICAgICAgIGlzQ3VycmVudE1vbnRoOiB0cnVlLFxuICAgICAgICBpc1RvZGF5OiB0aGlzLmlzU2FtZURheShkYXRlLCB0b2RheSksXG4gICAgICB9KTtcbiAgICB9XG5cbiAgICBjb25zdCByZW1haW5pbmcgPSA0MiAtIGRheXMubGVuZ3RoO1xuICAgIGNvbnN0IG5leHRNb250aCA9IG1vbnRoID09PSAxMSA/IDAgOiBtb250aCArIDE7XG4gICAgY29uc3QgbmV4dFllYXIgPSBtb250aCA9PT0gMTEgPyB5ZWFyICsgMSA6IHllYXI7XG4gICAgZm9yIChsZXQgZCA9IDE7IGQgPD0gcmVtYWluaW5nOyBkKyspIHtcbiAgICAgIGNvbnN0IGRhdGUgPSBuZXcgRGF0ZShuZXh0WWVhciwgbmV4dE1vbnRoLCBkKTtcbiAgICAgIGRheXMucHVzaCh7XG4gICAgICAgIGRhdGUsXG4gICAgICAgIGRheTogZCxcbiAgICAgICAgaXNDdXJyZW50TW9udGg6IGZhbHNlLFxuICAgICAgICBpc1RvZGF5OiB0aGlzLmlzU2FtZURheShkYXRlLCB0b2RheSksXG4gICAgICB9KTtcbiAgICB9XG5cbiAgICByZXR1cm4gZGF5cztcbiAgfVxuXG4gIGlzU2FtZURheShhOiBEYXRlLCBiOiBEYXRlKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIChcbiAgICAgIGEuZ2V0RnVsbFllYXIoKSA9PT0gYi5nZXRGdWxsWWVhcigpICYmXG4gICAgICBhLmdldE1vbnRoKCkgPT09IGIuZ2V0TW9udGgoKSAmJlxuICAgICAgYS5nZXREYXRlKCkgPT09IGIuZ2V0RGF0ZSgpXG4gICAgKTtcbiAgfVxuXG4gIGdldE1vbnRoWWVhckxhYmVsKHllYXI6IG51bWJlciwgbW9udGg6IG51bWJlcik6IHN0cmluZyB7XG4gICAgcmV0dXJuIGAke3llYXJ95bm0JHttb250aCArIDF95pyIYDtcbiAgfVxufVxuIl19
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Public API Surface of shdr-calendar
|
|
3
|
+
*/
|
|
4
|
+
export * from './lib/calendar.service';
|
|
5
|
+
export * from './lib/calendar.component';
|
|
6
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHVibGljLWFwaS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3Byb2plY3RzL3NoZHItY2FsZW5kYXIvc3JjL3B1YmxpYy1hcGkudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7O0dBRUc7QUFFSCxjQUFjLHdCQUF3QixDQUFDO0FBQ3ZDLGNBQWMsMEJBQTBCLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKlxuICogUHVibGljIEFQSSBTdXJmYWNlIG9mIHNoZHItY2FsZW5kYXJcbiAqL1xuXG5leHBvcnQgKiBmcm9tICcuL2xpYi9jYWxlbmRhci5zZXJ2aWNlJztcbmV4cG9ydCAqIGZyb20gJy4vbGliL2NhbGVuZGFyLmNvbXBvbmVudCc7XG4iXX0=
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generated bundle index. Do not edit.
|
|
3
|
+
*/
|
|
4
|
+
export * from './public-api';
|
|
5
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2hkci1jYWxlbmRhci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3Byb2plY3RzL3NoZHItY2FsZW5kYXIvc3JjL3NoZHItY2FsZW5kYXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7O0dBRUc7QUFFSCxjQUFjLGNBQWMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogR2VuZXJhdGVkIGJ1bmRsZSBpbmRleC4gRG8gbm90IGVkaXQuXG4gKi9cblxuZXhwb3J0ICogZnJvbSAnLi9wdWJsaWMtYXBpJztcbiJdfQ==
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import * as i0 from '@angular/core';
|
|
2
|
+
import { Injectable, inject, signal, computed, Component } from '@angular/core';
|
|
3
|
+
import { NgFor } from '@angular/common';
|
|
4
|
+
|
|
5
|
+
class CalendarService {
|
|
6
|
+
constructor() {
|
|
7
|
+
this.weekDays = ['日', '一', '二', '三', '四', '五', '六'];
|
|
8
|
+
}
|
|
9
|
+
getWeekDayLabels() {
|
|
10
|
+
return this.weekDays;
|
|
11
|
+
}
|
|
12
|
+
getDaysInMonth(year, month) {
|
|
13
|
+
const first = new Date(year, month, 1);
|
|
14
|
+
const last = new Date(year, month + 1, 0);
|
|
15
|
+
const firstDayOfWeek = first.getDay();
|
|
16
|
+
const daysInMonth = last.getDate();
|
|
17
|
+
const today = new Date();
|
|
18
|
+
today.setHours(0, 0, 0, 0);
|
|
19
|
+
const days = [];
|
|
20
|
+
const startPadding = firstDayOfWeek;
|
|
21
|
+
const prevMonth = month === 0 ? 11 : month - 1;
|
|
22
|
+
const prevYear = month === 0 ? year - 1 : year;
|
|
23
|
+
const prevMonthDays = new Date(prevYear, prevMonth + 1, 0).getDate();
|
|
24
|
+
for (let i = 0; i < startPadding; i++) {
|
|
25
|
+
const day = prevMonthDays - startPadding + i + 1;
|
|
26
|
+
const date = new Date(prevYear, prevMonth, day);
|
|
27
|
+
days.push({
|
|
28
|
+
date,
|
|
29
|
+
day,
|
|
30
|
+
isCurrentMonth: false,
|
|
31
|
+
isToday: this.isSameDay(date, today),
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
for (let d = 1; d <= daysInMonth; d++) {
|
|
35
|
+
const date = new Date(year, month, d);
|
|
36
|
+
days.push({
|
|
37
|
+
date,
|
|
38
|
+
day: d,
|
|
39
|
+
isCurrentMonth: true,
|
|
40
|
+
isToday: this.isSameDay(date, today),
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
const remaining = 42 - days.length;
|
|
44
|
+
const nextMonth = month === 11 ? 0 : month + 1;
|
|
45
|
+
const nextYear = month === 11 ? year + 1 : year;
|
|
46
|
+
for (let d = 1; d <= remaining; d++) {
|
|
47
|
+
const date = new Date(nextYear, nextMonth, d);
|
|
48
|
+
days.push({
|
|
49
|
+
date,
|
|
50
|
+
day: d,
|
|
51
|
+
isCurrentMonth: false,
|
|
52
|
+
isToday: this.isSameDay(date, today),
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
return days;
|
|
56
|
+
}
|
|
57
|
+
isSameDay(a, b) {
|
|
58
|
+
return (a.getFullYear() === b.getFullYear() &&
|
|
59
|
+
a.getMonth() === b.getMonth() &&
|
|
60
|
+
a.getDate() === b.getDate());
|
|
61
|
+
}
|
|
62
|
+
getMonthYearLabel(year, month) {
|
|
63
|
+
return `${year}年${month + 1}月`;
|
|
64
|
+
}
|
|
65
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: CalendarService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
66
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: CalendarService, providedIn: 'root' }); }
|
|
67
|
+
}
|
|
68
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: CalendarService, decorators: [{
|
|
69
|
+
type: Injectable,
|
|
70
|
+
args: [{
|
|
71
|
+
providedIn: 'root',
|
|
72
|
+
}]
|
|
73
|
+
}] });
|
|
74
|
+
|
|
75
|
+
class CalendarComponent {
|
|
76
|
+
constructor() {
|
|
77
|
+
this.calendarService = inject(CalendarService);
|
|
78
|
+
this.currentDate = signal(new Date());
|
|
79
|
+
this.selectedDate = signal(null);
|
|
80
|
+
this.weekDays = this.calendarService.getWeekDayLabels();
|
|
81
|
+
this.monthYearLabel = computed(() => {
|
|
82
|
+
const d = this.currentDate();
|
|
83
|
+
return this.calendarService.getMonthYearLabel(d.getFullYear(), d.getMonth());
|
|
84
|
+
});
|
|
85
|
+
this.days = computed(() => {
|
|
86
|
+
const d = this.currentDate();
|
|
87
|
+
const selected = this.selectedDate();
|
|
88
|
+
const days = this.calendarService.getDaysInMonth(d.getFullYear(), d.getMonth());
|
|
89
|
+
return days.map((day) => ({
|
|
90
|
+
...day,
|
|
91
|
+
isSelected: selected !== null &&
|
|
92
|
+
this.calendarService.isSameDay(day.date, selected),
|
|
93
|
+
}));
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
prevMonth() {
|
|
97
|
+
const d = this.currentDate();
|
|
98
|
+
this.currentDate.set(new Date(d.getFullYear(), d.getMonth() - 1));
|
|
99
|
+
}
|
|
100
|
+
nextMonth() {
|
|
101
|
+
const d = this.currentDate();
|
|
102
|
+
this.currentDate.set(new Date(d.getFullYear(), d.getMonth() + 1));
|
|
103
|
+
}
|
|
104
|
+
selectDay(day) {
|
|
105
|
+
this.selectedDate.set(day.date);
|
|
106
|
+
}
|
|
107
|
+
goToToday() {
|
|
108
|
+
const today = new Date();
|
|
109
|
+
this.currentDate.set(today);
|
|
110
|
+
this.selectedDate.set(today);
|
|
111
|
+
}
|
|
112
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: CalendarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
113
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.12", type: CalendarComponent, isStandalone: true, selector: "shdr-calendar", 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 (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{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)}\n"] }); }
|
|
114
|
+
}
|
|
115
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: CalendarComponent, decorators: [{
|
|
116
|
+
type: Component,
|
|
117
|
+
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 (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{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)}\n"] }]
|
|
118
|
+
}] });
|
|
119
|
+
|
|
120
|
+
/*
|
|
121
|
+
* Public API Surface of shdr-calendar
|
|
122
|
+
*/
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Generated bundle index. Do not edit.
|
|
126
|
+
*/
|
|
127
|
+
|
|
128
|
+
export { CalendarComponent, CalendarService };
|
|
129
|
+
//# sourceMappingURL=shdr-calendar.mjs.map
|
|
@@ -0,0 +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@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 } from '@angular/core';\nimport { NgFor } from '@angular/common';\nimport { CalendarService, type CalendarDay } 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 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 days = this.calendarService.getDaysInMonth(\n d.getFullYear(),\n d.getMonth()\n );\n return days.map((day) => ({\n ...day,\n isSelected:\n selected !== null &&\n this.calendarService.isSameDay(day.date, selected),\n }));\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 (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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"}
|
package/index.d.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { type CalendarDay } from './calendar.service';
|
|
2
|
+
import * as i0 from "@angular/core";
|
|
3
|
+
export declare class CalendarComponent {
|
|
4
|
+
private calendarService;
|
|
5
|
+
currentDate: import("@angular/core").WritableSignal<Date>;
|
|
6
|
+
selectedDate: import("@angular/core").WritableSignal<Date | null>;
|
|
7
|
+
weekDays: string[];
|
|
8
|
+
monthYearLabel: import("@angular/core").Signal<string>;
|
|
9
|
+
days: import("@angular/core").Signal<{
|
|
10
|
+
isSelected: boolean;
|
|
11
|
+
date: Date;
|
|
12
|
+
day: number;
|
|
13
|
+
isCurrentMonth: boolean;
|
|
14
|
+
isToday: boolean;
|
|
15
|
+
}[]>;
|
|
16
|
+
prevMonth(): void;
|
|
17
|
+
nextMonth(): void;
|
|
18
|
+
selectDay(day: CalendarDay): void;
|
|
19
|
+
goToToday(): void;
|
|
20
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<CalendarComponent, never>;
|
|
21
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<CalendarComponent, "shdr-calendar", never, {}, {}, never, never, true, never>;
|
|
22
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import * as i0 from "@angular/core";
|
|
2
|
+
export interface CalendarDay {
|
|
3
|
+
date: Date;
|
|
4
|
+
day: number;
|
|
5
|
+
isCurrentMonth: boolean;
|
|
6
|
+
isToday: boolean;
|
|
7
|
+
isSelected?: boolean;
|
|
8
|
+
}
|
|
9
|
+
export declare class CalendarService {
|
|
10
|
+
private readonly weekDays;
|
|
11
|
+
getWeekDayLabels(): string[];
|
|
12
|
+
getDaysInMonth(year: number, month: number): CalendarDay[];
|
|
13
|
+
isSameDay(a: Date, b: Date): boolean;
|
|
14
|
+
getMonthYearLabel(year: number, month: number): string;
|
|
15
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<CalendarService, never>;
|
|
16
|
+
static ɵprov: i0.ɵɵInjectableDeclaration<CalendarService>;
|
|
17
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "shdr-calendar",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "Angular 日历组件,支持月视图、选日与今天快捷跳转",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"angular",
|
|
7
|
+
"calendar",
|
|
8
|
+
"component"
|
|
9
|
+
],
|
|
10
|
+
"repository": {
|
|
11
|
+
"type": "git",
|
|
12
|
+
"url": "https://github.disney.com/SHDR-Projects/shdr-calendar-lib.git"
|
|
13
|
+
},
|
|
14
|
+
"peerDependencies": {
|
|
15
|
+
"@angular/common": "^17.0.0",
|
|
16
|
+
"@angular/core": "^17.0.0"
|
|
17
|
+
},
|
|
18
|
+
"dependencies": {
|
|
19
|
+
"tslib": "^2.3.0"
|
|
20
|
+
},
|
|
21
|
+
"sideEffects": false,
|
|
22
|
+
"publishConfig": {
|
|
23
|
+
"registry": "https://registry.npmjs.org/"
|
|
24
|
+
},
|
|
25
|
+
"module": "fesm2022/shdr-calendar.mjs",
|
|
26
|
+
"typings": "index.d.ts",
|
|
27
|
+
"exports": {
|
|
28
|
+
"./package.json": {
|
|
29
|
+
"default": "./package.json"
|
|
30
|
+
},
|
|
31
|
+
".": {
|
|
32
|
+
"types": "./index.d.ts",
|
|
33
|
+
"esm2022": "./esm2022/shdr-calendar.mjs",
|
|
34
|
+
"esm": "./esm2022/shdr-calendar.mjs",
|
|
35
|
+
"default": "./fesm2022/shdr-calendar.mjs"
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
package/public-api.d.ts
ADDED