@besaitech/ng-design-system 0.0.78 → 0.0.79
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/calendar/index.d.ts +73 -3
- package/fesm2022/besaitech-ng-design-system-calendar.mjs +268 -8
- package/fesm2022/besaitech-ng-design-system-calendar.mjs.map +1 -1
- package/fesm2022/besaitech-ng-design-system.mjs +779 -41
- package/fesm2022/besaitech-ng-design-system.mjs.map +1 -1
- package/index.d.ts +173 -23
- package/package.json +1 -1
package/calendar/index.d.ts
CHANGED
|
@@ -79,11 +79,24 @@ declare function occursOn(start: Date, end: Date, day: Date): boolean;
|
|
|
79
79
|
* on a grid that opens at 08:00 should still show, flush to the top, not vanish.
|
|
80
80
|
*/
|
|
81
81
|
declare function placeDay<T>(events: readonly SdsCalendarEvent<T>[], day: Date, startHour: number, endHour: number, defaultMinutes: number): PlacedEvent<T>[];
|
|
82
|
+
/**
|
|
83
|
+
* A dragged minute, snapped to the grid and held inside the visible window.
|
|
84
|
+
*
|
|
85
|
+
* <p>Clamping is not cosmetic: without it a drag that leaves the top of the grid proposes a time
|
|
86
|
+
* before the practice opens, and the host either books it or has to invent the same rule itself.
|
|
87
|
+
*/
|
|
88
|
+
declare function snapMinute(minute: number, stepMinutes: number, startHour: number, endHour: number): number;
|
|
82
89
|
/** The all-day (and multi-day) events touching a given day, in a stable order. */
|
|
83
90
|
declare function allDayOn<T>(events: readonly SdsCalendarEvent<T>[], day: Date, defaultMinutes: number): SdsCalendarEvent<T>[];
|
|
84
91
|
/** Every event touching a day, all-day first then by start — what a month cell lists. */
|
|
85
92
|
declare function eventsOn<T>(events: readonly SdsCalendarEvent<T>[], day: Date, defaultMinutes: number): SdsCalendarEvent<T>[];
|
|
86
93
|
|
|
94
|
+
/** Where an event was dropped. The component reports; the host decides whether it sticks. */
|
|
95
|
+
interface SdsCalendarDrop<T = unknown> {
|
|
96
|
+
event: SdsCalendarEvent<T>;
|
|
97
|
+
start: Date;
|
|
98
|
+
end: Date;
|
|
99
|
+
}
|
|
87
100
|
/** A click on empty time: what a host turns into "new appointment". */
|
|
88
101
|
interface SdsCalendarSlot {
|
|
89
102
|
start: Date;
|
|
@@ -127,6 +140,7 @@ interface SdsCalendarRange {
|
|
|
127
140
|
*/
|
|
128
141
|
declare class SdsEventCalendar<T = unknown> {
|
|
129
142
|
private readonly destroyRef;
|
|
143
|
+
private readonly host;
|
|
130
144
|
readonly events: _angular_core.InputSignal<readonly SdsCalendarEvent<T>[]>;
|
|
131
145
|
/** Two-way: the host can deep-link or restore a view. */
|
|
132
146
|
readonly view: _angular_core.ModelSignal<SdsEventCalendarView>;
|
|
@@ -161,7 +175,26 @@ declare class SdsEventCalendar<T = unknown> {
|
|
|
161
175
|
readonly weekLabel: _angular_core.InputSignal<string>;
|
|
162
176
|
readonly threeDayLabel: _angular_core.InputSignal<string>;
|
|
163
177
|
readonly dayLabel: _angular_core.InputSignal<string>;
|
|
178
|
+
/**
|
|
179
|
+
* Let an event be dragged to another time or day. <b>Opt-in</b>: a calendar whose host does not
|
|
180
|
+
* persist the move would show an appointment settle somewhere it has not been booked, which is
|
|
181
|
+
* worse than not offering the gesture.
|
|
182
|
+
*/
|
|
183
|
+
readonly draggable: _angular_core.InputSignalWithTransform<boolean, unknown>;
|
|
184
|
+
/** Drag across empty time to propose a span. The plain click keeps emitting `slotClick`. */
|
|
185
|
+
readonly selectable: _angular_core.InputSignalWithTransform<boolean, unknown>;
|
|
186
|
+
/** Both gestures snap to this. 15 minutes is the finest grid anybody reads off a week view. */
|
|
187
|
+
readonly snapMinutes: _angular_core.InputSignalWithTransform<number, unknown>;
|
|
164
188
|
readonly eventClick: _angular_core.OutputEmitterRef<SdsCalendarEvent<T>>;
|
|
189
|
+
/**
|
|
190
|
+
* An event was dragged somewhere else. The component does NOT move it: it reports where it was
|
|
191
|
+
* dropped and redraws from `events` as before, so the diary only changes once the host says it
|
|
192
|
+
* did. A drag that moved the chip locally would show a booking that does not exist whenever the
|
|
193
|
+
* write is refused.
|
|
194
|
+
*/
|
|
195
|
+
readonly eventDrop: _angular_core.OutputEmitterRef<SdsCalendarDrop<T>>;
|
|
196
|
+
/** A span was dragged out across empty time — "book something from here to here". */
|
|
197
|
+
readonly rangeSelect: _angular_core.OutputEmitterRef<SdsCalendarSlot>;
|
|
165
198
|
/** A click on empty time, snapped to the hour that was clicked. */
|
|
166
199
|
readonly slotClick: _angular_core.OutputEmitterRef<SdsCalendarSlot>;
|
|
167
200
|
readonly dayClick: _angular_core.OutputEmitterRef<Date>;
|
|
@@ -169,6 +202,18 @@ declare class SdsEventCalendar<T = unknown> {
|
|
|
169
202
|
readonly rangeChange: _angular_core.OutputEmitterRef<SdsCalendarRange>;
|
|
170
203
|
/** Ticks the now-indicator. One timer, cleared with the component. */
|
|
171
204
|
private readonly now;
|
|
205
|
+
/** The gesture in flight, if any. Null between gestures — there is never more than one. */
|
|
206
|
+
private readonly drag;
|
|
207
|
+
/** Set once the pointer has moved far enough to be a drag rather than a click. */
|
|
208
|
+
private readonly dragging;
|
|
209
|
+
/**
|
|
210
|
+
* A finished drag still produces a click, and it arrives AFTER pointerup — so checking
|
|
211
|
+
* "am I dragging" inside the click handler is always false by then. Measured: dropping an event
|
|
212
|
+
* emitted `eventDrop` AND `slotClick`, so a host both moved the appointment and opened a
|
|
213
|
+
* "new appointment" panel for where the finger lifted. This survives until the click it has to
|
|
214
|
+
* swallow, and is cleared either way.
|
|
215
|
+
*/
|
|
216
|
+
private suppressClick;
|
|
172
217
|
constructor();
|
|
173
218
|
protected readonly days: _angular_core.Signal<Date[]>;
|
|
174
219
|
protected readonly hours: _angular_core.Signal<number[]>;
|
|
@@ -198,10 +243,35 @@ declare class SdsEventCalendar<T = unknown> {
|
|
|
198
243
|
protected goToday(): void;
|
|
199
244
|
/** A click on empty grid becomes a slot of `defaultMinutes`, snapped to the hour clicked. */
|
|
200
245
|
protected onGridClick(event: MouseEvent, day: Date): void;
|
|
246
|
+
protected canDrag(placed: PlacedEvent<T>): boolean;
|
|
247
|
+
protected isDragging(placed: PlacedEvent<T>): boolean;
|
|
248
|
+
/** The dashed block: where this drag would land on this column, or null. */
|
|
249
|
+
protected ghostFor(dayIndex: number): {
|
|
250
|
+
top: number;
|
|
251
|
+
height: number;
|
|
252
|
+
label: string;
|
|
253
|
+
} | null;
|
|
254
|
+
protected startSelect(event: PointerEvent, dayIndex: number): void;
|
|
255
|
+
protected startMove(event: PointerEvent, placed: PlacedEvent<T>, dayIndex: number): void;
|
|
256
|
+
/**
|
|
257
|
+
* Listeners are attached for the gesture and removed on release, rather than living on the host
|
|
258
|
+
* for the component's whole life. A calendar sitting idle on a dashboard should not be handling
|
|
259
|
+
* every pointer move on the page.
|
|
260
|
+
*/
|
|
261
|
+
private begin;
|
|
262
|
+
private finish;
|
|
263
|
+
private snap;
|
|
264
|
+
private minuteAt;
|
|
265
|
+
private atMinute;
|
|
266
|
+
private columnAt;
|
|
267
|
+
private columnFor;
|
|
268
|
+
/** True once, for the click that a just-finished drag is about to produce. */
|
|
269
|
+
private swallowed;
|
|
270
|
+
private hhmm;
|
|
201
271
|
protected onEventClick(event: MouseEvent, placed: PlacedEvent<T>): void;
|
|
202
272
|
static ɵfac: _angular_core.ɵɵFactoryDeclaration<SdsEventCalendar<any>, never>;
|
|
203
|
-
static ɵcmp: _angular_core.ɵɵComponentDeclaration<SdsEventCalendar<any>, "sds-event-calendar", never, { "events": { "alias": "events"; "required": false; "isSignal": true; }; "view": { "alias": "view"; "required": false; "isSignal": true; }; "date": { "alias": "date"; "required": false; "isSignal": true; }; "firstDayOfWeek": { "alias": "firstDayOfWeek"; "required": false; "isSignal": true; }; "startHour": { "alias": "startHour"; "required": false; "isSignal": true; }; "endHour": { "alias": "endHour"; "required": false; "isSignal": true; }; "hourHeight": { "alias": "hourHeight"; "required": false; "isSignal": true; }; "defaultMinutes": { "alias": "defaultMinutes"; "required": false; "isSignal": true; }; "height": { "alias": "height"; "required": false; "isSignal": true; }; "locale": { "alias": "locale"; "required": false; "isSignal": true; }; "nowIndicator": { "alias": "nowIndicator"; "required": false; "isSignal": true; }; "showToolbar": { "alias": "showToolbar"; "required": false; "isSignal": true; }; "showViewSwitcher": { "alias": "showViewSwitcher"; "required": false; "isSignal": true; }; "maxPerCell": { "alias": "maxPerCell"; "required": false; "isSignal": true; }; "todayLabel": { "alias": "todayLabel"; "required": false; "isSignal": true; }; "previousLabel": { "alias": "previousLabel"; "required": false; "isSignal": true; }; "nextLabel": { "alias": "nextLabel"; "required": false; "isSignal": true; }; "allDayLabel": { "alias": "allDayLabel"; "required": false; "isSignal": true; }; "moreLabel": { "alias": "moreLabel"; "required": false; "isSignal": true; }; "viewSwitcherLabel": { "alias": "viewSwitcherLabel"; "required": false; "isSignal": true; }; "monthLabel": { "alias": "monthLabel"; "required": false; "isSignal": true; }; "weekLabel": { "alias": "weekLabel"; "required": false; "isSignal": true; }; "threeDayLabel": { "alias": "threeDayLabel"; "required": false; "isSignal": true; }; "dayLabel": { "alias": "dayLabel"; "required": false; "isSignal": true; }; }, { "view": "viewChange"; "date": "dateChange"; "eventClick": "eventClick"; "slotClick": "slotClick"; "dayClick": "dayClick"; "rangeChange": "rangeChange"; }, never, never, true, never>;
|
|
273
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<SdsEventCalendar<any>, "sds-event-calendar", never, { "events": { "alias": "events"; "required": false; "isSignal": true; }; "view": { "alias": "view"; "required": false; "isSignal": true; }; "date": { "alias": "date"; "required": false; "isSignal": true; }; "firstDayOfWeek": { "alias": "firstDayOfWeek"; "required": false; "isSignal": true; }; "startHour": { "alias": "startHour"; "required": false; "isSignal": true; }; "endHour": { "alias": "endHour"; "required": false; "isSignal": true; }; "hourHeight": { "alias": "hourHeight"; "required": false; "isSignal": true; }; "defaultMinutes": { "alias": "defaultMinutes"; "required": false; "isSignal": true; }; "height": { "alias": "height"; "required": false; "isSignal": true; }; "locale": { "alias": "locale"; "required": false; "isSignal": true; }; "nowIndicator": { "alias": "nowIndicator"; "required": false; "isSignal": true; }; "showToolbar": { "alias": "showToolbar"; "required": false; "isSignal": true; }; "showViewSwitcher": { "alias": "showViewSwitcher"; "required": false; "isSignal": true; }; "maxPerCell": { "alias": "maxPerCell"; "required": false; "isSignal": true; }; "todayLabel": { "alias": "todayLabel"; "required": false; "isSignal": true; }; "previousLabel": { "alias": "previousLabel"; "required": false; "isSignal": true; }; "nextLabel": { "alias": "nextLabel"; "required": false; "isSignal": true; }; "allDayLabel": { "alias": "allDayLabel"; "required": false; "isSignal": true; }; "moreLabel": { "alias": "moreLabel"; "required": false; "isSignal": true; }; "viewSwitcherLabel": { "alias": "viewSwitcherLabel"; "required": false; "isSignal": true; }; "monthLabel": { "alias": "monthLabel"; "required": false; "isSignal": true; }; "weekLabel": { "alias": "weekLabel"; "required": false; "isSignal": true; }; "threeDayLabel": { "alias": "threeDayLabel"; "required": false; "isSignal": true; }; "dayLabel": { "alias": "dayLabel"; "required": false; "isSignal": true; }; "draggable": { "alias": "draggable"; "required": false; "isSignal": true; }; "selectable": { "alias": "selectable"; "required": false; "isSignal": true; }; "snapMinutes": { "alias": "snapMinutes"; "required": false; "isSignal": true; }; }, { "view": "viewChange"; "date": "dateChange"; "eventClick": "eventClick"; "eventDrop": "eventDrop"; "rangeSelect": "rangeSelect"; "slotClick": "slotClick"; "dayClick": "dayClick"; "rangeChange": "rangeChange"; }, never, never, true, never>;
|
|
204
274
|
}
|
|
205
275
|
|
|
206
|
-
export { SdsEventCalendar, allDayOn, eventsOn, minutesOfDay, occursOn, placeDay, startOfWeek, step, toDate, visibleDays, visibleRange };
|
|
207
|
-
export type { PlacedEvent, SdsCalendarEvent, SdsCalendarRange, SdsCalendarSlot, SdsEventCalendarView, SdsEventColor };
|
|
276
|
+
export { SdsEventCalendar, allDayOn, eventsOn, minutesOfDay, occursOn, placeDay, snapMinute, startOfWeek, step, toDate, visibleDays, visibleRange };
|
|
277
|
+
export type { PlacedEvent, SdsCalendarDrop, SdsCalendarEvent, SdsCalendarRange, SdsCalendarSlot, SdsEventCalendarView, SdsEventColor };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { startOfDay, addDays, isSameDay, SdsIcon, SdsSegmented } from '@besaitech/ng-design-system';
|
|
2
2
|
import * as i0 from '@angular/core';
|
|
3
|
-
import { inject, DestroyRef, input, model, numberAttribute, booleanAttribute, output, signal, effect, untracked, computed, ChangeDetectionStrategy, Component } from '@angular/core';
|
|
3
|
+
import { inject, DestroyRef, ElementRef, input, model, numberAttribute, booleanAttribute, output, signal, effect, untracked, computed, ChangeDetectionStrategy, Component } from '@angular/core';
|
|
4
4
|
|
|
5
5
|
const MS_PER_MINUTE = 60_000;
|
|
6
6
|
function toDate(value) {
|
|
@@ -148,6 +148,16 @@ function placeDay(events, day, startHour, endHour, defaultMinutes) {
|
|
|
148
148
|
flush();
|
|
149
149
|
return placed;
|
|
150
150
|
}
|
|
151
|
+
/**
|
|
152
|
+
* A dragged minute, snapped to the grid and held inside the visible window.
|
|
153
|
+
*
|
|
154
|
+
* <p>Clamping is not cosmetic: without it a drag that leaves the top of the grid proposes a time
|
|
155
|
+
* before the practice opens, and the host either books it or has to invent the same rule itself.
|
|
156
|
+
*/
|
|
157
|
+
function snapMinute(minute, stepMinutes, startHour, endHour) {
|
|
158
|
+
const step = Math.max(1, stepMinutes);
|
|
159
|
+
return Math.min(endHour * 60, Math.max(startHour * 60, Math.round(minute / step) * step));
|
|
160
|
+
}
|
|
151
161
|
/** The all-day (and multi-day) events touching a given day, in a stable order. */
|
|
152
162
|
function allDayOn(events, day, defaultMinutes) {
|
|
153
163
|
return events
|
|
@@ -230,6 +240,7 @@ const DOT = {
|
|
|
230
240
|
*/
|
|
231
241
|
class SdsEventCalendar {
|
|
232
242
|
destroyRef = inject(DestroyRef);
|
|
243
|
+
host = inject(ElementRef);
|
|
233
244
|
events = input([], ...(ngDevMode ? [{ debugName: "events" }] : []));
|
|
234
245
|
/** Two-way: the host can deep-link or restore a view. */
|
|
235
246
|
view = model('week', ...(ngDevMode ? [{ debugName: "view" }] : []));
|
|
@@ -264,7 +275,26 @@ class SdsEventCalendar {
|
|
|
264
275
|
weekLabel = input('Week', ...(ngDevMode ? [{ debugName: "weekLabel" }] : []));
|
|
265
276
|
threeDayLabel = input('3 days', ...(ngDevMode ? [{ debugName: "threeDayLabel" }] : []));
|
|
266
277
|
dayLabel = input('Day', ...(ngDevMode ? [{ debugName: "dayLabel" }] : []));
|
|
278
|
+
/**
|
|
279
|
+
* Let an event be dragged to another time or day. <b>Opt-in</b>: a calendar whose host does not
|
|
280
|
+
* persist the move would show an appointment settle somewhere it has not been booked, which is
|
|
281
|
+
* worse than not offering the gesture.
|
|
282
|
+
*/
|
|
283
|
+
draggable = input(false, ...(ngDevMode ? [{ debugName: "draggable", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
|
|
284
|
+
/** Drag across empty time to propose a span. The plain click keeps emitting `slotClick`. */
|
|
285
|
+
selectable = input(true, ...(ngDevMode ? [{ debugName: "selectable", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
|
|
286
|
+
/** Both gestures snap to this. 15 minutes is the finest grid anybody reads off a week view. */
|
|
287
|
+
snapMinutes = input(15, ...(ngDevMode ? [{ debugName: "snapMinutes", transform: numberAttribute }] : [{ transform: numberAttribute }]));
|
|
267
288
|
eventClick = output();
|
|
289
|
+
/**
|
|
290
|
+
* An event was dragged somewhere else. The component does NOT move it: it reports where it was
|
|
291
|
+
* dropped and redraws from `events` as before, so the diary only changes once the host says it
|
|
292
|
+
* did. A drag that moved the chip locally would show a booking that does not exist whenever the
|
|
293
|
+
* write is refused.
|
|
294
|
+
*/
|
|
295
|
+
eventDrop = output();
|
|
296
|
+
/** A span was dragged out across empty time — "book something from here to here". */
|
|
297
|
+
rangeSelect = output();
|
|
268
298
|
/** A click on empty time, snapped to the hour that was clicked. */
|
|
269
299
|
slotClick = output();
|
|
270
300
|
dayClick = output();
|
|
@@ -272,6 +302,18 @@ class SdsEventCalendar {
|
|
|
272
302
|
rangeChange = output();
|
|
273
303
|
/** Ticks the now-indicator. One timer, cleared with the component. */
|
|
274
304
|
now = signal(new Date(), ...(ngDevMode ? [{ debugName: "now" }] : []));
|
|
305
|
+
/** The gesture in flight, if any. Null between gestures — there is never more than one. */
|
|
306
|
+
drag = signal(null, ...(ngDevMode ? [{ debugName: "drag" }] : []));
|
|
307
|
+
/** Set once the pointer has moved far enough to be a drag rather than a click. */
|
|
308
|
+
dragging = signal(false, ...(ngDevMode ? [{ debugName: "dragging" }] : []));
|
|
309
|
+
/**
|
|
310
|
+
* A finished drag still produces a click, and it arrives AFTER pointerup — so checking
|
|
311
|
+
* "am I dragging" inside the click handler is always false by then. Measured: dropping an event
|
|
312
|
+
* emitted `eventDrop` AND `slotClick`, so a host both moved the appointment and opened a
|
|
313
|
+
* "new appointment" panel for where the finger lifted. This survives until the click it has to
|
|
314
|
+
* swallow, and is cleared either way.
|
|
315
|
+
*/
|
|
316
|
+
suppressClick = false;
|
|
275
317
|
constructor() {
|
|
276
318
|
const timer = setInterval(() => this.now.set(new Date()), 60_000);
|
|
277
319
|
this.destroyRef.onDestroy(() => clearInterval(timer));
|
|
@@ -393,6 +435,9 @@ class SdsEventCalendar {
|
|
|
393
435
|
}
|
|
394
436
|
/** A click on empty grid becomes a slot of `defaultMinutes`, snapped to the hour clicked. */
|
|
395
437
|
onGridClick(event, day) {
|
|
438
|
+
if (this.swallowed()) {
|
|
439
|
+
return;
|
|
440
|
+
}
|
|
396
441
|
const host = event.currentTarget;
|
|
397
442
|
const y = event.clientY - host.getBoundingClientRect().top;
|
|
398
443
|
const minutes = this.startHour() * 60 + (y / this.hourHeight()) * 60;
|
|
@@ -403,13 +448,180 @@ class SdsEventCalendar {
|
|
|
403
448
|
end: new Date(start.getTime() + this.defaultMinutes() * 60_000),
|
|
404
449
|
});
|
|
405
450
|
}
|
|
451
|
+
// ------------------------------------------------------------------ dragging
|
|
452
|
+
canDrag(placed) {
|
|
453
|
+
return this.draggable() && !placed.event.cancelled;
|
|
454
|
+
}
|
|
455
|
+
isDragging(placed) {
|
|
456
|
+
const drag = this.drag();
|
|
457
|
+
return this.dragging() && drag?.kind === 'move' && drag.placed.event.id === placed.event.id;
|
|
458
|
+
}
|
|
459
|
+
/** The dashed block: where this drag would land on this column, or null. */
|
|
460
|
+
ghostFor(dayIndex) {
|
|
461
|
+
const drag = this.drag();
|
|
462
|
+
if (!drag || !this.dragging() || drag.dayIndex !== dayIndex) {
|
|
463
|
+
return null;
|
|
464
|
+
}
|
|
465
|
+
const perMinute = this.hourHeight() / 60;
|
|
466
|
+
const from = this.startHour() * 60;
|
|
467
|
+
const [a, b] = drag.kind === 'move'
|
|
468
|
+
? [drag.atMin, drag.atMin + drag.durationMin]
|
|
469
|
+
: [Math.min(drag.fromMin, drag.atMin), Math.max(drag.fromMin, drag.atMin)];
|
|
470
|
+
const top = (a - from) * perMinute;
|
|
471
|
+
return {
|
|
472
|
+
top,
|
|
473
|
+
height: Math.max((b - a) * perMinute, 2),
|
|
474
|
+
label: `${this.hhmm(a)} – ${this.hhmm(b)}`,
|
|
475
|
+
};
|
|
476
|
+
}
|
|
477
|
+
startSelect(event, dayIndex) {
|
|
478
|
+
if (!this.selectable() || event.button !== 0) {
|
|
479
|
+
return;
|
|
480
|
+
}
|
|
481
|
+
const column = event.currentTarget;
|
|
482
|
+
const minute = this.snap(this.minuteAt(event.clientY, column));
|
|
483
|
+
this.begin(event, { kind: 'select', dayIndex, fromMin: minute, atMin: minute });
|
|
484
|
+
}
|
|
485
|
+
startMove(event, placed, dayIndex) {
|
|
486
|
+
if (!this.canDrag(placed) || event.button !== 0) {
|
|
487
|
+
return;
|
|
488
|
+
}
|
|
489
|
+
// Stop the column beneath from also starting a range-select under the same finger.
|
|
490
|
+
event.stopPropagation();
|
|
491
|
+
const column = event.currentTarget.closest('[data-sds-day]');
|
|
492
|
+
if (!column) {
|
|
493
|
+
return;
|
|
494
|
+
}
|
|
495
|
+
const startMin = minutesOfDay(placed.start);
|
|
496
|
+
const durationMin = Math.max(this.snapMinutes(), Math.round((placed.end.getTime() - placed.start.getTime()) / 60_000));
|
|
497
|
+
this.begin(event, {
|
|
498
|
+
kind: 'move',
|
|
499
|
+
dayIndex,
|
|
500
|
+
placed,
|
|
501
|
+
durationMin,
|
|
502
|
+
// Where in the block the finger went down, so it does not jump to the top on the first move.
|
|
503
|
+
grabOffsetMin: this.minuteAt(event.clientY, column) - startMin,
|
|
504
|
+
atMin: startMin,
|
|
505
|
+
});
|
|
506
|
+
}
|
|
507
|
+
/**
|
|
508
|
+
* Listeners are attached for the gesture and removed on release, rather than living on the host
|
|
509
|
+
* for the component's whole life. A calendar sitting idle on a dashboard should not be handling
|
|
510
|
+
* every pointer move on the page.
|
|
511
|
+
*/
|
|
512
|
+
begin(event, state) {
|
|
513
|
+
this.drag.set(state);
|
|
514
|
+
this.dragging.set(false);
|
|
515
|
+
const startY = event.clientY;
|
|
516
|
+
const startX = event.clientX;
|
|
517
|
+
const move = (moved) => {
|
|
518
|
+
const current = this.drag();
|
|
519
|
+
if (!current) {
|
|
520
|
+
return;
|
|
521
|
+
}
|
|
522
|
+
// A few pixels of slop, so a click with a shaky hand is still a click.
|
|
523
|
+
if (!this.dragging() &&
|
|
524
|
+
Math.abs(moved.clientY - startY) < 4 &&
|
|
525
|
+
Math.abs(moved.clientX - startX) < 4) {
|
|
526
|
+
return;
|
|
527
|
+
}
|
|
528
|
+
this.dragging.set(true);
|
|
529
|
+
const column = this.columnAt(moved.clientX, moved.clientY);
|
|
530
|
+
const dayIndex = column ? Number(column.dataset['sdsDay']) : current.dayIndex;
|
|
531
|
+
const target = column ?? this.columnFor(current.dayIndex);
|
|
532
|
+
if (!target) {
|
|
533
|
+
return;
|
|
534
|
+
}
|
|
535
|
+
const raw = this.minuteAt(moved.clientY, target);
|
|
536
|
+
const atMin = current.kind === 'move' ? this.snap(raw - current.grabOffsetMin) : this.snap(raw);
|
|
537
|
+
this.drag.set({ ...current, dayIndex, atMin });
|
|
538
|
+
};
|
|
539
|
+
const up = () => {
|
|
540
|
+
window.removeEventListener('pointermove', move);
|
|
541
|
+
window.removeEventListener('pointerup', up);
|
|
542
|
+
window.removeEventListener('pointercancel', up);
|
|
543
|
+
const finished = this.drag();
|
|
544
|
+
const moved = this.dragging();
|
|
545
|
+
this.drag.set(null);
|
|
546
|
+
this.dragging.set(false);
|
|
547
|
+
if (finished && moved) {
|
|
548
|
+
this.suppressClick = true;
|
|
549
|
+
// If no click follows (the pointer left the grid, a touch cancel), do not swallow the
|
|
550
|
+
// NEXT genuine one — a flag that outlives its gesture is a dead control.
|
|
551
|
+
setTimeout(() => {
|
|
552
|
+
this.suppressClick = false;
|
|
553
|
+
});
|
|
554
|
+
this.finish(finished);
|
|
555
|
+
}
|
|
556
|
+
};
|
|
557
|
+
window.addEventListener('pointermove', move);
|
|
558
|
+
window.addEventListener('pointerup', up);
|
|
559
|
+
window.addEventListener('pointercancel', up);
|
|
560
|
+
}
|
|
561
|
+
finish(drag) {
|
|
562
|
+
const day = this.days()[drag.dayIndex];
|
|
563
|
+
if (!day) {
|
|
564
|
+
return;
|
|
565
|
+
}
|
|
566
|
+
if (drag.kind === 'move') {
|
|
567
|
+
const start = this.atMinute(day, drag.atMin);
|
|
568
|
+
this.eventDrop.emit({
|
|
569
|
+
event: drag.placed.event,
|
|
570
|
+
start,
|
|
571
|
+
end: new Date(start.getTime() + drag.durationMin * 60_000),
|
|
572
|
+
});
|
|
573
|
+
return;
|
|
574
|
+
}
|
|
575
|
+
const from = Math.min(drag.fromMin, drag.atMin);
|
|
576
|
+
const to = Math.max(drag.fromMin, drag.atMin);
|
|
577
|
+
if (to - from < this.snapMinutes()) {
|
|
578
|
+
// Not a span — the click handler will treat it as a slot click.
|
|
579
|
+
return;
|
|
580
|
+
}
|
|
581
|
+
this.rangeSelect.emit({ start: this.atMinute(day, from), end: this.atMinute(day, to) });
|
|
582
|
+
}
|
|
583
|
+
snap(minute) {
|
|
584
|
+
return snapMinute(minute, this.snapMinutes(), this.startHour(), this.endHour());
|
|
585
|
+
}
|
|
586
|
+
minuteAt(clientY, column) {
|
|
587
|
+
const y = clientY - column.getBoundingClientRect().top;
|
|
588
|
+
return this.startHour() * 60 + (y / this.hourHeight()) * 60;
|
|
589
|
+
}
|
|
590
|
+
atMinute(day, minute) {
|
|
591
|
+
return new Date(startOfDay(day).getTime() + minute * 60_000);
|
|
592
|
+
}
|
|
593
|
+
columnAt(x, y) {
|
|
594
|
+
return (document
|
|
595
|
+
.elementsFromPoint(x, y)
|
|
596
|
+
.find((el) => el instanceof HTMLElement && !!el.dataset['sdsDay']) ??
|
|
597
|
+
null);
|
|
598
|
+
}
|
|
599
|
+
columnFor(dayIndex) {
|
|
600
|
+
return this.host.nativeElement.querySelector(`[data-sds-day="${dayIndex}"]`);
|
|
601
|
+
}
|
|
602
|
+
/** True once, for the click that a just-finished drag is about to produce. */
|
|
603
|
+
swallowed() {
|
|
604
|
+
if (!this.suppressClick) {
|
|
605
|
+
return false;
|
|
606
|
+
}
|
|
607
|
+
this.suppressClick = false;
|
|
608
|
+
return true;
|
|
609
|
+
}
|
|
610
|
+
hhmm(minute) {
|
|
611
|
+
const h = Math.floor(minute / 60);
|
|
612
|
+
const m = Math.round(minute % 60);
|
|
613
|
+
return `${String(h).padStart(2, '0')}:${String(m).padStart(2, '0')}`;
|
|
614
|
+
}
|
|
406
615
|
onEventClick(event, placed) {
|
|
407
616
|
// Without this the click falls through to the grid and also opens "new appointment".
|
|
408
617
|
event.stopPropagation();
|
|
618
|
+
if (this.swallowed()) {
|
|
619
|
+
return;
|
|
620
|
+
}
|
|
409
621
|
this.eventClick.emit(placed.event);
|
|
410
622
|
}
|
|
411
623
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: SdsEventCalendar, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
412
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: SdsEventCalendar, isStandalone: true, selector: "sds-event-calendar", inputs: { events: { classPropertyName: "events", publicName: "events", isSignal: true, isRequired: false, transformFunction: null }, view: { classPropertyName: "view", publicName: "view", isSignal: true, isRequired: false, transformFunction: null }, date: { classPropertyName: "date", publicName: "date", isSignal: true, isRequired: false, transformFunction: null }, firstDayOfWeek: { classPropertyName: "firstDayOfWeek", publicName: "firstDayOfWeek", isSignal: true, isRequired: false, transformFunction: null }, startHour: { classPropertyName: "startHour", publicName: "startHour", isSignal: true, isRequired: false, transformFunction: null }, endHour: { classPropertyName: "endHour", publicName: "endHour", isSignal: true, isRequired: false, transformFunction: null }, hourHeight: { classPropertyName: "hourHeight", publicName: "hourHeight", isSignal: true, isRequired: false, transformFunction: null }, defaultMinutes: { classPropertyName: "defaultMinutes", publicName: "defaultMinutes", isSignal: true, isRequired: false, transformFunction: null }, height: { classPropertyName: "height", publicName: "height", isSignal: true, isRequired: false, transformFunction: null }, locale: { classPropertyName: "locale", publicName: "locale", isSignal: true, isRequired: false, transformFunction: null }, nowIndicator: { classPropertyName: "nowIndicator", publicName: "nowIndicator", isSignal: true, isRequired: false, transformFunction: null }, showToolbar: { classPropertyName: "showToolbar", publicName: "showToolbar", isSignal: true, isRequired: false, transformFunction: null }, showViewSwitcher: { classPropertyName: "showViewSwitcher", publicName: "showViewSwitcher", isSignal: true, isRequired: false, transformFunction: null }, maxPerCell: { classPropertyName: "maxPerCell", publicName: "maxPerCell", isSignal: true, isRequired: false, transformFunction: null }, todayLabel: { classPropertyName: "todayLabel", publicName: "todayLabel", isSignal: true, isRequired: false, transformFunction: null }, previousLabel: { classPropertyName: "previousLabel", publicName: "previousLabel", isSignal: true, isRequired: false, transformFunction: null }, nextLabel: { classPropertyName: "nextLabel", publicName: "nextLabel", isSignal: true, isRequired: false, transformFunction: null }, allDayLabel: { classPropertyName: "allDayLabel", publicName: "allDayLabel", isSignal: true, isRequired: false, transformFunction: null }, moreLabel: { classPropertyName: "moreLabel", publicName: "moreLabel", isSignal: true, isRequired: false, transformFunction: null }, viewSwitcherLabel: { classPropertyName: "viewSwitcherLabel", publicName: "viewSwitcherLabel", isSignal: true, isRequired: false, transformFunction: null }, monthLabel: { classPropertyName: "monthLabel", publicName: "monthLabel", isSignal: true, isRequired: false, transformFunction: null }, weekLabel: { classPropertyName: "weekLabel", publicName: "weekLabel", isSignal: true, isRequired: false, transformFunction: null }, threeDayLabel: { classPropertyName: "threeDayLabel", publicName: "threeDayLabel", isSignal: true, isRequired: false, transformFunction: null }, dayLabel: { classPropertyName: "dayLabel", publicName: "dayLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { view: "viewChange", date: "dateChange", eventClick: "eventClick", slotClick: "slotClick", dayClick: "dayClick", rangeChange: "rangeChange" }, host: { classAttribute: "block" }, ngImport: i0, template: `
|
|
624
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.25", type: SdsEventCalendar, isStandalone: true, selector: "sds-event-calendar", inputs: { events: { classPropertyName: "events", publicName: "events", isSignal: true, isRequired: false, transformFunction: null }, view: { classPropertyName: "view", publicName: "view", isSignal: true, isRequired: false, transformFunction: null }, date: { classPropertyName: "date", publicName: "date", isSignal: true, isRequired: false, transformFunction: null }, firstDayOfWeek: { classPropertyName: "firstDayOfWeek", publicName: "firstDayOfWeek", isSignal: true, isRequired: false, transformFunction: null }, startHour: { classPropertyName: "startHour", publicName: "startHour", isSignal: true, isRequired: false, transformFunction: null }, endHour: { classPropertyName: "endHour", publicName: "endHour", isSignal: true, isRequired: false, transformFunction: null }, hourHeight: { classPropertyName: "hourHeight", publicName: "hourHeight", isSignal: true, isRequired: false, transformFunction: null }, defaultMinutes: { classPropertyName: "defaultMinutes", publicName: "defaultMinutes", isSignal: true, isRequired: false, transformFunction: null }, height: { classPropertyName: "height", publicName: "height", isSignal: true, isRequired: false, transformFunction: null }, locale: { classPropertyName: "locale", publicName: "locale", isSignal: true, isRequired: false, transformFunction: null }, nowIndicator: { classPropertyName: "nowIndicator", publicName: "nowIndicator", isSignal: true, isRequired: false, transformFunction: null }, showToolbar: { classPropertyName: "showToolbar", publicName: "showToolbar", isSignal: true, isRequired: false, transformFunction: null }, showViewSwitcher: { classPropertyName: "showViewSwitcher", publicName: "showViewSwitcher", isSignal: true, isRequired: false, transformFunction: null }, maxPerCell: { classPropertyName: "maxPerCell", publicName: "maxPerCell", isSignal: true, isRequired: false, transformFunction: null }, todayLabel: { classPropertyName: "todayLabel", publicName: "todayLabel", isSignal: true, isRequired: false, transformFunction: null }, previousLabel: { classPropertyName: "previousLabel", publicName: "previousLabel", isSignal: true, isRequired: false, transformFunction: null }, nextLabel: { classPropertyName: "nextLabel", publicName: "nextLabel", isSignal: true, isRequired: false, transformFunction: null }, allDayLabel: { classPropertyName: "allDayLabel", publicName: "allDayLabel", isSignal: true, isRequired: false, transformFunction: null }, moreLabel: { classPropertyName: "moreLabel", publicName: "moreLabel", isSignal: true, isRequired: false, transformFunction: null }, viewSwitcherLabel: { classPropertyName: "viewSwitcherLabel", publicName: "viewSwitcherLabel", isSignal: true, isRequired: false, transformFunction: null }, monthLabel: { classPropertyName: "monthLabel", publicName: "monthLabel", isSignal: true, isRequired: false, transformFunction: null }, weekLabel: { classPropertyName: "weekLabel", publicName: "weekLabel", isSignal: true, isRequired: false, transformFunction: null }, threeDayLabel: { classPropertyName: "threeDayLabel", publicName: "threeDayLabel", isSignal: true, isRequired: false, transformFunction: null }, dayLabel: { classPropertyName: "dayLabel", publicName: "dayLabel", isSignal: true, isRequired: false, transformFunction: null }, draggable: { classPropertyName: "draggable", publicName: "draggable", isSignal: true, isRequired: false, transformFunction: null }, selectable: { classPropertyName: "selectable", publicName: "selectable", isSignal: true, isRequired: false, transformFunction: null }, snapMinutes: { classPropertyName: "snapMinutes", publicName: "snapMinutes", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { view: "viewChange", date: "dateChange", eventClick: "eventClick", eventDrop: "eventDrop", rangeSelect: "rangeSelect", slotClick: "slotClick", dayClick: "dayClick", rangeChange: "rangeChange" }, host: { classAttribute: "block" }, ngImport: i0, template: `
|
|
413
625
|
<div class="flex flex-col overflow-hidden rounded-card border border-border bg-surface">
|
|
414
626
|
@if (showToolbar()) {
|
|
415
627
|
<div class="flex flex-wrap items-center gap-x-3 gap-y-2 border-b border-border px-3 py-2.5">
|
|
@@ -588,11 +800,13 @@ class SdsEventCalendar {
|
|
|
588
800
|
}
|
|
589
801
|
</div>
|
|
590
802
|
|
|
591
|
-
@for (day of days(); track day.getTime()) {
|
|
803
|
+
@for (day of days(); track day.getTime(); let dayIndex = $index) {
|
|
592
804
|
<div
|
|
593
|
-
class="relative border-r border-border last:border-r-0"
|
|
805
|
+
class="relative touch-none border-r border-border last:border-r-0"
|
|
806
|
+
[attr.data-sds-day]="dayIndex"
|
|
594
807
|
[style.height.px]="bodyHeight()"
|
|
595
808
|
(click)="onGridClick($event, day)"
|
|
809
|
+
(pointerdown)="startSelect($event, dayIndex)"
|
|
596
810
|
>
|
|
597
811
|
@for (h of hours(); track h) {
|
|
598
812
|
<div
|
|
@@ -601,6 +815,25 @@ class SdsEventCalendar {
|
|
|
601
815
|
></div>
|
|
602
816
|
}
|
|
603
817
|
|
|
818
|
+
@if (ghostFor(dayIndex); as ghost) {
|
|
819
|
+
<!--
|
|
820
|
+
What the drag will produce, drawn where it will land. A drag with no preview
|
|
821
|
+
is a guess: you find out what you did once the server has been told.
|
|
822
|
+
-->
|
|
823
|
+
<div
|
|
824
|
+
class="pointer-events-none absolute inset-x-0.5 z-30 rounded border-2 border-dashed border-brand-500 bg-brand-500/15"
|
|
825
|
+
[style.top.px]="ghost.top"
|
|
826
|
+
[style.height.px]="ghost.height"
|
|
827
|
+
aria-hidden="true"
|
|
828
|
+
>
|
|
829
|
+
<span
|
|
830
|
+
class="block px-1 pt-0.5 text-[10px] font-medium text-brand-700 dark:text-brand-200"
|
|
831
|
+
>
|
|
832
|
+
{{ ghost.label }}
|
|
833
|
+
</span>
|
|
834
|
+
</div>
|
|
835
|
+
}
|
|
836
|
+
|
|
604
837
|
@if (nowIndicator() && isToday(day) && nowTop() !== null) {
|
|
605
838
|
<div
|
|
606
839
|
class="pointer-events-none absolute inset-x-0 z-20 flex items-center"
|
|
@@ -628,7 +861,10 @@ class SdsEventCalendar {
|
|
|
628
861
|
[attr.aria-label]="
|
|
629
862
|
p.event.title + ', ' + clock(p.start) + ' – ' + clock(p.end)
|
|
630
863
|
"
|
|
864
|
+
[class.cursor-grab]="canDrag(p)"
|
|
865
|
+
[class.opacity-40]="isDragging(p)"
|
|
631
866
|
(click)="onEventClick($event, p)"
|
|
867
|
+
(pointerdown)="startMove($event, p, dayIndex)"
|
|
632
868
|
>
|
|
633
869
|
<span class="block truncate text-[11px] font-medium leading-tight">
|
|
634
870
|
{{ p.event.title }}
|
|
@@ -839,11 +1075,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
839
1075
|
}
|
|
840
1076
|
</div>
|
|
841
1077
|
|
|
842
|
-
@for (day of days(); track day.getTime()) {
|
|
1078
|
+
@for (day of days(); track day.getTime(); let dayIndex = $index) {
|
|
843
1079
|
<div
|
|
844
|
-
class="relative border-r border-border last:border-r-0"
|
|
1080
|
+
class="relative touch-none border-r border-border last:border-r-0"
|
|
1081
|
+
[attr.data-sds-day]="dayIndex"
|
|
845
1082
|
[style.height.px]="bodyHeight()"
|
|
846
1083
|
(click)="onGridClick($event, day)"
|
|
1084
|
+
(pointerdown)="startSelect($event, dayIndex)"
|
|
847
1085
|
>
|
|
848
1086
|
@for (h of hours(); track h) {
|
|
849
1087
|
<div
|
|
@@ -852,6 +1090,25 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
852
1090
|
></div>
|
|
853
1091
|
}
|
|
854
1092
|
|
|
1093
|
+
@if (ghostFor(dayIndex); as ghost) {
|
|
1094
|
+
<!--
|
|
1095
|
+
What the drag will produce, drawn where it will land. A drag with no preview
|
|
1096
|
+
is a guess: you find out what you did once the server has been told.
|
|
1097
|
+
-->
|
|
1098
|
+
<div
|
|
1099
|
+
class="pointer-events-none absolute inset-x-0.5 z-30 rounded border-2 border-dashed border-brand-500 bg-brand-500/15"
|
|
1100
|
+
[style.top.px]="ghost.top"
|
|
1101
|
+
[style.height.px]="ghost.height"
|
|
1102
|
+
aria-hidden="true"
|
|
1103
|
+
>
|
|
1104
|
+
<span
|
|
1105
|
+
class="block px-1 pt-0.5 text-[10px] font-medium text-brand-700 dark:text-brand-200"
|
|
1106
|
+
>
|
|
1107
|
+
{{ ghost.label }}
|
|
1108
|
+
</span>
|
|
1109
|
+
</div>
|
|
1110
|
+
}
|
|
1111
|
+
|
|
855
1112
|
@if (nowIndicator() && isToday(day) && nowTop() !== null) {
|
|
856
1113
|
<div
|
|
857
1114
|
class="pointer-events-none absolute inset-x-0 z-20 flex items-center"
|
|
@@ -879,7 +1136,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
879
1136
|
[attr.aria-label]="
|
|
880
1137
|
p.event.title + ', ' + clock(p.start) + ' – ' + clock(p.end)
|
|
881
1138
|
"
|
|
1139
|
+
[class.cursor-grab]="canDrag(p)"
|
|
1140
|
+
[class.opacity-40]="isDragging(p)"
|
|
882
1141
|
(click)="onEventClick($event, p)"
|
|
1142
|
+
(pointerdown)="startMove($event, p, dayIndex)"
|
|
883
1143
|
>
|
|
884
1144
|
<span class="block truncate text-[11px] font-medium leading-tight">
|
|
885
1145
|
{{ p.event.title }}
|
|
@@ -904,7 +1164,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
904
1164
|
</div>
|
|
905
1165
|
`,
|
|
906
1166
|
}]
|
|
907
|
-
}], ctorParameters: () => [], propDecorators: { events: [{ type: i0.Input, args: [{ isSignal: true, alias: "events", required: false }] }], view: [{ type: i0.Input, args: [{ isSignal: true, alias: "view", required: false }] }, { type: i0.Output, args: ["viewChange"] }], date: [{ type: i0.Input, args: [{ isSignal: true, alias: "date", required: false }] }, { type: i0.Output, args: ["dateChange"] }], firstDayOfWeek: [{ type: i0.Input, args: [{ isSignal: true, alias: "firstDayOfWeek", required: false }] }], startHour: [{ type: i0.Input, args: [{ isSignal: true, alias: "startHour", required: false }] }], endHour: [{ type: i0.Input, args: [{ isSignal: true, alias: "endHour", required: false }] }], hourHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "hourHeight", required: false }] }], defaultMinutes: [{ type: i0.Input, args: [{ isSignal: true, alias: "defaultMinutes", required: false }] }], height: [{ type: i0.Input, args: [{ isSignal: true, alias: "height", required: false }] }], locale: [{ type: i0.Input, args: [{ isSignal: true, alias: "locale", required: false }] }], nowIndicator: [{ type: i0.Input, args: [{ isSignal: true, alias: "nowIndicator", required: false }] }], showToolbar: [{ type: i0.Input, args: [{ isSignal: true, alias: "showToolbar", required: false }] }], showViewSwitcher: [{ type: i0.Input, args: [{ isSignal: true, alias: "showViewSwitcher", required: false }] }], maxPerCell: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxPerCell", required: false }] }], todayLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "todayLabel", required: false }] }], previousLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "previousLabel", required: false }] }], nextLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "nextLabel", required: false }] }], allDayLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "allDayLabel", required: false }] }], moreLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "moreLabel", required: false }] }], viewSwitcherLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "viewSwitcherLabel", required: false }] }], monthLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "monthLabel", required: false }] }], weekLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "weekLabel", required: false }] }], threeDayLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "threeDayLabel", required: false }] }], dayLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "dayLabel", required: false }] }], eventClick: [{ type: i0.Output, args: ["eventClick"] }], slotClick: [{ type: i0.Output, args: ["slotClick"] }], dayClick: [{ type: i0.Output, args: ["dayClick"] }], rangeChange: [{ type: i0.Output, args: ["rangeChange"] }] } });
|
|
1167
|
+
}], ctorParameters: () => [], propDecorators: { events: [{ type: i0.Input, args: [{ isSignal: true, alias: "events", required: false }] }], view: [{ type: i0.Input, args: [{ isSignal: true, alias: "view", required: false }] }, { type: i0.Output, args: ["viewChange"] }], date: [{ type: i0.Input, args: [{ isSignal: true, alias: "date", required: false }] }, { type: i0.Output, args: ["dateChange"] }], firstDayOfWeek: [{ type: i0.Input, args: [{ isSignal: true, alias: "firstDayOfWeek", required: false }] }], startHour: [{ type: i0.Input, args: [{ isSignal: true, alias: "startHour", required: false }] }], endHour: [{ type: i0.Input, args: [{ isSignal: true, alias: "endHour", required: false }] }], hourHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "hourHeight", required: false }] }], defaultMinutes: [{ type: i0.Input, args: [{ isSignal: true, alias: "defaultMinutes", required: false }] }], height: [{ type: i0.Input, args: [{ isSignal: true, alias: "height", required: false }] }], locale: [{ type: i0.Input, args: [{ isSignal: true, alias: "locale", required: false }] }], nowIndicator: [{ type: i0.Input, args: [{ isSignal: true, alias: "nowIndicator", required: false }] }], showToolbar: [{ type: i0.Input, args: [{ isSignal: true, alias: "showToolbar", required: false }] }], showViewSwitcher: [{ type: i0.Input, args: [{ isSignal: true, alias: "showViewSwitcher", required: false }] }], maxPerCell: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxPerCell", required: false }] }], todayLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "todayLabel", required: false }] }], previousLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "previousLabel", required: false }] }], nextLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "nextLabel", required: false }] }], allDayLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "allDayLabel", required: false }] }], moreLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "moreLabel", required: false }] }], viewSwitcherLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "viewSwitcherLabel", required: false }] }], monthLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "monthLabel", required: false }] }], weekLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "weekLabel", required: false }] }], threeDayLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "threeDayLabel", required: false }] }], dayLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "dayLabel", required: false }] }], draggable: [{ type: i0.Input, args: [{ isSignal: true, alias: "draggable", required: false }] }], selectable: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectable", required: false }] }], snapMinutes: [{ type: i0.Input, args: [{ isSignal: true, alias: "snapMinutes", required: false }] }], eventClick: [{ type: i0.Output, args: ["eventClick"] }], eventDrop: [{ type: i0.Output, args: ["eventDrop"] }], rangeSelect: [{ type: i0.Output, args: ["rangeSelect"] }], slotClick: [{ type: i0.Output, args: ["slotClick"] }], dayClick: [{ type: i0.Output, args: ["dayClick"] }], rangeChange: [{ type: i0.Output, args: ["rangeChange"] }] } });
|
|
908
1168
|
|
|
909
1169
|
/*
|
|
910
1170
|
* @besaitech/ng-design-system/calendar — the event calendar, kept OUT of the main entry point.
|
|
@@ -920,5 +1180,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
920
1180
|
* Generated bundle index. Do not edit.
|
|
921
1181
|
*/
|
|
922
1182
|
|
|
923
|
-
export { SdsEventCalendar, allDayOn, eventsOn, minutesOfDay, occursOn, placeDay, startOfWeek, step, toDate, visibleDays, visibleRange };
|
|
1183
|
+
export { SdsEventCalendar, allDayOn, eventsOn, minutesOfDay, occursOn, placeDay, snapMinute, startOfWeek, step, toDate, visibleDays, visibleRange };
|
|
924
1184
|
//# sourceMappingURL=besaitech-ng-design-system-calendar.mjs.map
|