@event-calendar/core 4.7.0 → 5.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 (93) hide show
  1. package/README.md +29 -51
  2. package/dist/index.css +627 -731
  3. package/dist/index.js +2500 -3191
  4. package/package.json +2 -2
  5. package/src/Auxiliary.svelte +2 -13
  6. package/src/Buttons.svelte +62 -52
  7. package/src/Calendar.svelte +9 -3
  8. package/src/lib/a11y.js +2 -2
  9. package/src/lib/attachments.js +61 -0
  10. package/src/lib/chunks.js +117 -0
  11. package/src/lib/components/BaseDay.svelte +50 -0
  12. package/src/lib/components/BaseEvent.svelte +3 -3
  13. package/src/lib/components/ColHead.svelte +34 -0
  14. package/src/lib/components/DayHeader.svelte +14 -0
  15. package/src/lib/components/InteractableEvent.svelte +1 -3
  16. package/src/lib/components/index.js +3 -0
  17. package/src/lib/date.js +1 -1
  18. package/src/lib/dom.js +0 -4
  19. package/src/lib/events.js +10 -134
  20. package/src/lib/index.js +3 -2
  21. package/src/lib/{times.js → slots.js} +14 -19
  22. package/src/lib/stores.js +0 -33
  23. package/src/lib/utils.js +11 -2
  24. package/src/lib/view.js +0 -4
  25. package/src/plugins/day-grid/Day.svelte +36 -129
  26. package/src/plugins/day-grid/Event.svelte +42 -41
  27. package/src/plugins/day-grid/Popup.svelte +65 -48
  28. package/src/plugins/day-grid/View.svelte +76 -4
  29. package/src/plugins/day-grid/index.js +5 -5
  30. package/src/plugins/day-grid/lib.js +61 -0
  31. package/src/plugins/day-grid/stores.js +2 -20
  32. package/src/plugins/interaction/Action.svelte +40 -45
  33. package/src/plugins/interaction/Auxiliary.svelte +4 -4
  34. package/src/plugins/interaction/Pointer.svelte +8 -12
  35. package/src/plugins/interaction/Resizer.svelte +2 -2
  36. package/src/plugins/interaction/lib/utils.js +1 -5
  37. package/src/plugins/list/Day.svelte +8 -24
  38. package/src/plugins/list/View.svelte +39 -2
  39. package/src/plugins/resource-time-grid/Label.svelte +2 -2
  40. package/src/plugins/resource-time-grid/View.svelte +38 -82
  41. package/src/plugins/resource-time-grid/index.js +18 -10
  42. package/src/plugins/resource-time-grid/lib.js +31 -0
  43. package/src/plugins/resource-time-grid/options.js +10 -0
  44. package/src/plugins/resource-time-grid/stores.js +34 -0
  45. package/src/plugins/resource-timeline/Day.svelte +10 -73
  46. package/src/plugins/resource-timeline/Event.svelte +14 -23
  47. package/src/plugins/resource-timeline/Header.svelte +5 -5
  48. package/src/plugins/resource-timeline/Label.svelte +4 -12
  49. package/src/plugins/resource-timeline/NowIndicator.svelte +33 -28
  50. package/src/plugins/resource-timeline/View.svelte +129 -14
  51. package/src/plugins/resource-timeline/index.js +26 -23
  52. package/src/plugins/resource-timeline/lib.js +115 -118
  53. package/src/plugins/resource-timeline/stores.js +11 -7
  54. package/src/plugins/time-grid/AllDayEvent.svelte +31 -0
  55. package/src/plugins/time-grid/Day.svelte +11 -99
  56. package/src/plugins/time-grid/Event.svelte +18 -20
  57. package/src/plugins/time-grid/NowIndicator.svelte +32 -10
  58. package/src/plugins/time-grid/View.svelte +127 -35
  59. package/src/plugins/time-grid/index.js +10 -8
  60. package/src/plugins/time-grid/lib.js +142 -0
  61. package/src/plugins/time-grid/options.js +57 -0
  62. package/src/plugins/time-grid/stores.js +41 -8
  63. package/src/storage/options.js +4 -39
  64. package/src/storage/state.js +1 -4
  65. package/src/storage/stores.js +42 -11
  66. package/src/styles/days.css +91 -0
  67. package/src/styles/events.css +180 -0
  68. package/src/styles/index.css +126 -0
  69. package/src/styles/now-indicator.css +35 -0
  70. package/src/styles/popup.css +30 -0
  71. package/src/styles/sidebar.css +59 -0
  72. package/src/styles/slots.css +42 -0
  73. package/src/styles/theme.css +68 -0
  74. package/src/styles/toolbar.css +80 -0
  75. package/src/lib/actions.js +0 -52
  76. package/src/plugins/day-grid/Body.svelte +0 -54
  77. package/src/plugins/day-grid/Header.svelte +0 -20
  78. package/src/plugins/day-grid/Week.svelte +0 -60
  79. package/src/plugins/list/Body.svelte +0 -44
  80. package/src/plugins/resource-timeline/Body.svelte +0 -67
  81. package/src/plugins/resource-timeline/Days.svelte +0 -72
  82. package/src/plugins/resource-timeline/Sidebar.svelte +0 -35
  83. package/src/plugins/time-grid/Body.svelte +0 -43
  84. package/src/plugins/time-grid/Section.svelte +0 -29
  85. package/src/plugins/time-grid/all-day/Day.svelte +0 -65
  86. package/src/plugins/time-grid/all-day/Event.svelte +0 -37
  87. package/src/plugins/time-grid/all-day/Week.svelte +0 -65
  88. package/src/plugins/time-grid/utils.js +0 -58
  89. package/src/styles/day-grid.scss +0 -51
  90. package/src/styles/index.scss +0 -553
  91. package/src/styles/theme.scss +0 -95
  92. package/src/styles/time-grid.scss +0 -83
  93. package/src/styles/timeline.scss +0 -152
