@event-calendar/core 5.0.6 → 5.1.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 (79) hide show
  1. package/README.md +15 -4
  2. package/dist/index.css +2 -2
  3. package/dist/index.js +2200 -2122
  4. package/package.json +2 -2
  5. package/src/Buttons.svelte +36 -37
  6. package/src/Calendar.svelte +34 -37
  7. package/src/Toolbar.svelte +4 -4
  8. package/src/lib/components/BaseDay.svelte +13 -10
  9. package/src/lib/components/BaseEvent.svelte +17 -17
  10. package/src/lib/components/ColHead.svelte +6 -6
  11. package/src/lib/components/DayHeader.svelte +3 -3
  12. package/src/lib/components/InteractableEvent.svelte +7 -8
  13. package/src/lib/derived.js +80 -0
  14. package/src/lib/index.js +1 -2
  15. package/src/lib/slots.js +16 -16
  16. package/src/lib/utils.js +4 -9
  17. package/src/lib/view.js +0 -8
  18. package/src/plugins/day-grid/Day.svelte +25 -23
  19. package/src/plugins/day-grid/Event.svelte +15 -13
  20. package/src/plugins/day-grid/Popup.svelte +12 -12
  21. package/src/plugins/day-grid/View.svelte +24 -33
  22. package/src/plugins/day-grid/derived.js +102 -0
  23. package/src/plugins/day-grid/index.js +47 -36
  24. package/src/plugins/day-grid/state.svelte.js +19 -0
  25. package/src/plugins/interaction/Action.svelte +108 -76
  26. package/src/plugins/interaction/Auxiliary.svelte +9 -38
  27. package/src/plugins/interaction/Pointer.svelte +12 -17
  28. package/src/plugins/interaction/Resizer.svelte +9 -7
  29. package/src/plugins/interaction/effects.js +37 -0
  30. package/src/plugins/interaction/index.js +44 -38
  31. package/src/plugins/interaction/lib/utils.js +1 -1
  32. package/src/plugins/interaction/state.svelte.js +12 -0
  33. package/src/plugins/list/Day.svelte +8 -7
  34. package/src/plugins/list/Event.svelte +3 -3
  35. package/src/plugins/list/View.svelte +17 -16
  36. package/src/plugins/list/index.js +51 -43
  37. package/src/plugins/list/state.svelte.js +8 -0
  38. package/src/plugins/resource-time-grid/Label.svelte +8 -8
  39. package/src/plugins/resource-time-grid/View.svelte +38 -17
  40. package/src/plugins/resource-time-grid/derived.js +67 -0
  41. package/src/plugins/resource-time-grid/index.js +34 -28
  42. package/src/plugins/resource-time-grid/state.svelte.js +21 -0
  43. package/src/plugins/resource-timeline/Day.svelte +9 -4
  44. package/src/plugins/resource-timeline/Event.svelte +7 -6
  45. package/src/plugins/resource-timeline/Expander.svelte +7 -6
  46. package/src/plugins/resource-timeline/NowIndicator.svelte +10 -11
  47. package/src/plugins/resource-timeline/View.svelte +45 -60
  48. package/src/plugins/resource-timeline/derived.js +167 -0
  49. package/src/plugins/resource-timeline/index.js +17 -21
  50. package/src/plugins/resource-timeline/lib.js +4 -65
  51. package/src/plugins/resource-timeline/state.svelte.js +18 -0
  52. package/src/plugins/time-grid/Day.svelte +7 -2
  53. package/src/plugins/time-grid/Event.svelte +6 -6
  54. package/src/plugins/time-grid/NowIndicator.svelte +10 -9
  55. package/src/plugins/time-grid/View.svelte +46 -55
  56. package/src/plugins/time-grid/derived.js +162 -0
  57. package/src/plugins/time-grid/index.js +31 -25
  58. package/src/plugins/time-grid/lib.js +18 -74
  59. package/src/plugins/time-grid/options.js +21 -16
  60. package/src/plugins/time-grid/state.svelte.js +44 -0
  61. package/src/storage/derived.js +144 -0
  62. package/src/storage/effects.js +156 -0
  63. package/src/storage/options.svelte.js +275 -0
  64. package/src/storage/state.svelte.js +69 -0
  65. package/src/styles/events.css +1 -1
  66. package/src/Auxiliary.svelte +0 -47
  67. package/src/lib/debounce.js +0 -20
  68. package/src/lib/stores.js +0 -63
  69. package/src/plugins/day-grid/lib.js +0 -61
  70. package/src/plugins/day-grid/stores.js +0 -5
  71. package/src/plugins/resource-time-grid/lib.js +0 -31
  72. package/src/plugins/resource-time-grid/stores.js +0 -34
  73. package/src/plugins/resource-timeline/Header.svelte +0 -44
  74. package/src/plugins/resource-timeline/Label.svelte +0 -38
  75. package/src/plugins/resource-timeline/stores.js +0 -48
  76. package/src/plugins/time-grid/stores.js +0 -49
  77. package/src/storage/options.js +0 -136
  78. package/src/storage/state.js +0 -168
  79. package/src/storage/stores.js +0 -234
