@event-calendar/core 5.2.4 → 5.3.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@event-calendar/core",
3
- "version": "5.2.4",
3
+ "version": "5.3.0",
4
4
  "title": "Event Calendar Core package",
5
5
  "description": "Full-sized drag & drop event calendar with resource & timeline views",
6
6
  "keywords": [
@@ -32,6 +32,6 @@
32
32
  "#components": "./src/lib/components/index.js"
33
33
  },
34
34
  "dependencies": {
35
- "svelte": "^5.47.1"
35
+ "svelte": "^5.48.0"
36
36
  }
37
37
  }
@@ -48,8 +48,13 @@
48
48
  return isDate(value) ? toLocalDate(value) : value;
49
49
  }
50
50
 
51
+ export function refetchResources() {
52
+ mainState.fetchedRange.resources = {};
53
+ return this;
54
+ }
55
+
51
56
  export function refetchEvents() {
52
- mainState.fetchedRange = {start: undefined, end: undefined};
57
+ mainState.fetchedRange.events = {};
53
58
  return this;
54
59
  }
55
60
 
package/src/lib/chunks.js CHANGED
@@ -11,6 +11,7 @@ import {assign} from './utils.js';
11
11
  * zeroDuration: boolean,
12
12
  * gridColumn?: Number,
13
13
  * gridRow?: Number,
14
+ * resource?: Object,
14
15
  * group?: Object,
15
16
  * groupColumn?: Number,
16
17
  * dates?: Array
