@ngxsmk/cdk 1.3.1 → 2.0.0

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.
Files changed (179) hide show
  1. package/README.md +1 -1
  2. package/cva-base/cva-base.d.ts +34 -0
  3. package/cva-base/cva-base.d.ts.map +1 -0
  4. package/cva-base/index.d.ts +2 -0
  5. package/cva-base/index.d.ts.map +1 -0
  6. package/cva-base/ngxsmk-cdk-cva-base.d.ts.map +1 -0
  7. package/esm2022/cva-base/cva-base.mjs +45 -0
  8. package/esm2022/cva-base/index.mjs +2 -0
  9. package/esm2022/cva-base/ngxsmk-cdk-cva-base.mjs +5 -0
  10. package/esm2022/input-group/index.mjs +3 -0
  11. package/esm2022/input-group/input-group-engine.mjs +219 -0
  12. package/esm2022/input-group/models/index.mjs +2 -0
  13. package/esm2022/input-group/models/input-group.model.mjs +2 -0
  14. package/esm2022/input-group/ngxsmk-cdk-input-group.mjs +5 -0
  15. package/esm2022/listbox-keyboard/index.mjs +2 -0
  16. package/esm2022/listbox-keyboard/listbox-keyboard.mjs +145 -0
  17. package/esm2022/listbox-keyboard/ngxsmk-cdk-listbox-keyboard.mjs +5 -0
  18. package/esm2022/public-api.mjs +10 -1
  19. package/esm2022/scheduler/index.mjs +5 -0
  20. package/esm2022/scheduler/models/date-range.mjs +2 -0
  21. package/esm2022/scheduler/models/event.model.mjs +2 -0
  22. package/esm2022/scheduler/models/index.mjs +6 -0
  23. package/esm2022/scheduler/models/resource.model.mjs +5 -0
  24. package/esm2022/scheduler/models/selection.model.mjs +7 -0
  25. package/esm2022/scheduler/models/view.model.mjs +7 -0
  26. package/esm2022/scheduler/ngxsmk-cdk-scheduler.mjs +5 -0
  27. package/esm2022/scheduler/plugin/drag-plugin.mjs +82 -0
  28. package/esm2022/scheduler/plugin/index.mjs +8 -0
  29. package/esm2022/scheduler/plugin/keyboard-plugin.mjs +150 -0
  30. package/esm2022/scheduler/plugin/plugin-host.mjs +48 -0
  31. package/esm2022/scheduler/plugin/plugin.types.mjs +2 -0
  32. package/esm2022/scheduler/plugin/resize-plugin.mjs +74 -0
  33. package/esm2022/scheduler/plugin/selection-plugin.mjs +84 -0
  34. package/esm2022/scheduler/plugin/tooltip-plugin.mjs +103 -0
  35. package/esm2022/scheduler/scheduler-engine.mjs +316 -0
  36. package/esm2022/scheduler/utils/date-utils.mjs +131 -0
  37. package/esm2022/scheduler/utils/index.mjs +3 -0
  38. package/esm2022/scheduler/utils/snap.mjs +24 -0
  39. package/esm2022/spreadsheet/index.mjs +5 -0
  40. package/esm2022/spreadsheet/models/cell.model.mjs +2 -0
  41. package/esm2022/spreadsheet/models/column.model.mjs +2 -0
  42. package/esm2022/spreadsheet/models/filter.model.mjs +2 -0
  43. package/esm2022/spreadsheet/models/formula.model.mjs +2 -0
  44. package/esm2022/spreadsheet/models/index.mjs +8 -0
  45. package/esm2022/spreadsheet/models/row.model.mjs +2 -0
  46. package/esm2022/spreadsheet/models/selection.model.mjs +2 -0
  47. package/esm2022/spreadsheet/models/sort.model.mjs +2 -0
  48. package/esm2022/spreadsheet/ngxsmk-cdk-spreadsheet.mjs +5 -0
  49. package/esm2022/spreadsheet/plugin/clipboard-plugin.mjs +171 -0
  50. package/esm2022/spreadsheet/plugin/filter-plugin.mjs +87 -0
  51. package/esm2022/spreadsheet/plugin/formula-plugin.mjs +456 -0
  52. package/esm2022/spreadsheet/plugin/index.mjs +10 -0
  53. package/esm2022/spreadsheet/plugin/plugin-host.mjs +188 -0
  54. package/esm2022/spreadsheet/plugin/plugin.types.mjs +2 -0
  55. package/esm2022/spreadsheet/plugin/selection-plugin.mjs +114 -0
  56. package/esm2022/spreadsheet/plugin/sort-plugin.mjs +63 -0
  57. package/esm2022/spreadsheet/plugin/undo-plugin.mjs +138 -0
  58. package/esm2022/spreadsheet/plugin/validation-plugin.mjs +71 -0
  59. package/esm2022/spreadsheet/spreadsheet-engine.mjs +547 -0
  60. package/esm2022/spreadsheet/utils/cell-utils.mjs +129 -0
  61. package/esm2022/spreadsheet/utils/index.mjs +2 -0
  62. package/esm2022/testing/a11y.mjs +6 -3
  63. package/fesm2022/ngxsmk-cdk-cva-base.mjs +52 -0
  64. package/fesm2022/ngxsmk-cdk-cva-base.mjs.map +1 -0
  65. package/fesm2022/ngxsmk-cdk-input-group.mjs +226 -0
  66. package/fesm2022/ngxsmk-cdk-input-group.mjs.map +1 -0
  67. package/fesm2022/ngxsmk-cdk-listbox-keyboard.mjs +152 -0
  68. package/fesm2022/ngxsmk-cdk-listbox-keyboard.mjs.map +1 -0
  69. package/fesm2022/ngxsmk-cdk-scheduler.mjs +1035 -0
  70. package/fesm2022/ngxsmk-cdk-scheduler.mjs.map +1 -0
  71. package/fesm2022/ngxsmk-cdk-spreadsheet.mjs +1969 -0
  72. package/fesm2022/ngxsmk-cdk-spreadsheet.mjs.map +1 -0
  73. package/fesm2022/ngxsmk-cdk-testing.mjs +5 -2
  74. package/fesm2022/ngxsmk-cdk-testing.mjs.map +1 -1
  75. package/fesm2022/ngxsmk-cdk.mjs +5 -0
  76. package/fesm2022/ngxsmk-cdk.mjs.map +1 -1
  77. package/input-group/index.d.ts +3 -0
  78. package/input-group/index.d.ts.map +1 -0
  79. package/input-group/input-group-engine.d.ts +88 -0
  80. package/input-group/input-group-engine.d.ts.map +1 -0
  81. package/input-group/models/index.d.ts +2 -0
  82. package/input-group/models/index.d.ts.map +1 -0
  83. package/input-group/models/input-group.model.d.ts +114 -0
  84. package/input-group/models/input-group.model.d.ts.map +1 -0
  85. package/input-group/ngxsmk-cdk-input-group.d.ts.map +1 -0
  86. package/listbox-keyboard/index.d.ts +2 -0
  87. package/listbox-keyboard/index.d.ts.map +1 -0
  88. package/listbox-keyboard/listbox-keyboard.d.ts +60 -0
  89. package/listbox-keyboard/listbox-keyboard.d.ts.map +1 -0
  90. package/listbox-keyboard/ngxsmk-cdk-listbox-keyboard.d.ts.map +1 -0
  91. package/package.json +40 -1
  92. package/public-api.d.ts +8 -0
  93. package/public-api.d.ts.map +1 -1
  94. package/scheduler/index.d.ts +5 -0
  95. package/scheduler/index.d.ts.map +1 -0
  96. package/scheduler/models/date-range.d.ts +6 -0
  97. package/scheduler/models/date-range.d.ts.map +1 -0
  98. package/scheduler/models/event.model.d.ts +50 -0
  99. package/scheduler/models/event.model.d.ts.map +1 -0
  100. package/scheduler/models/index.d.ts +6 -0
  101. package/scheduler/models/index.d.ts.map +1 -0
  102. package/scheduler/models/resource.model.d.ts +16 -0
  103. package/scheduler/models/resource.model.d.ts.map +1 -0
  104. package/scheduler/models/selection.model.d.ts +12 -0
  105. package/scheduler/models/selection.model.d.ts.map +1 -0
  106. package/scheduler/models/view.model.d.ts +21 -0
  107. package/scheduler/models/view.model.d.ts.map +1 -0
  108. package/scheduler/ngxsmk-cdk-scheduler.d.ts.map +1 -0
  109. package/scheduler/plugin/drag-plugin.d.ts +28 -0
  110. package/scheduler/plugin/drag-plugin.d.ts.map +1 -0
  111. package/scheduler/plugin/index.d.ts +8 -0
  112. package/scheduler/plugin/index.d.ts.map +1 -0
  113. package/scheduler/plugin/keyboard-plugin.d.ts +24 -0
  114. package/scheduler/plugin/keyboard-plugin.d.ts.map +1 -0
  115. package/scheduler/plugin/plugin-host.d.ts +16 -0
  116. package/scheduler/plugin/plugin-host.d.ts.map +1 -0
  117. package/scheduler/plugin/plugin.types.d.ts +9 -0
  118. package/scheduler/plugin/plugin.types.d.ts.map +1 -0
  119. package/scheduler/plugin/resize-plugin.d.ts +26 -0
  120. package/scheduler/plugin/resize-plugin.d.ts.map +1 -0
  121. package/scheduler/plugin/selection-plugin.d.ts +40 -0
  122. package/scheduler/plugin/selection-plugin.d.ts.map +1 -0
  123. package/scheduler/plugin/tooltip-plugin.d.ts +41 -0
  124. package/scheduler/plugin/tooltip-plugin.d.ts.map +1 -0
  125. package/scheduler/scheduler-engine.d.ts +95 -0
  126. package/scheduler/scheduler-engine.d.ts.map +1 -0
  127. package/scheduler/utils/date-utils.d.ts +26 -0
  128. package/scheduler/utils/date-utils.d.ts.map +1 -0
  129. package/scheduler/utils/index.d.ts +3 -0
  130. package/scheduler/utils/index.d.ts.map +1 -0
  131. package/scheduler/utils/snap.d.ts +7 -0
  132. package/scheduler/utils/snap.d.ts.map +1 -0
  133. package/spreadsheet/index.d.ts +5 -0
  134. package/spreadsheet/index.d.ts.map +1 -0
  135. package/spreadsheet/models/cell.model.d.ts +44 -0
  136. package/spreadsheet/models/cell.model.d.ts.map +1 -0
  137. package/spreadsheet/models/column.model.d.ts +77 -0
  138. package/spreadsheet/models/column.model.d.ts.map +1 -0
  139. package/spreadsheet/models/filter.model.d.ts +15 -0
  140. package/spreadsheet/models/filter.model.d.ts.map +1 -0
  141. package/spreadsheet/models/formula.model.d.ts +65 -0
  142. package/spreadsheet/models/formula.model.d.ts.map +1 -0
  143. package/spreadsheet/models/index.d.ts +8 -0
  144. package/spreadsheet/models/index.d.ts.map +1 -0
  145. package/spreadsheet/models/row.model.d.ts +33 -0
  146. package/spreadsheet/models/row.model.d.ts.map +1 -0
  147. package/spreadsheet/models/selection.model.d.ts +18 -0
  148. package/spreadsheet/models/selection.model.d.ts.map +1 -0
  149. package/spreadsheet/models/sort.model.d.ts +14 -0
  150. package/spreadsheet/models/sort.model.d.ts.map +1 -0
  151. package/spreadsheet/ngxsmk-cdk-spreadsheet.d.ts.map +1 -0
  152. package/spreadsheet/plugin/clipboard-plugin.d.ts +24 -0
  153. package/spreadsheet/plugin/clipboard-plugin.d.ts.map +1 -0
  154. package/spreadsheet/plugin/filter-plugin.d.ts +21 -0
  155. package/spreadsheet/plugin/filter-plugin.d.ts.map +1 -0
  156. package/spreadsheet/plugin/formula-plugin.d.ts +39 -0
  157. package/spreadsheet/plugin/formula-plugin.d.ts.map +1 -0
  158. package/spreadsheet/plugin/index.d.ts +10 -0
  159. package/spreadsheet/plugin/index.d.ts.map +1 -0
  160. package/spreadsheet/plugin/plugin-host.d.ts +66 -0
  161. package/spreadsheet/plugin/plugin-host.d.ts.map +1 -0
  162. package/spreadsheet/plugin/plugin.types.d.ts +58 -0
  163. package/spreadsheet/plugin/plugin.types.d.ts.map +1 -0
  164. package/spreadsheet/plugin/selection-plugin.d.ts +28 -0
  165. package/spreadsheet/plugin/selection-plugin.d.ts.map +1 -0
  166. package/spreadsheet/plugin/sort-plugin.d.ts +18 -0
  167. package/spreadsheet/plugin/sort-plugin.d.ts.map +1 -0
  168. package/spreadsheet/plugin/undo-plugin.d.ts +40 -0
  169. package/spreadsheet/plugin/undo-plugin.d.ts.map +1 -0
  170. package/spreadsheet/plugin/validation-plugin.d.ts +29 -0
  171. package/spreadsheet/plugin/validation-plugin.d.ts.map +1 -0
  172. package/spreadsheet/spreadsheet-engine.d.ts +194 -0
  173. package/spreadsheet/spreadsheet-engine.d.ts.map +1 -0
  174. package/spreadsheet/utils/cell-utils.d.ts +26 -0
  175. package/spreadsheet/utils/cell-utils.d.ts.map +1 -0
  176. package/spreadsheet/utils/index.d.ts +2 -0
  177. package/spreadsheet/utils/index.d.ts.map +1 -0
  178. package/testing/a11y.d.ts +5 -1
  179. package/testing/a11y.d.ts.map +1 -1