package/src/lib/events.js CHANGED
@@ -1,4 +1,6 @@
1
- import {addDay, addDuration, datesEqual, createDate, cloneDate, setMidnight, toLocalDate, toISOString, noTimePart, copyTime} from './date.js';
1
+ import {
2
+ addDay, cloneDate, copyTime, createDate, datesEqual, noTimePart, setMidnight, toISOString, toLocalDate
3
+ } from './date.js';
2
4
  import {createElement} from './dom.js';
3
5
  import {assign, isArray, isFunction} from './utils.js';
4
6
  import {toViewWithLocalDates} from './view.js';
@@ -55,38 +57,6 @@ export function createEventSources(input) {
55
57
  }));
56
58
  }
57
59
 
58
- export function createEventChunk(event, start, end) {
59
- let chunk = {
60
- start: event.start > start ? event.start : start,
61
- end: event.end < end ? event.end : end,
62
- event
63
- };
64
- chunk.zeroDuration = datesEqual(chunk.start, chunk.end);
65
-
66
- return chunk;
67
- }
68
-
69
- export function sortEventChunks(chunks, eventOrder) {
70
- if (isFunction(eventOrder)) {
71
- chunks.sort((a, b) => eventOrder(
72
- _toChunkWithLocalDates(a),
73
- _toChunkWithLocalDates(b)
74
- ));
75
- } else {
76
- // Sort by start date (all-day events always on top)
77
- chunks.sort((a, b) => a.start - b.start || b.event.allDay - a.event.allDay);
78
- }
79
- }
80
-
81
- function _toChunkWithLocalDates(chunk) {
82
- return {
83
- ...chunk,
84
- start: toLocalDate(chunk.start),
85
- end: toLocalDate(chunk.end),
86
- event: toEventWithLocalDates(chunk.event)
87
- };
88
- }
89
-
90
60
  export function createEventContent(chunk, displayEventEnd, eventContent, theme, _intlEventTime, _view) {
91
61
  let timeText = _intlEventTime.formatRange(
92
62
  chunk.start,
@@ -113,7 +83,7 @@ export function createEventContent(chunk, displayEventEnd, eventContent, theme,
113
83
  domNodes = [];
114
84
  break;
115
85
  case 'pointer':
116
- domNodes = [createTimeElement(timeText, chunk, theme)];
86
+ domNodes = chunk.event.allDay ? [] : [createTimeElement(timeText, chunk, theme)];
117
87
  break;
118
88
  default:
119
89
  domNodes = [
@@ -169,118 +139,24 @@ function _cloneEvent(event, dateFn) {
169
139
  return event;
170
140
  }
171
141
 
172
- /**
173
- * Prepare event chunks for month view and all-day slot in week view
174
- */
175
- export function prepareEventChunks(chunks, hiddenDays, eventOrder) {
176
- let longChunks = {};
177
-
178
- if (chunks.length) {
179
- sortEventChunks(chunks, eventOrder);
180
-
181
- let prevChunk;
182
- for (let chunk of chunks) {
183
- let dates = [];
184
- let date = setMidnight(cloneDate(chunk.start));
185
- while (chunk.end > date) {
186
- if (!hiddenDays.includes(date.getUTCDay())) {
187
- dates.push(cloneDate(date));
188
- if (dates.length > 1) {
189
- let key = date.getTime();
190
- if (longChunks[key]) {
191
- longChunks[key].chunks.push(chunk);
192
- } else {
193
- longChunks[key] = {
194
- sorted: false,
195
- chunks: [chunk]
196
- };
197
- }
198
- }
199
- }
200
- addDay(date);
201
- }
202
- if (dates.length) {
203
- chunk.date = dates[0];
204
- chunk.days = dates.length;
205
- chunk.dates = dates;
206
- // Adjust the start and end dates of the chunk if hidden days affected them
207
- if (chunk.start < dates[0]) {
208
- chunk.start = dates[0];
209
- }
210
- let maxEnd = addDay(cloneDate(dates.at(-1)));
211
- if (chunk.end > maxEnd) {
212
- chunk.end = maxEnd;
213
- }
214
- } else {
215
- chunk.date = setMidnight(cloneDate(chunk.start));
216
- chunk.days = 1;
217
- chunk.dates = [chunk.date];
218
- }
219
-
220
- if (prevChunk && datesEqual(prevChunk.date, chunk.date)) {
221
- chunk.prev = prevChunk;
222
- }
223
- prevChunk = chunk;
224
- }
225
- }
226
-
227
- return longChunks;
228
- }
229
-
230
- export function repositionEvent(chunk, longChunks, height) {
231
- chunk.top = 0;
232
- if (chunk.prev) {
233
- chunk.top = chunk.prev.bottom + 1;
234
- }
235
- chunk.bottom = chunk.top + height;
236
- let margin = 1;
237
- let key = chunk.date.getTime();
238
- if (longChunks[key]) {
239
- if (!longChunks[key].sorted) {
240
- longChunks[key].chunks.sort((a, b) => a.top - b.top);
241
- longChunks[key].sorted = true;
242
- }
243
- for (let longChunk of longChunks[key].chunks) {
244
- if (chunk.top < longChunk.bottom && chunk.bottom > longChunk.top) {
245
- let offset = longChunk.bottom - chunk.top + 1;
246
- margin += offset;
247
- chunk.top += offset;
248
- chunk.bottom += offset;
249
- }
250
- }
251
- }
252
-
253
- return margin;
254
- }
255
-
256
142
  export function runReposition(refs, data) {
257
143
  refs.length = data.length;
258
- let result = [];
259
144
  for (let ref of refs) {
260
- result.push(ref?.reposition?.());
145
+ ref?.reposition();
261
146
  }
262
- return result;
263
147
  }
264
148
 
265
149
  /**
266
- * Check whether the event intersects with the given date range and resources
150
+ * Check whether the event intersects with the given date range and resource
267
151
  * @param event
268
152
  * @param start
269
153
  * @param end
270
- * @param resources
154
+ * @param resource
271
155
  * @return boolean
272
156
  */
273
- export function eventIntersects(event, start, end, resources) {
274
- if (event.start < end && event.end > start) {
275
- if (resources) {
276
- if (!isArray(resources)) {
277
- resources = [resources];
278
- }
279
- return resources.some(resource => event.resourceIds.includes(resource.id));
280
- }
281
- return true;
282
- }
283
- return false;
157
+ export function eventIntersects(event, start, end, resource = undefined) {
158
+ return (!resource || event.resourceIds.includes(resource.id)) && event.start < end && event.end > start;
159
+
284
160
  }
285
161
 
286
162
  export function helperEvent(display) {
package/src/lib/index.js CHANGED
@@ -1,5 +1,6 @@
1
1
  export * from './a11y.js';
2
- export * from './actions.js';
2
+ export * from './attachments.js';
3
+ export * from './chunks.js';
3
4
  export * from './date.js';
4
5
  export * from './debounce.js';
5
6
  export * from './dom.js';
@@ -8,7 +9,7 @@ export * from './options.js';
8
9
  export * from './payload.js';
9
10
  export * from './range.js';
10
11
  export * from './resources.js';
12
+ export * from './slots.js';
11
13
  export * from './stores.js';
12
- export * from './times.js';
13
14
  export * from './utils.js';
14
15
  export * from './view.js';
@@ -1,37 +1,32 @@
1
1
  import {addDuration, cloneDate, createDuration, DAY_IN_SECONDS, toISOString, toSeconds} from './date.js';
2
- import {max as maxFn, min as minFn, isFunction} from './utils.js';
2
+ import {max as maxFn, min as minFn, isFunction, floor} from './utils.js';
3
3
  import {bgEvent} from './events.js';
4
4
 
5
- export function createTimes(date, $slotDuration, $slotLabelInterval, $_slotTimeLimits, $_intlSlotLabel) {
5
+ export function createSlots(date, $slotDuration, $_slotLabelPeriodicity, $_slotTimeLimits, $_intlSlotLabel) {
6
+ let slots = [];
6
7
  date = cloneDate(date);
7
- let times = [];
8
8
  let end = cloneDate(date);
9
9
  addDuration(date, $_slotTimeLimits.min);
10
10
  addDuration(end, $_slotTimeLimits.max);
11
- // Labels
12
- if ($slotLabelInterval === undefined) {
13
- $slotLabelInterval = $slotDuration.seconds < 3600
14
- ? createDuration($slotDuration.seconds * 2)
15
- : $slotDuration;
16
- }
17
- let label = cloneDate(date);
18
- // Build times
11
+ // Build slots
19
12
  while (date < end) {
20
- times.push([
13
+ slots.push([
21
14
  toISOString(date),
22
- $_intlSlotLabel.format(date),
23
- date >= label
15
+ $_intlSlotLabel.format(date)
24
16
  ]);
25
- while ($slotLabelInterval.seconds && date >= label) {
26
- addDuration(label, $slotLabelInterval);
27
- }
28
- addDuration(date, $slotDuration);
17
+ addDuration(date, $slotDuration, $_slotLabelPeriodicity);
18
+ }
19
+ // Calculate span for last slot
20
+ let span = floor((date - end) / 1000 / toSeconds($slotDuration));
21
+ if (span && span !== $_slotLabelPeriodicity) {
22
+ slots.at(-1)[2] = $_slotLabelPeriodicity - span;
29
23
  }
30
24
 
31
- return times;
25
+ return slots;
32
26
  }
33
27
 
34
28
  export function createSlotTimeLimits($slotMinTime, $slotMaxTime, $flexibleSlotTimeLimits, $_viewDates, $_filteredEvents) {
29
+ // Copy values
35
30
  let min = createDuration($slotMinTime);
36
31
  let max = createDuration($slotMaxTime);
37
32
 
package/src/lib/stores.js CHANGED
@@ -1,8 +1,6 @@
1
1
  import {derived} from 'svelte/store';
2
2
  import {isFunction} from './utils.js';
3
3
  import {toLocalDate} from './date.js';
4
- import {createResources} from './resources.js';
5
- import {getPayload} from './payload.js';
6
4
 
7
5
  export function intl(locale, format) {
8
6
  return derived([locale, format], ([$locale, $format]) => {
@@ -63,34 +61,3 @@ function _getParts(source, parts) {
63
61
  }
64
62
  return result;
65
63
  }
66
-
67
- export function viewResources(state) {
68
- return derived(
69
- [state.resources, state.filterResourcesWithEvents, state._filteredEvents, state._activeRange],
70
- ([$resources, $filterResourcesWithEvents, $_filteredEvents, $_activeRange]) => {
71
- let result = $resources.filter(resource => !getPayload(resource).hidden);
72
-
73
- if ($filterResourcesWithEvents) {
74
- result = $resources.filter(resource => {
75
- for (let event of $_filteredEvents) {
76
- if (
77
- event.display !== 'background' &&
78
- event.resourceIds.includes(resource.id) &&
79
- event.start < $_activeRange.end &&
80
- event.end > $_activeRange.start
81
- ) {
82
- return true;
83
- }
84
- }
85
- return false;
86
- });
87
- }
88
-
89
- if (!result.length) {
90
- result = createResources([{}]);
91
- }
92
-
93
- return result;
94
- }
95
- );
96
- }
package/src/lib/utils.js CHANGED
@@ -38,6 +38,15 @@ export function isFunction(value) {
38
38
  return typeof value === 'function';
39
39
  }
40
40
 
41
+ export function isEmpty(obj) {
42
+ for (let prop in obj) {
43
+ if (Object.hasOwn(obj, prop)) {
44
+ return false;
45
+ }
46
+ }
47
+ return true;
48
+ }
49
+
41
50
  export function run(fn) {
42
51
  return fn();
43
52
  }
@@ -50,11 +59,11 @@ export function noop() {}
50
59
 
51
60
  export const identity = (x) => x;
52
61
 
53
- export function stopPropagation(fn) {
62
+ export function stopPropagation(fn, _this = undefined) {
54
63
  return function (event) {
55
64
  event.stopPropagation();
56
65
  if (fn) {
57
- fn.call(this, event);
66
+ fn.call(_this, event);
58
67
  }
59
68
  };
60
69
  }
package/src/lib/view.js CHANGED
@@ -26,7 +26,3 @@ export function toViewWithLocalDates(view) {
26
26
  export function listView(view) {
27
27
  return view.startsWith('list');
28
28
  }
29
-
30
- export function timelineView(view) {
31
- return view.includes('Timeline');
32
- }
@@ -1,58 +1,46 @@
1
1
  <script>
2
- import {getContext, onMount, tick, untrack} from 'svelte';
3
- import {SvelteSet} from 'svelte/reactivity';
2
+ import {getContext} from 'svelte';
4
3
  import {
5
- addDay, assign, cloneDate, createEventChunk, datesEqual, getWeekNumber, isFunction, keyEnter, outsideRange,
6
- runReposition, setContent, setPayload, toISOString, toLocalDate, stopPropagation
4
+ contentFrom, getWeekNumber, isFunction, keyEnter, toISOString, toLocalDate, stopPropagation
7
5
  } from '#lib';
8
- import Event from './Event.svelte';
9
- import Popup from './Popup.svelte';
6
+ import {BaseDay} from '#components';
10
7
 
11
- let {date, chunks, bgChunks, longChunks, iChunks = [], dates} = $props();
8
+ let {day} = $props();
12
9
 
13
10
  let {
14
- date: currentDate, dayMaxEvents, highlightedDates, firstDay, moreLinkContent, theme, validRange, weekNumbers,
15
- weekNumberContent, _hiddenEvents, _intlDayCell, _popupDate, _popupChunks, _today, _interaction
11
+ date, firstDay, moreLinkContent, theme, weekNumbers, weekNumberContent, _hiddenChunks, _intlDayCell, _popupDay
16
12
  } = getContext('state');
17
13
 
18
- let el = $state();
19
- let hiddenEvents = new SvelteSet(); // hidden events of this day
20
- $effect.pre(() => {
21
- $_hiddenEvents[date.getTime()] = untrack(() => hiddenEvents);
22
- });
23
- let refs = [];
24
- let isToday = $derived(datesEqual(date, $_today));
25
- let otherMonth = $derived(date.getUTCMonth() !== $currentDate.getUTCMonth());
26
- let highlight = $derived($highlightedDates.some(d => datesEqual(d, date)));
27
- let disabled = $derived(outsideRange(date, $validRange));
14
+ let {dayStart, disabled, highlight} = $derived(day);
15
+ let otherMonth = $derived(dayStart.getUTCMonth() !== $date.getUTCMonth());
16
+ let classes = $derived(classNames => [...classNames, otherMonth && $theme.otherMonth]);
28
17
 
29
- let dayBgChunks = $derived(!disabled ? bgChunks.filter(bgChunk => datesEqual(bgChunk.date, date)) : []);
30
- let dayChunks = $derived.by(() => {
31
- let dayChunks = [];
32
- if (!disabled) {
33
- for (let chunk of chunks) {
34
- if (datesEqual(chunk.date, date)) {
35
- dayChunks.push(chunk);
36
- // if ($dayMaxEvents !== false && dayChunks.length > $dayMaxEvents) {
37
- // chunk.hidden = true;
38
- // }
39
- }
18
+ // Week numbers
19
+ let showWeekNumber = $derived($weekNumbers && dayStart.getUTCDay() === ($firstDay ? 1 : 0));
20
+ let weekNumber = $derived.by(() => {
21
+ let weekNumber;
22
+ if (showWeekNumber) {
23
+ let week = getWeekNumber(dayStart, $firstDay);
24
+ if ($weekNumberContent) {
25
+ weekNumber = isFunction($weekNumberContent)
26
+ ? $weekNumberContent({date: toLocalDate(dayStart), week})
27
+ : $weekNumberContent;
28
+ } else {
29
+ weekNumber = 'W' + String(week).padStart(2, '0');
40
30
  }
41
31
  }
42
- return dayChunks;
43
- });
44
- $effect.pre(() => {
45
- dayChunks;
46
- hiddenEvents.clear();
32
+ return weekNumber;
47
33
  });
48
34
 
35
+ // More link
36
+ let hiddenChunks = $derived($_hiddenChunks[dayStart.getTime()]);
49
37
  let moreLink = $derived.by(() => {
50
38
  let moreLink = '';
51
- if (!disabled && hiddenEvents.size) {
52
- let text = '+' + hiddenEvents.size + ' more';
39
+ if (hiddenChunks) {
40
+ let text = '+' + hiddenChunks.length + ' more';
53
41
  if ($moreLinkContent) {
54
42
  moreLink = isFunction($moreLinkContent)
55
- ? $moreLinkContent({num: hiddenEvents.size, text})
43
+ ? $moreLinkContent({num: hiddenChunks.length, text})
56
44
  : $moreLinkContent;
57
45
  } else {
58
46
  moreLink = text;
@@ -61,121 +49,40 @@
61
49
  return moreLink;
62
50
  });
63
51
 
64
- // dateFromPoint
65
- onMount(() => {
66
- setPayload(el, () => ({allDay: true, date, resource: undefined, dayEl: el, disabled}));
67
- });
68
-
69
52
  // Popup
70
53
  function showMore() {
71
- $_popupDate = date;
72
- }
73
- let showPopup = $derived($_popupDate && datesEqual(date, $_popupDate));
74
- // Use `pre` to tick before popup positioning tick
75
- $effect.pre(() => {
76
- dayChunks;
77
- longChunks;
78
- if (showPopup) {
79
- // Let chunks to reposition then set popup chunks
80
- tick().then(setPopupChunks);
81
- }
82
- });
83
- function setPopupChunks() {
84
- let nextDay = addDay(cloneDate(date));
85
- let chunks = dayChunks.concat(longChunks[date.getTime()]?.chunks || []);
86
- $_popupChunks = chunks
87
- .map(chunk => assign({}, chunk, createEventChunk(chunk.event, date, nextDay), {days: 1, dates: [date]}))
88
- .sort((a, b) => a.top - b.top);
89
- }
90
-
91
- // Week numbers
92
- let showWeekNumber = $derived($weekNumbers && date.getUTCDay() == ($firstDay ? 1 : 0));
93
- let weekNumber = $derived.by(() => {
94
- let weekNumber;
95
- if (showWeekNumber) {
96
- let week = getWeekNumber(date, $firstDay);
97
- if ($weekNumberContent) {
98
- weekNumber = isFunction($weekNumberContent)
99
- ? $weekNumberContent({date: toLocalDate(date), week})
100
- : $weekNumberContent;
101
- } else {
102
- weekNumber = 'W' + String(week).padStart(2, '0');
103
- }
104
- }
105
- return weekNumber;
106
- });
107
-
108
- export function reposition() {
109
- if (!disabled) {
110
- runReposition(refs, dayChunks);
111
- }
54
+ $_popupDay = day;
112
55
  }
113
56
  </script>
114
57
 
115
- <div
116
- bind:this={el}
117
- class="{$theme.day} {$theme.weekdays?.[date.getUTCDay()]}{isToday ? ' ' + $theme.today : ''}{otherMonth ? ' ' + $theme.otherMonth : ''}{highlight ? ' ' + $theme.highlight : ''}{disabled ? ' ' + $theme.disabled : ''}"
118
- role="cell"
119
- onpointerdown={$_interaction.action?.select}
120
- >
58
+ <BaseDay date={dayStart} allDay {classes} {disabled} {highlight}>
121
59
  <div class="{$theme.dayHead}">
122
60
  <time
123
- datetime="{toISOString(date, 10)}"
124
- use:setContent={$_intlDayCell.format(date)}
61
+ datetime="{toISOString(dayStart, 10)}"
62
+ {@attach contentFrom($_intlDayCell.format(dayStart))}
125
63
  ></time>
126
64
  {#if showWeekNumber}
127
65
  <span
128
66
  class="{$theme.weekNumber}"
129
- use:setContent={weekNumber}
67
+ {@attach contentFrom(weekNumber)}
130
68
  ></span>
131
69
  {/if}
132
70
  </div>
133
- <div class="{$theme.bgEvents}">
134
- {#if !disabled}
135
- {#each dayBgChunks as chunk (chunk.event)}
136
- <Event {chunk}/>
137
- {/each}
138
- {/if}
139
- </div>
140
- {#if !disabled}
141
- <!-- Pointer -->
142
- {#if iChunks[2] && datesEqual(iChunks[2].date, date)}
143
- <div class="{$theme.events}">
144
- <Event chunk={iChunks[2]}/>
145
- </div>
146
- {/if}
147
- <!-- Drag & Resize -->
148
- {#if iChunks[0] && datesEqual(iChunks[0].date, date)}
149
- <div class="{$theme.events} {$theme.preview}">
150
- <Event chunk={iChunks[0]}/>
151
- </div>
152
- {/if}
153
- {/if}
154
- <div class="{$theme.events}">
155
- {#if !disabled}
156
- {#each dayChunks as chunk, i (chunk.event)}
157
- <!-- svelte-ignore binding_property_non_reactive -->
158
- <Event {chunk} {longChunks} {dates} bind:this={refs[i]}/>
159
- {/each}
160
- {/if}
161
- </div>
162
- {#if showPopup}
163
- <Popup/>
164
- {/if}
71
+
165
72
  <div class="{$theme.dayFoot}">
166
- {#if !disabled && hiddenEvents.size}
73
+ {#if hiddenChunks}
167
74
  <!-- svelte-ignore a11y_missing_attribute -->
168
75
  <!-- svelte-ignore a11y_missing_content -->
169
76
  <!-- svelte-ignore a11y_consider_explicit_label -->
170
77
  <a
171
78
  role="button"
172
79
  tabindex="0"
173
- aria-haspopup="true"
80
+ aria-haspopup="dialog"
174
81
  onclick={stopPropagation(showMore)}
175
82
  onkeydown={keyEnter(showMore)}
176
83
  onpointerdown={stopPropagation()}
177
- use:setContent={moreLink}
84
+ {@attach contentFrom(moreLink)}
178
85
  ></a>
179
86
  {/if}
180
87
  </div>
181
- </div>
88
+ </BaseDay>
@@ -1,34 +1,40 @@
1
1
  <script>
2
2
  import {getContext} from 'svelte';
3
- import {ancestor, bgEvent, height, max, rect, repositionEvent} from '#lib';
3
+ import {bgEvent, height, isEmpty, max, repositionEvent} from '#lib';
4
4
  import {InteractableEvent} from '#components';
5
5
 
6
- let {chunk, longChunks = {}, inPopup = false, dates = []} = $props();
6
+ let {chunk, gridEl, inPopup = false} = $props();
7
7
 
8
- let {dayMaxEvents, _hiddenEvents, _popupDate} = getContext('state');
8
+ let {_colsCount, _hiddenChunks, _popupDay, dayMaxEvents} = getContext('state');
9
9
 
10
10
  let el = $state();
11
- let margin = $state(1);
11
+ let margin = $state(0);
12
12
  let hidden = $state(false);
13
13
 
14
14
  let event = $derived(chunk.event);
15
15
  let display = $derived(chunk.event.display);
16
+ let dayEl = $derived(gridEl?.children.item((chunk.gridRow - 1) * $_colsCount + chunk.gridColumn - 1));
17
+
18
+ $effect(() => {
19
+ if (dayEl) {
20
+ margin = height(dayEl.firstElementChild);
21
+ }
22
+ });
16
23
 
17
24
  // Style
18
25
  let styles = $derived(style => {
19
- if (bgEvent(display)) {
20
- style['width'] = `calc(${chunk.days * 100}% + ${(chunk.days - 1)}px)`;
21
- } else {
22
- let marginTop = margin;
26
+ style['grid-column'] = `${chunk.gridColumn} / span ${chunk.dates.length}`;
27
+ style['grid-row'] = chunk.gridRow;
28
+ if (!bgEvent(display)) {
29
+ let marginTop = inPopup ? 1 : margin;
23
30
  if (event._margin) {
24
31
  // Force margin for helper events
25
- let [_margin, _dates] = event._margin;
26
- if (chunk.date >= _dates[0] && chunk.date <= _dates.at(-1)) {
32
+ let [_margin, _gridRow] = event._margin;
33
+ if (_margin > marginTop && chunk.gridRow === _gridRow) {
27
34
  marginTop = _margin;
28
35
  }
29
36
  }
30
- style['width'] = `calc(${chunk.days * 100}% + ${(chunk.days - 1) * 7}px)`;
31
- style['margin-top'] = `${marginTop}px`;
37
+ style['margin-block-start'] = `${marginTop}px`;
32
38
  }
33
39
  if (hidden) {
34
40
  style['visibility'] = 'hidden';
@@ -37,42 +43,37 @@
37
43
  });
38
44
 
39
45
  export function reposition() {
40
- margin = repositionEvent(chunk, longChunks, height(el));
41
- if ($dayMaxEvents === true) {
42
- hide();
43
- } else {
44
- hidden = false;
45
- }
46
+ margin = repositionEvent(chunk, height(el), height(dayEl.firstElementChild));
46
47
  }
47
48
 
48
- function hide() {
49
- let dayEl = ancestor(el, 2);
50
- let h = height(dayEl) - height(dayEl.firstElementChild) - footHeight(dayEl);
51
- hidden = chunk.bottom > h;
52
- let update = false;
53
- // Hide or show the event throughout all days
54
- for (let date of chunk.dates) {
55
- let hiddenEvents = $_hiddenEvents[date.getTime()];
56
- if (hiddenEvents) {
57
- let size = hiddenEvents.size;
58
- if (hidden) {
59
- hiddenEvents.add(chunk.event);
60
- } else {
61
- hiddenEvents.delete(chunk.event);
62
- }
63
- if (size !== hiddenEvents.size) {
64
- update = true;
49
+ export function hide() {
50
+ if ($dayMaxEvents === true) {
51
+ let h = height(dayEl) - footHeight(dayEl);
52
+ hidden = chunk.bottom > h;
53
+ if (hidden) {
54
+ // Hide the event throughout all days
55
+ for (let date of chunk.dates) {
56
+ let key = date.getTime();
57
+ if ($_hiddenChunks[key]) {
58
+ if (!$_hiddenChunks[key].includes(chunk)) {
59
+ $_hiddenChunks[key] = [...$_hiddenChunks[key], chunk];
60
+ }
61
+ } else {
62
+ $_hiddenChunks[key] = [chunk];
63
+ }
65
64
  }
66
65
  }
67
- }
68
- if (update) {
69
- $_hiddenEvents = $_hiddenEvents;
66
+ } else {
67
+ hidden = false;
68
+ if (!isEmpty($_hiddenChunks)) {
69
+ $_hiddenChunks = {};
70
+ }
70
71
  }
71
72
  }
72
73
 
73
74
  function footHeight(dayEl) {
74
75
  let h = 0;
75
- for (let i = 0; i < chunk.days; ++i) {
76
+ for (let i = 0; i < chunk.dates.length; ++ i) {
76
77
  h = max(h, height(dayEl.lastElementChild));
77
78
  dayEl = dayEl.nextElementSibling;
78
79
  if (!dayEl) {
@@ -88,6 +89,6 @@
88
89
  {chunk}
89
90
  {styles}
90
91
  axis="x"
91
- forceDate={() => inPopup ? $_popupDate : undefined}
92
- forceMargin={() => [rect(el).top - rect(ancestor(el, 1)).top, dates]}
92
+ forceDate={inPopup && $_popupDay.dayStart}
93
+ forceMargin={[margin, chunk.gridRow]}
93
94
  />