@event-calendar/core 5.2.3 → 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/README.md +133 -14
- package/dist/index.css +1 -1
- package/dist/index.js +792 -660
- package/package.json +2 -2
- package/src/Calendar.svelte +6 -1
- package/src/lib/chunks.js +6 -3
- package/src/lib/components/BaseEvent.svelte +11 -5
- package/src/lib/dom.js +9 -0
- package/src/lib/range.js +0 -10
- package/src/lib/resources.js +9 -8
- package/src/lib/utils.js +8 -9
- package/src/plugins/day-grid/View.svelte +50 -48
- package/src/plugins/list/View.svelte +2 -2
- package/src/plugins/resource-time-grid/View.svelte +10 -10
- package/src/plugins/resource-time-grid/derived.js +3 -3
- package/src/plugins/resource-timeline/View.svelte +80 -75
- package/src/plugins/resource-timeline/derived.js +1 -1
- package/src/plugins/resource-timeline/lib.js +7 -4
- package/src/plugins/time-grid/View.svelte +91 -88
- package/src/plugins/time-grid/lib.js +1 -0
- package/src/storage/derived.js +5 -4
- package/src/storage/effects.js +126 -74
- package/src/storage/options.svelte.js +6 -5
- package/src/storage/state.svelte.js +8 -3
|
@@ -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,
|
|
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,
|
|
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';
|
|
@@ -29,9 +29,10 @@
|
|
|
29
29
|
|
|
30
30
|
// Handle scrollTime
|
|
31
31
|
$effect(() => {
|
|
32
|
-
viewDates;
|
|
33
32
|
scrollTime;
|
|
34
|
-
|
|
33
|
+
if (!empty(viewDates)) {
|
|
34
|
+
tick().then(scrollToTime);
|
|
35
|
+
}
|
|
35
36
|
});
|
|
36
37
|
function scrollToTime() {
|
|
37
38
|
mainEl.scrollTop = (
|
|
@@ -47,97 +48,99 @@
|
|
|
47
48
|
$effect(reposition);
|
|
48
49
|
</script>
|
|
49
50
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
<
|
|
64
|
-
|
|
65
|
-
{
|
|
66
|
-
{
|
|
67
|
-
|
|
68
|
-
{
|
|
69
|
-
|
|
70
|
-
<
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
51
|
+
{#if !empty(grid) && !empty(grid[0])}
|
|
52
|
+
<section
|
|
53
|
+
bind:this={mainState.mainEl}
|
|
54
|
+
class="{theme.main}"
|
|
55
|
+
style:--ec-grid-cols="{length(grid) * length(grid[0])}"
|
|
56
|
+
style:--ec-col-group-span="{length(grid[0])}"
|
|
57
|
+
style:--ec-col-width="{columnWidth ?? 'minmax(0, 1fr)'}"
|
|
58
|
+
style:--ec-slot-label-periodicity="{slotLabelPeriodicity}"
|
|
59
|
+
style:--ec-slot-height="{slotHeight}px"
|
|
60
|
+
style:--ec-header-height="{headerHeight}px"
|
|
61
|
+
style:--ec-sidebar-width="{sidebarWidth}px"
|
|
62
|
+
{@attach resizeObserver(reposition)}
|
|
63
|
+
>
|
|
64
|
+
<header bind:offsetHeight={headerHeight} class="{theme.header}">
|
|
65
|
+
<aside class="{theme.sidebar}" bind:offsetWidth={viewState.sidebarWidth}></aside>
|
|
66
|
+
<div class="{theme.grid}" role="row">
|
|
67
|
+
{#if header}
|
|
68
|
+
{@render header()}
|
|
69
|
+
{:else}
|
|
70
|
+
{#each grid[0] as {dayStart: date, disabled, highlight}, i}
|
|
71
|
+
<ColHead {date} colIndex={1 + i} {disabled} {highlight}>
|
|
72
|
+
<DayHeader {date}/>
|
|
73
|
+
</ColHead>
|
|
74
|
+
{/each}
|
|
75
|
+
{/if}
|
|
76
|
+
</div>
|
|
75
77
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
78
|
+
{#if allDaySlot}
|
|
79
|
+
<div class="{theme.allDay}">
|
|
80
|
+
<aside class="{theme.sidebar}" {@attach contentFrom(allDayText)}></aside>
|
|
81
|
+
<div class="{theme.grid}" role="row">
|
|
82
|
+
{#each grid as days, i}
|
|
83
|
+
{#each days as day, j}
|
|
84
|
+
<Day {day} allDay noIeb={i + 1 === length(grid) && j + 1 === length(days)}/>
|
|
85
|
+
{/each}
|
|
83
86
|
{/each}
|
|
84
|
-
|
|
87
|
+
</div>
|
|
88
|
+
<div class="{theme.events}">
|
|
89
|
+
{#each allDayChunks as chunk, i (chunk.id)}
|
|
90
|
+
<!-- svelte-ignore binding_property_non_reactive -->
|
|
91
|
+
<AllDayEvent bind:this={refs[i]} {chunk}/>
|
|
92
|
+
{/each}
|
|
93
|
+
{#each allDayBgChunks as chunk (chunk.id)}
|
|
94
|
+
<AllDayEvent {chunk}/>
|
|
95
|
+
{/each}
|
|
96
|
+
{#each allDayIChunks as chunk}
|
|
97
|
+
<AllDayEvent {chunk}/>
|
|
98
|
+
{/each}
|
|
99
|
+
</div>
|
|
85
100
|
</div>
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
101
|
+
{/if}
|
|
102
|
+
</header>
|
|
103
|
+
|
|
104
|
+
<div class="{theme.body}" role="rowgroup">
|
|
105
|
+
<aside class="{theme.sidebar}" aria-hidden="true">
|
|
106
|
+
{#each slots as slot, i}
|
|
107
|
+
<div
|
|
108
|
+
class={[theme.slot, !i && theme.hidden]}
|
|
109
|
+
style:--ec-slot-label-periodicity={slot[2]}
|
|
110
|
+
>
|
|
111
|
+
<time
|
|
112
|
+
datetime="{slot[0]}"
|
|
113
|
+
{@attach contentFrom(slot[1])}
|
|
114
|
+
></time>
|
|
115
|
+
</div>
|
|
116
|
+
{/each}
|
|
117
|
+
</aside>
|
|
118
|
+
<div class="{theme.grid}" role="row">
|
|
119
|
+
{#each grid as days, i}
|
|
120
|
+
{#each days as day, j}
|
|
121
|
+
<Day {day} noIeb={i + 1 === length(grid) && j + 1 === length(days)} noBeb/>
|
|
96
122
|
{/each}
|
|
97
|
-
|
|
123
|
+
{/each}
|
|
98
124
|
</div>
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
<div class="{theme.body}" role="rowgroup">
|
|
103
|
-
<aside class="{theme.sidebar}" aria-hidden="true">
|
|
104
|
-
{#each slots as slot, i}
|
|
105
|
-
<div
|
|
106
|
-
class={[theme.slot, !i && theme.hidden]}
|
|
107
|
-
style:--ec-slot-label-periodicity={slot[2]}
|
|
108
|
-
>
|
|
109
|
-
<time
|
|
110
|
-
datetime="{slot[0]}"
|
|
111
|
-
{@attach contentFrom(slot[1])}
|
|
112
|
-
></time>
|
|
113
|
-
</div>
|
|
114
|
-
{/each}
|
|
115
|
-
</aside>
|
|
116
|
-
<div class="{theme.grid}" role="row">
|
|
117
|
-
{#each grid as days, i}
|
|
118
|
-
{#each days as day, j}
|
|
119
|
-
<Day {day} noIeb={i + 1 === grid.length && j + 1 === days.length} noBeb/>
|
|
125
|
+
<div class="{theme.events}">
|
|
126
|
+
{#each chunks as chunk (chunk.id)}
|
|
127
|
+
<Event {chunk}/>
|
|
120
128
|
{/each}
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
<Event {chunk}/>
|
|
129
|
-
{/each}
|
|
130
|
-
{#each iChunks as chunk}
|
|
131
|
-
<Event {chunk}/>
|
|
132
|
-
{/each}
|
|
129
|
+
{#each bgChunks as chunk (chunk.id)}
|
|
130
|
+
<Event {chunk}/>
|
|
131
|
+
{/each}
|
|
132
|
+
{#each iChunks as chunk}
|
|
133
|
+
<Event {chunk}/>
|
|
134
|
+
{/each}
|
|
135
|
+
</div>
|
|
133
136
|
</div>
|
|
134
|
-
</div>
|
|
135
137
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
138
|
+
{#if showNowIndicator}
|
|
139
|
+
{#if nowIndicator}
|
|
140
|
+
{@render nowIndicator()}
|
|
141
|
+
{:else}
|
|
142
|
+
<NowIndicator days={grid[0]}/>
|
|
143
|
+
{/if}
|
|
141
144
|
{/if}
|
|
142
|
-
|
|
143
|
-
|
|
145
|
+
</section>
|
|
146
|
+
{/if}
|
package/src/storage/derived.js
CHANGED
|
@@ -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
|
|
|
@@ -45,7 +45,7 @@ export function activeRange(mainState) {
|
|
|
45
45
|
export function filteredEvents(mainState) {
|
|
46
46
|
return () => {
|
|
47
47
|
// Dependencies
|
|
48
|
-
let {events, options: {eventFilter, eventOrder, filterEventsWithResources, resources}} = mainState;
|
|
48
|
+
let {events, options: {eventFilter, eventOrder, filterEventsWithResources, resources, view}} = mainState;
|
|
49
49
|
|
|
50
50
|
let result = [...events];
|
|
51
51
|
|
|
@@ -91,8 +91,9 @@ export function viewDates(mainState) {
|
|
|
91
91
|
let dates = [];
|
|
92
92
|
|
|
93
93
|
untrack(() => {
|
|
94
|
-
|
|
95
|
-
let
|
|
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));
|
package/src/storage/effects.js
CHANGED
|
@@ -1,88 +1,140 @@
|
|
|
1
1
|
import {getAbortSignal, tick, untrack} from 'svelte';
|
|
2
2
|
import {
|
|
3
|
-
assign, cloneDate, createDate, createEvents, datesEqual,
|
|
4
|
-
toViewWithLocalDates
|
|
3
|
+
assign, cloneDate, createDate, createEvents, createResources, datesEqual, empty, isArray, isFunction, setMidnight,
|
|
4
|
+
toISOString, toLocalDate, toViewWithLocalDates
|
|
5
5
|
} from '#lib';
|
|
6
6
|
|
|
7
|
-
export function loadEvents(mainState) {
|
|
8
|
-
let fetching = 0;
|
|
7
|
+
export function loadEvents(mainState, loadingInvoker) {
|
|
9
8
|
return () => {
|
|
10
9
|
// Dependencies
|
|
11
|
-
let {activeRange, fetchedRange
|
|
10
|
+
let {activeRange, fetchedRange: {events: fetchedRange}, viewDates,
|
|
11
|
+
options: {events, eventSources, lazyFetching}} = mainState;
|
|
12
12
|
|
|
13
13
|
untrack(() => {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
fetchedRange
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
14
|
+
load(
|
|
15
|
+
eventSources.map(source => isFunction(source.events) ? source.events : source),
|
|
16
|
+
events,
|
|
17
|
+
createEvents,
|
|
18
|
+
result => mainState.events = result,
|
|
19
|
+
activeRange,
|
|
20
|
+
fetchedRange,
|
|
21
|
+
viewDates,
|
|
22
|
+
true,
|
|
23
|
+
lazyFetching,
|
|
24
|
+
loadingInvoker
|
|
25
|
+
);
|
|
26
|
+
});
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export function loadResources(mainState, loadingInvoker) {
|
|
31
|
+
return () => {
|
|
32
|
+
// Dependencies
|
|
33
|
+
let {activeRange, fetchedRange: {resources: fetchedRange}, viewDates,
|
|
34
|
+
options: {lazyFetching, refetchResourcesOnNavigate, resources}} = mainState;
|
|
35
|
+
|
|
36
|
+
untrack(() => {
|
|
37
|
+
load(
|
|
38
|
+
isArray(resources) ? [] : [resources],
|
|
39
|
+
resources,
|
|
40
|
+
createResources,
|
|
41
|
+
result => mainState.resources = result,
|
|
42
|
+
activeRange,
|
|
43
|
+
fetchedRange,
|
|
44
|
+
viewDates,
|
|
45
|
+
refetchResourcesOnNavigate,
|
|
46
|
+
lazyFetching,
|
|
47
|
+
loadingInvoker
|
|
48
|
+
);
|
|
49
|
+
});
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function load(sources, defaultResult, parseResult, applyResult, activeRange, fetchedRange, viewDates, refetchOnNavigate, lazyFetching, loading) {
|
|
54
|
+
if (empty(viewDates)) {
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
if (empty(sources)) {
|
|
58
|
+
applyResult(defaultResult);
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
// Do not fetch if new range is within the previous one
|
|
62
|
+
if (
|
|
63
|
+
(refetchOnNavigate || !fetchedRange.start) &&
|
|
64
|
+
(
|
|
65
|
+
!lazyFetching ||
|
|
66
|
+
!fetchedRange.start ||
|
|
67
|
+
fetchedRange.start > activeRange.start ||
|
|
68
|
+
fetchedRange.end < activeRange.end
|
|
69
|
+
)
|
|
70
|
+
) {
|
|
71
|
+
let result = [];
|
|
72
|
+
// Prepare handlers
|
|
73
|
+
let failure = e => loading.stop();
|
|
74
|
+
let success = data => {
|
|
75
|
+
result = result.concat(parseResult(data));
|
|
76
|
+
applyResult(result);
|
|
77
|
+
loading.stop();
|
|
78
|
+
};
|
|
79
|
+
// Prepare other stuff
|
|
80
|
+
let startStr = toISOString(activeRange.start)
|
|
81
|
+
let endStr = toISOString(activeRange.end);
|
|
82
|
+
// Loop over event sources
|
|
83
|
+
for (let source of sources) {
|
|
84
|
+
loading.start();
|
|
85
|
+
if (isFunction(source)) {
|
|
86
|
+
// Source as a function
|
|
87
|
+
let result = source(refetchOnNavigate ? {
|
|
88
|
+
start: toLocalDate(activeRange.start),
|
|
89
|
+
end: toLocalDate(activeRange.end),
|
|
90
|
+
startStr,
|
|
91
|
+
endStr
|
|
92
|
+
} : {}, success, failure);
|
|
93
|
+
if (result !== undefined) {
|
|
94
|
+
Promise.resolve(result).then(success, failure);
|
|
95
|
+
}
|
|
96
|
+
} else {
|
|
97
|
+
// Source as a JSON feed
|
|
98
|
+
// Prepare params
|
|
99
|
+
let params = isFunction(source.extraParams) ? source.extraParams() : assign({}, source.extraParams);
|
|
100
|
+
if (refetchOnNavigate) {
|
|
101
|
+
params.start = startStr;
|
|
102
|
+
params.end = endStr;
|
|
27
103
|
}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
let success = data => {
|
|
37
|
-
events = events.concat(createEvents(data));
|
|
38
|
-
mainState.events = events;
|
|
39
|
-
stopLoading();
|
|
40
|
-
};
|
|
41
|
-
// Prepare other stuff
|
|
42
|
-
let startStr = toISOString(activeRange.start)
|
|
43
|
-
let endStr = toISOString(activeRange.end);
|
|
44
|
-
// Loop over event sources
|
|
45
|
-
for (let source of eventSources) {
|
|
46
|
-
if (isFunction(source.events)) {
|
|
47
|
-
// Events as a function
|
|
48
|
-
let result = source.events({
|
|
49
|
-
start: toLocalDate(activeRange.start),
|
|
50
|
-
end: toLocalDate(activeRange.end),
|
|
51
|
-
startStr,
|
|
52
|
-
endStr
|
|
53
|
-
}, success, failure);
|
|
54
|
-
if (result !== undefined) {
|
|
55
|
-
Promise.resolve(result).then(success, failure);
|
|
56
|
-
}
|
|
57
|
-
} else {
|
|
58
|
-
// Events as a JSON feed
|
|
59
|
-
// Prepare params
|
|
60
|
-
let params = isFunction(source.extraParams) ? source.extraParams() : assign({}, source.extraParams);
|
|
61
|
-
params.start = startStr;
|
|
62
|
-
params.end = endStr;
|
|
63
|
-
params = new URLSearchParams(params);
|
|
64
|
-
// Prepare fetch
|
|
65
|
-
let url = source.url, headers = {}, body;
|
|
66
|
-
if (['GET', 'HEAD'].includes(source.method)) {
|
|
67
|
-
url += (url.includes('?') ? '&' : '?') + params;
|
|
68
|
-
} else {
|
|
69
|
-
headers['content-type'] = 'application/x-www-form-urlencoded;charset=UTF-8';
|
|
70
|
-
body = String(params); // Safari 10.1 doesn't convert to string automatically
|
|
71
|
-
}
|
|
72
|
-
// Do the fetch
|
|
73
|
-
fetch(url, {
|
|
74
|
-
method: source.method, headers, body, signal: getAbortSignal(), credentials: 'same-origin'
|
|
75
|
-
})
|
|
76
|
-
.then(response => response.json())
|
|
77
|
-
.then(success)
|
|
78
|
-
.catch(failure);
|
|
79
|
-
}
|
|
80
|
-
++fetching;
|
|
104
|
+
params = new URLSearchParams(params);
|
|
105
|
+
// Prepare fetch
|
|
106
|
+
let url = source.url, headers = {}, body;
|
|
107
|
+
if (['GET', 'HEAD'].includes(source.method)) {
|
|
108
|
+
url += (url.includes('?') ? '&' : '?') + params;
|
|
109
|
+
} else {
|
|
110
|
+
headers['content-type'] = 'application/x-www-form-urlencoded;charset=UTF-8';
|
|
111
|
+
body = String(params); // Safari 10.1 doesn't convert to string automatically
|
|
81
112
|
}
|
|
82
|
-
//
|
|
83
|
-
|
|
113
|
+
// Do the fetch
|
|
114
|
+
fetch(url, {
|
|
115
|
+
method: source.method, headers, body, signal: getAbortSignal(), credentials: 'same-origin'
|
|
116
|
+
})
|
|
117
|
+
.then(response => response.json())
|
|
118
|
+
.then(success)
|
|
119
|
+
.catch(failure);
|
|
84
120
|
}
|
|
85
|
-
}
|
|
121
|
+
}
|
|
122
|
+
// Save current range for future requests
|
|
123
|
+
assign(fetchedRange, activeRange);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
export function createLoadingInvoker(options) {
|
|
128
|
+
let counter = 0;
|
|
129
|
+
function invoke(value) {
|
|
130
|
+
let {loading} = options;
|
|
131
|
+
if (isFunction(loading)) {
|
|
132
|
+
loading(value);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
return {
|
|
136
|
+
start: () => ++counter === 1 && invoke(true),
|
|
137
|
+
stop: () => --counter === 0 && invoke(false)
|
|
86
138
|
};
|
|
87
139
|
}
|
|
88
140
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {untrack} from 'svelte';
|
|
2
2
|
import {
|
|
3
|
-
createDate, createDateRange, createDuration, createEvents, createEventSources, createResources, entries,
|
|
3
|
+
createDate, createDateRange, createDuration, createEvents, createEventSources, createResources, entries, isArray,
|
|
4
4
|
isFunction, keys, setMidnight
|
|
5
5
|
} from '#lib';
|
|
6
6
|
import {SvelteMap} from "svelte/reactivity";
|
|
@@ -55,6 +55,7 @@ function createOptions(plugins) {
|
|
|
55
55
|
lazyFetching: true,
|
|
56
56
|
loading: undefined,
|
|
57
57
|
locale: undefined,
|
|
58
|
+
refetchResourcesOnNavigate: false,
|
|
58
59
|
resources: [],
|
|
59
60
|
selectable: false,
|
|
60
61
|
theme: {
|
|
@@ -110,13 +111,13 @@ function createOptions(plugins) {
|
|
|
110
111
|
|
|
111
112
|
function createParsers(plugins) {
|
|
112
113
|
let parsers = {
|
|
113
|
-
date:
|
|
114
|
+
date: input => setMidnight(createDate(input)),
|
|
114
115
|
duration: createDuration,
|
|
115
116
|
events: createEvents,
|
|
116
117
|
eventSources: createEventSources,
|
|
117
|
-
hiddenDays:
|
|
118
|
-
highlightedDates:
|
|
119
|
-
resources: createResources,
|
|
118
|
+
hiddenDays: input => [...new Set(input)],
|
|
119
|
+
highlightedDates: input => input.map(item => setMidnight(createDate(item))),
|
|
120
|
+
resources: input => isArray(input) ? createResources(input) : input,
|
|
120
121
|
validRange: createDateRange
|
|
121
122
|
};
|
|
122
123
|
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import {SvelteMap} from 'svelte/reactivity';
|
|
2
2
|
import {createDate, identity, intl, intlRange, setMidnight} from '#lib';
|
|
3
3
|
import {optionsState} from './options.svelte.js';
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
createLoadingInvoker, loadEvents, loadResources, runDatesSet, runEventAllUpdated, runViewDidMount, setNowAndToday
|
|
6
|
+
} from './effects.js';
|
|
5
7
|
import {activeRange, currentRange, filteredEvents, view, viewDates, viewTitle} from './derived.js';
|
|
6
8
|
|
|
7
9
|
export default class State {
|
|
@@ -18,11 +20,12 @@ export default class State {
|
|
|
18
20
|
this.auxComponents = $state([]);
|
|
19
21
|
this.currentRange = $derived.by(currentRange(this));
|
|
20
22
|
this.activeRange = $derived.by(activeRange(this));
|
|
21
|
-
this.fetchedRange = $state
|
|
23
|
+
this.fetchedRange = $state({events: {}, resources: {}});
|
|
22
24
|
this.events = $state.raw([]);
|
|
23
25
|
this.filteredEvents = $derived.by(filteredEvents(this));
|
|
24
26
|
this.mainEl = $state();
|
|
25
27
|
this.now = $state(createDate());
|
|
28
|
+
this.resources = $state.raw([]);
|
|
26
29
|
this.today = $state(setMidnight(createDate()));
|
|
27
30
|
this.intlEventTime = $derived.by(intlRange(this, 'eventTimeFormat'));
|
|
28
31
|
this.intlDayHeader = $derived.by(intl(this, 'dayHeaderFormat'));
|
|
@@ -50,8 +53,10 @@ export default class State {
|
|
|
50
53
|
}
|
|
51
54
|
|
|
52
55
|
#initEffects() {
|
|
56
|
+
let loading = createLoadingInvoker(this.options);
|
|
53
57
|
$effect.pre(setNowAndToday(this));
|
|
54
|
-
$effect(loadEvents(this));
|
|
58
|
+
$effect(loadEvents(this, loading));
|
|
59
|
+
$effect(loadResources(this, loading));
|
|
55
60
|
$effect(runDatesSet(this));
|
|
56
61
|
$effect(runEventAllUpdated(this));
|
|
57
62
|
$effect(runViewDidMount(this));
|