ngx-resource-scheduler 0.1.3 → 0.1.5

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 ADDED
@@ -0,0 +1,194 @@
1
+ # ngx-resource-scheduler
2
+
3
+ A lightweight, flexible **resource scheduler** for Angular.
4
+
5
+ ## ✨ Features
6
+
7
+ - Days ↔ Resources as primary axis
8
+ - Configurable visible range (1–7 days)
9
+ - Configurable working hours (e.g. `08:00–20:00`)
10
+ - Timezone-aware (UTC, local, or IANA zones)
11
+ - Overlapping event layout
12
+ - Slot & event click callbacks
13
+ - Custom event rendering via `ng-template`
14
+ - Built-in toolbar **or** external navigation
15
+ - Clean, modern styling (system fonts)
16
+
17
+ ## 📦 Installation
18
+
19
+ ```bash
20
+ npm install ngx-resource-scheduler
21
+ ````
22
+
23
+ ## 🚀 Basic Usage
24
+
25
+ ### html
26
+ ```html
27
+ <ngx-resource-scheduler
28
+ [startDate]="startDate"
29
+ [resources]="resources"
30
+ [events]="events">
31
+ </ngx-resource-scheduler>
32
+ ```
33
+
34
+ ### TS
35
+
36
+ ```ts
37
+ startDate = new Date();
38
+
39
+ resources: SchedulerResource[] = [
40
+ { id: 'r1', title: 'Room A' },
41
+ { id: 'r2', title: 'Room B' },
42
+ ];
43
+
44
+ events: SchedulerEvent[] = [
45
+ {
46
+ id: 'e1',
47
+ title: 'Meeting',
48
+ resourceId: 'r1',
49
+ start: new Date('2025-01-10T10:00:00Z'),
50
+ end: new Date('2025-01-10T11:00:00Z'),
51
+ },
52
+ ];
53
+ ```
54
+
55
+ ## 🔧 Inputs
56
+
57
+ ### Required
58
+ | Input | Type | Type |
59
+ | ------------- | ------------- | ------------- |
60
+ | `startDate` | Date | First visible day (recommended at 00:00) |
61
+ | `resources` | SchedulerResource[] | List of schedulable resources
62
+ | `events` | SchedulerEvent[] | Events (UTC instants recommended)
63
+
64
+ ### Layout & Range
65
+
66
+ | Input | Default | Description |
67
+ | ------------- | ------------- | ------------- |
68
+ | `nDays` | `7` | Number of visible days (1–7) |
69
+ | `primaryAxis` | `days` | `days` or `resources` |
70
+ | `dayStart` | `08:00` | Start of visible hours |
71
+ | `dayEnd` | `20:00` | End of visible hours |
72
+ | `slotDuration` | `00:30` | Slot resolution |
73
+ | `snapToSlot` | `true` | Snap clicks to slots |
74
+
75
+ ### Appearance
76
+
77
+ | Input | Default | Description |
78
+ | ------------- | ------------- | ------------- |
79
+ | `showToolbar` | `true` | Show built-in navigation toolbar |
80
+ | `showSlotLines` | `true` | Show slot grid lines |
81
+ | `slotLineStyle` | `slot` | `slot`, `hour`, or `both` |
82
+ | `readonly` | `false` | Disable interactions |
83
+ | `timezone` | `local` | `local`, `UTC`, or IANA zone (e.g. `Europe/Kiev`) |
84
+ | `weekStartsOn` | `1` | First day of week. 0 = Sunday |
85
+
86
+ > **Important**
87
+ >
88
+ > Events should be provided as UTC instants. The scheduler converts them for display using timezone.
89
+
90
+ ## i18n
91
+
92
+ | Input | Default | Description |
93
+ | ------------- | ------------- | ------------- |
94
+ | `showDaysResourcesLabel` | `true` | If the number of days/resources should be shown |
95
+ | `todayLabel` | `Today` | Your translation for "Today" |
96
+ | `daysLabel` | `days` | Your translation for "days" |
97
+ | `resourcesLabel` | `resources` | Your translation for "resources" |
98
+ | `prevLabel` | `<` | Your translation for "<" |
99
+ | `nextLabel` | `>` | Your translation for ">" |
100
+ | `locale` | `null` | Locale to be used in the dates header |
101
+
102
+
103
+ ## 🎯 Outputs
104
+
105
+ | Output | Payload | Description |
106
+ | ------------- | ------------- | ------------- |
107
+ | `slotClick` | `SchedulerSlotClick` | User clicked an empty slot |
108
+ | `eventClick` | `SchedulerEventClick` | User clicked an event |
109
+ | `rangeChange` | `SchedulerRangeChange` | Visible date range changed |
110
+ | `startDateChange` | `Date` | Navigation occurred |
111
+ | `eventChange` | - | Under development |
112
+
113
+ ## 🧭 Navigation example (External Controls)
114
+
115
+ You can hide the toolbar and control navigation from outside the scheduler.
116
+
117
+ ```html
118
+ <button (click)="scheduler.prev()">Prev</button>
119
+ <button (click)="scheduler.today()">Today</button>
120
+ <button (click)="scheduler.next()">Next</button>
121
+
122
+ <ngx-resource-scheduler
123
+ #scheduler
124
+ [showToolbar]="false"
125
+ [nDays]="7"
126
+ [resources]="resources"
127
+ [events]="events">
128
+ </ngx-resource-scheduler>
129
+ ```
130
+
131
+ No date math required.
132
+
133
+ ## 🎨 Custom Event Template
134
+
135
+ You can fully customize how events are rendered.
136
+
137
+ ```html
138
+ <ngx-resource-scheduler
139
+ [events]="events"
140
+ [eventTemplate]="eventTpl">
141
+ </ngx-resource-scheduler>
142
+
143
+ <ng-template
144
+ #eventTpl
145
+ let-event
146
+ let-startZoned="startZoned"
147
+ let-endZoned="endZoned">
148
+ <div>
149
+ <strong>{{ event.title }}</strong>
150
+ <div>
151
+ {{ startZoned | date:'HH:mm' }}–{{ endZoned | date:'HH:mm' }}
152
+ </div>
153
+ </div>
154
+ </ng-template>
155
+ ```
156
+
157
+ ### Template Context
158
+
159
+ | Variable | Description |
160
+ | ------------- | ------------- |
161
+ | `event` / `$implicit` | The event |
162
+ | `startZoned` | Start date in scheduler timezone |
163
+ | `endZoned` | End date in scheduler timezone |
164
+ | `resourceId` | Resource id |
165
+ | `day` | Day of the cell |
166
+
167
+ ## 🧩 Styling Events
168
+
169
+ ### HTML
170
+ ```html
171
+ <ngx-resource-scheduler
172
+ [eventClass]="eventClass"
173
+ [eventStyle]="eventStyle">
174
+ </ngx-resource-scheduler>
175
+ ```
176
+
177
+ ### TS
178
+ ```ts
179
+ eventClass = (e) => ({
180
+ 'is-important': e.title.includes('Important'),
181
+ });
182
+
183
+ eventStyle = (e) => ({
184
+ backgroundColor: '#ffe4e6',
185
+ });
186
+ ```
187
+
188
+ > Layout styles (top, left, height, width) are managed internally and cannot be overridden.
189
+
190
+ ## 📌 Notes
191
+
192
+ * Drag & resize are not included in v1 (comming to v2)
193
+ * Designed for clarity and extensibility
194
+ * No external calendar dependencies
@@ -20,7 +20,6 @@ class NgxResourceSchedulerComponent {
20
20
  this.slotLineStyle = 'slot';
21
21
  // NAVIGATION
22
22
  this.showToolbar = true;
23
- this.todayLabel = 'Today';
24
23
  this.prevLabel = '‹';
25
24
  this.nextLabel = '›';
26
25
  this.lastRangeKey = null;
@@ -28,6 +27,7 @@ class NgxResourceSchedulerComponent {
28
27
  this.showDaysResourcesLabel = true;
29
28
  this.daysLabel = 'days';
30
29
  this.resourcesLabel = 'resources';
30
+ this.todayLabel = 'Today';
31
31
  // --- MISC ---
32
32
  this.weekStartsOn = 1;
33
33
  this.readonly = false;
@@ -498,11 +498,11 @@ class NgxResourceSchedulerComponent {
498
498
  };
499
499
  }
500
500
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: NgxResourceSchedulerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
501
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: NgxResourceSchedulerComponent, isStandalone: false, selector: "ngx-resource-scheduler", inputs: { startDate: "startDate", resources: "resources", events: "events", nDays: "nDays", primaryAxis: "primaryAxis", dayStart: "dayStart", dayEnd: "dayEnd", slotDuration: "slotDuration", snapToSlot: "snapToSlot", showSlotLines: "showSlotLines", slotLineStyle: "slotLineStyle", showToolbar: "showToolbar", todayLabel: "todayLabel", prevLabel: "prevLabel", nextLabel: "nextLabel", eventTemplate: "eventTemplate", eventClass: "eventClass", eventStyle: "eventStyle", showDaysResourcesLabel: "showDaysResourcesLabel", daysLabel: "daysLabel", resourcesLabel: "resourcesLabel", weekStartsOn: "weekStartsOn", locale: "locale", timezone: "timezone", readonly: "readonly" }, outputs: { slotClick: "slotClick", eventClick: "eventClick", eventChange: "eventChange", rangeChange: "rangeChange", startDateChange: "startDateChange" }, usesOnChanges: true, ngImport: i0, template: "<div class=\"ngx-scheduler\">\n\n <!-- Toolbar -->\n @if (showToolbar) {\n <div class=\"ngx-toolbar\">\n <div class=\"ngx-toolbar-left\">\n <button type=\"button\" class=\"ngx-btn\" (click)=\"navigatePrev()\">{{ prevLabel }}</button>\n <button type=\"button\" class=\"ngx-btn ngx-btn--ghost\" (click)=\"navigateToday()\">{{ todayLabel }}</button>\n <button type=\"button\" class=\"ngx-btn\" (click)=\"navigateNext()\">{{ nextLabel }}</button>\n </div>\n <div class=\"ngx-toolbar-title\">\n {{ rangeTitle }}\n </div>\n <div class=\"ngx-toolbar-right\">\n @if (showDaysResourcesLabel) {\n <span class=\"ngx-toolbar-meta\">\n {{ primaryAxis === 'days' ? (visibleDays.length + ' ' + daysLabel) : (resources.length + ' ' + resourcesLabel ) }}\n </span>\n }\n @if (!showDaysResourcesLabel) {\n <span class=\"ngx-toolbar-meta\">&nbsp;</span>\n }\n </div>\n </div>\n }\n\n <!-- Header row -->\n <div class=\"ngx-header\">\n <div class=\"ngx-time-gutter\"></div>\n\n <div class=\"ngx-primary-headers\" [style.gridTemplateColumns]=\"'repeat(' + primaryColumns.length + ', minmax(0, 1fr))'\">\n @for (p of primaryColumns; track trackPrimary($index, p)) {\n <div class=\"ngx-primary-header\">\n <div class=\"ngx-primary-title-row\">\n <div class=\"ngx-primary-title\">{{ p.title }}</div>\n </div>\n <div class=\"ngx-secondary-header-row\" [style.gridTemplateColumns]=\"'repeat(' + secondaryColumns.length + ', minmax(0, 1fr))'\">\n @for (s of secondaryColumns; track trackSecondary($index, s)) {\n <div class=\"ngx-secondary-header\">\n <span class=\"ngx-secondary-header-title\">{{ s.title }}</span>\n </div>\n }\n </div>\n </div>\n }\n </div>\n </div>\n\n <!-- Body -->\n <div class=\"ngx-body\">\n <!-- time gutter -->\n <div class=\"ngx-time-gutter\" [style.height.px]=\"timelineHeightPx\">\n @for (h of hourLabels; track h) {\n <div\n class=\"ngx-hour-label\"\n [style.top.px]=\"hourTopPx(h)\">\n {{ formatHour(h) }}\n </div>\n }\n </div>\n\n\n <!-- grid -->\n <div class=\"ngx-grid\"\n [style.gridTemplateColumns]=\"'repeat(' + primaryColumns.length + ', minmax(0, 1fr))'\"\n [style.height.px]=\"timelineHeightPx\">\n\n @for (p of primaryColumns; track trackPrimary($index, p)) {\n <div class=\"ngx-primary-col\">\n <div class=\"ngx-secondary-cols\"\n [style.gridTemplateColumns]=\"'repeat(' + secondaryColumns.length + ', minmax(0, 1fr))'\"\n [style.height.px]=\"timelineHeightPx\">\n <!-- Each cell is (day, resource) regardless of axis order -->\n @for (s of secondaryColumns; track trackSecondary($index, s)) {\n <div class=\"ngx-cell\"\n #cellEl\n [style.height.px]=\"timelineHeightPx\"\n (click)=\"cellClick(p, s, $event)\"\n [attr.data-day]=\"cellDayKey(p,s)\"\n [attr.data-resource]=\"cellResourceId(p,s)\">\n <!-- grid lines -->\n <div class=\"ngx-lines\" aria-hidden=\"true\">\n <!-- slot lines -->\n @for (line of slotLines; track line) {\n <div\n class=\"ngx-line ngx-line--slot\"\n [style.top.px]=\"line.top\"\n [class.ngx-line--half]=\"line.isHalfHour\"\n [class.is-hidden]=\"slotLineStyle === 'hour'\">\n </div>\n }\n <!-- hour lines -->\n @for (top of hourLineOffsetsPx; track top) {\n <div\n class=\"ngx-line ngx-line--hour\"\n [style.top.px]=\"top\"\n [class.is-hidden]=\"slotLineStyle === 'slot'\">\n </div>\n }\n </div>\n <!-- events -->\n <!-- ngClass and 2nd ngStyle are only used when user passes custom class/style -->\n @for (e of cellEvents(p, s); track trackEvent($index, e)) {\n <div class=\"ngx-event\"\n [ngStyle]=\"getEventLayoutStyle(e, p, s)\"\n (click)=\"onEventClick(e, $event); $event.stopPropagation()\"\n [ngClass]=\"eventClass ? eventClass(e) : null\"\n [attr.title]=\"eventTooltip(e)\">\n @if (eventTemplate) {\n <ng-container\n [ngTemplateOutlet]=\"eventTemplate\"\n [ngTemplateOutletContext]=\"eventTemplateCtx(e, p, s)\">\n </ng-container>\n } @else {\n <div class=\"ngx-event-title\">{{ e.title }}</div>\n <div class=\"ngx-event-time\">\n {{ toDisplayZone(e.start) | date:'HH:mm' }}\u2013{{ toDisplayZone(e.end) | date:'HH:mm' }}\n </div>\n }\n </div>\n }\n </div>\n }\n </div>\n </div>\n }\n\n </div>\n </div>\n\n</div>\n", styles: [":host{display:block;--ngx-bg: #ffffff;--ngx-surface: #ffffff;--ngx-muted: #f6f7f9;--ngx-border: rgba(16, 24, 40, .1);--ngx-border-soft: rgba(16, 24, 40, .06);--ngx-text: #101828;--ngx-text-muted: rgba(16, 24, 40, .6);--ngx-radius: 6px;--ngx-shadow: 0 10px 25px rgba(16, 24, 40, .06);--ngx-shadow-soft: 0 8px 18px rgba(16, 24, 40, .05);--ngx-event-bg: #eef4ff;--ngx-event-border: rgba(53, 122, 246, .25);--ngx-event-text: #0b1f44;--ngx-time-gutter-width: 72px;--ngx-header-height: 78px;--ngx-primary-title-height: 40px;--ngx-secondary-title-height: 45px;background:var(--ngx-bg);color:var(--ngx-text);--ngx-grid-gap: 5px;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Inter,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"}.ngx-scheduler{display:grid;grid-template-rows:auto 1fr;gap:var(--ngx-grid-gap)}.ngx-toolbar{display:grid;grid-template-columns:auto 1fr auto;align-items:center;gap:12px;padding:10px 10px 2px}.ngx-toolbar-title{text-align:center;font-weight:650;font-size:14px;color:var(--ngx-text);letter-spacing:.2px}.ngx-toolbar-meta{font-size:12px;color:var(--ngx-text-muted);padding-right:6px}.ngx-toolbar-left{display:flex;gap:8px;align-items:center}.ngx-btn{height:34px;padding:0 10px;border-radius:12px;border:1px solid var(--ngx-border);background:#fff;color:var(--ngx-text);font-weight:600;font-size:12px;cursor:pointer;box-shadow:0 8px 14px #1018280f;transition:transform .12s ease,box-shadow .12s ease,background .12s ease}.ngx-btn:hover{transform:translateY(-1px);box-shadow:0 12px 18px #1018281a}.ngx-btn:active{transform:translateY(0);box-shadow:0 8px 14px #10182814}.ngx-btn--ghost{background:var(--ngx-muted)}.ngx-header{position:sticky;top:0;z-index:5;-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);gap:var(--ngx-grid-gap);display:grid;grid-template-columns:var(--ngx-time-gutter-width) 1fr;align-items:stretch;background:var(--ngx-bg)}.ngx-header .ngx-time-gutter{background:transparent}.ngx-primary-headers{display:grid;gap:var(--ngx-grid-gap)}.ngx-primary-header{border:1px solid var(--ngx-border);border-radius:var(--ngx-radius);overflow:hidden;background:var(--ngx-surface);box-shadow:var(--ngx-shadow-soft)}.ngx-primary-title-row{height:var(--ngx-primary-title-height);display:flex;align-items:center;padding:0 12px;font-weight:650;font-size:13px;letter-spacing:.2px;border-bottom:1px solid var(--ngx-border-soft);background:linear-gradient(to bottom,#fff,#fbfbfc)}.ngx-primary-title-row .ngx-primary-title{margin:auto}.ngx-secondary-header-row{height:var(--ngx-secondary-title-height);display:grid}.ngx-secondary-header{display:flex;align-items:center;padding:0 6px;font-size:12px;text-align:center;color:var(--ngx-text-muted);border-left:1px solid var(--ngx-border-soft);background:#fff}.ngx-secondary-header-title{margin:auto}.ngx-secondary-header:first-child{border-left:none}.ngx-body{display:grid;grid-template-columns:var(--ngx-time-gutter-width) 1fr;gap:10px;min-height:320px}.ngx-time-gutter{position:relative;-webkit-user-select:none;user-select:none}.ngx-hour-label{position:absolute;left:0;right:8px;transform:translateY(-50%);text-align:right;font-size:12px;color:var(--ngx-text-muted);pointer-events:none}.ngx-hour-label:first-child{transform:translateY(0);top:0!important}.ngx-hour-label:last-child{transform:translateY(-100%)}.ngx-grid{position:relative;display:grid;gap:var(--ngx-grid-gap)}.ngx-primary-col{border:1px solid var(--ngx-border);border-radius:var(--ngx-radius);overflow:hidden;background:var(--ngx-surface);box-shadow:var(--ngx-shadow)}.ngx-secondary-cols{display:grid;height:100%}.ngx-cell{position:relative;border-left:1px solid var(--ngx-border-soft);background:#fff;cursor:pointer;transition:background .12s ease}.ngx-cell .ngx-event{box-sizing:border-box}.ngx-cell:first-child{border-left:none}.ngx-cell:hover{background:#10182805}.ngx-lines{position:absolute;inset:0;pointer-events:none}.ngx-line{position:absolute;left:0;right:0;height:0;border-top:1px solid var(--ngx-border-soft);opacity:.75}.ngx-line--slot{opacity:.5}.ngx-line--half{opacity:.7;border-top-color:#10182817}.ngx-line--hour{opacity:.9;border-top-color:#1018281a}.is-hidden{display:none}.ngx-event{display:flex;flex-direction:column;gap:2px;touch-action:none;-webkit-user-select:none;user-select:none;overflow:hidden;position:absolute;min-width:0;margin:0;border-radius:4px;background:var(--ngx-event-bg);border:1px solid var(--ngx-event-border);color:var(--ngx-event-text);padding:2px 4px;box-sizing:border-box;box-shadow:0 10px 18px #10182814;cursor:pointer;transition:transform .12s ease,box-shadow .12s ease,filter .12s ease}.ngx-event:hover{transform:translateY(-1px);box-shadow:0 14px 22px #1018281f;filter:saturate(1.05)}.ngx-event:hover .ngx-resize{opacity:1}.ngx-event:active{transform:translateY(0);box-shadow:0 10px 18px #1018281a;cursor:grabbing}.ngx-event-title{font-weight:650;font-size:11px;line-height:1.2;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.ngx-event-time{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;margin-top:3px;font-size:10px;color:#0b1f44b8}.ngx-event-time,.ngx-toolbar-meta,.ngx-secondary-header{letter-spacing:.01em}.ngx-hour,.ngx-event-time{font-variant-numeric:tabular-nums}.ngx-body{overflow:auto;padding-bottom:4px;gap:var(--ngx-grid-gap)}.ngx-body::-webkit-scrollbar{width:10px;height:10px}.ngx-body::-webkit-scrollbar-thumb{background:#10182824;border-radius:10px;border:2px solid rgba(255,255,255,.9)}.ngx-body::-webkit-scrollbar-track{background:#1018280a;border-radius:10px}@media(max-width:900px){:host{--ngx-time-gutter-width: 58px}.ngx-primary-headers,.ngx-grid{display:grid;gap:10px}.ngx-primary-headers{padding-left:calc(var(--ngx-grid-gap) / 2);padding-right:calc(var(--ngx-grid-gap) / 2)}.ngx-event{left:6px;right:6px;border-radius:10px}}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "pipe", type: i1.DatePipe, name: "date" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
501
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: NgxResourceSchedulerComponent, isStandalone: false, selector: "ngx-resource-scheduler", inputs: { startDate: "startDate", resources: "resources", events: "events", nDays: "nDays", primaryAxis: "primaryAxis", dayStart: "dayStart", dayEnd: "dayEnd", slotDuration: "slotDuration", snapToSlot: "snapToSlot", showSlotLines: "showSlotLines", slotLineStyle: "slotLineStyle", showToolbar: "showToolbar", prevLabel: "prevLabel", nextLabel: "nextLabel", eventTemplate: "eventTemplate", eventClass: "eventClass", eventStyle: "eventStyle", showDaysResourcesLabel: "showDaysResourcesLabel", daysLabel: "daysLabel", resourcesLabel: "resourcesLabel", todayLabel: "todayLabel", weekStartsOn: "weekStartsOn", locale: "locale", timezone: "timezone", readonly: "readonly" }, outputs: { slotClick: "slotClick", eventClick: "eventClick", eventChange: "eventChange", rangeChange: "rangeChange", startDateChange: "startDateChange" }, usesOnChanges: true, ngImport: i0, template: "<div class=\"ngx-scheduler\">\n\n <!-- Toolbar -->\n @if (showToolbar) {\n <div class=\"ngx-toolbar\">\n <div class=\"ngx-toolbar-left\">\n <button type=\"button\" class=\"ngx-btn\" (click)=\"navigatePrev()\">{{ prevLabel }}</button>\n <button type=\"button\" class=\"ngx-btn ngx-btn--ghost\" (click)=\"navigateToday()\">{{ todayLabel }}</button>\n <button type=\"button\" class=\"ngx-btn\" (click)=\"navigateNext()\">{{ nextLabel }}</button>\n </div>\n <div class=\"ngx-toolbar-title\">\n {{ rangeTitle }}\n </div>\n <div class=\"ngx-toolbar-right\">\n @if (showDaysResourcesLabel) {\n <span class=\"ngx-toolbar-meta\">\n {{ primaryAxis === 'days' ? (visibleDays.length + ' ' + daysLabel) : (resources.length + ' ' + resourcesLabel ) }}\n </span>\n }\n @if (!showDaysResourcesLabel) {\n <span class=\"ngx-toolbar-meta\">&nbsp;</span>\n }\n </div>\n </div>\n }\n\n <!-- Header row -->\n <div class=\"ngx-header\">\n <div class=\"ngx-time-gutter\"></div>\n\n <div class=\"ngx-primary-headers\" [style.gridTemplateColumns]=\"'repeat(' + primaryColumns.length + ', minmax(0, 1fr))'\">\n @for (p of primaryColumns; track trackPrimary($index, p)) {\n <div class=\"ngx-primary-header\">\n <div class=\"ngx-primary-title-row\">\n <div class=\"ngx-primary-title\">{{ p.title }}</div>\n </div>\n <div class=\"ngx-secondary-header-row\" [style.gridTemplateColumns]=\"'repeat(' + secondaryColumns.length + ', minmax(0, 1fr))'\">\n @for (s of secondaryColumns; track trackSecondary($index, s)) {\n <div class=\"ngx-secondary-header\">\n <span class=\"ngx-secondary-header-title\">{{ s.title }}</span>\n </div>\n }\n </div>\n </div>\n }\n </div>\n </div>\n\n <!-- Body -->\n <div class=\"ngx-body\">\n <!-- time gutter -->\n <div class=\"ngx-time-gutter\" [style.height.px]=\"timelineHeightPx\">\n @for (h of hourLabels; track h) {\n <div\n class=\"ngx-hour-label\"\n [style.top.px]=\"hourTopPx(h)\">\n {{ formatHour(h) }}\n </div>\n }\n </div>\n\n\n <!-- grid -->\n <div class=\"ngx-grid\"\n [style.gridTemplateColumns]=\"'repeat(' + primaryColumns.length + ', minmax(0, 1fr))'\"\n [style.height.px]=\"timelineHeightPx\">\n\n @for (p of primaryColumns; track trackPrimary($index, p)) {\n <div class=\"ngx-primary-col\">\n <div class=\"ngx-secondary-cols\"\n [style.gridTemplateColumns]=\"'repeat(' + secondaryColumns.length + ', minmax(0, 1fr))'\"\n [style.height.px]=\"timelineHeightPx\">\n <!-- Each cell is (day, resource) regardless of axis order -->\n @for (s of secondaryColumns; track trackSecondary($index, s)) {\n <div class=\"ngx-cell\"\n #cellEl\n [style.height.px]=\"timelineHeightPx\"\n (click)=\"cellClick(p, s, $event)\"\n [attr.data-day]=\"cellDayKey(p,s)\"\n [attr.data-resource]=\"cellResourceId(p,s)\">\n <!-- grid lines -->\n <div class=\"ngx-lines\" aria-hidden=\"true\">\n <!-- slot lines -->\n @for (line of slotLines; track line) {\n <div\n class=\"ngx-line ngx-line--slot\"\n [style.top.px]=\"line.top\"\n [class.ngx-line--half]=\"line.isHalfHour\"\n [class.is-hidden]=\"slotLineStyle === 'hour'\">\n </div>\n }\n <!-- hour lines -->\n @for (top of hourLineOffsetsPx; track top) {\n <div\n class=\"ngx-line ngx-line--hour\"\n [style.top.px]=\"top\"\n [class.is-hidden]=\"slotLineStyle === 'slot'\">\n </div>\n }\n </div>\n <!-- events -->\n <!-- ngClass and 2nd ngStyle are only used when user passes custom class/style -->\n @for (e of cellEvents(p, s); track trackEvent($index, e)) {\n <div class=\"ngx-event\"\n [ngStyle]=\"getEventLayoutStyle(e, p, s)\"\n (click)=\"onEventClick(e, $event); $event.stopPropagation()\"\n [ngClass]=\"eventClass ? eventClass(e) : null\"\n [attr.title]=\"eventTooltip(e)\">\n @if (eventTemplate) {\n <ng-container\n [ngTemplateOutlet]=\"eventTemplate\"\n [ngTemplateOutletContext]=\"eventTemplateCtx(e, p, s)\">\n </ng-container>\n } @else {\n <div class=\"ngx-event-title\">{{ e.title }}</div>\n <div class=\"ngx-event-time\">\n {{ toDisplayZone(e.start) | date:'HH:mm' }}\u2013{{ toDisplayZone(e.end) | date:'HH:mm' }}\n </div>\n }\n </div>\n }\n </div>\n }\n </div>\n </div>\n }\n\n </div>\n </div>\n\n</div>\n", styles: [":host{display:block;--ngx-bg: #ffffff;--ngx-surface: #ffffff;--ngx-muted: #f6f7f9;--ngx-border: rgba(16, 24, 40, .1);--ngx-border-soft: rgba(16, 24, 40, .06);--ngx-text: #101828;--ngx-text-muted: rgba(16, 24, 40, .6);--ngx-radius: 6px;--ngx-shadow: 0 10px 25px rgba(16, 24, 40, .06);--ngx-shadow-soft: 0 8px 18px rgba(16, 24, 40, .05);--ngx-event-bg: #eef4ff;--ngx-event-border: rgba(53, 122, 246, .25);--ngx-event-text: #0b1f44;--ngx-time-gutter-width: 72px;--ngx-header-height: 78px;--ngx-primary-title-height: 40px;--ngx-secondary-title-height: 45px;background:var(--ngx-bg);color:var(--ngx-text);--ngx-grid-gap: 5px;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Inter,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"}.ngx-scheduler{display:grid;grid-template-rows:auto 1fr;gap:var(--ngx-grid-gap)}.ngx-toolbar{display:grid;grid-template-columns:auto 1fr auto;align-items:center;gap:12px;padding:10px 10px 2px}.ngx-toolbar-title{text-align:center;font-weight:650;font-size:14px;color:var(--ngx-text);letter-spacing:.2px}.ngx-toolbar-meta{font-size:12px;color:var(--ngx-text-muted);padding-right:6px}.ngx-toolbar-left{display:flex;gap:8px;align-items:center}.ngx-btn{height:34px;padding:0 10px;border-radius:12px;border:1px solid var(--ngx-border);background:#fff;color:var(--ngx-text);font-weight:600;font-size:12px;cursor:pointer;box-shadow:0 8px 14px #1018280f;transition:transform .12s ease,box-shadow .12s ease,background .12s ease}.ngx-btn:hover{transform:translateY(-1px);box-shadow:0 12px 18px #1018281a}.ngx-btn:active{transform:translateY(0);box-shadow:0 8px 14px #10182814}.ngx-btn--ghost{background:var(--ngx-muted)}.ngx-header{position:sticky;top:0;z-index:5;-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);gap:var(--ngx-grid-gap);display:grid;grid-template-columns:var(--ngx-time-gutter-width) 1fr;align-items:stretch;background:var(--ngx-bg)}.ngx-header .ngx-time-gutter{background:transparent}.ngx-primary-headers{display:grid;gap:var(--ngx-grid-gap)}.ngx-primary-header{border:1px solid var(--ngx-border);border-radius:var(--ngx-radius);overflow:hidden;background:var(--ngx-surface);box-shadow:var(--ngx-shadow-soft)}.ngx-primary-title-row{height:var(--ngx-primary-title-height);display:flex;align-items:center;padding:0 12px;font-weight:650;font-size:13px;letter-spacing:.2px;border-bottom:1px solid var(--ngx-border-soft);background:linear-gradient(to bottom,#fff,#fbfbfc)}.ngx-primary-title-row .ngx-primary-title{margin:auto;text-align:center}.ngx-secondary-header-row{height:var(--ngx-secondary-title-height);display:grid}.ngx-secondary-header{display:flex;align-items:center;padding:0 6px;font-size:12px;text-align:center;color:var(--ngx-text-muted);border-left:1px solid var(--ngx-border-soft);background:#fff}.ngx-secondary-header-title{margin:auto}.ngx-secondary-header:first-child{border-left:none}.ngx-body{display:grid;grid-template-columns:var(--ngx-time-gutter-width) 1fr;gap:10px;min-height:320px}.ngx-time-gutter{position:relative;-webkit-user-select:none;user-select:none}.ngx-hour-label{position:absolute;left:0;right:8px;transform:translateY(-50%);text-align:right;font-size:12px;color:var(--ngx-text-muted);pointer-events:none}.ngx-hour-label:first-child{transform:translateY(0);top:0!important}.ngx-hour-label:last-child{transform:translateY(-100%)}.ngx-grid{position:relative;display:grid;gap:var(--ngx-grid-gap)}.ngx-primary-col{border:1px solid var(--ngx-border);border-radius:var(--ngx-radius);overflow:hidden;background:var(--ngx-surface);box-shadow:var(--ngx-shadow)}.ngx-secondary-cols{display:grid;height:100%}.ngx-cell{position:relative;border-left:1px solid var(--ngx-border-soft);background:#fff;cursor:pointer;transition:background .12s ease}.ngx-cell .ngx-event{box-sizing:border-box}.ngx-cell:first-child{border-left:none}.ngx-cell:hover{background:#10182805}.ngx-lines{position:absolute;inset:0;pointer-events:none}.ngx-line{position:absolute;left:0;right:0;height:0;border-top:1px solid var(--ngx-border-soft);opacity:.75}.ngx-line--slot{opacity:.5}.ngx-line--half{opacity:.7;border-top-color:#10182817}.ngx-line--hour{opacity:.9;border-top-color:#1018281a}.is-hidden{display:none}.ngx-event{display:flex;flex-direction:column;gap:2px;touch-action:none;-webkit-user-select:none;user-select:none;overflow:hidden;position:absolute;min-width:0;margin:0;border-radius:4px;background:var(--ngx-event-bg);border:1px solid var(--ngx-event-border);color:var(--ngx-event-text);padding:2px 4px;box-sizing:border-box;box-shadow:0 10px 18px #10182814;cursor:pointer;transition:transform .12s ease,box-shadow .12s ease,filter .12s ease}.ngx-event:hover{transform:translateY(-1px);box-shadow:0 14px 22px #1018281f;filter:saturate(1.05)}.ngx-event:hover .ngx-resize{opacity:1}.ngx-event:active{transform:translateY(0);box-shadow:0 10px 18px #1018281a;cursor:grabbing}.ngx-event-title{font-weight:650;font-size:11px;line-height:1.2;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.ngx-event-time{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;margin-top:3px;font-size:10px;color:#0b1f44b8}.ngx-event-time,.ngx-toolbar-meta,.ngx-secondary-header{letter-spacing:.01em}.ngx-hour,.ngx-event-time{font-variant-numeric:tabular-nums}.ngx-body{overflow:auto;padding-bottom:4px;gap:var(--ngx-grid-gap)}.ngx-body::-webkit-scrollbar{width:10px;height:10px}.ngx-body::-webkit-scrollbar-thumb{background:#10182824;border-radius:10px;border:2px solid rgba(255,255,255,.9)}.ngx-body::-webkit-scrollbar-track{background:#1018280a;border-radius:10px}@media(max-width:900px){:host{--ngx-time-gutter-width: 58px}.ngx-primary-headers,.ngx-grid{display:grid;gap:10px}.ngx-primary-headers{padding-left:calc(var(--ngx-grid-gap) / 2);padding-right:calc(var(--ngx-grid-gap) / 2)}.ngx-event{left:6px;right:6px;border-radius:10px}}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "pipe", type: i1.DatePipe, name: "date" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
502
502
  }
503
503
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: NgxResourceSchedulerComponent, decorators: [{
504
504
  type: Component,
505
- args: [{ selector: 'ngx-resource-scheduler', changeDetection: ChangeDetectionStrategy.OnPush, standalone: false, template: "<div class=\"ngx-scheduler\">\n\n <!-- Toolbar -->\n @if (showToolbar) {\n <div class=\"ngx-toolbar\">\n <div class=\"ngx-toolbar-left\">\n <button type=\"button\" class=\"ngx-btn\" (click)=\"navigatePrev()\">{{ prevLabel }}</button>\n <button type=\"button\" class=\"ngx-btn ngx-btn--ghost\" (click)=\"navigateToday()\">{{ todayLabel }}</button>\n <button type=\"button\" class=\"ngx-btn\" (click)=\"navigateNext()\">{{ nextLabel }}</button>\n </div>\n <div class=\"ngx-toolbar-title\">\n {{ rangeTitle }}\n </div>\n <div class=\"ngx-toolbar-right\">\n @if (showDaysResourcesLabel) {\n <span class=\"ngx-toolbar-meta\">\n {{ primaryAxis === 'days' ? (visibleDays.length + ' ' + daysLabel) : (resources.length + ' ' + resourcesLabel ) }}\n </span>\n }\n @if (!showDaysResourcesLabel) {\n <span class=\"ngx-toolbar-meta\">&nbsp;</span>\n }\n </div>\n </div>\n }\n\n <!-- Header row -->\n <div class=\"ngx-header\">\n <div class=\"ngx-time-gutter\"></div>\n\n <div class=\"ngx-primary-headers\" [style.gridTemplateColumns]=\"'repeat(' + primaryColumns.length + ', minmax(0, 1fr))'\">\n @for (p of primaryColumns; track trackPrimary($index, p)) {\n <div class=\"ngx-primary-header\">\n <div class=\"ngx-primary-title-row\">\n <div class=\"ngx-primary-title\">{{ p.title }}</div>\n </div>\n <div class=\"ngx-secondary-header-row\" [style.gridTemplateColumns]=\"'repeat(' + secondaryColumns.length + ', minmax(0, 1fr))'\">\n @for (s of secondaryColumns; track trackSecondary($index, s)) {\n <div class=\"ngx-secondary-header\">\n <span class=\"ngx-secondary-header-title\">{{ s.title }}</span>\n </div>\n }\n </div>\n </div>\n }\n </div>\n </div>\n\n <!-- Body -->\n <div class=\"ngx-body\">\n <!-- time gutter -->\n <div class=\"ngx-time-gutter\" [style.height.px]=\"timelineHeightPx\">\n @for (h of hourLabels; track h) {\n <div\n class=\"ngx-hour-label\"\n [style.top.px]=\"hourTopPx(h)\">\n {{ formatHour(h) }}\n </div>\n }\n </div>\n\n\n <!-- grid -->\n <div class=\"ngx-grid\"\n [style.gridTemplateColumns]=\"'repeat(' + primaryColumns.length + ', minmax(0, 1fr))'\"\n [style.height.px]=\"timelineHeightPx\">\n\n @for (p of primaryColumns; track trackPrimary($index, p)) {\n <div class=\"ngx-primary-col\">\n <div class=\"ngx-secondary-cols\"\n [style.gridTemplateColumns]=\"'repeat(' + secondaryColumns.length + ', minmax(0, 1fr))'\"\n [style.height.px]=\"timelineHeightPx\">\n <!-- Each cell is (day, resource) regardless of axis order -->\n @for (s of secondaryColumns; track trackSecondary($index, s)) {\n <div class=\"ngx-cell\"\n #cellEl\n [style.height.px]=\"timelineHeightPx\"\n (click)=\"cellClick(p, s, $event)\"\n [attr.data-day]=\"cellDayKey(p,s)\"\n [attr.data-resource]=\"cellResourceId(p,s)\">\n <!-- grid lines -->\n <div class=\"ngx-lines\" aria-hidden=\"true\">\n <!-- slot lines -->\n @for (line of slotLines; track line) {\n <div\n class=\"ngx-line ngx-line--slot\"\n [style.top.px]=\"line.top\"\n [class.ngx-line--half]=\"line.isHalfHour\"\n [class.is-hidden]=\"slotLineStyle === 'hour'\">\n </div>\n }\n <!-- hour lines -->\n @for (top of hourLineOffsetsPx; track top) {\n <div\n class=\"ngx-line ngx-line--hour\"\n [style.top.px]=\"top\"\n [class.is-hidden]=\"slotLineStyle === 'slot'\">\n </div>\n }\n </div>\n <!-- events -->\n <!-- ngClass and 2nd ngStyle are only used when user passes custom class/style -->\n @for (e of cellEvents(p, s); track trackEvent($index, e)) {\n <div class=\"ngx-event\"\n [ngStyle]=\"getEventLayoutStyle(e, p, s)\"\n (click)=\"onEventClick(e, $event); $event.stopPropagation()\"\n [ngClass]=\"eventClass ? eventClass(e) : null\"\n [attr.title]=\"eventTooltip(e)\">\n @if (eventTemplate) {\n <ng-container\n [ngTemplateOutlet]=\"eventTemplate\"\n [ngTemplateOutletContext]=\"eventTemplateCtx(e, p, s)\">\n </ng-container>\n } @else {\n <div class=\"ngx-event-title\">{{ e.title }}</div>\n <div class=\"ngx-event-time\">\n {{ toDisplayZone(e.start) | date:'HH:mm' }}\u2013{{ toDisplayZone(e.end) | date:'HH:mm' }}\n </div>\n }\n </div>\n }\n </div>\n }\n </div>\n </div>\n }\n\n </div>\n </div>\n\n</div>\n", styles: [":host{display:block;--ngx-bg: #ffffff;--ngx-surface: #ffffff;--ngx-muted: #f6f7f9;--ngx-border: rgba(16, 24, 40, .1);--ngx-border-soft: rgba(16, 24, 40, .06);--ngx-text: #101828;--ngx-text-muted: rgba(16, 24, 40, .6);--ngx-radius: 6px;--ngx-shadow: 0 10px 25px rgba(16, 24, 40, .06);--ngx-shadow-soft: 0 8px 18px rgba(16, 24, 40, .05);--ngx-event-bg: #eef4ff;--ngx-event-border: rgba(53, 122, 246, .25);--ngx-event-text: #0b1f44;--ngx-time-gutter-width: 72px;--ngx-header-height: 78px;--ngx-primary-title-height: 40px;--ngx-secondary-title-height: 45px;background:var(--ngx-bg);color:var(--ngx-text);--ngx-grid-gap: 5px;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Inter,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"}.ngx-scheduler{display:grid;grid-template-rows:auto 1fr;gap:var(--ngx-grid-gap)}.ngx-toolbar{display:grid;grid-template-columns:auto 1fr auto;align-items:center;gap:12px;padding:10px 10px 2px}.ngx-toolbar-title{text-align:center;font-weight:650;font-size:14px;color:var(--ngx-text);letter-spacing:.2px}.ngx-toolbar-meta{font-size:12px;color:var(--ngx-text-muted);padding-right:6px}.ngx-toolbar-left{display:flex;gap:8px;align-items:center}.ngx-btn{height:34px;padding:0 10px;border-radius:12px;border:1px solid var(--ngx-border);background:#fff;color:var(--ngx-text);font-weight:600;font-size:12px;cursor:pointer;box-shadow:0 8px 14px #1018280f;transition:transform .12s ease,box-shadow .12s ease,background .12s ease}.ngx-btn:hover{transform:translateY(-1px);box-shadow:0 12px 18px #1018281a}.ngx-btn:active{transform:translateY(0);box-shadow:0 8px 14px #10182814}.ngx-btn--ghost{background:var(--ngx-muted)}.ngx-header{position:sticky;top:0;z-index:5;-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);gap:var(--ngx-grid-gap);display:grid;grid-template-columns:var(--ngx-time-gutter-width) 1fr;align-items:stretch;background:var(--ngx-bg)}.ngx-header .ngx-time-gutter{background:transparent}.ngx-primary-headers{display:grid;gap:var(--ngx-grid-gap)}.ngx-primary-header{border:1px solid var(--ngx-border);border-radius:var(--ngx-radius);overflow:hidden;background:var(--ngx-surface);box-shadow:var(--ngx-shadow-soft)}.ngx-primary-title-row{height:var(--ngx-primary-title-height);display:flex;align-items:center;padding:0 12px;font-weight:650;font-size:13px;letter-spacing:.2px;border-bottom:1px solid var(--ngx-border-soft);background:linear-gradient(to bottom,#fff,#fbfbfc)}.ngx-primary-title-row .ngx-primary-title{margin:auto}.ngx-secondary-header-row{height:var(--ngx-secondary-title-height);display:grid}.ngx-secondary-header{display:flex;align-items:center;padding:0 6px;font-size:12px;text-align:center;color:var(--ngx-text-muted);border-left:1px solid var(--ngx-border-soft);background:#fff}.ngx-secondary-header-title{margin:auto}.ngx-secondary-header:first-child{border-left:none}.ngx-body{display:grid;grid-template-columns:var(--ngx-time-gutter-width) 1fr;gap:10px;min-height:320px}.ngx-time-gutter{position:relative;-webkit-user-select:none;user-select:none}.ngx-hour-label{position:absolute;left:0;right:8px;transform:translateY(-50%);text-align:right;font-size:12px;color:var(--ngx-text-muted);pointer-events:none}.ngx-hour-label:first-child{transform:translateY(0);top:0!important}.ngx-hour-label:last-child{transform:translateY(-100%)}.ngx-grid{position:relative;display:grid;gap:var(--ngx-grid-gap)}.ngx-primary-col{border:1px solid var(--ngx-border);border-radius:var(--ngx-radius);overflow:hidden;background:var(--ngx-surface);box-shadow:var(--ngx-shadow)}.ngx-secondary-cols{display:grid;height:100%}.ngx-cell{position:relative;border-left:1px solid var(--ngx-border-soft);background:#fff;cursor:pointer;transition:background .12s ease}.ngx-cell .ngx-event{box-sizing:border-box}.ngx-cell:first-child{border-left:none}.ngx-cell:hover{background:#10182805}.ngx-lines{position:absolute;inset:0;pointer-events:none}.ngx-line{position:absolute;left:0;right:0;height:0;border-top:1px solid var(--ngx-border-soft);opacity:.75}.ngx-line--slot{opacity:.5}.ngx-line--half{opacity:.7;border-top-color:#10182817}.ngx-line--hour{opacity:.9;border-top-color:#1018281a}.is-hidden{display:none}.ngx-event{display:flex;flex-direction:column;gap:2px;touch-action:none;-webkit-user-select:none;user-select:none;overflow:hidden;position:absolute;min-width:0;margin:0;border-radius:4px;background:var(--ngx-event-bg);border:1px solid var(--ngx-event-border);color:var(--ngx-event-text);padding:2px 4px;box-sizing:border-box;box-shadow:0 10px 18px #10182814;cursor:pointer;transition:transform .12s ease,box-shadow .12s ease,filter .12s ease}.ngx-event:hover{transform:translateY(-1px);box-shadow:0 14px 22px #1018281f;filter:saturate(1.05)}.ngx-event:hover .ngx-resize{opacity:1}.ngx-event:active{transform:translateY(0);box-shadow:0 10px 18px #1018281a;cursor:grabbing}.ngx-event-title{font-weight:650;font-size:11px;line-height:1.2;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.ngx-event-time{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;margin-top:3px;font-size:10px;color:#0b1f44b8}.ngx-event-time,.ngx-toolbar-meta,.ngx-secondary-header{letter-spacing:.01em}.ngx-hour,.ngx-event-time{font-variant-numeric:tabular-nums}.ngx-body{overflow:auto;padding-bottom:4px;gap:var(--ngx-grid-gap)}.ngx-body::-webkit-scrollbar{width:10px;height:10px}.ngx-body::-webkit-scrollbar-thumb{background:#10182824;border-radius:10px;border:2px solid rgba(255,255,255,.9)}.ngx-body::-webkit-scrollbar-track{background:#1018280a;border-radius:10px}@media(max-width:900px){:host{--ngx-time-gutter-width: 58px}.ngx-primary-headers,.ngx-grid{display:grid;gap:10px}.ngx-primary-headers{padding-left:calc(var(--ngx-grid-gap) / 2);padding-right:calc(var(--ngx-grid-gap) / 2)}.ngx-event{left:6px;right:6px;border-radius:10px}}\n"] }]
505
+ args: [{ selector: 'ngx-resource-scheduler', changeDetection: ChangeDetectionStrategy.OnPush, standalone: false, template: "<div class=\"ngx-scheduler\">\n\n <!-- Toolbar -->\n @if (showToolbar) {\n <div class=\"ngx-toolbar\">\n <div class=\"ngx-toolbar-left\">\n <button type=\"button\" class=\"ngx-btn\" (click)=\"navigatePrev()\">{{ prevLabel }}</button>\n <button type=\"button\" class=\"ngx-btn ngx-btn--ghost\" (click)=\"navigateToday()\">{{ todayLabel }}</button>\n <button type=\"button\" class=\"ngx-btn\" (click)=\"navigateNext()\">{{ nextLabel }}</button>\n </div>\n <div class=\"ngx-toolbar-title\">\n {{ rangeTitle }}\n </div>\n <div class=\"ngx-toolbar-right\">\n @if (showDaysResourcesLabel) {\n <span class=\"ngx-toolbar-meta\">\n {{ primaryAxis === 'days' ? (visibleDays.length + ' ' + daysLabel) : (resources.length + ' ' + resourcesLabel ) }}\n </span>\n }\n @if (!showDaysResourcesLabel) {\n <span class=\"ngx-toolbar-meta\">&nbsp;</span>\n }\n </div>\n </div>\n }\n\n <!-- Header row -->\n <div class=\"ngx-header\">\n <div class=\"ngx-time-gutter\"></div>\n\n <div class=\"ngx-primary-headers\" [style.gridTemplateColumns]=\"'repeat(' + primaryColumns.length + ', minmax(0, 1fr))'\">\n @for (p of primaryColumns; track trackPrimary($index, p)) {\n <div class=\"ngx-primary-header\">\n <div class=\"ngx-primary-title-row\">\n <div class=\"ngx-primary-title\">{{ p.title }}</div>\n </div>\n <div class=\"ngx-secondary-header-row\" [style.gridTemplateColumns]=\"'repeat(' + secondaryColumns.length + ', minmax(0, 1fr))'\">\n @for (s of secondaryColumns; track trackSecondary($index, s)) {\n <div class=\"ngx-secondary-header\">\n <span class=\"ngx-secondary-header-title\">{{ s.title }}</span>\n </div>\n }\n </div>\n </div>\n }\n </div>\n </div>\n\n <!-- Body -->\n <div class=\"ngx-body\">\n <!-- time gutter -->\n <div class=\"ngx-time-gutter\" [style.height.px]=\"timelineHeightPx\">\n @for (h of hourLabels; track h) {\n <div\n class=\"ngx-hour-label\"\n [style.top.px]=\"hourTopPx(h)\">\n {{ formatHour(h) }}\n </div>\n }\n </div>\n\n\n <!-- grid -->\n <div class=\"ngx-grid\"\n [style.gridTemplateColumns]=\"'repeat(' + primaryColumns.length + ', minmax(0, 1fr))'\"\n [style.height.px]=\"timelineHeightPx\">\n\n @for (p of primaryColumns; track trackPrimary($index, p)) {\n <div class=\"ngx-primary-col\">\n <div class=\"ngx-secondary-cols\"\n [style.gridTemplateColumns]=\"'repeat(' + secondaryColumns.length + ', minmax(0, 1fr))'\"\n [style.height.px]=\"timelineHeightPx\">\n <!-- Each cell is (day, resource) regardless of axis order -->\n @for (s of secondaryColumns; track trackSecondary($index, s)) {\n <div class=\"ngx-cell\"\n #cellEl\n [style.height.px]=\"timelineHeightPx\"\n (click)=\"cellClick(p, s, $event)\"\n [attr.data-day]=\"cellDayKey(p,s)\"\n [attr.data-resource]=\"cellResourceId(p,s)\">\n <!-- grid lines -->\n <div class=\"ngx-lines\" aria-hidden=\"true\">\n <!-- slot lines -->\n @for (line of slotLines; track line) {\n <div\n class=\"ngx-line ngx-line--slot\"\n [style.top.px]=\"line.top\"\n [class.ngx-line--half]=\"line.isHalfHour\"\n [class.is-hidden]=\"slotLineStyle === 'hour'\">\n </div>\n }\n <!-- hour lines -->\n @for (top of hourLineOffsetsPx; track top) {\n <div\n class=\"ngx-line ngx-line--hour\"\n [style.top.px]=\"top\"\n [class.is-hidden]=\"slotLineStyle === 'slot'\">\n </div>\n }\n </div>\n <!-- events -->\n <!-- ngClass and 2nd ngStyle are only used when user passes custom class/style -->\n @for (e of cellEvents(p, s); track trackEvent($index, e)) {\n <div class=\"ngx-event\"\n [ngStyle]=\"getEventLayoutStyle(e, p, s)\"\n (click)=\"onEventClick(e, $event); $event.stopPropagation()\"\n [ngClass]=\"eventClass ? eventClass(e) : null\"\n [attr.title]=\"eventTooltip(e)\">\n @if (eventTemplate) {\n <ng-container\n [ngTemplateOutlet]=\"eventTemplate\"\n [ngTemplateOutletContext]=\"eventTemplateCtx(e, p, s)\">\n </ng-container>\n } @else {\n <div class=\"ngx-event-title\">{{ e.title }}</div>\n <div class=\"ngx-event-time\">\n {{ toDisplayZone(e.start) | date:'HH:mm' }}\u2013{{ toDisplayZone(e.end) | date:'HH:mm' }}\n </div>\n }\n </div>\n }\n </div>\n }\n </div>\n </div>\n }\n\n </div>\n </div>\n\n</div>\n", styles: [":host{display:block;--ngx-bg: #ffffff;--ngx-surface: #ffffff;--ngx-muted: #f6f7f9;--ngx-border: rgba(16, 24, 40, .1);--ngx-border-soft: rgba(16, 24, 40, .06);--ngx-text: #101828;--ngx-text-muted: rgba(16, 24, 40, .6);--ngx-radius: 6px;--ngx-shadow: 0 10px 25px rgba(16, 24, 40, .06);--ngx-shadow-soft: 0 8px 18px rgba(16, 24, 40, .05);--ngx-event-bg: #eef4ff;--ngx-event-border: rgba(53, 122, 246, .25);--ngx-event-text: #0b1f44;--ngx-time-gutter-width: 72px;--ngx-header-height: 78px;--ngx-primary-title-height: 40px;--ngx-secondary-title-height: 45px;background:var(--ngx-bg);color:var(--ngx-text);--ngx-grid-gap: 5px;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-weight:400;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Inter,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"}.ngx-scheduler{display:grid;grid-template-rows:auto 1fr;gap:var(--ngx-grid-gap)}.ngx-toolbar{display:grid;grid-template-columns:auto 1fr auto;align-items:center;gap:12px;padding:10px 10px 2px}.ngx-toolbar-title{text-align:center;font-weight:650;font-size:14px;color:var(--ngx-text);letter-spacing:.2px}.ngx-toolbar-meta{font-size:12px;color:var(--ngx-text-muted);padding-right:6px}.ngx-toolbar-left{display:flex;gap:8px;align-items:center}.ngx-btn{height:34px;padding:0 10px;border-radius:12px;border:1px solid var(--ngx-border);background:#fff;color:var(--ngx-text);font-weight:600;font-size:12px;cursor:pointer;box-shadow:0 8px 14px #1018280f;transition:transform .12s ease,box-shadow .12s ease,background .12s ease}.ngx-btn:hover{transform:translateY(-1px);box-shadow:0 12px 18px #1018281a}.ngx-btn:active{transform:translateY(0);box-shadow:0 8px 14px #10182814}.ngx-btn--ghost{background:var(--ngx-muted)}.ngx-header{position:sticky;top:0;z-index:5;-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);gap:var(--ngx-grid-gap);display:grid;grid-template-columns:var(--ngx-time-gutter-width) 1fr;align-items:stretch;background:var(--ngx-bg)}.ngx-header .ngx-time-gutter{background:transparent}.ngx-primary-headers{display:grid;gap:var(--ngx-grid-gap)}.ngx-primary-header{border:1px solid var(--ngx-border);border-radius:var(--ngx-radius);overflow:hidden;background:var(--ngx-surface);box-shadow:var(--ngx-shadow-soft)}.ngx-primary-title-row{height:var(--ngx-primary-title-height);display:flex;align-items:center;padding:0 12px;font-weight:650;font-size:13px;letter-spacing:.2px;border-bottom:1px solid var(--ngx-border-soft);background:linear-gradient(to bottom,#fff,#fbfbfc)}.ngx-primary-title-row .ngx-primary-title{margin:auto;text-align:center}.ngx-secondary-header-row{height:var(--ngx-secondary-title-height);display:grid}.ngx-secondary-header{display:flex;align-items:center;padding:0 6px;font-size:12px;text-align:center;color:var(--ngx-text-muted);border-left:1px solid var(--ngx-border-soft);background:#fff}.ngx-secondary-header-title{margin:auto}.ngx-secondary-header:first-child{border-left:none}.ngx-body{display:grid;grid-template-columns:var(--ngx-time-gutter-width) 1fr;gap:10px;min-height:320px}.ngx-time-gutter{position:relative;-webkit-user-select:none;user-select:none}.ngx-hour-label{position:absolute;left:0;right:8px;transform:translateY(-50%);text-align:right;font-size:12px;color:var(--ngx-text-muted);pointer-events:none}.ngx-hour-label:first-child{transform:translateY(0);top:0!important}.ngx-hour-label:last-child{transform:translateY(-100%)}.ngx-grid{position:relative;display:grid;gap:var(--ngx-grid-gap)}.ngx-primary-col{border:1px solid var(--ngx-border);border-radius:var(--ngx-radius);overflow:hidden;background:var(--ngx-surface);box-shadow:var(--ngx-shadow)}.ngx-secondary-cols{display:grid;height:100%}.ngx-cell{position:relative;border-left:1px solid var(--ngx-border-soft);background:#fff;cursor:pointer;transition:background .12s ease}.ngx-cell .ngx-event{box-sizing:border-box}.ngx-cell:first-child{border-left:none}.ngx-cell:hover{background:#10182805}.ngx-lines{position:absolute;inset:0;pointer-events:none}.ngx-line{position:absolute;left:0;right:0;height:0;border-top:1px solid var(--ngx-border-soft);opacity:.75}.ngx-line--slot{opacity:.5}.ngx-line--half{opacity:.7;border-top-color:#10182817}.ngx-line--hour{opacity:.9;border-top-color:#1018281a}.is-hidden{display:none}.ngx-event{display:flex;flex-direction:column;gap:2px;touch-action:none;-webkit-user-select:none;user-select:none;overflow:hidden;position:absolute;min-width:0;margin:0;border-radius:4px;background:var(--ngx-event-bg);border:1px solid var(--ngx-event-border);color:var(--ngx-event-text);padding:2px 4px;box-sizing:border-box;box-shadow:0 10px 18px #10182814;cursor:pointer;transition:transform .12s ease,box-shadow .12s ease,filter .12s ease}.ngx-event:hover{transform:translateY(-1px);box-shadow:0 14px 22px #1018281f;filter:saturate(1.05)}.ngx-event:hover .ngx-resize{opacity:1}.ngx-event:active{transform:translateY(0);box-shadow:0 10px 18px #1018281a;cursor:grabbing}.ngx-event-title{font-weight:650;font-size:11px;line-height:1.2;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.ngx-event-time{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;margin-top:3px;font-size:10px;color:#0b1f44b8}.ngx-event-time,.ngx-toolbar-meta,.ngx-secondary-header{letter-spacing:.01em}.ngx-hour,.ngx-event-time{font-variant-numeric:tabular-nums}.ngx-body{overflow:auto;padding-bottom:4px;gap:var(--ngx-grid-gap)}.ngx-body::-webkit-scrollbar{width:10px;height:10px}.ngx-body::-webkit-scrollbar-thumb{background:#10182824;border-radius:10px;border:2px solid rgba(255,255,255,.9)}.ngx-body::-webkit-scrollbar-track{background:#1018280a;border-radius:10px}@media(max-width:900px){:host{--ngx-time-gutter-width: 58px}.ngx-primary-headers,.ngx-grid{display:grid;gap:10px}.ngx-primary-headers{padding-left:calc(var(--ngx-grid-gap) / 2);padding-right:calc(var(--ngx-grid-gap) / 2)}.ngx-event{left:6px;right:6px;border-radius:10px}}\n"] }]
506
506
  }], propDecorators: { startDate: [{
507
507
  type: Input
508
508
  }], resources: [{
@@ -527,8 +527,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImpor
527
527
  type: Input
528
528
  }], showToolbar: [{
529
529
  type: Input
530
- }], todayLabel: [{
531
- type: Input
532
530
  }], prevLabel: [{
533
531
  type: Input
534
532
  }], nextLabel: [{
@@ -545,6 +543,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImpor
545
543
  type: Input
546
544
  }], resourcesLabel: [{
547
545
  type: Input
546
+ }], todayLabel: [{
547
+ type: Input
548
548
  }], weekStartsOn: [{
549
549
  type: Input
550
550
  }], locale: [{
@@ -1 +1 @@
1
- {"version":3,"file":"ngx-resource-scheduler.mjs","sources":["../../../projects/ngx-resource-scheduler/src/lib/ngx-resource-scheduler.component.ts","../../../projects/ngx-resource-scheduler/src/lib/ngx-resource-scheduler.component.html","../../../projects/ngx-resource-scheduler/src/lib/types.ts","../../../projects/ngx-resource-scheduler/src/lib/ngx-resource-scheduler.module.ts","../../../projects/ngx-resource-scheduler/src/public-api.ts","../../../projects/ngx-resource-scheduler/src/ngx-resource-scheduler.ts"],"sourcesContent":["import {\n Component,\n ChangeDetectionStrategy,\n EventEmitter,\n HostBinding,\n Input,\n OnChanges,\n Output,\n SimpleChanges,\n TemplateRef,\n} from '@angular/core';\n\nimport {\n PrimaryAxis,\n SchedulerEvent,\n SchedulerEventClick,\n SchedulerRangeChange,\n SchedulerResource,\n SchedulerSlotClick,\n SchedulerView,\n} from './types';\n\nimport { toZonedTime, fromZonedTime } from 'date-fns-tz';\nimport { PositionedEvent } from './internal/types-internal';\n\ntype PrimaryColumn =\n | { kind: 'day'; day: Date; key: string; title: string }\n | { kind: 'resource'; resource: SchedulerResource; key: string; title: string };\n\ntype SecondaryColumn =\n | { kind: 'day'; day: Date; key: string; title: string }\n | { kind: 'resource'; resource: SchedulerResource; key: string; title: string };\n\nexport interface SchedulerEventTemplateContext {\n $implicit: PositionedEvent; // allows: let-event\n event: PositionedEvent;\n startZoned: Date;\n endZoned: Date;\n resourceId: string;\n day: Date;\n}\n\n@Component({\n selector: 'ngx-resource-scheduler',\n templateUrl: './ngx-resource-scheduler.component.html',\n styleUrls: ['./ngx-resource-scheduler.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n standalone: false\n})\nexport class NgxResourceSchedulerComponent implements OnChanges {\n // --- REQUIRED ---\n @Input() startDate!: Date; // first visible day (00:00 recommended)\n @Input() resources: SchedulerResource[] = [];\n @Input() events: SchedulerEvent[] = [];\n\n // --- FLEXIBILITY ---\n @Input() nDays: number = 7; // clamp [1..7]\n @Input() primaryAxis: PrimaryAxis = 'days';\n\n // --- TIME WINDOW (vertical) ---\n @Input() dayStart: string = '08:00'; // HH:mm\n @Input() dayEnd: string = '20:00'; // HH:mm\n @Input() slotDuration: string = '00:30'; // HH:mm (grid resolution)\n @Input() snapToSlot: boolean = true;\n\n @Input() showSlotLines: boolean = true;\n @Input() slotLineStyle: 'slot' | 'hour' | 'both' = 'slot';\n\n // NAVIGATION\n @Input() showToolbar: boolean = true;\n @Input() todayLabel: string = 'Today';\n @Input() prevLabel: string = '‹';\n @Input() nextLabel: string = '›';\n private lastRangeKey: string | null = null; \n\n // CUSTOM STYLING\n @Input() eventTemplate?: TemplateRef<SchedulerEventTemplateContext>;\n @Input() eventClass?: (e: PositionedEvent) => string | string[] | Set<string> | { [klass: string]: any };\n @Input() eventStyle?: (e: PositionedEvent) => { [k: string]: any };\n\n // i18n\n @Input() showDaysResourcesLabel: boolean = true;\n @Input() daysLabel: string = 'days';\n @Input() resourcesLabel: string = 'resources';\n\n // --- MISC ---\n @Input() weekStartsOn: 0 | 1 | 2 | 3 | 4 | 5 | 6 = 1;\n @Input() locale?: string;\n @Input() timezone?: 'local' | 'UTC' | string; // IANA Time Zone Identifier\n @Input() readonly: boolean = false;\n\n // --- OUTPUTS ---\n @Output() slotClick = new EventEmitter<SchedulerSlotClick>();\n @Output() eventClick = new EventEmitter<SchedulerEventClick>();\n @Output() eventChange = new EventEmitter<any>();\n @Output() rangeChange = new EventEmitter<SchedulerRangeChange>();\n @Output() startDateChange = new EventEmitter<Date>();\n\n // --- INTERNAL LAYOUT CONSTANTS ---\n readonly pxPerMinute = 1; // 60px per hour\n\n // --- COMPUTED ---\n visibleDays: Date[] = [];\n primaryColumns: PrimaryColumn[] = [];\n secondaryColumns: SecondaryColumn[] = [];\n\n dayStartMinutes = 8 * 60;\n dayEndMinutes = 20 * 60;\n slotMinutes = 30;\n\n ngOnChanges(_: SimpleChanges): void {\n this.recompute();\n }\n\n // ---------- PUBLIC METHODS ---------\n\n /** Navigate by one \"page\" (nDays) backward */\n public prev(): void {\n this.navigatePrev();\n }\n\n /** Navigate by one \"page\" (nDays) forward */\n public next(): void {\n this.navigateNext();\n }\n\n /** Go to today (start of day) */\n public today(): void {\n this.navigateToday();\n }\n\n /** Programmatically set the visible start date */\n public goToDate(d: Date): void {\n this.setStartDate(this.startOfDay(d));\n }\n\n // ---------- TEMPLATE HELPERS ----------\n\n get timelineHeightPx(): number {\n return Math.max(0, (this.dayEndMinutes - this.dayStartMinutes) * this.pxPerMinute);\n }\n\n get hourLabels(): number[] {\n const startH = Math.floor(this.dayStartMinutes / 60);\n const endH = Math.floor(this.dayEndMinutes / 60);\n\n const hours: number[] = [];\n for (let h = startH; h <= endH; h++) hours.push(h);\n return hours;\n }\n\n get slotLines(): Array<{ top: number; isHalfHour: boolean }> {\n if (!this.showSlotLines) return [];\n\n const spanMin = this.dayEndMinutes - this.dayStartMinutes;\n if (spanMin <= 0 || this.slotMinutes <= 0) return [];\n\n const lines: Array<{ top: number; isHalfHour: boolean }> = [];\n for (let m = 0; m <= spanMin; m += this.slotMinutes) {\n const absoluteMin = this.dayStartMinutes + m;\n\n // true at hh:30 exactly (e.g., 08:30, 09:30, ...)\n const isHalfHour = absoluteMin % 60 === 30;\n\n lines.push({\n top: m * this.pxPerMinute,\n isHalfHour,\n });\n }\n return lines;\n }\n\n get hourLineOffsetsPx(): number[] {\n const spanMin = this.dayEndMinutes - this.dayStartMinutes;\n if (spanMin <= 0) return [];\n\n const offsets: number[] = [];\n const firstHourMin = Math.ceil(this.dayStartMinutes / 60) * 60;\n\n for (let m = firstHourMin; m <= this.dayEndMinutes; m += 60) {\n offsets.push((m - this.dayStartMinutes) * this.pxPerMinute);\n }\n // Also include the top edge at 0 for a clean line\n offsets.unshift(0);\n\n return offsets;\n }\n\n get rangeTitle(): string {\n if (!this.visibleDays.length) return '';\n\n const start = this.visibleDays[0];\n const end = this.visibleDays[this.visibleDays.length - 1];\n\n const sameMonth = start.getFullYear() === end.getFullYear() && start.getMonth() === end.getMonth();\n const opts: Intl.DateTimeFormatOptions = { month: 'short', day: 'numeric' };\n\n if (this.visibleDays.length === 1) {\n return start.toLocaleDateString(this.locale, { weekday: 'short', ...opts });\n }\n\n if (sameMonth) {\n const month = start.toLocaleDateString(this.locale, { month: 'short' });\n return `${month} ${start.getDate()}–${end.getDate()}`;\n }\n\n return `${start.toLocaleDateString(this.locale, opts)} – ${end.toLocaleDateString(this.locale, opts)}`;\n }\n\n /**\n * Returns events that intersect a given (day, resource) cell.\n */\n eventsForCell(day: Date, resourceId: string): PositionedEvent[] {\n const { startUtc, endUtc } = this.windowBoundsUtc(day);\n\n const list = this.events\n .filter((e) =>\n e.resourceId === resourceId &&\n e.start < endUtc &&\n e.end > startUtc\n )\n .sort((a, b) => a.start.getTime() - b.start.getTime());\n\n return this.layoutOverlaps(list);\n }\n\n /**\n * CSS positioning for an event within a day cell.\n */\n styleForEvent(e: PositionedEvent, day: Date): { [k: string]: string } {\n const { startUtc: windowStartUtc, endUtc: windowEndUtc } = this.windowBoundsUtc(day);\n\n // If event doesn't intersect visible window, don't render it\n if (e.end <= windowStartUtc || e.start >= windowEndUtc) {\n return { display: 'none' };\n }\n\n const start = new Date(Math.max(e.start.getTime(), windowStartUtc.getTime()));\n const end = new Date(Math.min(e.end.getTime(), windowEndUtc.getTime()));\n\n const topMin = (start.getTime() - windowStartUtc.getTime()) / 60000;\n const durMin = Math.max(10, (end.getTime() - start.getTime()) / 60000);\n\n // overlap columns (same as you already have)\n const gapPx = 6;\n const cols = Math.max(1, e._cols);\n const col = Math.max(0, e._col);\n\n const widthExpr = `calc(${100 / cols}% - ${gapPx}px)`;\n const leftExpr = `calc(${(100 * col) / cols}% + ${gapPx / 2}px)`;\n\n return {\n top: `${topMin * this.pxPerMinute}px`,\n height: `${durMin * this.pxPerMinute}px`,\n width: widthExpr,\n left: leftExpr,\n right: 'auto',\n };\n }\n\n onEventClick(e: SchedulerEvent, mouse: MouseEvent) {\n this.eventClick.emit({ event: e, nativeEvent: mouse });\n }\n\n onCellClick(day: Date, resourceId: string, mouse: MouseEvent) {\n if (this.readonly) return;\n\n const clickedDate = this.computeClickedTime(day, mouse);\n const primaryKey = this.primaryAxis === 'days' ? this.dayKey(day) : resourceId;\n const secondaryKey = this.primaryAxis === 'days' ? resourceId : this.dayKey(day);\n\n this.slotClick.emit({\n date: clickedDate,\n day: this.startOfDay(day),\n resourceId,\n primaryAxis: this.primaryAxis,\n primaryKey,\n secondaryKey,\n });\n }\n\n cellDayKey(p:any,s:any): string {\n return this.dayKey(this.resolveCellDay(p,s));\n }\n\n cellResourceId(p:any,s:any): string {\n return this.resolveCellResourceId(p,s);\n }\n\n resolveCellResourceId(p: any, s: any): string {\n return this.primaryAxis === 'days' ? s.resource.id : p.resource.id;\n }\n\n resolveCellResource(p: any, s: any): SchedulerResource {\n return this.primaryAxis === 'days' ? s.resource : p.resource;\n }\n\n cellEvents(p: any, s: any): PositionedEvent[] {\n const day = this.resolveCellDay(p, s);\n const resourceId = this.resolveCellResourceId(p, s);\n return this.eventsForCell(day, resourceId); // now PositionedEvent[]\n }\n\n cellClick(p: any, s: any, ev: MouseEvent) {\n const day = this.resolveCellDay(p, s);\n const resourceId = this.resolveCellResourceId(p, s);\n this.onCellClick(day, resourceId, ev);\n }\n\n getEventLayoutStyle(e: PositionedEvent, p: any, s: any) {\n const day = this.resolveCellDay(p, s);\n\n const layout = this.styleForEvent(e, day); // contains top/height/left/width\n const userStyle = this.eventStyle ? this.eventStyle(e) : null;\n\n // IMPORTANT: layout must win so users can’t break positioning\n return userStyle ? { ...userStyle, ...layout } : layout;\n }\n\n // ---------- INTERNAL COMPUTATION ----------\n\n private windowBoundsUtc(day: Date): { startUtc: Date; endUtc: Date } {\n const base = this.startOfDay(day);\n\n // wall-clock dates for \"day at HH:mm\" (fields matter)\n const wallStart = this.setTime(base, this.dayStartMinutes);\n const wallEnd = this.setTime(base, this.dayEndMinutes);\n\n if (!this.timezone || this.timezone === 'local') {\n // interpreted as device local instants\n return { startUtc: wallStart, endUtc: wallEnd };\n }\n\n if (this.timezone === 'UTC') {\n // build true UTC instants for the wall clock\n const y = base.getFullYear();\n const m = base.getMonth();\n const d = base.getDate();\n\n const sH = Math.floor(this.dayStartMinutes / 60);\n const sM = this.dayStartMinutes % 60;\n const eH = Math.floor(this.dayEndMinutes / 60);\n const eM = this.dayEndMinutes % 60;\n\n return {\n startUtc: new Date(Date.UTC(y, m, d, sH, sM, 0, 0)),\n endUtc: new Date(Date.UTC(y, m, d, eH, eM, 0, 0)),\n };\n }\n\n // IANA timezone: wall-clock in zone -> UTC instant\n return {\n startUtc: fromZonedTime(wallStart, this.timezone),\n endUtc: fromZonedTime(wallEnd, this.timezone),\n };\n }\n\n private assignColumns(cluster: SchedulerEvent[]): PositionedEvent[] {\n // columnsEndTimes[col] = endTime of last event in that col\n const columnsEndTimes: number[] = [];\n const out: PositionedEvent[] = [];\n\n for (const e of cluster) {\n const s = e.start.getTime();\n const en = e.end.getTime();\n\n // Find first available column\n let col = 0;\n for (; col < columnsEndTimes.length; col++) {\n if (s >= columnsEndTimes[col]) break;\n }\n\n if (col === columnsEndTimes.length) columnsEndTimes.push(en);\n else columnsEndTimes[col] = en;\n\n out.push({ ...e, _col: col, _cols: 0 });\n }\n\n const totalCols = columnsEndTimes.length;\n // write total columns for all events in this cluster\n for (const pe of out) pe._cols = totalCols;\n\n return out;\n }\n\n private emitRangeIfChanged(payload: SchedulerRangeChange) {\n const key = `${payload.start.toISOString()}|${payload.end.toISOString()}|${payload.primaryAxis}|${payload.days}`;\n if (key === this.lastRangeKey) return;\n this.lastRangeKey = key;\n queueMicrotask(() => this.rangeChange.emit(payload));\n }\n\n private setStartDate(d: Date) {\n this.startDate = d;\n this.recompute();\n this.startDateChange.emit(d);\n }\n\n // Computes clicked time from y offset within a cell (very handy for creating events)\n private computeClickedTime(day: Date, mouse: MouseEvent): Date {\n const target = mouse.currentTarget as HTMLElement | null;\n if (!target || typeof (target as any).getBoundingClientRect !== 'function') {\n return this.setTime(this.startOfDay(day), this.dayStartMinutes);\n }\n\n const rect = target.getBoundingClientRect();\n const y = mouse.clientY - rect.top;\n\n const minutesFromStart = Math.max(0, Math.min(this.dayEndMinutes - this.dayStartMinutes, y / this.pxPerMinute));\n let snapped = minutesFromStart;\n\n if (this.snapToSlot && this.slotMinutes > 0) {\n snapped = Math.round(minutesFromStart / this.slotMinutes) * this.slotMinutes;\n }\n\n const totalMinutes = this.dayStartMinutes + snapped;\n return this.setTime(this.startOfDay(day), totalMinutes);\n }\n\n private layoutOverlaps(events: SchedulerEvent[]): PositionedEvent[] {\n // Sweep through events, grouping overlapping \"clusters\"\n const positioned: PositionedEvent[] = [];\n\n let cluster: SchedulerEvent[] = [];\n let clusterEnd = -Infinity;\n\n const flushCluster = () => {\n if (cluster.length === 0) return;\n positioned.push(...this.assignColumns(cluster));\n cluster = [];\n clusterEnd = -Infinity;\n };\n\n for (const e of events) {\n const s = e.start.getTime();\n const en = e.end.getTime();\n\n if (cluster.length === 0) {\n cluster = [e];\n clusterEnd = en;\n continue;\n }\n\n // If this event starts after cluster ends, it's a new cluster\n if (s >= clusterEnd) {\n flushCluster();\n cluster = [e];\n clusterEnd = en;\n continue;\n }\n\n // Still overlapping cluster\n cluster.push(e);\n if (en > clusterEnd) clusterEnd = en;\n }\n\n flushCluster();\n return positioned;\n }\n \n private resolveCellDay(p: any, s: any): Date {\n return this.primaryAxis === 'days' ? p.day : s.day;\n }\n\n private recompute() {\n // Clamp days\n const d = Math.max(1, Math.min(7, Math.floor(this.nDays || 7)));\n\n // Parse times\n this.dayStartMinutes = this.parseHmToMinutes(this.dayStart, 8 * 60);\n this.dayEndMinutes = this.parseHmToMinutes(this.dayEnd, 20 * 60);\n if (this.dayEndMinutes <= this.dayStartMinutes) {\n // fallback to a sane window\n this.dayEndMinutes = this.dayStartMinutes + 10 * 60;\n }\n\n this.slotMinutes = this.parseHmToMinutes(this.slotDuration, 30);\n if (this.slotMinutes <= 0) this.slotMinutes = 30;\n\n // Visible days\n const start = this.startOfDay(this.startDate ?? new Date());\n this.visibleDays = Array.from({ length: d }, (_, i) => this.addDays(start, i));\n\n // Columns\n if (this.primaryAxis === 'days') {\n this.primaryColumns = this.visibleDays.map((day) => ({\n kind: 'day',\n day,\n key: this.dayKey(day),\n title: this.formatDay(day),\n }));\n\n this.secondaryColumns = this.resources.map((r) => ({\n kind: 'resource',\n resource: r,\n key: r.id,\n title: r.title,\n }));\n } else {\n this.primaryColumns = this.resources.map((r) => ({\n kind: 'resource',\n resource: r,\n key: r.id,\n title: r.title,\n }));\n\n this.secondaryColumns = this.visibleDays.map((day) => ({\n kind: 'day',\n day,\n key: this.dayKey(day),\n title: this.formatDay(day),\n }));\n }\n\n // Emit range\n const rangeStart = start;\n const rangeEnd = this.addDays(start, d);\n const view: SchedulerView = 'custom-range';\n\n\n this.emitRangeIfChanged({\n start: rangeStart,\n end: rangeEnd,\n days: d,\n primaryAxis: this.primaryAxis,\n view,\n });\n }\n\n // ------------- NAVIGATION -------------\n\n navigatePrev() {\n const next = this.addDays(this.startOfDay(this.startDate ?? new Date()), -this.normalizedDays());\n this.setStartDate(next);\n }\n\n navigateNext() {\n const next = this.addDays(this.startOfDay(this.startDate ?? new Date()), this.normalizedDays());\n this.setStartDate(next);\n }\n\n navigateToday() {\n const today = this.startOfDay(new Date());\n this.setStartDate(today);\n }\n\n // ---------- DATE/TIME UTILS ----------\n\n formatHour(h: number): string {\n return `${String(h).padStart(2, '0')}:00`;\n }\n\n hourTopPx(h: number): number {\n const minutes = (h * 60) - this.dayStartMinutes;\n return minutes * this.pxPerMinute;\n }\n\n isIanaTz(): boolean {\n return !!this.timezone && this.timezone !== 'local' && this.timezone !== 'UTC';\n }\n\n toDisplayZone(dUtc: Date): Date {\n if (this.timezone === 'UTC') return new Date(dUtc);\n if (this.timezone === 'local' || !this.timezone) return new Date(dUtc);\n\n // Converts a UTC instant to a Date whose wall-clock matches the IANA zone\n return toZonedTime(dUtc, this.timezone);\n }\n\n fromDisplayZone(dZoned: Date): Date {\n if (this.timezone === 'UTC') return new Date(dZoned);\n if (this.timezone === 'local' || !this.timezone) return new Date(dZoned);\n\n // Converts a wall-clock-in-zone Date back to a UTC instant\n return fromZonedTime(dZoned, this.timezone);\n }\n\n private parseHmToMinutes(hm: string, fallback: number): number {\n const m = /^(\\d{1,2}):(\\d{2})$/.exec((hm || '').trim());\n if (!m) return fallback;\n const hh = Number(m[1]);\n const mm = Number(m[2]);\n if (!Number.isFinite(hh) || !Number.isFinite(mm)) return fallback;\n return Math.max(0, Math.min(24 * 60, hh * 60 + mm));\n }\n\n private startOfDay(d: Date): Date {\n const x = new Date(d);\n x.setHours(0, 0, 0, 0);\n return x;\n }\n\n private addDays(d: Date, n: number): Date {\n const x = new Date(d);\n x.setDate(x.getDate() + n);\n return x;\n }\n\n private setTime(day: Date, minutes: number): Date {\n const x = new Date(day);\n const hh = Math.floor(minutes / 60);\n const mm = minutes % 60;\n x.setHours(hh, mm, 0, 0);\n return x;\n }\n\n private dayKey(d: Date): string {\n // Use YYYY-MM-DD (stable key) instead of full ISO with timezone offsets\n const y = d.getFullYear();\n const m = String(d.getMonth() + 1).padStart(2, '0');\n const day = String(d.getDate()).padStart(2, '0');\n return `${y}-${m}-${day}`;\n }\n\n private formatDay(d: Date): string {\n return d.toLocaleDateString(this.locale, { weekday: 'short', month: 'short', day: 'numeric' });\n }\n\n private normalizedDays(): number {\n const v = Math.floor(this.nDays ?? 7);\n return Math.max(1, Math.min(7, v));\n }\n\n // ------------- EVENT TOOLTIP -------------\n\n eventTooltip(e: SchedulerEvent): string {\n const start = this.toDisplayZone(e.start);\n const end = this.toDisplayZone(e.end);\n const startStr = start.toLocaleTimeString(this.locale, { hour: '2-digit', minute: '2-digit' });\n const endStr = end.toLocaleTimeString(this.locale, { hour: '2-digit', minute: '2-digit' });\n\n // keep it short so the native tooltip looks good\n return `${e.title}\\n${startStr}–${endStr}`;\n }\n\n // ------------- CUSTOM EVENT STYLING -----------\n\n eventTemplateCtx(e: PositionedEvent, p: any, s: any): SchedulerEventTemplateContext {\n const day = this.resolveCellDay(p, s);\n const resourceId = this.resolveCellResourceId(p, s);\n return {\n $implicit: e,\n event: e,\n startZoned: this.toDisplayZone(e.start),\n endZoned: this.toDisplayZone(e.end),\n resourceId,\n day,\n };\n }\n\n // ------------- TRACK BYS -------------\n \n trackPrimary = (_: number, c: PrimaryColumn) => c.key;\n trackSecondary = (_: number, c: SecondaryColumn) => c.key;\n trackEvent = (_: number, e: SchedulerEvent) => e.id;\n}\n","<div class=\"ngx-scheduler\">\n\n <!-- Toolbar -->\n @if (showToolbar) {\n <div class=\"ngx-toolbar\">\n <div class=\"ngx-toolbar-left\">\n <button type=\"button\" class=\"ngx-btn\" (click)=\"navigatePrev()\">{{ prevLabel }}</button>\n <button type=\"button\" class=\"ngx-btn ngx-btn--ghost\" (click)=\"navigateToday()\">{{ todayLabel }}</button>\n <button type=\"button\" class=\"ngx-btn\" (click)=\"navigateNext()\">{{ nextLabel }}</button>\n </div>\n <div class=\"ngx-toolbar-title\">\n {{ rangeTitle }}\n </div>\n <div class=\"ngx-toolbar-right\">\n @if (showDaysResourcesLabel) {\n <span class=\"ngx-toolbar-meta\">\n {{ primaryAxis === 'days' ? (visibleDays.length + ' ' + daysLabel) : (resources.length + ' ' + resourcesLabel ) }}\n </span>\n }\n @if (!showDaysResourcesLabel) {\n <span class=\"ngx-toolbar-meta\">&nbsp;</span>\n }\n </div>\n </div>\n }\n\n <!-- Header row -->\n <div class=\"ngx-header\">\n <div class=\"ngx-time-gutter\"></div>\n\n <div class=\"ngx-primary-headers\" [style.gridTemplateColumns]=\"'repeat(' + primaryColumns.length + ', minmax(0, 1fr))'\">\n @for (p of primaryColumns; track trackPrimary($index, p)) {\n <div class=\"ngx-primary-header\">\n <div class=\"ngx-primary-title-row\">\n <div class=\"ngx-primary-title\">{{ p.title }}</div>\n </div>\n <div class=\"ngx-secondary-header-row\" [style.gridTemplateColumns]=\"'repeat(' + secondaryColumns.length + ', minmax(0, 1fr))'\">\n @for (s of secondaryColumns; track trackSecondary($index, s)) {\n <div class=\"ngx-secondary-header\">\n <span class=\"ngx-secondary-header-title\">{{ s.title }}</span>\n </div>\n }\n </div>\n </div>\n }\n </div>\n </div>\n\n <!-- Body -->\n <div class=\"ngx-body\">\n <!-- time gutter -->\n <div class=\"ngx-time-gutter\" [style.height.px]=\"timelineHeightPx\">\n @for (h of hourLabels; track h) {\n <div\n class=\"ngx-hour-label\"\n [style.top.px]=\"hourTopPx(h)\">\n {{ formatHour(h) }}\n </div>\n }\n </div>\n\n\n <!-- grid -->\n <div class=\"ngx-grid\"\n [style.gridTemplateColumns]=\"'repeat(' + primaryColumns.length + ', minmax(0, 1fr))'\"\n [style.height.px]=\"timelineHeightPx\">\n\n @for (p of primaryColumns; track trackPrimary($index, p)) {\n <div class=\"ngx-primary-col\">\n <div class=\"ngx-secondary-cols\"\n [style.gridTemplateColumns]=\"'repeat(' + secondaryColumns.length + ', minmax(0, 1fr))'\"\n [style.height.px]=\"timelineHeightPx\">\n <!-- Each cell is (day, resource) regardless of axis order -->\n @for (s of secondaryColumns; track trackSecondary($index, s)) {\n <div class=\"ngx-cell\"\n #cellEl\n [style.height.px]=\"timelineHeightPx\"\n (click)=\"cellClick(p, s, $event)\"\n [attr.data-day]=\"cellDayKey(p,s)\"\n [attr.data-resource]=\"cellResourceId(p,s)\">\n <!-- grid lines -->\n <div class=\"ngx-lines\" aria-hidden=\"true\">\n <!-- slot lines -->\n @for (line of slotLines; track line) {\n <div\n class=\"ngx-line ngx-line--slot\"\n [style.top.px]=\"line.top\"\n [class.ngx-line--half]=\"line.isHalfHour\"\n [class.is-hidden]=\"slotLineStyle === 'hour'\">\n </div>\n }\n <!-- hour lines -->\n @for (top of hourLineOffsetsPx; track top) {\n <div\n class=\"ngx-line ngx-line--hour\"\n [style.top.px]=\"top\"\n [class.is-hidden]=\"slotLineStyle === 'slot'\">\n </div>\n }\n </div>\n <!-- events -->\n <!-- ngClass and 2nd ngStyle are only used when user passes custom class/style -->\n @for (e of cellEvents(p, s); track trackEvent($index, e)) {\n <div class=\"ngx-event\"\n [ngStyle]=\"getEventLayoutStyle(e, p, s)\"\n (click)=\"onEventClick(e, $event); $event.stopPropagation()\"\n [ngClass]=\"eventClass ? eventClass(e) : null\"\n [attr.title]=\"eventTooltip(e)\">\n @if (eventTemplate) {\n <ng-container\n [ngTemplateOutlet]=\"eventTemplate\"\n [ngTemplateOutletContext]=\"eventTemplateCtx(e, p, s)\">\n </ng-container>\n } @else {\n <div class=\"ngx-event-title\">{{ e.title }}</div>\n <div class=\"ngx-event-time\">\n {{ toDisplayZone(e.start) | date:'HH:mm' }}–{{ toDisplayZone(e.end) | date:'HH:mm' }}\n </div>\n }\n </div>\n }\n </div>\n }\n </div>\n </div>\n }\n\n </div>\n </div>\n\n</div>\n","/**\n * Public types for ngx-resource-scheduler\n * Keep this file framework-agnostic (no Angular imports).\n */\n\n/** Which dimension is the top-level column grouping. */\nexport type PrimaryAxis = 'days' | 'resources';\n\n/** v1 view modes (future-proofed). */\nexport type SchedulerView = 'custom-range'; // controlled by startDate + days\n\n/** Resource shown in the scheduler. */\nexport interface SchedulerResource {\n id: string;\n title: string;\n\n /** Optional arbitrary metadata for the consumer. */\n data?: unknown;\n\n /** Optional CSS class(es) applied to the resource header/cells. */\n className?: string | string[];\n}\n\n/** Event rendered in the scheduler. */\nexport interface SchedulerEvent {\n id: string;\n title: string;\n\n /** Inclusive start date-time. */\n start: Date;\n\n /** Exclusive end date-time (recommended). */\n end: Date;\n\n /** Resource column this event belongs to. */\n resourceId: string;\n\n /** Optional styling helpers. */\n color?: string;\n className?: string | string[];\n\n /** Optional arbitrary metadata for the consumer. */\n data?: unknown;\n}\n\n/** Emitted when the user clicks an empty slot/cell in the scheduler. */\nexport interface SchedulerSlotClick {\n /** Clicked date-time (snapped if snapToSlot is enabled). */\n date: Date;\n\n /** The day bucket for the clicked cell (00:00 local/zone). */\n day: Date;\n\n /** Resource for the clicked cell. */\n resourceId: string;\n\n /** Layout info for consumers building custom UI around the scheduler. */\n primaryAxis: PrimaryAxis;\n\n /**\n * Identifies which primary column group was clicked.\n * - if primaryAxis === 'days': ISO date string of `day`\n * - if primaryAxis === 'resources': `resourceId`\n */\n primaryKey: string;\n\n /**\n * Identifies which nested column group was clicked.\n * - if primaryAxis === 'days': `resourceId`\n * - if primaryAxis === 'resources': ISO date string of `day`\n */\n secondaryKey: string;\n}\n\n/** Emitted when an event element is clicked. */\nexport interface SchedulerEventClick {\n event: SchedulerEvent;\n nativeEvent: MouseEvent;\n}\n\n/** Emitted when the visible time range changes (startDate/days/view). */\nexport interface SchedulerRangeChange {\n /** Inclusive start of visible range. */\n start: Date;\n\n /** Exclusive end of visible range. */\n end: Date;\n\n /** Number of visible days (1..7). */\n days: number;\n\n /** The primary axis currently in use. */\n primaryAxis: PrimaryAxis;\n\n /** Current view identifier (v1 uses custom-range). */\n view: SchedulerView;\n}\n\n/** Optional simple renderer hooks (string return keeps it light for v1). */\nexport type EventRenderer = (args: { event: SchedulerEvent }) => string;\n\nexport type HeaderRenderer =\n (args: { type: 'day' | 'resource'; day?: Date; resource?: SchedulerResource }) => string;\n","import { NgModule } from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport { NgxResourceSchedulerComponent } from './ngx-resource-scheduler.component';\n\n@NgModule({\n imports: [CommonModule],\n declarations: [NgxResourceSchedulerComponent],\n exports: [NgxResourceSchedulerComponent],\n})\nexport class NgxResourceSchedulerModule {}\n","/*\n * Public API Surface of ngx-resource-scheduler\n */\n\nexport * from './lib/ngx-resource-scheduler.component';\nexport * from './lib/types';\nexport * from './lib/ngx-resource-scheduler.module';\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":"ngx-resource-scheduler.mjs","sources":["../../../projects/ngx-resource-scheduler/src/lib/ngx-resource-scheduler.component.ts","../../../projects/ngx-resource-scheduler/src/lib/ngx-resource-scheduler.component.html","../../../projects/ngx-resource-scheduler/src/lib/types.ts","../../../projects/ngx-resource-scheduler/src/lib/ngx-resource-scheduler.module.ts","../../../projects/ngx-resource-scheduler/src/public-api.ts","../../../projects/ngx-resource-scheduler/src/ngx-resource-scheduler.ts"],"sourcesContent":["import {\n Component,\n ChangeDetectionStrategy,\n EventEmitter,\n Input,\n OnChanges,\n Output,\n SimpleChanges,\n TemplateRef,\n} from '@angular/core';\n\nimport {\n PrimaryAxis,\n SchedulerEvent,\n SchedulerEventClick,\n SchedulerRangeChange,\n SchedulerResource,\n SchedulerSlotClick,\n SchedulerView,\n} from './types';\n\nimport { toZonedTime, fromZonedTime } from 'date-fns-tz';\nimport { PositionedEvent } from './internal/types-internal';\n\ntype PrimaryColumn =\n | { kind: 'day'; day: Date; key: string; title: string }\n | { kind: 'resource'; resource: SchedulerResource; key: string; title: string };\n\ntype SecondaryColumn =\n | { kind: 'day'; day: Date; key: string; title: string }\n | { kind: 'resource'; resource: SchedulerResource; key: string; title: string };\n\nexport interface SchedulerEventTemplateContext {\n $implicit: PositionedEvent; // allows: let-event\n event: PositionedEvent;\n startZoned: Date;\n endZoned: Date;\n resourceId: string;\n day: Date;\n}\n\n@Component({\n selector: 'ngx-resource-scheduler',\n templateUrl: './ngx-resource-scheduler.component.html',\n styleUrls: ['./ngx-resource-scheduler.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n standalone: false\n})\nexport class NgxResourceSchedulerComponent implements OnChanges {\n // --- REQUIRED ---\n @Input() startDate!: Date; // first visible day (00:00 recommended)\n @Input() resources: SchedulerResource[] = [];\n @Input() events: SchedulerEvent[] = [];\n\n // --- FLEXIBILITY ---\n @Input() nDays: number = 7; // clamp [1..7]\n @Input() primaryAxis: PrimaryAxis = 'days';\n\n // --- TIME WINDOW (vertical) ---\n @Input() dayStart: string = '08:00'; // HH:mm\n @Input() dayEnd: string = '20:00'; // HH:mm\n @Input() slotDuration: string = '00:30'; // HH:mm (grid resolution)\n @Input() snapToSlot: boolean = true;\n\n @Input() showSlotLines: boolean = true;\n @Input() slotLineStyle: 'slot' | 'hour' | 'both' = 'slot';\n\n // NAVIGATION\n @Input() showToolbar: boolean = true;\n @Input() prevLabel: string = '‹';\n @Input() nextLabel: string = '›';\n private lastRangeKey: string | null = null; \n\n // CUSTOM STYLING\n @Input() eventTemplate?: TemplateRef<SchedulerEventTemplateContext>;\n @Input() eventClass?: (e: PositionedEvent) => string | string[] | Set<string> | { [klass: string]: any };\n @Input() eventStyle?: (e: PositionedEvent) => { [k: string]: any };\n\n // i18n\n @Input() showDaysResourcesLabel: boolean = true;\n @Input() daysLabel: string = 'days';\n @Input() resourcesLabel: string = 'resources';\n @Input() todayLabel: string = 'Today';\n\n // --- MISC ---\n @Input() weekStartsOn: 0 | 1 | 2 | 3 | 4 | 5 | 6 = 1;\n @Input() locale?: string;\n @Input() timezone?: 'local' | 'UTC' | string; // IANA Time Zone Identifier\n @Input() readonly: boolean = false;\n\n // --- OUTPUTS ---\n @Output() slotClick = new EventEmitter<SchedulerSlotClick>();\n @Output() eventClick = new EventEmitter<SchedulerEventClick>();\n @Output() eventChange = new EventEmitter<any>();\n @Output() rangeChange = new EventEmitter<SchedulerRangeChange>();\n @Output() startDateChange = new EventEmitter<Date>();\n\n // --- INTERNAL LAYOUT CONSTANTS ---\n readonly pxPerMinute = 1; // 60px per hour\n\n // --- COMPUTED ---\n visibleDays: Date[] = [];\n primaryColumns: PrimaryColumn[] = [];\n secondaryColumns: SecondaryColumn[] = [];\n\n dayStartMinutes = 8 * 60;\n dayEndMinutes = 20 * 60;\n slotMinutes = 30;\n\n ngOnChanges(_: SimpleChanges): void {\n this.recompute();\n }\n\n // ---------- PUBLIC METHODS ---------\n\n /** Navigate by one \"page\" (nDays) backward */\n public prev(): void {\n this.navigatePrev();\n }\n\n /** Navigate by one \"page\" (nDays) forward */\n public next(): void {\n this.navigateNext();\n }\n\n /** Go to today (start of day) */\n public today(): void {\n this.navigateToday();\n }\n\n /** Programmatically set the visible start date */\n public goToDate(d: Date): void {\n this.setStartDate(this.startOfDay(d));\n }\n\n // ---------- TEMPLATE HELPERS ----------\n\n get timelineHeightPx(): number {\n return Math.max(0, (this.dayEndMinutes - this.dayStartMinutes) * this.pxPerMinute);\n }\n\n get hourLabels(): number[] {\n const startH = Math.floor(this.dayStartMinutes / 60);\n const endH = Math.floor(this.dayEndMinutes / 60);\n\n const hours: number[] = [];\n for (let h = startH; h <= endH; h++) hours.push(h);\n return hours;\n }\n\n get slotLines(): Array<{ top: number; isHalfHour: boolean }> {\n if (!this.showSlotLines) return [];\n\n const spanMin = this.dayEndMinutes - this.dayStartMinutes;\n if (spanMin <= 0 || this.slotMinutes <= 0) return [];\n\n const lines: Array<{ top: number; isHalfHour: boolean }> = [];\n for (let m = 0; m <= spanMin; m += this.slotMinutes) {\n const absoluteMin = this.dayStartMinutes + m;\n\n // true at hh:30 exactly (e.g., 08:30, 09:30, ...)\n const isHalfHour = absoluteMin % 60 === 30;\n\n lines.push({\n top: m * this.pxPerMinute,\n isHalfHour,\n });\n }\n return lines;\n }\n\n get hourLineOffsetsPx(): number[] {\n const spanMin = this.dayEndMinutes - this.dayStartMinutes;\n if (spanMin <= 0) return [];\n\n const offsets: number[] = [];\n const firstHourMin = Math.ceil(this.dayStartMinutes / 60) * 60;\n\n for (let m = firstHourMin; m <= this.dayEndMinutes; m += 60) {\n offsets.push((m - this.dayStartMinutes) * this.pxPerMinute);\n }\n // Also include the top edge at 0 for a clean line\n offsets.unshift(0);\n\n return offsets;\n }\n\n get rangeTitle(): string {\n if (!this.visibleDays.length) return '';\n\n const start = this.visibleDays[0];\n const end = this.visibleDays[this.visibleDays.length - 1];\n\n const sameMonth = start.getFullYear() === end.getFullYear() && start.getMonth() === end.getMonth();\n const opts: Intl.DateTimeFormatOptions = { month: 'short', day: 'numeric' };\n\n if (this.visibleDays.length === 1) {\n return start.toLocaleDateString(this.locale, { weekday: 'short', ...opts });\n }\n\n if (sameMonth) {\n const month = start.toLocaleDateString(this.locale, { month: 'short' });\n return `${month} ${start.getDate()}–${end.getDate()}`;\n }\n\n return `${start.toLocaleDateString(this.locale, opts)} – ${end.toLocaleDateString(this.locale, opts)}`;\n }\n\n /**\n * Returns events that intersect a given (day, resource) cell.\n */\n eventsForCell(day: Date, resourceId: string): PositionedEvent[] {\n const { startUtc, endUtc } = this.windowBoundsUtc(day);\n\n const list = this.events\n .filter((e) =>\n e.resourceId === resourceId &&\n e.start < endUtc &&\n e.end > startUtc\n )\n .sort((a, b) => a.start.getTime() - b.start.getTime());\n\n return this.layoutOverlaps(list);\n }\n\n /**\n * CSS positioning for an event within a day cell.\n */\n styleForEvent(e: PositionedEvent, day: Date): { [k: string]: string } {\n const { startUtc: windowStartUtc, endUtc: windowEndUtc } = this.windowBoundsUtc(day);\n\n // If event doesn't intersect visible window, don't render it\n if (e.end <= windowStartUtc || e.start >= windowEndUtc) {\n return { display: 'none' };\n }\n\n const start = new Date(Math.max(e.start.getTime(), windowStartUtc.getTime()));\n const end = new Date(Math.min(e.end.getTime(), windowEndUtc.getTime()));\n\n const topMin = (start.getTime() - windowStartUtc.getTime()) / 60000;\n const durMin = Math.max(10, (end.getTime() - start.getTime()) / 60000);\n\n // overlap columns (same as you already have)\n const gapPx = 6;\n const cols = Math.max(1, e._cols);\n const col = Math.max(0, e._col);\n\n const widthExpr = `calc(${100 / cols}% - ${gapPx}px)`;\n const leftExpr = `calc(${(100 * col) / cols}% + ${gapPx / 2}px)`;\n\n return {\n top: `${topMin * this.pxPerMinute}px`,\n height: `${durMin * this.pxPerMinute}px`,\n width: widthExpr,\n left: leftExpr,\n right: 'auto',\n };\n }\n\n onEventClick(e: SchedulerEvent, mouse: MouseEvent) {\n this.eventClick.emit({ event: e, nativeEvent: mouse });\n }\n\n onCellClick(day: Date, resourceId: string, mouse: MouseEvent) {\n if (this.readonly) return;\n\n const clickedDate = this.computeClickedTime(day, mouse);\n const primaryKey = this.primaryAxis === 'days' ? this.dayKey(day) : resourceId;\n const secondaryKey = this.primaryAxis === 'days' ? resourceId : this.dayKey(day);\n\n this.slotClick.emit({\n date: clickedDate,\n day: this.startOfDay(day),\n resourceId,\n primaryAxis: this.primaryAxis,\n primaryKey,\n secondaryKey,\n });\n }\n\n cellDayKey(p:any,s:any): string {\n return this.dayKey(this.resolveCellDay(p,s));\n }\n\n cellResourceId(p:any,s:any): string {\n return this.resolveCellResourceId(p,s);\n }\n\n resolveCellResourceId(p: any, s: any): string {\n return this.primaryAxis === 'days' ? s.resource.id : p.resource.id;\n }\n\n resolveCellResource(p: any, s: any): SchedulerResource {\n return this.primaryAxis === 'days' ? s.resource : p.resource;\n }\n\n cellEvents(p: any, s: any): PositionedEvent[] {\n const day = this.resolveCellDay(p, s);\n const resourceId = this.resolveCellResourceId(p, s);\n return this.eventsForCell(day, resourceId); // now PositionedEvent[]\n }\n\n cellClick(p: any, s: any, ev: MouseEvent) {\n const day = this.resolveCellDay(p, s);\n const resourceId = this.resolveCellResourceId(p, s);\n this.onCellClick(day, resourceId, ev);\n }\n\n getEventLayoutStyle(e: PositionedEvent, p: any, s: any) {\n const day = this.resolveCellDay(p, s);\n\n const layout = this.styleForEvent(e, day); // contains top/height/left/width\n const userStyle = this.eventStyle ? this.eventStyle(e) : null;\n\n // IMPORTANT: layout must win so users can’t break positioning\n return userStyle ? { ...userStyle, ...layout } : layout;\n }\n\n // ---------- INTERNAL COMPUTATION ----------\n\n private windowBoundsUtc(day: Date): { startUtc: Date; endUtc: Date } {\n const base = this.startOfDay(day);\n\n // wall-clock dates for \"day at HH:mm\" (fields matter)\n const wallStart = this.setTime(base, this.dayStartMinutes);\n const wallEnd = this.setTime(base, this.dayEndMinutes);\n\n if (!this.timezone || this.timezone === 'local') {\n // interpreted as device local instants\n return { startUtc: wallStart, endUtc: wallEnd };\n }\n\n if (this.timezone === 'UTC') {\n // build true UTC instants for the wall clock\n const y = base.getFullYear();\n const m = base.getMonth();\n const d = base.getDate();\n\n const sH = Math.floor(this.dayStartMinutes / 60);\n const sM = this.dayStartMinutes % 60;\n const eH = Math.floor(this.dayEndMinutes / 60);\n const eM = this.dayEndMinutes % 60;\n\n return {\n startUtc: new Date(Date.UTC(y, m, d, sH, sM, 0, 0)),\n endUtc: new Date(Date.UTC(y, m, d, eH, eM, 0, 0)),\n };\n }\n\n // IANA timezone: wall-clock in zone -> UTC instant\n return {\n startUtc: fromZonedTime(wallStart, this.timezone),\n endUtc: fromZonedTime(wallEnd, this.timezone),\n };\n }\n\n private assignColumns(cluster: SchedulerEvent[]): PositionedEvent[] {\n // columnsEndTimes[col] = endTime of last event in that col\n const columnsEndTimes: number[] = [];\n const out: PositionedEvent[] = [];\n\n for (const e of cluster) {\n const s = e.start.getTime();\n const en = e.end.getTime();\n\n // Find first available column\n let col = 0;\n for (; col < columnsEndTimes.length; col++) {\n if (s >= columnsEndTimes[col]) break;\n }\n\n if (col === columnsEndTimes.length) columnsEndTimes.push(en);\n else columnsEndTimes[col] = en;\n\n out.push({ ...e, _col: col, _cols: 0 });\n }\n\n const totalCols = columnsEndTimes.length;\n // write total columns for all events in this cluster\n for (const pe of out) pe._cols = totalCols;\n\n return out;\n }\n\n private emitRangeIfChanged(payload: SchedulerRangeChange) {\n const key = `${payload.start.toISOString()}|${payload.end.toISOString()}|${payload.primaryAxis}|${payload.days}`;\n if (key === this.lastRangeKey) return;\n this.lastRangeKey = key;\n queueMicrotask(() => this.rangeChange.emit(payload));\n }\n\n private setStartDate(d: Date) {\n this.startDate = d;\n this.recompute();\n this.startDateChange.emit(d);\n }\n\n // Computes clicked time from y offset within a cell (very handy for creating events)\n private computeClickedTime(day: Date, mouse: MouseEvent): Date {\n const target = mouse.currentTarget as HTMLElement | null;\n if (!target || typeof (target as any).getBoundingClientRect !== 'function') {\n return this.setTime(this.startOfDay(day), this.dayStartMinutes);\n }\n\n const rect = target.getBoundingClientRect();\n const y = mouse.clientY - rect.top;\n\n const minutesFromStart = Math.max(0, Math.min(this.dayEndMinutes - this.dayStartMinutes, y / this.pxPerMinute));\n let snapped = minutesFromStart;\n\n if (this.snapToSlot && this.slotMinutes > 0) {\n snapped = Math.round(minutesFromStart / this.slotMinutes) * this.slotMinutes;\n }\n\n const totalMinutes = this.dayStartMinutes + snapped;\n return this.setTime(this.startOfDay(day), totalMinutes);\n }\n\n private layoutOverlaps(events: SchedulerEvent[]): PositionedEvent[] {\n // Sweep through events, grouping overlapping \"clusters\"\n const positioned: PositionedEvent[] = [];\n\n let cluster: SchedulerEvent[] = [];\n let clusterEnd = -Infinity;\n\n const flushCluster = () => {\n if (cluster.length === 0) return;\n positioned.push(...this.assignColumns(cluster));\n cluster = [];\n clusterEnd = -Infinity;\n };\n\n for (const e of events) {\n const s = e.start.getTime();\n const en = e.end.getTime();\n\n if (cluster.length === 0) {\n cluster = [e];\n clusterEnd = en;\n continue;\n }\n\n // If this event starts after cluster ends, it's a new cluster\n if (s >= clusterEnd) {\n flushCluster();\n cluster = [e];\n clusterEnd = en;\n continue;\n }\n\n // Still overlapping cluster\n cluster.push(e);\n if (en > clusterEnd) clusterEnd = en;\n }\n\n flushCluster();\n return positioned;\n }\n \n private resolveCellDay(p: any, s: any): Date {\n return this.primaryAxis === 'days' ? p.day : s.day;\n }\n\n private recompute() {\n // Clamp days\n const d = Math.max(1, Math.min(7, Math.floor(this.nDays || 7)));\n\n // Parse times\n this.dayStartMinutes = this.parseHmToMinutes(this.dayStart, 8 * 60);\n this.dayEndMinutes = this.parseHmToMinutes(this.dayEnd, 20 * 60);\n if (this.dayEndMinutes <= this.dayStartMinutes) {\n // fallback to a sane window\n this.dayEndMinutes = this.dayStartMinutes + 10 * 60;\n }\n\n this.slotMinutes = this.parseHmToMinutes(this.slotDuration, 30);\n if (this.slotMinutes <= 0) this.slotMinutes = 30;\n\n // Visible days\n const start = this.startOfDay(this.startDate ?? new Date());\n this.visibleDays = Array.from({ length: d }, (_, i) => this.addDays(start, i));\n\n // Columns\n if (this.primaryAxis === 'days') {\n this.primaryColumns = this.visibleDays.map((day) => ({\n kind: 'day',\n day,\n key: this.dayKey(day),\n title: this.formatDay(day),\n }));\n\n this.secondaryColumns = this.resources.map((r) => ({\n kind: 'resource',\n resource: r,\n key: r.id,\n title: r.title,\n }));\n } else {\n this.primaryColumns = this.resources.map((r) => ({\n kind: 'resource',\n resource: r,\n key: r.id,\n title: r.title,\n }));\n\n this.secondaryColumns = this.visibleDays.map((day) => ({\n kind: 'day',\n day,\n key: this.dayKey(day),\n title: this.formatDay(day),\n }));\n }\n\n // Emit range\n const rangeStart = start;\n const rangeEnd = this.addDays(start, d);\n const view: SchedulerView = 'custom-range';\n\n\n this.emitRangeIfChanged({\n start: rangeStart,\n end: rangeEnd,\n days: d,\n primaryAxis: this.primaryAxis,\n view,\n });\n }\n\n // ------------- NAVIGATION -------------\n\n navigatePrev() {\n const next = this.addDays(this.startOfDay(this.startDate ?? new Date()), -this.normalizedDays());\n this.setStartDate(next);\n }\n\n navigateNext() {\n const next = this.addDays(this.startOfDay(this.startDate ?? new Date()), this.normalizedDays());\n this.setStartDate(next);\n }\n\n navigateToday() {\n const today = this.startOfDay(new Date());\n this.setStartDate(today);\n }\n\n // ---------- DATE/TIME UTILS ----------\n\n formatHour(h: number): string {\n return `${String(h).padStart(2, '0')}:00`;\n }\n\n hourTopPx(h: number): number {\n const minutes = (h * 60) - this.dayStartMinutes;\n return minutes * this.pxPerMinute;\n }\n\n isIanaTz(): boolean {\n return !!this.timezone && this.timezone !== 'local' && this.timezone !== 'UTC';\n }\n\n toDisplayZone(dUtc: Date): Date {\n if (this.timezone === 'UTC') return new Date(dUtc);\n if (this.timezone === 'local' || !this.timezone) return new Date(dUtc);\n\n // Converts a UTC instant to a Date whose wall-clock matches the IANA zone\n return toZonedTime(dUtc, this.timezone);\n }\n\n fromDisplayZone(dZoned: Date): Date {\n if (this.timezone === 'UTC') return new Date(dZoned);\n if (this.timezone === 'local' || !this.timezone) return new Date(dZoned);\n\n // Converts a wall-clock-in-zone Date back to a UTC instant\n return fromZonedTime(dZoned, this.timezone);\n }\n\n private parseHmToMinutes(hm: string, fallback: number): number {\n const m = /^(\\d{1,2}):(\\d{2})$/.exec((hm || '').trim());\n if (!m) return fallback;\n const hh = Number(m[1]);\n const mm = Number(m[2]);\n if (!Number.isFinite(hh) || !Number.isFinite(mm)) return fallback;\n return Math.max(0, Math.min(24 * 60, hh * 60 + mm));\n }\n\n private startOfDay(d: Date): Date {\n const x = new Date(d);\n x.setHours(0, 0, 0, 0);\n return x;\n }\n\n private addDays(d: Date, n: number): Date {\n const x = new Date(d);\n x.setDate(x.getDate() + n);\n return x;\n }\n\n private setTime(day: Date, minutes: number): Date {\n const x = new Date(day);\n const hh = Math.floor(minutes / 60);\n const mm = minutes % 60;\n x.setHours(hh, mm, 0, 0);\n return x;\n }\n\n private dayKey(d: Date): string {\n // Use YYYY-MM-DD (stable key) instead of full ISO with timezone offsets\n const y = d.getFullYear();\n const m = String(d.getMonth() + 1).padStart(2, '0');\n const day = String(d.getDate()).padStart(2, '0');\n return `${y}-${m}-${day}`;\n }\n\n private formatDay(d: Date): string {\n return d.toLocaleDateString(this.locale, { weekday: 'short', month: 'short', day: 'numeric' });\n }\n\n private normalizedDays(): number {\n const v = Math.floor(this.nDays ?? 7);\n return Math.max(1, Math.min(7, v));\n }\n\n // ------------- EVENT TOOLTIP -------------\n\n eventTooltip(e: SchedulerEvent): string {\n const start = this.toDisplayZone(e.start);\n const end = this.toDisplayZone(e.end);\n const startStr = start.toLocaleTimeString(this.locale, { hour: '2-digit', minute: '2-digit' });\n const endStr = end.toLocaleTimeString(this.locale, { hour: '2-digit', minute: '2-digit' });\n\n // keep it short so the native tooltip looks good\n return `${e.title}\\n${startStr}–${endStr}`;\n }\n\n // ------------- CUSTOM EVENT STYLING -----------\n\n eventTemplateCtx(e: PositionedEvent, p: any, s: any): SchedulerEventTemplateContext {\n const day = this.resolveCellDay(p, s);\n const resourceId = this.resolveCellResourceId(p, s);\n return {\n $implicit: e,\n event: e,\n startZoned: this.toDisplayZone(e.start),\n endZoned: this.toDisplayZone(e.end),\n resourceId,\n day,\n };\n }\n\n // ------------- TRACK BYS -------------\n \n trackPrimary = (_: number, c: PrimaryColumn) => c.key;\n trackSecondary = (_: number, c: SecondaryColumn) => c.key;\n trackEvent = (_: number, e: SchedulerEvent) => e.id;\n}\n","<div class=\"ngx-scheduler\">\n\n <!-- Toolbar -->\n @if (showToolbar) {\n <div class=\"ngx-toolbar\">\n <div class=\"ngx-toolbar-left\">\n <button type=\"button\" class=\"ngx-btn\" (click)=\"navigatePrev()\">{{ prevLabel }}</button>\n <button type=\"button\" class=\"ngx-btn ngx-btn--ghost\" (click)=\"navigateToday()\">{{ todayLabel }}</button>\n <button type=\"button\" class=\"ngx-btn\" (click)=\"navigateNext()\">{{ nextLabel }}</button>\n </div>\n <div class=\"ngx-toolbar-title\">\n {{ rangeTitle }}\n </div>\n <div class=\"ngx-toolbar-right\">\n @if (showDaysResourcesLabel) {\n <span class=\"ngx-toolbar-meta\">\n {{ primaryAxis === 'days' ? (visibleDays.length + ' ' + daysLabel) : (resources.length + ' ' + resourcesLabel ) }}\n </span>\n }\n @if (!showDaysResourcesLabel) {\n <span class=\"ngx-toolbar-meta\">&nbsp;</span>\n }\n </div>\n </div>\n }\n\n <!-- Header row -->\n <div class=\"ngx-header\">\n <div class=\"ngx-time-gutter\"></div>\n\n <div class=\"ngx-primary-headers\" [style.gridTemplateColumns]=\"'repeat(' + primaryColumns.length + ', minmax(0, 1fr))'\">\n @for (p of primaryColumns; track trackPrimary($index, p)) {\n <div class=\"ngx-primary-header\">\n <div class=\"ngx-primary-title-row\">\n <div class=\"ngx-primary-title\">{{ p.title }}</div>\n </div>\n <div class=\"ngx-secondary-header-row\" [style.gridTemplateColumns]=\"'repeat(' + secondaryColumns.length + ', minmax(0, 1fr))'\">\n @for (s of secondaryColumns; track trackSecondary($index, s)) {\n <div class=\"ngx-secondary-header\">\n <span class=\"ngx-secondary-header-title\">{{ s.title }}</span>\n </div>\n }\n </div>\n </div>\n }\n </div>\n </div>\n\n <!-- Body -->\n <div class=\"ngx-body\">\n <!-- time gutter -->\n <div class=\"ngx-time-gutter\" [style.height.px]=\"timelineHeightPx\">\n @for (h of hourLabels; track h) {\n <div\n class=\"ngx-hour-label\"\n [style.top.px]=\"hourTopPx(h)\">\n {{ formatHour(h) }}\n </div>\n }\n </div>\n\n\n <!-- grid -->\n <div class=\"ngx-grid\"\n [style.gridTemplateColumns]=\"'repeat(' + primaryColumns.length + ', minmax(0, 1fr))'\"\n [style.height.px]=\"timelineHeightPx\">\n\n @for (p of primaryColumns; track trackPrimary($index, p)) {\n <div class=\"ngx-primary-col\">\n <div class=\"ngx-secondary-cols\"\n [style.gridTemplateColumns]=\"'repeat(' + secondaryColumns.length + ', minmax(0, 1fr))'\"\n [style.height.px]=\"timelineHeightPx\">\n <!-- Each cell is (day, resource) regardless of axis order -->\n @for (s of secondaryColumns; track trackSecondary($index, s)) {\n <div class=\"ngx-cell\"\n #cellEl\n [style.height.px]=\"timelineHeightPx\"\n (click)=\"cellClick(p, s, $event)\"\n [attr.data-day]=\"cellDayKey(p,s)\"\n [attr.data-resource]=\"cellResourceId(p,s)\">\n <!-- grid lines -->\n <div class=\"ngx-lines\" aria-hidden=\"true\">\n <!-- slot lines -->\n @for (line of slotLines; track line) {\n <div\n class=\"ngx-line ngx-line--slot\"\n [style.top.px]=\"line.top\"\n [class.ngx-line--half]=\"line.isHalfHour\"\n [class.is-hidden]=\"slotLineStyle === 'hour'\">\n </div>\n }\n <!-- hour lines -->\n @for (top of hourLineOffsetsPx; track top) {\n <div\n class=\"ngx-line ngx-line--hour\"\n [style.top.px]=\"top\"\n [class.is-hidden]=\"slotLineStyle === 'slot'\">\n </div>\n }\n </div>\n <!-- events -->\n <!-- ngClass and 2nd ngStyle are only used when user passes custom class/style -->\n @for (e of cellEvents(p, s); track trackEvent($index, e)) {\n <div class=\"ngx-event\"\n [ngStyle]=\"getEventLayoutStyle(e, p, s)\"\n (click)=\"onEventClick(e, $event); $event.stopPropagation()\"\n [ngClass]=\"eventClass ? eventClass(e) : null\"\n [attr.title]=\"eventTooltip(e)\">\n @if (eventTemplate) {\n <ng-container\n [ngTemplateOutlet]=\"eventTemplate\"\n [ngTemplateOutletContext]=\"eventTemplateCtx(e, p, s)\">\n </ng-container>\n } @else {\n <div class=\"ngx-event-title\">{{ e.title }}</div>\n <div class=\"ngx-event-time\">\n {{ toDisplayZone(e.start) | date:'HH:mm' }}–{{ toDisplayZone(e.end) | date:'HH:mm' }}\n </div>\n }\n </div>\n }\n </div>\n }\n </div>\n </div>\n }\n\n </div>\n </div>\n\n</div>\n","/**\n * Public types for ngx-resource-scheduler\n * Keep this file framework-agnostic (no Angular imports).\n */\n\n/** Which dimension is the top-level column grouping. */\nexport type PrimaryAxis = 'days' | 'resources';\n\n/** v1 view modes (future-proofed). */\nexport type SchedulerView = 'custom-range'; // controlled by startDate + days\n\n/** Resource shown in the scheduler. */\nexport interface SchedulerResource {\n id: string;\n title: string;\n\n /** Optional arbitrary metadata for the consumer. */\n data?: unknown;\n\n /** Optional CSS class(es) applied to the resource header/cells. */\n className?: string | string[];\n}\n\n/** Event rendered in the scheduler. */\nexport interface SchedulerEvent {\n id: string;\n title: string;\n\n /** Inclusive start date-time. */\n start: Date;\n\n /** Exclusive end date-time (recommended). */\n end: Date;\n\n /** Resource column this event belongs to. */\n resourceId: string;\n\n /** Optional styling helpers. */\n color?: string;\n className?: string | string[];\n\n /** Optional arbitrary metadata for the consumer. */\n data?: unknown;\n}\n\n/** Emitted when the user clicks an empty slot/cell in the scheduler. */\nexport interface SchedulerSlotClick {\n /** Clicked date-time (snapped if snapToSlot is enabled). */\n date: Date;\n\n /** The day bucket for the clicked cell (00:00 local/zone). */\n day: Date;\n\n /** Resource for the clicked cell. */\n resourceId: string;\n\n /** Layout info for consumers building custom UI around the scheduler. */\n primaryAxis: PrimaryAxis;\n\n /**\n * Identifies which primary column group was clicked.\n * - if primaryAxis === 'days': ISO date string of `day`\n * - if primaryAxis === 'resources': `resourceId`\n */\n primaryKey: string;\n\n /**\n * Identifies which nested column group was clicked.\n * - if primaryAxis === 'days': `resourceId`\n * - if primaryAxis === 'resources': ISO date string of `day`\n */\n secondaryKey: string;\n}\n\n/** Emitted when an event element is clicked. */\nexport interface SchedulerEventClick {\n event: SchedulerEvent;\n nativeEvent: MouseEvent;\n}\n\n/** Emitted when the visible time range changes (startDate/days/view). */\nexport interface SchedulerRangeChange {\n /** Inclusive start of visible range. */\n start: Date;\n\n /** Exclusive end of visible range. */\n end: Date;\n\n /** Number of visible days (1..7). */\n days: number;\n\n /** The primary axis currently in use. */\n primaryAxis: PrimaryAxis;\n\n /** Current view identifier (v1 uses custom-range). */\n view: SchedulerView;\n}\n\n/** Optional simple renderer hooks (string return keeps it light for v1). */\nexport type EventRenderer = (args: { event: SchedulerEvent }) => string;\n\nexport type HeaderRenderer =\n (args: { type: 'day' | 'resource'; day?: Date; resource?: SchedulerResource }) => string;\n","import { NgModule } from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport { NgxResourceSchedulerComponent } from './ngx-resource-scheduler.component';\n\n@NgModule({\n imports: [CommonModule],\n declarations: [NgxResourceSchedulerComponent],\n exports: [NgxResourceSchedulerComponent],\n})\nexport class NgxResourceSchedulerModule {}\n","/*\n * Public API Surface of ngx-resource-scheduler\n */\n\nexport * from './lib/ngx-resource-scheduler.component';\nexport * from './lib/types';\nexport * from './lib/ngx-resource-scheduler.module';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ngx-resource-scheduler",
3
- "version": "0.1.3",
3
+ "version": "0.1.5",
4
4
  "description": "Angular scheduler with date columns and nested resource columns or inverted",
5
5
  "keywords": [
6
6
  "angular",
@@ -11,7 +11,7 @@
11
11
  "license": "MIT",
12
12
  "repository": {
13
13
  "type": "git",
14
- "url": "https://github.com/YOUR_NAME/ngx-resource-scheduler.git"
14
+ "url": "https://github.com/rmpt/ngx-resource-scheduler"
15
15
  },
16
16
  "peerDependencies": {
17
17
  "@angular/common": ">=20.0.0 <22.0.0",
@@ -134,7 +134,6 @@ declare class NgxResourceSchedulerComponent implements OnChanges {
134
134
  showSlotLines: boolean;
135
135
  slotLineStyle: 'slot' | 'hour' | 'both';
136
136
  showToolbar: boolean;
137
- todayLabel: string;
138
137
  prevLabel: string;
139
138
  nextLabel: string;
140
139
  private lastRangeKey;
@@ -148,6 +147,7 @@ declare class NgxResourceSchedulerComponent implements OnChanges {
148
147
  showDaysResourcesLabel: boolean;
149
148
  daysLabel: string;
150
149
  resourcesLabel: string;
150
+ todayLabel: string;
151
151
  weekStartsOn: 0 | 1 | 2 | 3 | 4 | 5 | 6;
152
152
  locale?: string;
153
153
  timezone?: 'local' | 'UTC' | string;
@@ -231,7 +231,7 @@ declare class NgxResourceSchedulerComponent implements OnChanges {
231
231
  trackSecondary: (_: number, c: SecondaryColumn) => string;
232
232
  trackEvent: (_: number, e: SchedulerEvent) => string;
233
233
  static ɵfac: i0.ɵɵFactoryDeclaration<NgxResourceSchedulerComponent, never>;
234
- static ɵcmp: i0.ɵɵComponentDeclaration<NgxResourceSchedulerComponent, "ngx-resource-scheduler", never, { "startDate": { "alias": "startDate"; "required": false; }; "resources": { "alias": "resources"; "required": false; }; "events": { "alias": "events"; "required": false; }; "nDays": { "alias": "nDays"; "required": false; }; "primaryAxis": { "alias": "primaryAxis"; "required": false; }; "dayStart": { "alias": "dayStart"; "required": false; }; "dayEnd": { "alias": "dayEnd"; "required": false; }; "slotDuration": { "alias": "slotDuration"; "required": false; }; "snapToSlot": { "alias": "snapToSlot"; "required": false; }; "showSlotLines": { "alias": "showSlotLines"; "required": false; }; "slotLineStyle": { "alias": "slotLineStyle"; "required": false; }; "showToolbar": { "alias": "showToolbar"; "required": false; }; "todayLabel": { "alias": "todayLabel"; "required": false; }; "prevLabel": { "alias": "prevLabel"; "required": false; }; "nextLabel": { "alias": "nextLabel"; "required": false; }; "eventTemplate": { "alias": "eventTemplate"; "required": false; }; "eventClass": { "alias": "eventClass"; "required": false; }; "eventStyle": { "alias": "eventStyle"; "required": false; }; "showDaysResourcesLabel": { "alias": "showDaysResourcesLabel"; "required": false; }; "daysLabel": { "alias": "daysLabel"; "required": false; }; "resourcesLabel": { "alias": "resourcesLabel"; "required": false; }; "weekStartsOn": { "alias": "weekStartsOn"; "required": false; }; "locale": { "alias": "locale"; "required": false; }; "timezone": { "alias": "timezone"; "required": false; }; "readonly": { "alias": "readonly"; "required": false; }; }, { "slotClick": "slotClick"; "eventClick": "eventClick"; "eventChange": "eventChange"; "rangeChange": "rangeChange"; "startDateChange": "startDateChange"; }, never, never, false, never>;
234
+ static ɵcmp: i0.ɵɵComponentDeclaration<NgxResourceSchedulerComponent, "ngx-resource-scheduler", never, { "startDate": { "alias": "startDate"; "required": false; }; "resources": { "alias": "resources"; "required": false; }; "events": { "alias": "events"; "required": false; }; "nDays": { "alias": "nDays"; "required": false; }; "primaryAxis": { "alias": "primaryAxis"; "required": false; }; "dayStart": { "alias": "dayStart"; "required": false; }; "dayEnd": { "alias": "dayEnd"; "required": false; }; "slotDuration": { "alias": "slotDuration"; "required": false; }; "snapToSlot": { "alias": "snapToSlot"; "required": false; }; "showSlotLines": { "alias": "showSlotLines"; "required": false; }; "slotLineStyle": { "alias": "slotLineStyle"; "required": false; }; "showToolbar": { "alias": "showToolbar"; "required": false; }; "prevLabel": { "alias": "prevLabel"; "required": false; }; "nextLabel": { "alias": "nextLabel"; "required": false; }; "eventTemplate": { "alias": "eventTemplate"; "required": false; }; "eventClass": { "alias": "eventClass"; "required": false; }; "eventStyle": { "alias": "eventStyle"; "required": false; }; "showDaysResourcesLabel": { "alias": "showDaysResourcesLabel"; "required": false; }; "daysLabel": { "alias": "daysLabel"; "required": false; }; "resourcesLabel": { "alias": "resourcesLabel"; "required": false; }; "todayLabel": { "alias": "todayLabel"; "required": false; }; "weekStartsOn": { "alias": "weekStartsOn"; "required": false; }; "locale": { "alias": "locale"; "required": false; }; "timezone": { "alias": "timezone"; "required": false; }; "readonly": { "alias": "readonly"; "required": false; }; }, { "slotClick": "slotClick"; "eventClick": "eventClick"; "eventChange": "eventChange"; "rangeChange": "rangeChange"; "startDateChange": "startDateChange"; }, never, never, false, never>;
235
235
  }
236
236
 
237
237
  declare class NgxResourceSchedulerModule {