@@ -1,38 +0,0 @@
1
- <script>
2
- import {getContext, onMount} from 'svelte';
3
- import {contentFrom, toLocalDate, isFunction} from '#lib';
4
-
5
- let {resource, date = undefined} = $props();
6
-
7
- let {resourceLabelContent, resourceLabelDidMount} = getContext('state');
8
-
9
- let el = $state();
10
- // Content
11
- let content = $derived.by(() => {
12
- if ($resourceLabelContent) {
13
- return isFunction($resourceLabelContent)
14
- ? $resourceLabelContent({
15
- resource,
16
- date: date ? toLocalDate(date) : undefined,
17
- })
18
- : $resourceLabelContent;
19
- } else {
20
- return resource.title;
21
- }
22
- });
23
-
24
- onMount(() => {
25
- if (isFunction($resourceLabelDidMount)) {
26
- $resourceLabelDidMount({
27
- resource,
28
- date: date ? toLocalDate(date) : undefined,
29
- el
30
- });
31
- }
32
- });
33
- </script>
34
-
35
- <span
36
- bind:this={el}
37
- {@attach contentFrom(content)}
38
- ></span>
@@ -1,48 +0,0 @@
1
- import {derived} from 'svelte/store';
2
- import {createSlotTimeLimits, createSlots, getPayload, toSeconds} from '#lib';
3
-
4
- // slotTimeLimits per day
5
- export function dayTimeLimits(state) {
6
- return derived(
7
- [state.slotMinTime, state.slotMaxTime, state.flexibleSlotTimeLimits, state._viewDates, state._filteredEvents],
8
- ([$slotMinTime, $slotMaxTime, $flexibleSlotTimeLimits, $_viewDates, $_filteredEvents]) => {
9
- let dayTimeLimits = {};
10
- for (let date of $_viewDates) {
11
- dayTimeLimits[date.getTime()] = createSlotTimeLimits(
12
- $slotMinTime,
13
- $slotMaxTime,
14
- $flexibleSlotTimeLimits,
15
- [date],
16
- $_filteredEvents
17
- );
18
- }
19
-
20
- return dayTimeLimits;
21
- }
22
- );
23
- }
24
-
25
- export function daySlots(state) {
26
- return derived(
27
- [state._viewDates, state.slotDuration, state._slotLabelPeriodicity, state._dayTimeLimits, state._intlSlotLabel],
28
- ([$_viewDates, $slotDuration, $_slotLabelPeriodicity, $_dayTimeLimits, $_intlSlotLabel]) => {
29
- let dayTimes = {};
30
- for (let date of $_viewDates) {
31
- let key = date.getTime();
32
- dayTimes[key] = key in $_dayTimeLimits
33
- ? createSlots(date, $slotDuration, $_slotLabelPeriodicity, $_dayTimeLimits[key], $_intlSlotLabel)
34
- : [];
35
- }
36
-
37
- return dayTimes;
38
- }
39
- );
40
- }
41
-
42
- export function nestedResources(state) {
43
- return derived(state.resources, $resources => $resources.some(resource => getPayload(resource).children.length));
44
- }
45
-
46
- export function monthView(state) {
47
- return derived(state.slotDuration, $slotDuration => !toSeconds($slotDuration));
48
- }
@@ -1,49 +0,0 @@
1
- import {derived, writable} from 'svelte/store';
2
- import {ceil, createDate, createSlotTimeLimits, createSlots, intl, setMidnight, toSeconds} from '#lib';
3
-
4
- function slotTimeLimits(state) {
5
- return derived(
6
- [state.slotMinTime, state.slotMaxTime, state.flexibleSlotTimeLimits, state._viewDates, state._filteredEvents],
7
- args => createSlotTimeLimits(...args)
8
- );
9
- }
10
-
11
- function slotLabelPeriodicity(state) {
12
- return derived(
13
- [state.slotDuration, state.slotLabelInterval],
14
- ([$slotDuration, $slotLabelInterval]) => {
15
- if ($slotLabelInterval === undefined) {
16
- return toSeconds($slotDuration) < 3600 ? 2 : 1;
17
- }
18
- return ceil(toSeconds($slotLabelInterval) / toSeconds($slotDuration)) || 1;
19
- }
20
- );
21
- }
22
-
23
- function slots(state) {
24
- return derived(
25
- [state.slotDuration, state._slotLabelPeriodicity, state._slotTimeLimits, state._intlSlotLabel],
26
- args => createSlots(setMidnight(createDate()), ...args)
27
- );
28
- }
29
-
30
- /**
31
- * TimeGrid + ResourceTimeGrid + ResourceTimeline
32
- */
33
- export function createTRRStores(state) {
34
- if (!('_sidebarWidth' in state)) {
35
- state._intlSlotLabel = intl(state.locale, state.slotLabelFormat);
36
- state._slotLabelPeriodicity = slotLabelPeriodicity(state);
37
- state._sidebarWidth = writable(0);
38
- }
39
- }
40
-
41
- /**
42
- * TimeGrid + ResourceTimeGrid
43
- */
44
- export function createTRStores(state) {
45
- if (!('_slots' in state)) {
46
- state._slotTimeLimits = slotTimeLimits(state); // flexible limits
47
- state._slots = slots(state);
48
- }
49
- }
@@ -1,136 +0,0 @@
1
- import {
2
- createDate, createDuration, createEvents, createEventSources, createResources, createDateRange, keys, setMidnight
3
- } from '#lib';
4
-
5
- // Options where initial value is passed to the function
6
- export const specialOptions = ['buttonText', 'customButtons', 'theme'];
7
-
8
- export function createOptions(plugins) {
9
- let options = {
10
- buttonText: {
11
- today: 'today',
12
- },
13
- customButtons: {},
14
- date: new Date(),
15
- datesSet: undefined,
16
- dayHeaderFormat: {
17
- weekday: 'short',
18
- month: 'numeric',
19
- day: 'numeric'
20
- },
21
- dayHeaderAriaLabelFormat: {
22
- dateStyle: 'full'
23
- },
24
- displayEventEnd: true,
25
- duration: {weeks: 1},
26
- events: [],
27
- eventAllUpdated: undefined,
28
- eventBackgroundColor: undefined,
29
- eventClassNames: undefined,
30
- eventClick: undefined,
31
- eventColor: undefined,
32
- eventContent: undefined,
33
- eventDidMount: undefined,
34
- eventFilter: undefined, // ec option
35
- eventMouseEnter: undefined,
36
- eventMouseLeave: undefined,
37
- eventOrder: undefined,
38
- eventSources: [],
39
- eventTextColor: undefined,
40
- eventTimeFormat: {
41
- hour: 'numeric',
42
- minute: '2-digit'
43
- },
44
- filterEventsWithResources: false,
45
- firstDay: 0,
46
- headerToolbar: {
47
- start: 'title',
48
- center: '',
49
- end: 'today prev,next'
50
- },
51
- height: undefined,
52
- hiddenDays: [],
53
- highlightedDates: [], // ec option
54
- lazyFetching: true,
55
- loading: undefined,
56
- locale: undefined,
57
- resources: [],
58
- selectable: false,
59
- theme: {
60
- allDay: 'ec-all-day',
61
- active: 'ec-active',
62
- bgEvent: 'ec-bg-event',
63
- bgEvents: 'ec-bg-events',
64
- body: 'ec-body',
65
- button: 'ec-button',
66
- buttonGroup: 'ec-button-group',
67
- calendar: 'ec',
68
- colHead: 'ec-col-head',
69
- day: 'ec-day',
70
- dayHead: 'ec-day-head',
71
- disabled: 'ec-disabled',
72
- event: 'ec-event',
73
- eventBody: 'ec-event-body',
74
- eventTime: 'ec-event-time',
75
- eventTitle: 'ec-event-title',
76
- events: 'ec-events',
77
- grid: 'ec-grid',
78
- header: 'ec-header',
79
- hidden: 'ec-hidden',
80
- highlight: 'ec-highlight',
81
- icon: 'ec-icon',
82
- main: 'ec-main',
83
- noBeb: 'ec-no-beb', // no block end border
84
- noIeb: 'ec-no-ieb', // no inline end border
85
- today: 'ec-today',
86
- title: 'ec-title',
87
- toolbar: 'ec-toolbar',
88
- view: '',
89
- weekdays: ['ec-sun', 'ec-mon', 'ec-tue', 'ec-wed', 'ec-thu', 'ec-fri', 'ec-sat'],
90
- },
91
- titleFormat: {
92
- year: 'numeric',
93
- month: 'short',
94
- day: 'numeric'
95
- },
96
- validRange: undefined,
97
- view: undefined,
98
- viewDidMount: undefined,
99
- views: {}
100
- };
101
-
102
- for (let plugin of plugins) {
103
- plugin.createOptions?.(options);
104
- }
105
-
106
- return options;
107
- }
108
-
109
- export function createParsers(plugins) {
110
- let parsers = {
111
- date: date => setMidnight(createDate(date)),
112
- duration: createDuration,
113
- events: createEvents,
114
- eventSources: createEventSources,
115
- hiddenDays: days => [...new Set(days)],
116
- highlightedDates: dates => dates.map(date => setMidnight(createDate(date))),
117
- resources: createResources,
118
- validRange: createDateRange
119
- };
120
-
121
- for (let plugin of plugins) {
122
- plugin.createParsers?.(parsers);
123
- }
124
-
125
- return parsers;
126
- }
127
-
128
- export function diff(options, prevOptions) {
129
- let diff = [];
130
- for (let key of keys(options)) {
131
- if (options[key] !== prevOptions[key]) {
132
- diff.push([key, options[key]]);
133
- }
134
- }
135
- return diff;
136
- }
@@ -1,168 +0,0 @@
1
- import {get, writable} from 'svelte/store';
2
- import {tick} from 'svelte';
3
- import {createOptions, createParsers, specialOptions} from './options.js';
4
- import {activeRange, currentRange, dayGrid, events, now, today, view as view2, viewDates, viewTitle, filteredEvents} from './stores.js';
5
- import {identity, intl, intlRange, isFunction, keys, toViewWithLocalDates} from '#lib';
6
-
7
- export default class {
8
- constructor(plugins, input) {
9
- plugins = plugins || [];
10
-
11
- // Create options
12
- let options = createOptions(plugins);
13
- let parsers = createParsers(plugins);
14
-
15
- // Parse options
16
- options = parseOpts(options, parsers);
17
- input = parseOpts(input, parsers);
18
-
19
- // Create stores for options
20
- for (let [option, value] of Object.entries(options)) {
21
- this[option] = writable(value);
22
- }
23
-
24
- // Private stores
25
- this._queue = writable(new Map()); // debounce queue (beforeUpdate)
26
- this._tasks = new Map(); // timeout IDs for tasks
27
- this._auxiliary = writable([]); // auxiliary components
28
- this._dayGrid = dayGrid(this);
29
- this._currentRange = currentRange(this);
30
- this._activeRangeExt = writable(identity);
31
- this._activeRange = activeRange(this);
32
- this._fetchedRange = writable({start: undefined, end: undefined});
33
- this._events = events(this);
34
- this._mainEl = writable(undefined);
35
- this._now = now();
36
- this._today = today(this);
37
- this._intlEventTime = intlRange(this.locale, this.eventTimeFormat);
38
- this._intlDayHeader = intl(this.locale, this.dayHeaderFormat);
39
- this._intlDayHeaderAL = intl(this.locale, this.dayHeaderAriaLabelFormat);
40
- this._intlTitle = intlRange(this.locale, this.titleFormat);
41
- this._viewTitle = viewTitle(this);
42
- this._viewDates = viewDates(this);
43
- this._view = view2(this);
44
- this._viewComponent = writable(undefined);
45
- this._filteredEvents = filteredEvents(this);
46
- // Interaction
47
- this._interaction = writable({});
48
- this._iEvents = writable([null, null]); // interaction events: [drag/resize, pointer]
49
- this._iClasses = writable(identity); // interaction event css classes
50
- this._iClass = writable(undefined); // interaction css class for entire calendar
51
-
52
- // Set & Get
53
- this._set = (key, value) => {
54
- if (validKey(key, this)) {
55
- if (parsers[key]) {
56
- value = parsers[key](value);
57
- }
58
- this[key].set(value);
59
- }
60
- };
61
- this._get = key => validKey(key, this) ? get(this[key]) : undefined;
62
-
63
- // Let plugins create their private stores
64
- for (let plugin of plugins) {
65
- plugin.createStores?.(this);
66
- }
67
-
68
- if (input.view) {
69
- // Set initial view based on input
70
- this.view.set(input.view);
71
- }
72
-
73
- // Set options for each view
74
- let views = new Set([...keys(options.views), ...keys(input.views ?? {})]);
75
- for (let view of views) {
76
- let defOpts = mergeOpts(options, options.views[view] ?? {});
77
- let opts = mergeOpts(defOpts, input, input.views?.[view] ?? {});
78
- let component = opts.component;
79
- // Make sure we deal with valid opts from now on
80
- filterOpts(opts, this);
81
- // Process options
82
- for (let key of keys(opts)) {
83
- let {set, _set = set, ...rest} = this[key];
84
-
85
- this[key] = {
86
- // Set value in all views
87
- set: specialOptions.includes(key)
88
- ? value => {
89
- if (isFunction(value)) {
90
- let result = value(defOpts[key]);
91
- opts[key] = result;
92
- set(set === _set ? result : value);
93
- } else {
94
- opts[key] = value;
95
- set(value);
96
- }
97
- }
98
- : value => {
99
- opts[key] = value;
100
- set(value);
101
- },
102
- _set,
103
- ...rest
104
- };
105
- }
106
- // When view changes...
107
- this.view.subscribe(newView => {
108
- if (newView === view) {
109
- // switch view component
110
- this._viewComponent.set(component);
111
- if (isFunction(opts.viewDidMount)) {
112
- tick().then(() => opts.viewDidMount({
113
- view: toViewWithLocalDates(get(this._view))
114
- }));
115
- }
116
- // update store values
117
- for (let key of keys(opts)) {
118
- this[key]._set(opts[key]);
119
- }
120
- }
121
- });
122
- }
123
- }
124
- }
125
-
126
- function parseOpts(opts, parsers) {
127
- let result = {...opts};
128
- for (let key of keys(parsers)) {
129
- if (key in result) {
130
- result[key] = parsers[key](result[key]);
131
- }
132
- }
133
- if (opts.views) {
134
- result.views = {};
135
- for (let view of keys(opts.views)) {
136
- result.views[view] = parseOpts(opts.views[view], parsers);
137
- }
138
- }
139
- return result;
140
- }
141
-
142
- function mergeOpts(...args) {
143
- let result = {};
144
- for (let opts of args) {
145
- let override = {};
146
- for (let key of specialOptions) {
147
- if (isFunction(opts[key])) {
148
- override[key] = opts[key](result[key]);
149
- }
150
- }
151
- result = {
152
- ...result,
153
- ...opts,
154
- ...override
155
- };
156
- }
157
- return result;
158
- }
159
-
160
- function filterOpts(opts, state) {
161
- keys(opts)
162
- .filter(key => !validKey(key, state) || key === 'view')
163
- .forEach(key => delete opts[key]);
164
- }
165
-
166
- function validKey(key, state) {
167
- return state.hasOwnProperty(key) && key[0] !== '_';
168
- }
@@ -1,234 +0,0 @@
1
- import {derived, get, readable, writable} from 'svelte/store';
2
- import {
3
- addDay, addDuration, assign, cloneDate, createDate, createEvents, createView, datesEqual, DAY_IN_SECONDS, debounce,
4
- isFunction, nextClosestDay, prevClosestDay, setMidnight, subtractDay, toEventWithLocalDates, toISOString,
5
- toLocalDate
6
- } from '#lib';
7
-
8
- export function dayGrid(state) {
9
- return derived(state.view, $view => $view?.startsWith('dayGrid'));
10
- }
11
-
12
- export function activeRange(state) {
13
- return derived(
14
- [state._currentRange, state._activeRangeExt],
15
- ([$_currentRange, $_activeRangeExt]) => {
16
- return $_activeRangeExt({start: cloneDate($_currentRange.start), end: cloneDate($_currentRange.end)});
17
- }
18
- );
19
- }
20
-
21
- export function currentRange(state) {
22
- return derived(
23
- [state.date, state.duration, state.firstDay],
24
- ([$date, $duration, $firstDay]) => {
25
- let start = cloneDate($date), end;
26
- if ($duration.months) {
27
- start.setUTCDate(1);
28
- } else if ($duration.inWeeks) {
29
- // First day of week
30
- prevClosestDay(start, $firstDay);
31
- }
32
- end = addDuration(cloneDate(start), $duration);
33
-
34
- return {start, end};
35
- }
36
- );
37
- }
38
-
39
- export function viewDates(state) {
40
- return derived([state._activeRange, state.hiddenDays], ([$_activeRange, $hiddenDays]) => {
41
- let dates = [];
42
- let date = setMidnight(cloneDate($_activeRange.start));
43
- let end = setMidnight(cloneDate($_activeRange.end));
44
- while (date < end) {
45
- if (!$hiddenDays.includes(date.getUTCDay())) {
46
- dates.push(cloneDate(date));
47
- }
48
- addDay(date);
49
- }
50
- if (!dates.length && $hiddenDays.length && $hiddenDays.length < 7) {
51
- // Try to move the date
52
- state.date.update(date => {
53
- while ($hiddenDays.includes(date.getUTCDay())) {
54
- addDay(date);
55
- }
56
- return date;
57
- });
58
- dates = get(state._viewDates);
59
- }
60
-
61
- return dates;
62
- });
63
- }
64
-
65
- export function viewTitle(state) {
66
- return derived(
67
- [state.date, state._activeRange, state._intlTitle, state._dayGrid],
68
- ([$date, $_activeRange, $_intlTitle, $_dayGrid]) => {
69
- return $_dayGrid
70
- ? $_intlTitle.formatRange($date, $date)
71
- : $_intlTitle.formatRange($_activeRange.start, subtractDay(cloneDate($_activeRange.end)));
72
- }
73
- );
74
- }
75
-
76
- export function view(state) {
77
- return derived([state.view, state._viewTitle, state._currentRange, state._activeRange], args => createView(...args));
78
- }
79
-
80
- export function events(state) {
81
- let _events = writable([]);
82
- let abortController;
83
- let fetching = 0;
84
- let debounceHandle = {};
85
- derived(
86
- [state.events, state.eventSources, state._activeRange, state._fetchedRange, state.lazyFetching, state.loading],
87
- (values, set) => debounce(() => {
88
- let [$events, $eventSources, $_activeRange, $_fetchedRange, $lazyFetching, $loading] = values;
89
- if (!$eventSources.length) {
90
- set($events);
91
- return;
92
- }
93
- // Do not fetch if new range is within the previous one
94
- if (!$_fetchedRange.start || $_fetchedRange.start > $_activeRange.start || $_fetchedRange.end < $_activeRange.end || !$lazyFetching) {
95
- if (abortController) {
96
- // Abort previous request
97
- abortController.abort();
98
- }
99
- // Create new abort controller
100
- abortController = new AbortController();
101
- // Call loading hook
102
- if (isFunction($loading) && !fetching) {
103
- $loading(true);
104
- }
105
- let stopLoading = () => {
106
- if (--fetching === 0 && isFunction($loading)) {
107
- $loading(false);
108
- }
109
- };
110
- let events = [];
111
- // Prepare handlers
112
- let failure = e => stopLoading();
113
- let success = data => {
114
- events = events.concat(createEvents(data));
115
- set(events);
116
- stopLoading();
117
- };
118
- // Prepare other stuff
119
- let startStr = toISOString($_activeRange.start)
120
- let endStr = toISOString($_activeRange.end);
121
- // Loop over event sources
122
- for (let source of $eventSources) {
123
- if (isFunction(source.events)) {
124
- // Events as a function
125
- let result = source.events({
126
- start: toLocalDate($_activeRange.start),
127
- end: toLocalDate($_activeRange.end),
128
- startStr,
129
- endStr
130
- }, success, failure);
131
- if (result !== undefined) {
132
- Promise.resolve(result).then(success, failure);
133
- }
134
- } else {
135
- // Events as a JSON feed
136
- // Prepare params
137
- let params = isFunction(source.extraParams) ? source.extraParams() : assign({}, source.extraParams);
138
- params.start = startStr;
139
- params.end = endStr;
140
- params = new URLSearchParams(params);
141
- // Prepare fetch
142
- let url = source.url, headers = {}, body;
143
- if (['GET', 'HEAD'].includes(source.method)) {
144
- url += (url.includes('?') ? '&' : '?') + params;
145
- } else {
146
- headers['content-type'] = 'application/x-www-form-urlencoded;charset=UTF-8';
147
- body = String(params); // Safari 10.1 doesn't convert to string automatically
148
- }
149
- // Do the fetch
150
- fetch(url, {method: source.method, headers, body, signal: abortController.signal, credentials: 'same-origin'})
151
- .then(response => response.json())
152
- .then(success)
153
- .catch(failure);
154
- }
155
- ++fetching;
156
- }
157
- // Save current range for future requests
158
- $_fetchedRange.start = $_activeRange.start;
159
- $_fetchedRange.end = $_activeRange.end;
160
- }
161
- }, debounceHandle, state._queue),
162
- []
163
- ).subscribe(_events.set);
164
-
165
- return _events;
166
- }
167
-
168
- export function filteredEvents(state){
169
- let view;
170
- state._view.subscribe($_view => view = $_view);
171
- let debounceHandle = {};
172
- return derived(
173
- [state._events, state.eventFilter, state.eventOrder, state.filterEventsWithResources, state.resources],
174
- (values, set) => debounce(() => {
175
- let [$_events, $eventFilter, $eventOrder, $filterEventsWithResources, $resources] = values;
176
-
177
- let result = [...$_events];
178
-
179
- // Filter events
180
- if (isFunction($eventFilter)) {
181
- let events = $_events.map(toEventWithLocalDates);
182
- result = result
183
- .filter((event, index) => $eventFilter({
184
- event: toEventWithLocalDates(event),
185
- index,
186
- events,
187
- view
188
- }));
189
- }
190
- if ($filterEventsWithResources) {
191
- result = result.filter(event => $resources.some(resource => event.resourceIds.includes(resource.id)));
192
- }
193
-
194
- // Sort events
195
- if (isFunction($eventOrder)) {
196
- result.sort((a, b) => $eventOrder(
197
- toEventWithLocalDates(a),
198
- toEventWithLocalDates(b)
199
- ));
200
- } else {
201
- // Sort by start date (all-day events always on top)
202
- result.sort((a, b) => a.start - b.start || b.allDay - a.allDay);
203
- }
204
-
205
- set(result);
206
-
207
- }, debounceHandle, state._queue),
208
- []
209
- );
210
- }
211
-
212
- export function now() {
213
- return readable(createDate(), set => {
214
- let interval = setInterval(() => {
215
- set(createDate());
216
- }, 1000);
217
-
218
- return () => clearInterval(interval);
219
- });
220
- }
221
-
222
- export function today(state) {
223
- let $today = setMidnight(createDate());
224
- let today = writable($today);
225
- state._now.subscribe($_now => {
226
- let newToday = setMidnight(cloneDate($_now));
227
- if (!datesEqual($today, newToday)) {
228
- $today = newToday;
229
- today.set(newToday);
230
- }
231
- });
232
-
233
- return today;
234
- }