@@ -0,0 +1,1035 @@
1
+ import * as i0 from '@angular/core';
2
+ import { signal, computed, Injectable } from '@angular/core';
3
+
4
+ function startOfDay(date) {
5
+ const d = new Date(date);
6
+ d.setHours(0, 0, 0, 0);
7
+ return d;
8
+ }
9
+ function startOfWeek(date, firstDayOfWeek) {
10
+ const d = startOfDay(date);
11
+ const day = d.getDay();
12
+ const diff = (day - firstDayOfWeek + 7) % 7;
13
+ d.setDate(d.getDate() - diff);
14
+ return d;
15
+ }
16
+ function endOfWeek(date, firstDayOfWeek) {
17
+ const start = startOfWeek(date, firstDayOfWeek);
18
+ const end = new Date(start);
19
+ end.setDate(end.getDate() + 7);
20
+ end.setMilliseconds(-1);
21
+ return end;
22
+ }
23
+ function startOfMonth(date) {
24
+ const d = new Date(date.getFullYear(), date.getMonth(), 1);
25
+ d.setHours(0, 0, 0, 0);
26
+ return d;
27
+ }
28
+ function endOfMonth(date) {
29
+ const d = new Date(date.getFullYear(), date.getMonth() + 1, 0);
30
+ d.setHours(23, 59, 59, 999);
31
+ return d;
32
+ }
33
+ function addDays(date, days) {
34
+ const d = new Date(date);
35
+ d.setDate(d.getDate() + days);
36
+ return d;
37
+ }
38
+ function addMinutes(date, minutes) {
39
+ return new Date(date.getTime() + minutes * 60_000);
40
+ }
41
+ function addWeeks(date, weeks) {
42
+ return addDays(date, weeks * 7);
43
+ }
44
+ function diffMinutes(start, end) {
45
+ return (end.getTime() - start.getTime()) / 60_000;
46
+ }
47
+ function diffDays(start, end) {
48
+ const s = startOfDay(start);
49
+ const e = startOfDay(end);
50
+ return Math.round((e.getTime() - s.getTime()) / 86_400_000);
51
+ }
52
+ function isSameDay(a, b) {
53
+ return (a.getFullYear() === b.getFullYear() &&
54
+ a.getMonth() === b.getMonth() &&
55
+ a.getDate() === b.getDate());
56
+ }
57
+ function isSameWeek(a, b, firstDayOfWeek) {
58
+ return isSameDay(startOfWeek(a, firstDayOfWeek), startOfWeek(b, firstDayOfWeek));
59
+ }
60
+ function isToday(date) {
61
+ return isSameDay(date, new Date());
62
+ }
63
+ function isWeekend(date) {
64
+ const day = date.getDay();
65
+ return day === 0 || day === 6;
66
+ }
67
+ function isPast(date) {
68
+ return date.getTime() < Date.now();
69
+ }
70
+ function dateRangeOverlaps(aStart, aEnd, bStart, bEnd) {
71
+ return aStart.getTime() < bEnd.getTime() && aEnd.getTime() > bStart.getTime();
72
+ }
73
+ function clampDate(date, min, max) {
74
+ const t = date.getTime();
75
+ if (t < min.getTime())
76
+ return new Date(min);
77
+ if (t > max.getTime())
78
+ return new Date(max);
79
+ return new Date(date);
80
+ }
81
+ function getHoursInRange(start, end) {
82
+ const hours = [];
83
+ const d = new Date(start);
84
+ while (d < end) {
85
+ hours.push(d.getHours());
86
+ d.setHours(d.getHours() + 1, 0, 0, 0);
87
+ }
88
+ return hours;
89
+ }
90
+ function formatHour(h, locale = 'en-US') {
91
+ const d = new Date();
92
+ d.setHours(h, 0, 0, 0);
93
+ return d.toLocaleTimeString(locale, { hour: 'numeric', minute: undefined });
94
+ }
95
+ function formatDateRange(start, end, locale = 'en-US') {
96
+ const opts = { month: 'short', day: 'numeric' };
97
+ const yearOpts = { month: 'short', day: 'numeric', year: 'numeric' };
98
+ const sameYear = start.getFullYear() === end.getFullYear();
99
+ const fmt = new Intl.DateTimeFormat(locale, sameYear ? opts : yearOpts);
100
+ return `${fmt.format(start)} – ${fmt.format(end)}${sameYear ? `, ${start.getFullYear()}` : ''}`;
101
+ }
102
+ function getWeekDates(date, firstDayOfWeek) {
103
+ const start = startOfWeek(date, firstDayOfWeek);
104
+ return Array.from({ length: 7 }, (_, i) => addDays(start, i));
105
+ }
106
+ function getWorkWeekDates(date, firstDayOfWeek) {
107
+ const weekDates = getWeekDates(date, firstDayOfWeek);
108
+ return weekDates.filter((d) => !isWeekend(d));
109
+ }
110
+ function getMonthGrid(date, firstDayOfWeek) {
111
+ const monthStart = startOfMonth(date);
112
+ const gridStart = startOfWeek(monthStart, firstDayOfWeek);
113
+ const gridEnd = addDays(gridStart, 42);
114
+ const weeks = [];
115
+ let current = new Date(gridStart);
116
+ while (current < gridEnd) {
117
+ weeks.push(Array.from({ length: 7 }, (_, i) => addDays(current, i)));
118
+ current = addDays(current, 7);
119
+ }
120
+ return weeks;
121
+ }
122
+ function getDayNames(locale = 'en-US', format = 'short') {
123
+ return Array.from({ length: 7 }, (_, i) => {
124
+ const d = new Date(2026, 0, 4 + i);
125
+ return d.toLocaleDateString(locale, { weekday: format });
126
+ });
127
+ }
128
+ function getMonthNames(locale = 'en-US', format = 'long') {
129
+ return Array.from({ length: 12 }, (_, i) => {
130
+ const d = new Date(2026, i, 1);
131
+ return d.toLocaleDateString(locale, { month: format });
132
+ });
133
+ }
134
+
135
+ const HOUR_HEIGHT_MAP = {
136
+ compact: 48,
137
+ comfortable: 60,
138
+ dense: 36,
139
+ };
140
+ function computeRange(type, date, firstDayOfWeek) {
141
+ switch (type) {
142
+ case 'timeGridDay':
143
+ case 'dayGridDay':
144
+ case 'agenda':
145
+ return { start: startOfDay(date), end: addDays(startOfDay(date), 1) };
146
+ case 'timeGridWeek':
147
+ case 'dayGridWeek':
148
+ return { start: startOfWeek(date, firstDayOfWeek), end: endOfWeek(date, firstDayOfWeek) };
149
+ case 'timeGridWorkWeek': {
150
+ const weekStart = startOfWeek(date, firstDayOfWeek);
151
+ return { start: addDays(weekStart, 1), end: addDays(weekStart, 5) };
152
+ }
153
+ case 'timeGrid3Day':
154
+ return { start: startOfDay(date), end: addDays(startOfDay(date), 3) };
155
+ case 'dayGridMonth':
156
+ return { start: startOfMonth(date), end: endOfMonth(date) };
157
+ case 'timeline':
158
+ return { start: startOfWeek(date, firstDayOfWeek), end: endOfWeek(date, firstDayOfWeek) };
159
+ default:
160
+ return { start: startOfWeek(date, firstDayOfWeek), end: endOfWeek(date, firstDayOfWeek) };
161
+ }
162
+ }
163
+ class SchedulerEngine {
164
+ constructor(config = {}) {
165
+ this.now = signal(new Date());
166
+ this._config = config;
167
+ const firstDay = config.firstDayOfWeek ?? 1;
168
+ const date = config.date ?? new Date();
169
+ const view = config.defaultView ?? 'timeGridWeek';
170
+ const range = computeRange(view, date, firstDay);
171
+ this._lifecycle = {
172
+ beforeRender: signal(() => true),
173
+ afterRender: signal(() => {
174
+ /* noop */
175
+ }),
176
+ beforeCreate: signal(() => true),
177
+ afterCreate: signal(() => {
178
+ /* noop */
179
+ }),
180
+ beforeUpdate: signal(() => true),
181
+ afterUpdate: signal(() => {
182
+ /* noop */
183
+ }),
184
+ beforeDelete: signal(() => true),
185
+ afterDelete: signal(() => {
186
+ /* noop */
187
+ }),
188
+ beforeDrag: signal(() => true),
189
+ afterDrag: signal(() => {
190
+ /* noop */
191
+ }),
192
+ beforeResize: signal(() => true),
193
+ afterResize: signal(() => {
194
+ /* noop */
195
+ }),
196
+ };
197
+ this.events = signal(config.initialEvents ?? []);
198
+ this.resources = signal(config.initialResources ?? []);
199
+ this.plugins = signal(config.plugins ?? []);
200
+ this.viewState = signal({
201
+ type: view,
202
+ date: new Date(date),
203
+ rangeStart: range.start,
204
+ rangeEnd: range.end,
205
+ slotDuration: config.slotDuration ?? 30,
206
+ snapDuration: config.snapDuration ?? 15,
207
+ visibleHours: config.visibleHours ?? [0, 24],
208
+ firstDayOfWeek: firstDay,
209
+ locale: config.locale ?? 'en-US',
210
+ rtl: config.rtl ?? false,
211
+ density: config.density ?? 'comfortable',
212
+ showAllDay: config.showAllDay ?? true,
213
+ showWeekends: config.showWeekends ?? true,
214
+ showCurrentTime: config.showCurrentTime ?? true,
215
+ });
216
+ this.selection = signal({
217
+ selectedEventIds: new Set(),
218
+ selectedRange: null,
219
+ multiSelect: false,
220
+ focusedCell: null,
221
+ });
222
+ this.hourHeight = computed(() => HOUR_HEIGHT_MAP[this.viewState().density] ?? 60);
223
+ this.visibleEvents = computed(() => {
224
+ const vs = this.viewState();
225
+ const events = this.events();
226
+ return events.filter((e) => !e.allDay && dateRangeOverlaps(e.start, e.end, vs.rangeStart, vs.rangeEnd));
227
+ });
228
+ this.allDayEvents = computed(() => {
229
+ const vs = this.viewState();
230
+ const events = this.events();
231
+ return events.filter((e) => e.allDay && dateRangeOverlaps(e.start, e.end, vs.rangeStart, vs.rangeEnd));
232
+ });
233
+ this.timedEvents = computed(() => this.visibleEvents());
234
+ this.weekDates = computed(() => {
235
+ const vs = this.viewState();
236
+ const start = vs.rangeStart;
237
+ const dates = [];
238
+ let current = new Date(start);
239
+ while (current < vs.rangeEnd) {
240
+ dates.push(new Date(current));
241
+ current = addDays(current, 1);
242
+ }
243
+ return dates;
244
+ });
245
+ this.dayNames = computed(() => {
246
+ const locale = this.viewState().locale;
247
+ return Array.from({ length: 7 }, (_, i) => {
248
+ const d = startOfWeek(new Date(), this.viewState().firstDayOfWeek);
249
+ d.setDate(d.getDate() + i);
250
+ return d.toLocaleDateString(locale, { weekday: 'short' });
251
+ });
252
+ });
253
+ this.weekLabel = computed(() => {
254
+ const vs = this.viewState();
255
+ return (vs.rangeStart.toLocaleDateString(vs.locale, {
256
+ month: 'short',
257
+ day: 'numeric',
258
+ }) +
259
+ ' – ' +
260
+ vs.rangeEnd.toLocaleDateString(vs.locale, {
261
+ month: 'short',
262
+ day: 'numeric',
263
+ year: 'numeric',
264
+ }));
265
+ });
266
+ }
267
+ get lifecycle() {
268
+ return this._lifecycle;
269
+ }
270
+ // ── Navigation ──
271
+ next() {
272
+ const vs = this.viewState();
273
+ const date = addDays(vs.date, this._viewSpan(vs.type));
274
+ this._navigateTo(date);
275
+ }
276
+ previous() {
277
+ const vs = this.viewState();
278
+ const date = addDays(vs.date, -this._viewSpan(vs.type));
279
+ this._navigateTo(date);
280
+ }
281
+ today() {
282
+ this._navigateTo(new Date());
283
+ }
284
+ goto(date) {
285
+ this._navigateTo(date);
286
+ }
287
+ setView(type, date) {
288
+ const vs = this.viewState();
289
+ const refDate = date ?? vs.date;
290
+ const range = computeRange(type, refDate, vs.firstDayOfWeek);
291
+ this.viewState.update((s) => ({
292
+ ...s,
293
+ type,
294
+ date: new Date(refDate),
295
+ rangeStart: range.start,
296
+ rangeEnd: range.end,
297
+ }));
298
+ }
299
+ // ── Event Mutations ──
300
+ addEvent(event) {
301
+ if (!this._runHook(this._lifecycle.beforeCreate, event))
302
+ return;
303
+ this.events.update((evts) => [...evts, event]);
304
+ this._lifecycle.afterCreate()(event);
305
+ }
306
+ updateEvent(id, patch) {
307
+ const existing = this.events().find((e) => e.id === id);
308
+ if (!existing)
309
+ return;
310
+ const updated = { ...existing, ...patch };
311
+ if (!this._runHook(this._lifecycle.beforeUpdate, updated))
312
+ return;
313
+ this.events.update((evts) => evts.map((e) => (e.id === id ? updated : e)));
314
+ this._lifecycle.afterUpdate()(updated);
315
+ }
316
+ removeEvent(id) {
317
+ const existing = this.events().find((e) => e.id === id);
318
+ if (!existing)
319
+ return;
320
+ if (!this._runHook(this._lifecycle.beforeDelete, existing))
321
+ return;
322
+ this.events.update((evts) => evts.filter((e) => e.id !== id));
323
+ this._lifecycle.afterDelete()(existing);
324
+ }
325
+ moveEvent(id, newStart, newEnd, resourceId) {
326
+ const existing = this.events().find((e) => e.id === id);
327
+ if (!existing)
328
+ return;
329
+ const move = {
330
+ event: existing,
331
+ from: existing.start,
332
+ to: newStart,
333
+ newStart,
334
+ newEnd,
335
+ resourceId,
336
+ };
337
+ if (!this._runHook(this._lifecycle.beforeDrag, existing))
338
+ return;
339
+ this.events.update((evts) => evts.map((e) => e.id === id
340
+ ? { ...e, start: newStart, end: newEnd, resourceId: resourceId ?? e.resourceId }
341
+ : e));
342
+ this._lifecycle.afterDrag()(move);
343
+ }
344
+ resizeEvent(id, newEnd) {
345
+ const existing = this.events().find((e) => e.id === id);
346
+ if (!existing)
347
+ return;
348
+ const resize = {
349
+ event: existing,
350
+ oldEnd: existing.end,
351
+ newEnd,
352
+ };
353
+ if (!this._runHook(this._lifecycle.beforeResize, existing))
354
+ return;
355
+ this.events.update((evts) => evts.map((e) => (e.id === id ? { ...e, end: newEnd } : e)));
356
+ this._lifecycle.afterResize()(resize);
357
+ }
358
+ // ── Selection ──
359
+ selectEvent(id, multi = false) {
360
+ this.selection.update((s) => {
361
+ const ids = new Set(multi ? s.selectedEventIds : []);
362
+ if (ids.has(id)) {
363
+ ids.delete(id);
364
+ }
365
+ else {
366
+ ids.add(id);
367
+ }
368
+ return { ...s, selectedEventIds: ids };
369
+ });
370
+ }
371
+ selectRange(start, end, resourceId) {
372
+ this.selection.update((s) => ({
373
+ ...s,
374
+ selectedRange: { start, end, resourceId },
375
+ }));
376
+ }
377
+ clearSelection() {
378
+ this.selection.update((s) => ({
379
+ ...s,
380
+ selectedEventIds: new Set(),
381
+ selectedRange: null,
382
+ }));
383
+ }
384
+ isEventSelected(id) {
385
+ return this.selection().selectedEventIds.has(id);
386
+ }
387
+ // ── Queries ──
388
+ eventsForDay(day) {
389
+ return this.visibleEvents().filter((e) => isSameDay(e.start, day));
390
+ }
391
+ allDayEventsForDay(day) {
392
+ return this.allDayEvents().filter((e) => e.start.getTime() <= day.getTime() + 86_400_000 && e.end.getTime() >= day.getTime());
393
+ }
394
+ getEventsInRange(start, end) {
395
+ return this.events().filter((e) => dateRangeOverlaps(e.start, e.end, start, end));
396
+ }
397
+ eventTop(event) {
398
+ const hh = this.hourHeight();
399
+ return ((event.start.getHours() * 60 + event.start.getMinutes()) / 60) * hh;
400
+ }
401
+ eventHeight(event) {
402
+ const hh = this.hourHeight();
403
+ const durationMin = diffMinutes(event.start, event.end);
404
+ return Math.max((durationMin / 60) * hh, 18);
405
+ }
406
+ currentTimeY() {
407
+ const hh = this.hourHeight();
408
+ const now = this.now();
409
+ return ((now.getHours() * 60 + now.getMinutes()) / 60) * hh;
410
+ }
411
+ // ── Private ──
412
+ _navigateTo(date) {
413
+ const vs = this.viewState();
414
+ const range = computeRange(vs.type, date, vs.firstDayOfWeek);
415
+ this.viewState.update((s) => ({
416
+ ...s,
417
+ date: new Date(date),
418
+ rangeStart: range.start,
419
+ rangeEnd: range.end,
420
+ }));
421
+ }
422
+ _viewSpan(type) {
423
+ switch (type) {
424
+ case 'timeGridDay':
425
+ case 'dayGridDay':
426
+ case 'agenda':
427
+ return 1;
428
+ case 'timeGrid3Day':
429
+ return 3;
430
+ case 'timeGridWorkWeek':
431
+ case 'timeGridWeek':
432
+ case 'dayGridWeek':
433
+ return 7;
434
+ case 'dayGridMonth':
435
+ return 30;
436
+ case 'timeline':
437
+ return 7;
438
+ default:
439
+ return 7;
440
+ }
441
+ }
442
+ _runHook(hook, arg) {
443
+ const fn = hook();
444
+ const result = fn(arg);
445
+ return result === false ? false : true;
446
+ }
447
+ }
448
+
449
+ const DEFAULT_WORKING_HOURS = {
450
+ days: [1, 2, 3, 4, 5],
451
+ ranges: [[480, 1020]],
452
+ };
453
+
454
+ function isTimeGridView(view) {
455
+ return view.startsWith('timeGrid');
456
+ }
457
+ function isDayGridView(view) {
458
+ return view.startsWith('dayGrid');
459
+ }
460
+
461
+ const DEFAULT_SELECTION = {
462
+ selectedEventIds: new Set(),
463
+ selectedRange: null,
464
+ multiSelect: false,
465
+ focusedCell: null,
466
+ };
467
+
468
+ class PluginHost {
469
+ constructor() {
470
+ this._plugins = new Map();
471
+ this._engine = null;
472
+ }
473
+ register(engine, plugins) {
474
+ this._engine = engine;
475
+ const sorted = [...plugins].sort((a, b) => (a.priority ?? 100) - (b.priority ?? 100));
476
+ for (const plugin of sorted) {
477
+ if (this._plugins.has(plugin.name))
478
+ continue;
479
+ this._plugins.set(plugin.name, plugin);
480
+ plugin.onInit?.(engine);
481
+ }
482
+ }
483
+ unregister(name) {
484
+ const plugin = this._plugins.get(name);
485
+ if (plugin) {
486
+ plugin.onDestroy?.();
487
+ this._plugins.delete(name);
488
+ }
489
+ }
490
+ notifyRender() {
491
+ for (const plugin of this._plugins.values()) {
492
+ plugin.onRender?.();
493
+ }
494
+ }
495
+ destroy() {
496
+ for (const plugin of this._plugins.values()) {
497
+ plugin.onDestroy?.();
498
+ }
499
+ this._plugins.clear();
500
+ }
501
+ has(name) {
502
+ return this._plugins.has(name);
503
+ }
504
+ get(name) {
505
+ return this._plugins.get(name);
506
+ }
507
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.0", ngImport: i0, type: PluginHost, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
508
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.0", ngImport: i0, type: PluginHost }); }
509
+ }
510
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.0", ngImport: i0, type: PluginHost, decorators: [{
511
+ type: Injectable
512
+ }] });
513
+
514
+ class DragPlugin {
515
+ constructor(options = {}) {
516
+ this.name = 'drag';
517
+ this.priority = 10;
518
+ this._dragging = null;
519
+ this._options = options;
520
+ }
521
+ onInit(engine) {
522
+ this._engine = engine;
523
+ }
524
+ onDestroy() {
525
+ this._dragging = null;
526
+ }
527
+ startDrag(eventId, pointerY, dayEl, day) {
528
+ const event = this._engine.events().find((e) => e.id === eventId);
529
+ if (!event || event.draggable === false)
530
+ return false;
531
+ if (this._options.onDragStart && !this._options.onDragStart(event))
532
+ return false;
533
+ const scrollTop = dayEl.closest('.ngxsmk-sch__scroll')?.scrollTop ?? 0;
534
+ const colTop = dayEl.getBoundingClientRect().top;
535
+ const eventTop = this._engine.eventTop(event);
536
+ const offsetY = pointerY - colTop - eventTop + scrollTop;
537
+ this._dragging = {
538
+ eventId,
539
+ offsetY,
540
+ startTop: eventTop,
541
+ originDay: day,
542
+ };
543
+ return true;
544
+ }
545
+ moveDrag(pointerY, dayEl, day) {
546
+ if (!this._dragging)
547
+ return null;
548
+ const hh = this._engine.hourHeight();
549
+ const scrollTop = dayEl.closest('.ngxsmk-sch__scroll')?.scrollTop ?? 0;
550
+ const colTop = dayEl.getBoundingClientRect().top;
551
+ const rawY = pointerY - colTop + scrollTop - this._dragging.offsetY;
552
+ const snap = this._options.snapDuration ?? this._engine.viewState().snapDuration;
553
+ const snapPx = (snap / 60) * hh;
554
+ const top = Math.max(0, Math.round(rawY / snapPx) * snapPx);
555
+ return { top, day };
556
+ }
557
+ endDrag(top, day) {
558
+ if (!this._dragging)
559
+ return null;
560
+ const event = this._engine.events().find((e) => e.id === this._dragging.eventId);
561
+ if (!event) {
562
+ this._dragging = null;
563
+ return null;
564
+ }
565
+ const hh = this._engine.hourHeight();
566
+ const minutes = (top / hh) * 60;
567
+ const durationMs = event.end.getTime() - event.start.getTime();
568
+ const newStart = new Date(day);
569
+ newStart.setHours(0, 0, 0, 0);
570
+ newStart.setMinutes(minutes);
571
+ const newEnd = new Date(newStart.getTime() + durationMs);
572
+ const move = {
573
+ event,
574
+ from: event.start,
575
+ to: day,
576
+ newStart,
577
+ newEnd,
578
+ resourceId: event.resourceId,
579
+ };
580
+ this._engine.moveEvent(event.id, newStart, newEnd);
581
+ this._options.onDragEnd?.(move);
582
+ this._dragging = null;
583
+ return move;
584
+ }
585
+ cancelDrag() {
586
+ this._dragging = null;
587
+ }
588
+ get dragging() {
589
+ return this._dragging !== null;
590
+ }
591
+ get draggingEventId() {
592
+ return this._dragging?.eventId ?? null;
593
+ }
594
+ }
595
+
596
+ class ResizePlugin {
597
+ constructor(options = {}) {
598
+ this.name = 'resize';
599
+ this.priority = 11;
600
+ this._resizing = null;
601
+ this._options = options;
602
+ }
603
+ onInit(engine) {
604
+ this._engine = engine;
605
+ }
606
+ onDestroy() {
607
+ this._resizing = null;
608
+ }
609
+ startResize(eventId) {
610
+ const event = this._engine.events().find((e) => e.id === eventId);
611
+ if (!event || event.resizable === false)
612
+ return false;
613
+ if (this._options.onResizeStart && !this._options.onResizeStart(event))
614
+ return false;
615
+ this._resizing = { eventId, originEnd: new Date(event.end) };
616
+ return true;
617
+ }
618
+ moveResize(pointerY, dayEl) {
619
+ if (!this._resizing)
620
+ return null;
621
+ const event = this._engine.events().find((e) => e.id === this._resizing.eventId);
622
+ if (!event)
623
+ return null;
624
+ const hh = this._engine.hourHeight();
625
+ const scrollTop = dayEl.closest('.ngxsmk-sch__scroll')?.scrollTop ?? 0;
626
+ const colTop = dayEl.getBoundingClientRect().top;
627
+ const rawY = pointerY - colTop + scrollTop;
628
+ const snap = this._options.snapDuration ?? this._engine.viewState().snapDuration;
629
+ const snapPx = (snap / 60) * hh;
630
+ const y = Math.max(this._engine.eventTop(event) + snapPx, Math.round(rawY / snapPx) * snapPx);
631
+ const minutes = (y / hh) * 60;
632
+ const newEnd = new Date(event.start);
633
+ newEnd.setHours(0, 0, 0, 0);
634
+ newEnd.setMinutes(minutes);
635
+ const minDur = this._options.minDuration ?? 15;
636
+ if (newEnd.getTime() - event.start.getTime() < minDur * 60_000) {
637
+ newEnd.setTime(event.start.getTime() + minDur * 60_000);
638
+ }
639
+ return newEnd;
640
+ }
641
+ endResize() {
642
+ if (!this._resizing)
643
+ return null;
644
+ const event = this._engine.events().find((e) => e.id === this._resizing.eventId);
645
+ if (!event) {
646
+ this._resizing = null;
647
+ return null;
648
+ }
649
+ const resize = {
650
+ event,
651
+ oldEnd: this._resizing.originEnd,
652
+ newEnd: event.end,
653
+ };
654
+ this._engine.resizeEvent(event.id, event.end);
655
+ this._options.onResizeEnd?.(resize);
656
+ this._resizing = null;
657
+ return resize;
658
+ }
659
+ cancelResize() {
660
+ this._resizing = null;
661
+ }
662
+ get resizing() {
663
+ return this._resizing !== null;
664
+ }
665
+ get resizingEventId() {
666
+ return this._resizing?.eventId ?? null;
667
+ }
668
+ }
669
+
670
+ class SelectionPlugin {
671
+ constructor(options = {}) {
672
+ this.name = 'selection';
673
+ this.priority = 5;
674
+ this._rangeSelecting = false;
675
+ this._rangeStart = null;
676
+ this._options = options;
677
+ }
678
+ onInit(engine) {
679
+ this._engine = engine;
680
+ if (this._options.multiSelect) {
681
+ this._engine.selection.update((s) => ({ ...s, multiSelect: true }));
682
+ }
683
+ }
684
+ onDestroy() {
685
+ this._rangeSelecting = false;
686
+ this._rangeStart = null;
687
+ }
688
+ toggleEvent(eventId, modifierKey = false) {
689
+ const multi = this._options.multiSelect && modifierKey;
690
+ this._engine.selectEvent(eventId, multi);
691
+ const selectedIds = this._engine.selection().selectedEventIds;
692
+ const selectedEvents = this._engine.events().filter((e) => selectedIds.has(e.id));
693
+ if (selectedIds.has(eventId)) {
694
+ this._options.onSelect?.(selectedEvents);
695
+ }
696
+ else {
697
+ this._options.onDeselect?.(selectedEvents);
698
+ }
699
+ }
700
+ selectOnly(eventId) {
701
+ this._engine.clearSelection();
702
+ this._engine.selectEvent(eventId);
703
+ const event = this._engine.events().find((e) => e.id === eventId);
704
+ if (event)
705
+ this._options.onSelect?.([event]);
706
+ }
707
+ selectRange(start, end) {
708
+ this._engine.selectRange(start, end);
709
+ this._options.onRangeSelect?.(start, end);
710
+ }
711
+ startRangeSelect(date) {
712
+ this._rangeSelecting = true;
713
+ this._rangeStart = date;
714
+ }
715
+ updateRangeSelect(date) {
716
+ if (!this._rangeSelecting || !this._rangeStart)
717
+ return;
718
+ const s = this._rangeStart < date ? this._rangeStart : date;
719
+ const e = this._rangeStart < date ? date : this._rangeStart;
720
+ this._engine.selectRange(s, e);
721
+ }
722
+ endRangeSelect() {
723
+ if (!this._rangeSelecting || !this._rangeStart)
724
+ return null;
725
+ const range = this._engine.selection().selectedRange;
726
+ this._rangeSelecting = false;
727
+ this._rangeStart = null;
728
+ return range;
729
+ }
730
+ selectAll() {
731
+ const all = this._engine.events();
732
+ this._engine.selection.update((s) => ({
733
+ ...s,
734
+ selectedEventIds: new Set(all.map((e) => e.id)),
735
+ }));
736
+ }
737
+ clearSelection() {
738
+ this._engine.clearSelection();
739
+ }
740
+ get selectedIds() {
741
+ return this._engine.selection().selectedEventIds;
742
+ }
743
+ get selectedCount() {
744
+ return this._engine.selection().selectedEventIds.size;
745
+ }
746
+ get hasSelection() {
747
+ return this._engine.selection().selectedEventIds.size > 0;
748
+ }
749
+ get isRangeSelecting() {
750
+ return this._rangeSelecting;
751
+ }
752
+ }
753
+
754
+ function createDefaultTooltipState() {
755
+ return {
756
+ visible: false,
757
+ event: null,
758
+ x: 0,
759
+ y: 0,
760
+ placement: 'top',
761
+ content: '',
762
+ };
763
+ }
764
+ class TooltipPlugin {
765
+ constructor(options = {}) {
766
+ this.name = 'tooltip';
767
+ this.priority = 50;
768
+ this._timeout = null;
769
+ this._state = createDefaultTooltipState();
770
+ this._listeners = [];
771
+ this._options = {
772
+ delay: options.delay ?? 400,
773
+ showArrow: options.showArrow ?? true,
774
+ placement: options.placement ?? 'top',
775
+ maxWidth: options.maxWidth ?? 280,
776
+ onShow: options.onShow ?? (() => true),
777
+ onHide: options.onHide ??
778
+ (() => {
779
+ /* noop */
780
+ }),
781
+ content: options.content ?? defaultContent,
782
+ };
783
+ }
784
+ onInit(engine) {
785
+ this._engine = engine;
786
+ }
787
+ onDestroy() {
788
+ this.hide();
789
+ this._clearTimeout();
790
+ for (const unlisten of this._listeners)
791
+ unlisten();
792
+ this._listeners = [];
793
+ }
794
+ show(event, targetEl) {
795
+ this._clearTimeout();
796
+ this._timeout = setTimeout(() => {
797
+ if (this._options.onShow(event) === false)
798
+ return;
799
+ const rect = targetEl.getBoundingClientRect();
800
+ const pos = this._computePosition(rect);
801
+ this._state = {
802
+ visible: true,
803
+ event,
804
+ x: pos.x,
805
+ y: pos.y,
806
+ placement: pos.placement,
807
+ content: this._options.content(event),
808
+ };
809
+ }, this._options.delay);
810
+ }
811
+ hide() {
812
+ this._clearTimeout();
813
+ if (this._state.event) {
814
+ this._options.onHide(this._state.event);
815
+ }
816
+ this._state = createDefaultTooltipState();
817
+ }
818
+ updatePosition(targetEl) {
819
+ if (!this._state.visible || !this._state.event)
820
+ return;
821
+ const rect = targetEl.getBoundingClientRect();
822
+ const pos = this._computePosition(rect);
823
+ this._state = { ...this._state, x: pos.x, y: pos.y, placement: pos.placement };
824
+ }
825
+ get state() {
826
+ return this._state;
827
+ }
828
+ get isVisible() {
829
+ return this._state.visible;
830
+ }
831
+ _computePosition(rect) {
832
+ const placement = this._options.placement;
833
+ const offset = 8;
834
+ switch (placement) {
835
+ case 'top':
836
+ return { x: rect.left + rect.width / 2, y: rect.top - offset, placement };
837
+ case 'bottom':
838
+ return { x: rect.left + rect.width / 2, y: rect.bottom + offset, placement };
839
+ case 'left':
840
+ return { x: rect.left - offset, y: rect.top + rect.height / 2, placement };
841
+ case 'right':
842
+ return { x: rect.right + offset, y: rect.top + rect.height / 2, placement };
843
+ }
844
+ }
845
+ _clearTimeout() {
846
+ if (this._timeout) {
847
+ clearTimeout(this._timeout);
848
+ this._timeout = null;
849
+ }
850
+ }
851
+ }
852
+ function defaultContent(event) {
853
+ const time = `${event.start.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })} – ${event.end.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })}`;
854
+ return `${event.title}\n${time}`;
855
+ }
856
+
857
+ class KeyboardPlugin {
858
+ constructor(options = {}) {
859
+ this.name = 'keyboard';
860
+ this.priority = 20;
861
+ this._handler = null;
862
+ this._options = options;
863
+ }
864
+ onInit(engine) {
865
+ this._engine = engine;
866
+ if (typeof document !== 'undefined') {
867
+ this._handler = (e) => this._onKeyDown(e);
868
+ document.addEventListener('keydown', this._handler);
869
+ }
870
+ }
871
+ onDestroy() {
872
+ if (this._handler) {
873
+ document.removeEventListener('keydown', this._handler);
874
+ this._handler = null;
875
+ }
876
+ }
877
+ _onKeyDown(e) {
878
+ const target = e.target;
879
+ if (target.tagName === 'INPUT' || target.tagName === 'TEXTAREA' || target.isContentEditable)
880
+ return;
881
+ switch (e.key) {
882
+ case 'ArrowRight':
883
+ e.preventDefault();
884
+ this._moveFocus(1);
885
+ break;
886
+ case 'ArrowLeft':
887
+ e.preventDefault();
888
+ this._moveFocus(-1);
889
+ break;
890
+ case 'ArrowUp':
891
+ e.preventDefault();
892
+ this._moveFocusTime(-30);
893
+ break;
894
+ case 'ArrowDown':
895
+ e.preventDefault();
896
+ this._moveFocusTime(30);
897
+ break;
898
+ case 'Enter':
899
+ case ' ':
900
+ e.preventDefault();
901
+ this._activateFocused();
902
+ break;
903
+ case 'Delete':
904
+ case 'Backspace':
905
+ e.preventDefault();
906
+ this._deleteSelected();
907
+ break;
908
+ case 'Escape':
909
+ e.preventDefault();
910
+ this._deselect();
911
+ this._options.onKeyAction?.('escape');
912
+ break;
913
+ case 'a':
914
+ if (e.ctrlKey || e.metaKey) {
915
+ e.preventDefault();
916
+ this._selectAll();
917
+ }
918
+ break;
919
+ case 't':
920
+ if (!e.ctrlKey && !e.metaKey && !e.altKey) {
921
+ e.preventDefault();
922
+ this._goToday();
923
+ }
924
+ break;
925
+ }
926
+ }
927
+ _moveFocus(deltaDays) {
928
+ const sel = this._engine.selection();
929
+ const focused = sel.focusedCell;
930
+ if (focused) {
931
+ const newDate = addDays(focused.date, deltaDays);
932
+ this._engine.selection.update((s) => ({
933
+ ...s,
934
+ focusedCell: { date: newDate, resourceId: focused.resourceId },
935
+ }));
936
+ }
937
+ else {
938
+ const vs = this._engine.viewState();
939
+ this._engine.selection.update((s) => ({
940
+ ...s,
941
+ focusedCell: { date: vs.date },
942
+ }));
943
+ }
944
+ this._options.onKeyAction?.('moveFocus');
945
+ }
946
+ _moveFocusTime(deltaMinutes) {
947
+ const sel = this._engine.selection();
948
+ const focused = sel.focusedCell;
949
+ if (focused) {
950
+ const newDate = addMinutes(focused.date, deltaMinutes);
951
+ this._engine.selection.update((s) => ({
952
+ ...s,
953
+ focusedCell: { date: newDate, resourceId: focused.resourceId },
954
+ }));
955
+ }
956
+ else {
957
+ this._moveFocus(0);
958
+ }
959
+ this._options.onKeyAction?.('moveFocusTime');
960
+ }
961
+ _activateFocused() {
962
+ const sel = this._engine.selection();
963
+ const ids = sel.selectedEventIds;
964
+ if (ids.size === 1) {
965
+ const eventId = Array.from(ids)[0];
966
+ const event = this._engine.events().find((e) => e.id === eventId);
967
+ if (event)
968
+ this._options.onKeyAction?.('activate');
969
+ }
970
+ else {
971
+ const focused = sel.focusedCell;
972
+ if (focused) {
973
+ const dayEvents = this._engine.eventsForDay(focused.date);
974
+ if (dayEvents.length > 0) {
975
+ this._engine.selectEvent(dayEvents[0].id);
976
+ }
977
+ }
978
+ }
979
+ }
980
+ _deleteSelected() {
981
+ if (this._options.onKeyAction?.('delete') === false)
982
+ return;
983
+ const ids = this._engine.selection().selectedEventIds;
984
+ for (const id of ids) {
985
+ this._engine.removeEvent(id);
986
+ }
987
+ this._engine.clearSelection();
988
+ }
989
+ _deselect() {
990
+ this._engine.clearSelection();
991
+ }
992
+ _selectAll() {
993
+ const events = this._engine.events();
994
+ this._engine.selection.update((s) => ({
995
+ ...s,
996
+ selectedEventIds: new Set(events.map((e) => e.id)),
997
+ }));
998
+ this._options.onKeyAction?.('selectAll');
999
+ }
1000
+ _goToday() {
1001
+ this._engine.today();
1002
+ this._options.onKeyAction?.('today');
1003
+ }
1004
+ }
1005
+
1006
+ function snapToSlot(value, snapDuration) {
1007
+ return Math.round(value / snapDuration) * snapDuration;
1008
+ }
1009
+ function snapDateToSlot(date, snapDuration) {
1010
+ const ms = date.getTime();
1011
+ const snapMs = snapDuration * 60_000;
1012
+ return new Date(Math.round(ms / snapMs) * snapMs);
1013
+ }
1014
+ function minutesToPixels(minutes, hourHeight) {
1015
+ return (minutes / 60) * hourHeight;
1016
+ }
1017
+ function pixelsToMinutes(pixels, hourHeight) {
1018
+ return (pixels / hourHeight) * 60;
1019
+ }
1020
+ function timeToMinutes(date) {
1021
+ return date.getHours() * 60 + date.getMinutes();
1022
+ }
1023
+ function minutesToTime(baseDate, minutes) {
1024
+ const d = new Date(baseDate);
1025
+ d.setHours(0, 0, 0, 0);
1026
+ d.setMinutes(minutes);
1027
+ return d;
1028
+ }
1029
+
1030
+ /**
1031
+ * Generated bundle index. Do not edit.
1032
+ */
1033
+
1034
+ export { DEFAULT_SELECTION, DEFAULT_WORKING_HOURS, DragPlugin, KeyboardPlugin, PluginHost, ResizePlugin, SchedulerEngine, SelectionPlugin, TooltipPlugin, addDays, addMinutes, addWeeks, clampDate, createDefaultTooltipState, dateRangeOverlaps, diffDays, diffMinutes, endOfMonth, endOfWeek, formatDateRange, formatHour, getDayNames, getHoursInRange, getMonthGrid, getMonthNames, getWeekDates, getWorkWeekDates, isDayGridView, isPast, isSameDay, isSameWeek, isTimeGridView, isToday, isWeekend, minutesToPixels, minutesToTime, pixelsToMinutes, snapDateToSlot, snapToSlot, startOfDay, startOfMonth, startOfWeek, timeToMinutes };
1035
+ //# sourceMappingURL=ngxsmk-cdk-scheduler.mjs.map