@@ -44,20 +45,22 @@ export function createAllDayChunks(event, days, withId = true) {
44
45
  let lastEnd;
45
46
  let gridColumn;
46
47
  let gridRow;
47
- for (let {gridColumn: column, gridRow: row, resource, dayStart, dayEnd, disabled} of days) {
48
- if (!disabled && eventIntersects(event, dayStart, dayEnd, resource)) {
48
+ let resource;
49
+ for (let {gridColumn: column, gridRow: row, resource: dayResource, dayStart, dayEnd, disabled} of days) {
50
+ if (!disabled && eventIntersects(event, dayStart, dayEnd, dayResource)) {
49
51
  dates.push(dayStart);
50
52
  lastEnd = dayEnd;
51
53
  if (!gridColumn) {
52
54
  gridColumn = column;
53
55
  gridRow = row;
56
+ resource = dayResource;
54
57
  }
55
58
  }
56
59
  }
57
60
  if (dates.length) {
58
61
  let chunk = createEventChunk(event, dates[0], lastEnd);
59
62
  // Chunk layout
60
- assign(chunk, {gridColumn, gridRow, dates});
63
+ assign(chunk, {gridColumn, gridRow, resource, dates});
61
64
  if (withId) {
62
65
  assignChunkId(chunk);
63
66
  }
@@ -2,7 +2,8 @@
2
2
  import {getContext, onMount} from 'svelte';
3
3
  import {
4
4
  bgEvent, createEventClasses, createEventContent, entries, helperEvent, identity, isFunction, keyEnter,
5
- resourceBackgroundColor, resourceTextColor, contentFrom, toEventWithLocalDates, toViewWithLocalDates
5
+ findFirstResource, contentFrom, toEventWithLocalDates, toViewWithLocalDates, eventBackgroundColor as getEventBackgroundColor,
6
+ eventTextColor as getEventTextColor
6
7
  } from '#lib';
7
8
 
8
9
  let {
@@ -14,17 +15,22 @@
14
15
  body
15
16
  } = $props();
16
17
 
17
- let {intlEventTime, view, options: {
18
+ let {intlEventTime, resources, view, options: {
18
19
  displayEventEnd, eventBackgroundColor, eventColor, eventContent, eventClick, eventDidMount, eventClassNames,
19
- eventMouseEnter, eventMouseLeave, eventTextColor, resources, theme
20
+ eventMouseEnter, eventMouseLeave, eventTextColor, theme
20
21
  }} = $derived(getContext('state'));
21
22
 
22
23
  let event = $derived(chunk.event);
23
24
  let display = $derived(chunk.event.display);
24
25
 
25
26
  // Style
26
- let bgColor = $derived(event.backgroundColor ?? resourceBackgroundColor(event, resources) ?? eventBackgroundColor ?? eventColor);
27
- let txtColor = $derived(event.textColor ?? resourceTextColor(event, resources) ?? eventTextColor);
27
+ let bgColor = $derived(
28
+ event.backgroundColor ?? getEventBackgroundColor(chunk.resource ?? findFirstResource(event, resources)) ??
29
+ eventBackgroundColor ?? eventColor
30
+ );
31
+ let txtColor = $derived(
32
+ event.textColor ?? getEventTextColor(chunk.resource ?? findFirstResource(event, resources)) ?? eventTextColor
33
+ );
28
34
  let style = $derived(entries(styles(
29
35
  {'background-color': bgColor, 'color': txtColor}
30
36
  )).map(entry => `${entry[0]}:${entry[1]}`).concat(event.styles).join(';'));
package/src/lib/dom.js CHANGED
@@ -52,3 +52,12 @@ export function listen(node, event, handler, options) {
52
52
  node.addEventListener(event, handler, options);
53
53
  return () => node.removeEventListener(event, handler, options);
54
54
  }
55
+
56
+ export function stopPropagation(fn, _this = undefined) {
57
+ return function (jsEvent) {
58
+ jsEvent.stopPropagation();
59
+ if (fn) {
60
+ fn.call(_this, jsEvent);
61
+ }
62
+ };
63
+ }
@@ -1,4 +1,5 @@
1
1
  import {setPayload} from './payload.js';
2
+ import {empty} from './utils.js';
2
3
 
3
4
  export function createResources(input) {
4
5
  let result = [];
@@ -30,20 +31,20 @@ export function createResource(input) {
30
31
  return {
31
32
  id: String(input.id),
32
33
  title: input.title || '',
33
- eventBackgroundColor: input.eventBackgroundColor,
34
- eventTextColor: input.eventTextColor,
34
+ eventBackgroundColor: eventBackgroundColor(input),
35
+ eventTextColor: eventTextColor(input),
35
36
  extendedProps: input.extendedProps ?? {}
36
37
  };
37
38
  }
38
39
 
39
- export function resourceBackgroundColor(event, resources) {
40
- return findResource(event, resources)?.eventBackgroundColor;
40
+ export function eventBackgroundColor(resource) {
41
+ return resource?.eventBackgroundColor;
41
42
  }
42
43
 
43
- export function resourceTextColor(event, resources) {
44
- return findResource(event, resources)?.eventTextColor;
44
+ export function eventTextColor(resource) {
45
+ return resource?.eventTextColor;
45
46
  }
46
47
 
47
- function findResource(event, resources) {
48
- return resources.find(resource => event.resourceIds.includes(resource.id));
48
+ export function findFirstResource(event, resources) {
49
+ return empty(event.resourceIds) ? undefined : resources.find(resource => event.resourceIds.includes(resource.id));
49
50
  }
package/src/lib/utils.js CHANGED
@@ -30,6 +30,14 @@ export function symbol() {
30
30
  return Symbol('ec');
31
31
  }
32
32
 
33
+ export function length(array) {
34
+ return array.length;
35
+ }
36
+
37
+ export function empty(array) {
38
+ return !length(array);
39
+ }
40
+
33
41
  export function isArray(value) {
34
42
  return Array.isArray(value);
35
43
  }
@@ -62,15 +70,6 @@ export function noop() {}
62
70
 
63
71
  export const identity = (x) => x;
64
72
 
65
- export function stopPropagation(fn, _this = undefined) {
66
- return function (event) {
67
- event.stopPropagation();
68
- if (fn) {
69
- fn.call(_this, event);
70
- }
71
- };
72
- }
73
-
74
73
  export function isRtl() {
75
74
  return window.getComputedStyle(document.documentElement).direction === 'rtl';
76
75
  }
@@ -1,6 +1,6 @@
1
1
  <script>
2
2
  import {getContext, setContext, tick} from 'svelte';
3
- import {contentFrom, resizeObserver, runReposition} from '#lib';
3
+ import {contentFrom, empty, length, resizeObserver, runReposition} from '#lib';
4
4
  import ViewState from './state.svelte.js';
5
5
  import Day from './Day.svelte';
6
6
  import Event from './Event.svelte';
@@ -28,12 +28,12 @@
28
28
  $effect(hide);
29
29
  </script>
30
30
 
31
- {#if grid.length && grid[0].length}
31
+ {#if !empty(grid) && !empty(grid[0])}
32
32
  <section
33
33
  bind:this={mainState.mainEl}
34
34
  class={[theme.main, dayMaxEvents === true && theme.uniform]}
35
- style:--ec-grid-cols="{grid[0].length}"
36
- style:--ec-grid-rows="{grid.length}"
35
+ style:--ec-grid-cols="{length(grid[0])}"
36
+ style:--ec-grid-rows="{length(grid)}"
37
37
  {@attach resizeObserver(reposition)}
38
38
  >
39
39
  <header class="{theme.header}">
@@ -57,7 +57,7 @@
57
57
  <div bind:this={viewState.gridEl} class="{theme.grid}">
58
58
  {#each grid as days, i}
59
59
  {#each days as day, j}
60
- <Day {day} noIeb={j + 1 === days.length} noBeb={i + 1 === grid.length}/>
60
+ <Day {day} noIeb={j + 1 === length(days)} noBeb={i + 1 === length(grid)}/>
61
61
  {/each}
62
62
  {/each}
63
63
  </div>
@@ -1,6 +1,6 @@
1
1
  <script>
2
2
  import {getContext, setContext} from 'svelte';
3
- import {addDay, cloneDate, contentFrom, bgEvent, isFunction, toViewWithLocalDates} from '#lib';
3
+ import {addDay, cloneDate, contentFrom, bgEvent, isFunction, toViewWithLocalDates, empty} from '#lib';
4
4
  import ViewState from './state.svelte.js';
5
5
  import Day from './Day.svelte';
6
6
 
@@ -12,7 +12,7 @@
12
12
 
13
13
  let noEvents = $derived.by(() => {
14
14
  let noEvents = true;
15
- if (viewDates.length) {
15
+ if (!empty(viewDates)) {
16
16
  let start = viewDates[0];
17
17
  let end = addDay(cloneDate(viewDates.at(-1)));
18
18
  for (let event of filteredEvents) {
@@ -1,7 +1,7 @@
1
1
  <script>
2
2
  import {getContext, tick} from 'svelte';
3
3
  import {ColHead, DayHeader} from '#components';
4
- import {datesEqual, isRtl} from '#lib';
4
+ import {datesEqual, isRtl, length} from '#lib';
5
5
  import ViewState from './state.svelte.js';
6
6
  import Label from './Label.svelte';
7
7
  import View from '../time-grid/View.svelte';
@@ -28,7 +28,7 @@
28
28
  for (let days of grid) {
29
29
  let day = days[0];
30
30
  if (datesEqual(day.dayStart, today)) {
31
- mainEl.scrollLeft = (mainEl.scrollWidth - sidebarWidth) / (grid.length * days.length) * (day.gridColumn - 1) * (isRtl() ? -1 : 1);
31
+ mainEl.scrollLeft = (mainEl.scrollWidth - sidebarWidth) / (length(grid) * length(days)) * (day.gridColumn - 1) * (isRtl() ? -1 : 1);
32
32
  break;
33
33
  }
34
34
  }
@@ -42,10 +42,10 @@
42
42
  {@const {dayStart: date, resource, disabled, highlight} = days[0]}
43
43
  <ColHead
44
44
  {date}
45
- className={grid[0].length > 1 ? theme.colGroup : undefined}
45
+ className={length(grid[0]) > 1 ? theme.colGroup : undefined}
46
46
  weekday={datesAboveResources}
47
- colSpan={days.length}
48
- colIndex={1 + i * days.length}
47
+ colSpan={length(days)}
48
+ colIndex={1 + i * length(days)}
49
49
  disabled={datesAboveResources && disabled}
50
50
  highlight={datesAboveResources && highlight}
51
51
  >
@@ -56,11 +56,11 @@
56
56
  {/if}
57
57
  </ColHead>
58
58
  {/each}
59
- {#if grid[0].length > 1}
59
+ {#if length(grid[0]) > 1}
60
60
  {#each grid as days, i}
61
61
  {#each days as day, j}
62
62
  {@const {dayStart: date, resource, disabled, highlight} = day}
63
- <ColHead {date} colIndex={1 + j + i * days.length} {disabled} {highlight}>
63
+ <ColHead {date} colIndex={1 + j + i * length(days)} {disabled} {highlight}>
64
64
  {#if datesAboveResources}
65
65
  <Label {resource} {date}/>
66
66
  {:else}
@@ -74,14 +74,14 @@
74
74
 
75
75
  {#snippet nowIndicator()}
76
76
  {#if datesAboveResources}
77
- <NowIndicator days={grid.flat()} span={grid[0].length}/>
77
+ <NowIndicator days={grid.flat()} span={length(grid[0])}/>
78
78
  {:else}
79
- {#if grid[0].length > 1}
79
+ {#if length(grid[0]) > 1}
80
80
  {#each grid as days}
81
81
  <NowIndicator {days} />
82
82
  {/each}
83
83
  {:else}
84
- <NowIndicator days={grid.flat()} span={grid.length}/>
84
+ <NowIndicator days={grid.flat()} span={length(grid)}/>
85
85
  {/if}
86
86
  {/if}
87
87
  {/snippet}
@@ -7,7 +7,7 @@ export function viewResources(mainState) {
7
7
  return () => {
8
8
  // Dependencies
9
9
  let {
10
- activeRange, filteredEvents, options: {filterResourcesWithEvents, resources}, extensions: {viewResources}
10
+ activeRange, filteredEvents, resources, options: {filterResourcesWithEvents}, extensions: {viewResources}
11
11
  } = mainState;
12
12
 
13
13
  let result = viewResources ? viewResources(resources) : resources;
@@ -1,6 +1,8 @@
1
1
  <script>
2
2
  import {getContext, setContext, tick} from 'svelte';
3
- import {max, resizeObserver, runReposition, contentFrom, toSeconds, datesEqual, min, isRtl} from '#lib';
3
+ import {
4
+ max, resizeObserver, runReposition, contentFrom, toSeconds, datesEqual, min, isRtl, empty, length
5
+ } from '#lib';
4
6
  import {getSlotTimeLimits} from './lib.js';
5
7
  import ViewState from './state.svelte.js';
6
8
  import {ColHead, DayHeader} from '#components';
@@ -23,7 +25,7 @@
23
25
  // Handle scrollTime
24
26
  $effect(() => {
25
27
  scrollTime;
26
- if (viewDates.length) {
28
+ if (!empty(viewDates)) {
27
29
  tick().then(scrollToTime);
28
30
  }
29
31
  });
@@ -35,7 +37,7 @@
35
37
  let days = grid[0];
36
38
  for (let day of days) {
37
39
  if (datesEqual(day.dayStart, today)) {
38
- mainEl.scrollLeft = (mainEl.scrollWidth - sidebarWidth) / days.length * (day.gridColumn - 1) * (isRtl() ? -1 : 1);
40
+ mainEl.scrollLeft = (mainEl.scrollWidth - sidebarWidth) / length(days) * (day.gridColumn - 1) * (isRtl() ? -1 : 1);
39
41
  break;
40
42
  }
41
43
  }
@@ -65,12 +67,12 @@
65
67
  $effect(reposition);
66
68
  </script>
67
69
 
68
- {#if grid.length && grid[0].length}
70
+ {#if !empty(grid) && !empty(grid[0])}
69
71
  <section
70
72
  bind:this={mainState.mainEl}
71
73
  class="{theme.main}"
72
- style:--ec-grid-cols="{grid[0].length}"
73
- style:--ec-grid-rows="{grid.length > 1 ? `repeat(${grid.length - 1}, auto)` : ''} 1fr"
74
+ style:--ec-grid-cols="{length(grid[0])}"
75
+ style:--ec-grid-rows="{length(grid) > 1 ? `repeat(${length(grid) - 1}, auto)` : ''} 1fr"
74
76
  style:--ec-col-width="{columnWidth ?? 'minmax(4em, 1fr)'}"
75
77
  style:--ec-slot-label-periodicity="{slotLabelPeriodicity}"
76
78
  style:--ec-slot-height="{slotHeight}px"
@@ -121,7 +123,7 @@
121
123
  <div class="{theme.grid}" role="row">
122
124
  {#each grid as days, i}
123
125
  {#each days as day, j}
124
- <Day {day} noIeb={j + 1 === days.length} noBeb={i + 1 === grid.length}/>
126
+ <Day {day} noIeb={j + 1 === length(days)} noBeb={i + 1 === length(grid)}/>
125
127
  {/each}
126
128
  {/each}
127
129
  </div>
@@ -141,7 +141,7 @@ export function daySlots(mainState, viewState) {
141
141
  export function nestedResources(mainState) {
142
142
  return () => {
143
143
  // Dependencies
144
- let {options: {resources}} = mainState;
144
+ let {resources} = mainState;
145
145
 
146
146
  let nested;
147
147
 
@@ -6,26 +6,29 @@ export function createChunks(event, days, monthView, withId = true) {
6
6
  let lastEnd;
7
7
  let gridColumn;
8
8
  let gridRow;
9
+ let resource;
9
10
  let left;
10
11
  let width = 0;
11
- for (let {gridColumn: column, gridRow: row, resource, dayStart, dayEnd, start, end, disabled} of days) {
12
+ for (let {gridColumn: column, gridRow: row, resource: dayResource, dayStart, dayEnd, start, end, disabled} of days) {
12
13
  if (!disabled) {
13
14
  if (monthView) {
14
- if (eventIntersects(event, dayStart, dayEnd, resource)) {
15
+ if (eventIntersects(event, dayStart, dayEnd, dayResource)) {
15
16
  if (!dates.length) {
16
17
  firstStart = dayStart;
17
18
  gridColumn = column;
18
19
  gridRow = row;
20
+ resource = dayResource;
19
21
  }
20
22
  dates.push(dayStart);
21
23
  lastEnd = end;
22
24
  }
23
25
  } else {
24
- if (eventIntersects(event, start, end, resource)) {
26
+ if (eventIntersects(event, start, end, dayResource)) {
25
27
  if (!dates.length) {
26
28
  firstStart = start;
27
29
  gridColumn = column;
28
30
  gridRow = row;
31
+ resource = dayResource;
29
32
  left = max(event.start - start, 0) / 1000;
30
33
  }
31
34
  dates.push(dayStart);
@@ -38,7 +41,7 @@ export function createChunks(event, days, monthView, withId = true) {
38
41
  if (dates.length) {
39
42
  let chunk = createEventChunk(event, firstStart, lastEnd);
40
43
  // Chunk layout
41
- assign(chunk, {gridColumn, gridRow, dates, left, width});
44
+ assign(chunk, {gridColumn, gridRow, resource, dates, left, width});
42
45
  if (withId) {
43
46
  assignChunkId(chunk);
44
47
  }
@@ -1,6 +1,6 @@
1
1
  <script>
2
2
  import {getContext, setContext, tick} from 'svelte';
3
- import {contentFrom, resizeObserver, runReposition, toSeconds} from '#lib';
3
+ import {contentFrom, empty, length, resizeObserver, runReposition, toSeconds} from '#lib';
4
4
  import {createAllDayContent} from './lib.js';
5
5
  import ViewState from './state.svelte.js';
6
6
  import {ColHead, DayHeader} from '#components';
@@ -30,7 +30,7 @@
30
30
  // Handle scrollTime
31
31
  $effect(() => {
32
32
  scrollTime;
33
- if (viewDates.length) {
33
+ if (!empty(viewDates)) {
34
34
  tick().then(scrollToTime);
35
35
  }
36
36
  });
@@ -48,12 +48,12 @@
48
48
  $effect(reposition);
49
49
  </script>
50
50
 
51
- {#if grid.length && grid[0].length}
51
+ {#if !empty(grid) && !empty(grid[0])}
52
52
  <section
53
53
  bind:this={mainState.mainEl}
54
54
  class="{theme.main}"
55
- style:--ec-grid-cols="{grid.length * grid[0].length}"
56
- style:--ec-col-group-span="{grid[0].length}"
55
+ style:--ec-grid-cols="{length(grid) * length(grid[0])}"
56
+ style:--ec-col-group-span="{length(grid[0])}"
57
57
  style:--ec-col-width="{columnWidth ?? 'minmax(0, 1fr)'}"
58
58
  style:--ec-slot-label-periodicity="{slotLabelPeriodicity}"
59
59
  style:--ec-slot-height="{slotHeight}px"
@@ -81,7 +81,7 @@
81
81
  <div class="{theme.grid}" role="row">
82
82
  {#each grid as days, i}
83
83
  {#each days as day, j}
84
- <Day {day} allDay noIeb={i + 1 === grid.length && j + 1 === days.length}/>
84
+ <Day {day} allDay noIeb={i + 1 === length(grid) && j + 1 === length(days)}/>
85
85
  {/each}
86
86
  {/each}
87
87
  </div>
@@ -118,7 +118,7 @@
118
118
  <div class="{theme.grid}" role="row">
119
119
  {#each grid as days, i}
120
120
  {#each days as day, j}
121
- <Day {day} noIeb={i + 1 === grid.length && j + 1 === days.length} noBeb/>
121
+ <Day {day} noIeb={i + 1 === length(grid) && j + 1 === length(days)} noBeb/>
122
122
  {/each}
123
123
  {/each}
124
124
  </div>
@@ -12,6 +12,7 @@ export function createChunks(event, days, withId = true) {
12
12
  assign(chunk, {
13
13
  gridColumn,
14
14
  gridRow,
15
+ resource,
15
16
  top: (chunk.start - start) / 1000,
16
17
  height: (chunk.end - chunk.start) / 1000,
17
18
  maxHeight: (end - chunk.start) / 1000
@@ -1,6 +1,6 @@
1
1
  import {tick, untrack} from 'svelte';
2
2
  import {
3
- addDay, addDuration, cloneDate, createView, isFunction, prevClosestDay, subtractDay,
3
+ addDay, addDuration, cloneDate, createView, isFunction, prevClosestDay, setMidnight, subtractDay,
4
4
  toEventWithLocalDates, toViewWithLocalDates
5
5
  } from '#lib';
6
6
 
@@ -91,8 +91,9 @@ export function viewDates(mainState) {
91
91
  let dates = [];
92
92
 
93
93
  untrack(() => {
94
- let date = cloneDate(activeRange.start);
95
- let end = cloneDate(activeRange.end);
94
+ // activeRange may be offset by hours due to slotMaxTime, so we set it to midnight
95
+ let date = setMidnight(cloneDate(activeRange.start));
96
+ let end = setMidnight(cloneDate(activeRange.end));
96
97
  while (date < end) {
97
98
  if (!hiddenDays.includes(date.getUTCDay())) {
98
99
  dates.push(cloneDate(date));