@event-calendar/core 5.0.5 → 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.
- package/README.md +15 -4
- package/dist/index.css +2 -2
- package/dist/index.js +2201 -2128
- package/package.json +2 -2
- package/src/Buttons.svelte +36 -37
- package/src/Calendar.svelte +34 -37
- package/src/Toolbar.svelte +4 -4
- package/src/lib/components/BaseDay.svelte +13 -10
- package/src/lib/components/BaseEvent.svelte +17 -17
- package/src/lib/components/ColHead.svelte +6 -6
- package/src/lib/components/DayHeader.svelte +3 -3
- package/src/lib/components/InteractableEvent.svelte +7 -8
- package/src/lib/derived.js +80 -0
- package/src/lib/index.js +1 -2
- package/src/lib/slots.js +16 -16
- package/src/lib/utils.js +4 -9
- package/src/lib/view.js +0 -8
- package/src/plugins/day-grid/Day.svelte +25 -23
- package/src/plugins/day-grid/Event.svelte +15 -13
- package/src/plugins/day-grid/Popup.svelte +12 -12
- package/src/plugins/day-grid/View.svelte +24 -36
- package/src/plugins/day-grid/derived.js +102 -0
- package/src/plugins/day-grid/index.js +47 -36
- package/src/plugins/day-grid/state.svelte.js +19 -0
- package/src/plugins/interaction/Action.svelte +108 -76
- package/src/plugins/interaction/Auxiliary.svelte +9 -38
- package/src/plugins/interaction/Pointer.svelte +12 -17
- package/src/plugins/interaction/Resizer.svelte +9 -7
- package/src/plugins/interaction/effects.js +37 -0
- package/src/plugins/interaction/index.js +44 -38
- package/src/plugins/interaction/lib/utils.js +1 -1
- package/src/plugins/interaction/state.svelte.js +12 -0
- package/src/plugins/list/Day.svelte +8 -7
- package/src/plugins/list/Event.svelte +3 -3
- package/src/plugins/list/View.svelte +18 -13
- package/src/plugins/list/index.js +51 -43
- package/src/plugins/list/state.svelte.js +8 -0
- package/src/plugins/resource-time-grid/Label.svelte +8 -8
- package/src/plugins/resource-time-grid/View.svelte +38 -17
- package/src/plugins/resource-time-grid/derived.js +67 -0
- package/src/plugins/resource-time-grid/index.js +34 -28
- package/src/plugins/resource-time-grid/state.svelte.js +21 -0
- package/src/plugins/resource-timeline/Day.svelte +9 -4
- package/src/plugins/resource-timeline/Event.svelte +7 -6
- package/src/plugins/resource-timeline/Expander.svelte +7 -6
- package/src/plugins/resource-timeline/NowIndicator.svelte +10 -11
- package/src/plugins/resource-timeline/View.svelte +45 -63
- package/src/plugins/resource-timeline/derived.js +167 -0
- package/src/plugins/resource-timeline/index.js +17 -21
- package/src/plugins/resource-timeline/lib.js +4 -65
- package/src/plugins/resource-timeline/state.svelte.js +18 -0
- package/src/plugins/time-grid/Day.svelte +7 -2
- package/src/plugins/time-grid/Event.svelte +6 -6
- package/src/plugins/time-grid/NowIndicator.svelte +10 -9
- package/src/plugins/time-grid/View.svelte +46 -59
- package/src/plugins/time-grid/derived.js +162 -0
- package/src/plugins/time-grid/index.js +31 -25
- package/src/plugins/time-grid/lib.js +18 -74
- package/src/plugins/time-grid/options.js +21 -16
- package/src/plugins/time-grid/state.svelte.js +44 -0
- package/src/storage/derived.js +144 -0
- package/src/storage/effects.js +156 -0
- package/src/storage/options.svelte.js +275 -0
- package/src/storage/state.svelte.js +69 -0
- package/src/styles/events.css +1 -1
- package/src/Auxiliary.svelte +0 -47
- package/src/lib/debounce.js +0 -20
- package/src/lib/stores.js +0 -63
- package/src/plugins/day-grid/lib.js +0 -61
- package/src/plugins/day-grid/stores.js +0 -5
- package/src/plugins/resource-time-grid/lib.js +0 -31
- package/src/plugins/resource-time-grid/stores.js +0 -34
- package/src/plugins/resource-timeline/Header.svelte +0 -44
- package/src/plugins/resource-timeline/Label.svelte +0 -38
- package/src/plugins/resource-timeline/stores.js +0 -48
- package/src/plugins/time-grid/stores.js +0 -49
- package/src/storage/options.js +0 -136
- package/src/storage/state.js +0 -168
- package/src/storage/stores.js +0 -234
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
import {untrack} from 'svelte';
|
|
2
|
+
import {
|
|
3
|
+
createDate, createDateRange, createDuration, createEvents, createEventSources, createResources, entries,
|
|
4
|
+
isFunction, keys, setMidnight
|
|
5
|
+
} from '#lib';
|
|
6
|
+
import {SvelteMap} from "svelte/reactivity";
|
|
7
|
+
|
|
8
|
+
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
|
+
active: 'ec-active',
|
|
61
|
+
bgEvent: 'ec-bg-event',
|
|
62
|
+
bgEvents: 'ec-bg-events',
|
|
63
|
+
body: 'ec-body',
|
|
64
|
+
button: 'ec-button',
|
|
65
|
+
buttonGroup: 'ec-button-group',
|
|
66
|
+
calendar: 'ec',
|
|
67
|
+
colHead: 'ec-col-head',
|
|
68
|
+
day: 'ec-day',
|
|
69
|
+
dayHead: 'ec-day-head',
|
|
70
|
+
disabled: 'ec-disabled',
|
|
71
|
+
event: 'ec-event',
|
|
72
|
+
eventBody: 'ec-event-body',
|
|
73
|
+
eventTime: 'ec-event-time',
|
|
74
|
+
eventTitle: 'ec-event-title',
|
|
75
|
+
events: 'ec-events',
|
|
76
|
+
grid: 'ec-grid',
|
|
77
|
+
header: 'ec-header',
|
|
78
|
+
hidden: 'ec-hidden',
|
|
79
|
+
highlight: 'ec-highlight',
|
|
80
|
+
icon: 'ec-icon',
|
|
81
|
+
main: 'ec-main',
|
|
82
|
+
noBeb: 'ec-no-beb', // no block end border
|
|
83
|
+
noIeb: 'ec-no-ieb', // no inline end border
|
|
84
|
+
today: 'ec-today',
|
|
85
|
+
title: 'ec-title',
|
|
86
|
+
toolbar: 'ec-toolbar',
|
|
87
|
+
view: '',
|
|
88
|
+
weekdays: ['ec-sun', 'ec-mon', 'ec-tue', 'ec-wed', 'ec-thu', 'ec-fri', 'ec-sat'],
|
|
89
|
+
},
|
|
90
|
+
titleFormat: {
|
|
91
|
+
year: 'numeric',
|
|
92
|
+
month: 'short',
|
|
93
|
+
day: 'numeric'
|
|
94
|
+
},
|
|
95
|
+
validRange: undefined,
|
|
96
|
+
view: undefined,
|
|
97
|
+
viewDidMount: undefined,
|
|
98
|
+
views: {}
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
// Let plugins add their options
|
|
102
|
+
for (let plugin of plugins) {
|
|
103
|
+
plugin.createOptions?.(options);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
return options;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
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
|
+
// Let plugins add their parsers
|
|
122
|
+
for (let plugin of plugins) {
|
|
123
|
+
plugin.createParsers?.(parsers);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
return parsers;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// Options where default value is passed to the function
|
|
130
|
+
const specialOptions = ['buttonText', 'customButtons', 'theme'];
|
|
131
|
+
|
|
132
|
+
export function optionsState(mainState, plugins, userOptions) {
|
|
133
|
+
// Create default options and parsers
|
|
134
|
+
let defOptions = createOptions(plugins);
|
|
135
|
+
let parsers = createParsers(plugins);
|
|
136
|
+
|
|
137
|
+
// Parse options
|
|
138
|
+
defOptions = parseOptions(defOptions, parsers);
|
|
139
|
+
userOptions = parseOptions(userOptions, parsers);
|
|
140
|
+
|
|
141
|
+
// Extract view-specific options
|
|
142
|
+
let defViewOptions = extractOption(defOptions, 'views') ?? {};
|
|
143
|
+
let userViewOptions = extractOption(userOptions, 'views') ?? {};
|
|
144
|
+
|
|
145
|
+
// Create options state
|
|
146
|
+
let options = new SvelteMap();
|
|
147
|
+
setOptions(options, defOptions);
|
|
148
|
+
|
|
149
|
+
let setters = {};
|
|
150
|
+
let currentOpts = {};
|
|
151
|
+
|
|
152
|
+
function initEffects() {
|
|
153
|
+
// Set initial view based on input
|
|
154
|
+
if (userOptions.view) {
|
|
155
|
+
options.set('view', userOptions.view);
|
|
156
|
+
}
|
|
157
|
+
// Set options for each view
|
|
158
|
+
let views = new Set([...keys(defViewOptions), ...keys(userViewOptions)]);
|
|
159
|
+
for (let view of views) {
|
|
160
|
+
let defOpts = mergeOpts(defOptions, defViewOptions[view] ?? {});
|
|
161
|
+
let opts = mergeOpts(defOpts, userOptions, userViewOptions[view] ?? {});
|
|
162
|
+
let component = extractOption(opts, 'component');
|
|
163
|
+
// View has been set
|
|
164
|
+
delete opts.view;
|
|
165
|
+
// Set up option setters and delete unknown options
|
|
166
|
+
for (let key of keys(opts)) {
|
|
167
|
+
if (options.has(key)) {
|
|
168
|
+
if (!setters[key]) {
|
|
169
|
+
setters[key] = [];
|
|
170
|
+
}
|
|
171
|
+
setters[key].push(
|
|
172
|
+
specialOptions.includes(key)
|
|
173
|
+
? value => opts[key] = isFunction(value) ? value(defOpts[key]) : value
|
|
174
|
+
: value => opts[key] = value
|
|
175
|
+
);
|
|
176
|
+
} else {
|
|
177
|
+
delete opts[key];
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
// When view changes...
|
|
181
|
+
$effect.pre(() => {
|
|
182
|
+
let newView = options.get('view');
|
|
183
|
+
untrack(() => {
|
|
184
|
+
if (newView === view) {
|
|
185
|
+
// ...switch view component
|
|
186
|
+
mainState.setViewComponent(component);
|
|
187
|
+
// ...and update options
|
|
188
|
+
currentOpts = opts;
|
|
189
|
+
setOptions(options, opts);
|
|
190
|
+
}
|
|
191
|
+
});
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
return {
|
|
197
|
+
proxy: new Proxy(options, {
|
|
198
|
+
set(options, key, value) {
|
|
199
|
+
currentOpts[key] = value;
|
|
200
|
+
options.set(key, value);
|
|
201
|
+
return true;
|
|
202
|
+
},
|
|
203
|
+
get(options, key) {
|
|
204
|
+
return options.get(key);
|
|
205
|
+
}
|
|
206
|
+
}),
|
|
207
|
+
setOption(key, value, parsed) {
|
|
208
|
+
if (options.has(key)) {
|
|
209
|
+
if (!parsed && key in parsers) {
|
|
210
|
+
value = parsers[key](value);
|
|
211
|
+
}
|
|
212
|
+
// Set value for all views
|
|
213
|
+
setters[key]?.forEach(set => set(value));
|
|
214
|
+
options.set(key, currentOpts[key] ?? value);
|
|
215
|
+
}
|
|
216
|
+
},
|
|
217
|
+
initEffects
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
function parseOptions(opts, parsers) {
|
|
222
|
+
let result = {...opts};
|
|
223
|
+
for (let key of keys(parsers)) {
|
|
224
|
+
if (key in result) {
|
|
225
|
+
result[key] = parsers[key](result[key]);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
if (opts.views) {
|
|
229
|
+
result.views = {};
|
|
230
|
+
for (let view of keys(opts.views)) {
|
|
231
|
+
result.views[view] = parseOptions(opts.views[view], parsers);
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
return result;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
function extractOption(options, name) {
|
|
238
|
+
let extracted = options[name];
|
|
239
|
+
delete options[name];
|
|
240
|
+
return extracted;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
function mergeOpts(...args) {
|
|
244
|
+
let result = {};
|
|
245
|
+
for (let opts of args) {
|
|
246
|
+
let override = {};
|
|
247
|
+
for (let key of specialOptions) {
|
|
248
|
+
if (isFunction(opts[key])) {
|
|
249
|
+
override[key] = opts[key](result[key]);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
result = {
|
|
253
|
+
...result,
|
|
254
|
+
...opts,
|
|
255
|
+
...override
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
return result;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
function setOptions(map, options) {
|
|
262
|
+
for (let [key, value] of entries(options)) {
|
|
263
|
+
map.set(key, value);
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
export function diff(options, prevOptions) {
|
|
268
|
+
let diff = [];
|
|
269
|
+
for (let key of keys(options)) {
|
|
270
|
+
if (options[key] !== prevOptions[key]) {
|
|
271
|
+
diff.push([key, options[key]]);
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
return diff;
|
|
275
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import {SvelteMap} from 'svelte/reactivity';
|
|
2
|
+
import {createDate, identity, intl, intlRange, setMidnight} from '#lib';
|
|
3
|
+
import {optionsState} from './options.svelte.js';
|
|
4
|
+
import {loadEvents, runDatesSet, runEventAllUpdated, runViewDidMount, setNowAndToday} from './effects.js';
|
|
5
|
+
import {activeRange, currentRange, filteredEvents, view, viewDates, viewTitle} from './derived.js';
|
|
6
|
+
|
|
7
|
+
export default class State {
|
|
8
|
+
|
|
9
|
+
#setOption;
|
|
10
|
+
|
|
11
|
+
constructor(plugins, options) {
|
|
12
|
+
// Create options state
|
|
13
|
+
let {proxy, setOption, initEffects} = optionsState(this, plugins, options);
|
|
14
|
+
this.options = proxy;
|
|
15
|
+
this.#setOption = setOption;
|
|
16
|
+
|
|
17
|
+
// Create other states
|
|
18
|
+
this.auxComponents = $state([]);
|
|
19
|
+
this.currentRange = $derived.by(currentRange(this));
|
|
20
|
+
this.activeRange = $derived.by(activeRange(this));
|
|
21
|
+
this.fetchedRange = $state({start: undefined, end: undefined});
|
|
22
|
+
this.events = $state.raw([]);
|
|
23
|
+
this.filteredEvents = $derived.by(filteredEvents(this));
|
|
24
|
+
this.mainEl = $state();
|
|
25
|
+
this.now = $state(createDate());
|
|
26
|
+
this.today = $state(setMidnight(createDate()));
|
|
27
|
+
this.intlEventTime = $derived.by(intlRange(this, 'eventTimeFormat'));
|
|
28
|
+
this.intlDayHeader = $derived.by(intl(this, 'dayHeaderFormat'));
|
|
29
|
+
this.intlDayHeaderAL = $derived.by(intl(this, 'dayHeaderAriaLabelFormat'));
|
|
30
|
+
this.intlTitle = $derived.by(intlRange(this, 'titleFormat'));
|
|
31
|
+
this.viewDates = $derived.by(viewDates(this));
|
|
32
|
+
this.viewTitle = $derived.by(viewTitle(this));
|
|
33
|
+
this.view = $derived.by(view(this));
|
|
34
|
+
this.viewComponent = $state();
|
|
35
|
+
this.extensions = $state({});
|
|
36
|
+
this.features = $state([]);
|
|
37
|
+
// Interaction
|
|
38
|
+
this.interaction = $state({});
|
|
39
|
+
this.iEvents = new SvelteMap();
|
|
40
|
+
this.iClasses = $state(identity);
|
|
41
|
+
this.iClass = $state();
|
|
42
|
+
|
|
43
|
+
// Let plugins init their states
|
|
44
|
+
for (let plugin of plugins) {
|
|
45
|
+
plugin.initState?.(this);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
initEffects();
|
|
49
|
+
this.#initEffects();
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
#initEffects() {
|
|
53
|
+
$effect.pre(setNowAndToday(this));
|
|
54
|
+
$effect(loadEvents(this));
|
|
55
|
+
$effect(runDatesSet(this));
|
|
56
|
+
$effect(runEventAllUpdated(this));
|
|
57
|
+
$effect(runViewDidMount(this));
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
setViewComponent(component) {
|
|
61
|
+
this.extensions = {};
|
|
62
|
+
this.features = [];
|
|
63
|
+
this.viewComponent = component(this);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
setOption(name, value, parsed = true) {
|
|
67
|
+
this.#setOption(name, value, parsed);
|
|
68
|
+
}
|
|
69
|
+
}
|
package/src/styles/events.css
CHANGED
package/src/Auxiliary.svelte
DELETED
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
<script>
|
|
2
|
-
import {getContext, untrack} from 'svelte';
|
|
3
|
-
import {
|
|
4
|
-
toISOString, toLocalDate, toViewWithLocalDates, isFunction, task, flushDebounce
|
|
5
|
-
} from '#lib';
|
|
6
|
-
|
|
7
|
-
let {
|
|
8
|
-
datesSet, eventAllUpdated, _auxiliary, _activeRange, _filteredEvents, _tasks, _queue, _view
|
|
9
|
-
} = getContext('state');
|
|
10
|
-
|
|
11
|
-
// datesSet callback
|
|
12
|
-
$effect(() => {
|
|
13
|
-
$_activeRange;
|
|
14
|
-
untrack(() => {
|
|
15
|
-
if (isFunction($datesSet)) {
|
|
16
|
-
$datesSet({
|
|
17
|
-
start: toLocalDate($_activeRange.start),
|
|
18
|
-
end: toLocalDate($_activeRange.end),
|
|
19
|
-
startStr: toISOString($_activeRange.start),
|
|
20
|
-
endStr: toISOString($_activeRange.end),
|
|
21
|
-
view: toViewWithLocalDates($_view)
|
|
22
|
-
});
|
|
23
|
-
}
|
|
24
|
-
});
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
// eventAllUpdated callback
|
|
28
|
-
$effect(() => {
|
|
29
|
-
$_filteredEvents;
|
|
30
|
-
untrack(() => {
|
|
31
|
-
if (isFunction($eventAllUpdated)) {
|
|
32
|
-
task(() => $eventAllUpdated({view: toViewWithLocalDates($_view)}), 'eau', _tasks);
|
|
33
|
-
}
|
|
34
|
-
});
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
$effect(() => {
|
|
38
|
-
$_queue;
|
|
39
|
-
untrack(() => {
|
|
40
|
-
flushDebounce($_queue);
|
|
41
|
-
});
|
|
42
|
-
});
|
|
43
|
-
</script>
|
|
44
|
-
|
|
45
|
-
{#each $_auxiliary as Component}
|
|
46
|
-
<Component/>
|
|
47
|
-
{/each}
|
package/src/lib/debounce.js
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import {runAll} from './utils.js';
|
|
2
|
-
|
|
3
|
-
export function debounce(fn, handle, queueStore) {
|
|
4
|
-
queueStore.update(queue => queue.set(handle, fn));
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
export function flushDebounce(queue) {
|
|
8
|
-
runAll(queue);
|
|
9
|
-
queue.clear();
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export function task(fn, handle, tasks) {
|
|
13
|
-
handle ??= fn;
|
|
14
|
-
if (!tasks.has(handle)) {
|
|
15
|
-
tasks.set(handle, setTimeout(() => {
|
|
16
|
-
tasks.delete(handle);
|
|
17
|
-
fn();
|
|
18
|
-
}));
|
|
19
|
-
}
|
|
20
|
-
}
|
package/src/lib/stores.js
DELETED
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
import {derived} from 'svelte/store';
|
|
2
|
-
import {isFunction} from './utils.js';
|
|
3
|
-
import {toLocalDate} from './date.js';
|
|
4
|
-
|
|
5
|
-
export function intl(locale, format) {
|
|
6
|
-
return derived([locale, format], ([$locale, $format]) => {
|
|
7
|
-
let intl = isFunction($format)
|
|
8
|
-
? {format: $format}
|
|
9
|
-
: new Intl.DateTimeFormat($locale, $format);
|
|
10
|
-
return {
|
|
11
|
-
format: date => intl.format(toLocalDate(date))
|
|
12
|
-
};
|
|
13
|
-
});
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export function intlRange(locale, format) {
|
|
17
|
-
return derived([locale, format], ([$locale, $format]) => {
|
|
18
|
-
let formatRange;
|
|
19
|
-
if (isFunction($format)) {
|
|
20
|
-
formatRange = $format;
|
|
21
|
-
} else {
|
|
22
|
-
let intl = new Intl.DateTimeFormat($locale, $format);
|
|
23
|
-
formatRange = (start, end) => {
|
|
24
|
-
if (start <= end) {
|
|
25
|
-
return intl.formatRange(start, end);
|
|
26
|
-
} else {
|
|
27
|
-
// In iOS 16 and older, intl.formatRange() throws an exception if the start date is later than the end date.
|
|
28
|
-
// Therefore, we first swap the parameters, and then swap the resulting parts.
|
|
29
|
-
/** @see https://github.com/vkurko/calendar/issues/227 */
|
|
30
|
-
let parts = intl.formatRangeToParts(end, start);
|
|
31
|
-
let result = '';
|
|
32
|
-
let sources = ['startRange', 'endRange'];
|
|
33
|
-
let processed = [false, false];
|
|
34
|
-
for (let part of parts) {
|
|
35
|
-
let i = sources.indexOf(part.source);
|
|
36
|
-
if (i >= 0) {
|
|
37
|
-
if (!processed[i]) {
|
|
38
|
-
result += _getParts(sources[1 - i], parts);
|
|
39
|
-
processed[i] = true;
|
|
40
|
-
}
|
|
41
|
-
} else {
|
|
42
|
-
result += part.value;
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
return result;
|
|
46
|
-
}
|
|
47
|
-
};
|
|
48
|
-
}
|
|
49
|
-
return {
|
|
50
|
-
formatRange: (start, end) => formatRange(toLocalDate(start), toLocalDate(end))
|
|
51
|
-
};
|
|
52
|
-
});
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
function _getParts(source, parts) {
|
|
56
|
-
let result = '';
|
|
57
|
-
for (let part of parts) {
|
|
58
|
-
if (part.source == source) {
|
|
59
|
-
result += part.value;
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
return result;
|
|
63
|
-
}
|
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
import {addDay, bgEvent, cloneDate, createAllDayChunks, datesEqual, outsideRange, prepareAllDayChunks} from '#lib';
|
|
2
|
-
|
|
3
|
-
export function createGrid($_viewDates, $_colsCount, $validRange, $highlightedDates) {
|
|
4
|
-
let grid = [];
|
|
5
|
-
let days = [];
|
|
6
|
-
let gridColumn = 1;
|
|
7
|
-
let gridRow = 1;
|
|
8
|
-
for (let date of $_viewDates) {
|
|
9
|
-
days.push({
|
|
10
|
-
gridColumn,
|
|
11
|
-
gridRow,
|
|
12
|
-
resource: undefined,
|
|
13
|
-
dayStart: date,
|
|
14
|
-
dayEnd: addDay(cloneDate(date)),
|
|
15
|
-
disabled: outsideRange(date, $validRange),
|
|
16
|
-
highlight: $highlightedDates.some(d => datesEqual(d, date))
|
|
17
|
-
});
|
|
18
|
-
if (gridColumn === $_colsCount) {
|
|
19
|
-
grid.push(days);
|
|
20
|
-
days = [];
|
|
21
|
-
gridColumn = 0;
|
|
22
|
-
++ gridRow;
|
|
23
|
-
}
|
|
24
|
-
++ gridColumn;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
return grid;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
export function createEventChunks($_filteredEvents, grid) {
|
|
31
|
-
let chunks = [];
|
|
32
|
-
let bgChunks = [];
|
|
33
|
-
for (let event of $_filteredEvents) {
|
|
34
|
-
for (let days of grid) {
|
|
35
|
-
if (bgEvent(event.display)) {
|
|
36
|
-
if (event.allDay) {
|
|
37
|
-
bgChunks = bgChunks.concat(createAllDayChunks(event, days));
|
|
38
|
-
}
|
|
39
|
-
} else {
|
|
40
|
-
chunks = chunks.concat(createAllDayChunks(event, days));
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
prepareAllDayChunks(chunks);
|
|
45
|
-
|
|
46
|
-
return {chunks, bgChunks};
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
export function createIEventChunks($_iEvents, grid) {
|
|
50
|
-
let iChunks = [];
|
|
51
|
-
for (let event of $_iEvents) {
|
|
52
|
-
if (!event) {
|
|
53
|
-
continue;
|
|
54
|
-
}
|
|
55
|
-
for (let days of grid) {
|
|
56
|
-
iChunks = iChunks.concat(createAllDayChunks(event, days));
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
return iChunks;
|
|
61
|
-
}
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
addDay, addDuration, cloneDate, datesEqual, outsideRange
|
|
3
|
-
} from '#lib';
|
|
4
|
-
|
|
5
|
-
export function createGrid($_viewDates, $_viewResources, $_slotTimeLimits, $datesAboveResources, $validRange, $highlightedDates) {
|
|
6
|
-
let grid = [];
|
|
7
|
-
let gridColumn = 1;
|
|
8
|
-
let loop = $datesAboveResources ? [$_viewDates, $_viewResources] : [$_viewResources, $_viewDates];
|
|
9
|
-
for (let item0 of loop[0]) {
|
|
10
|
-
let days = [];
|
|
11
|
-
for (let item1 of loop[1]) {
|
|
12
|
-
let date = $datesAboveResources ? item0 : item1;
|
|
13
|
-
let resource = $datesAboveResources ? item1 : item0;
|
|
14
|
-
days.push({
|
|
15
|
-
gridColumn,
|
|
16
|
-
gridRow: 1,
|
|
17
|
-
resource,
|
|
18
|
-
start: addDuration(cloneDate(date), $_slotTimeLimits.min),
|
|
19
|
-
end: addDuration(cloneDate(date), $_slotTimeLimits.max),
|
|
20
|
-
dayStart: date,
|
|
21
|
-
dayEnd: addDay(cloneDate(date)),
|
|
22
|
-
disabled: outsideRange(date, $validRange),
|
|
23
|
-
highlight: $highlightedDates.some(d => datesEqual(d, date))
|
|
24
|
-
});
|
|
25
|
-
++ gridColumn;
|
|
26
|
-
}
|
|
27
|
-
grid.push(days);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
return grid;
|
|
31
|
-
}
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import {derived} from 'svelte/store';
|
|
2
|
-
import {createResources, eventIntersects, getPayload} from '#lib';
|
|
3
|
-
|
|
4
|
-
function viewResources(state) {
|
|
5
|
-
return derived(
|
|
6
|
-
[state.resources, state.filterResourcesWithEvents, state._filteredEvents, state._activeRange],
|
|
7
|
-
([$resources, $filterResourcesWithEvents, $_filteredEvents, $_activeRange]) => {
|
|
8
|
-
let result = $resources.filter(resource => !getPayload(resource).hidden);
|
|
9
|
-
|
|
10
|
-
if ($filterResourcesWithEvents) {
|
|
11
|
-
result = $resources.filter(
|
|
12
|
-
resource => $_filteredEvents.some(
|
|
13
|
-
event => eventIntersects(event, $_activeRange.start, $_activeRange.end, resource)
|
|
14
|
-
)
|
|
15
|
-
);
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
if (!result.length) {
|
|
19
|
-
result = createResources([{}]);
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
return result;
|
|
23
|
-
}
|
|
24
|
-
);
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* ResourceTimeGrid + ResourceTimeline
|
|
29
|
-
*/
|
|
30
|
-
export function createRRStores(state) {
|
|
31
|
-
if (!('_viewResources' in state)) {
|
|
32
|
-
state._viewResources = viewResources(state);
|
|
33
|
-
}
|
|
34
|
-
}
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
<script>
|
|
2
|
-
import {getContext} from 'svelte';
|
|
3
|
-
import {datesEqual, contentFrom, toISOString, toSeconds, resizeObserver} from '#lib';
|
|
4
|
-
|
|
5
|
-
let {_headerEl, _headerHeight, _intlDayHeader, _intlDayHeaderAL, _dayTimes, _today, _viewDates,
|
|
6
|
-
slotDuration, theme} = getContext('state');
|
|
7
|
-
</script>
|
|
8
|
-
|
|
9
|
-
<div class="{$theme.header}" bind:this={$_headerEl} {@attach resizeObserver(() => $_headerHeight = $_headerEl.clientHeight)}>
|
|
10
|
-
<div class="{$theme.days}" role="row">
|
|
11
|
-
{#each $_viewDates as date}
|
|
12
|
-
<div class="{$theme.day} {$theme.weekdays?.[date.getUTCDay()]}{datesEqual(date, $_today) ? ' ' + $theme.today : ''}">
|
|
13
|
-
{#if toSeconds($slotDuration)}
|
|
14
|
-
<div class="{$theme.dayHead}">
|
|
15
|
-
<time
|
|
16
|
-
datetime="{toISOString(date, 10)}"
|
|
17
|
-
aria-label="{$_intlDayHeaderAL.format(date)}"
|
|
18
|
-
{@attach contentFrom($_intlDayHeader.format(date))}
|
|
19
|
-
></time>
|
|
20
|
-
</div>
|
|
21
|
-
<div class="{$theme.times}">
|
|
22
|
-
{#each $_dayTimes[date.getTime()] as time}
|
|
23
|
-
<div class="{$theme.time}{time[2] ? '' : ' ' + $theme.minor}" role="columnheader">
|
|
24
|
-
<time
|
|
25
|
-
datetime="{time[0]}"
|
|
26
|
-
{@attach contentFrom(time[1])}
|
|
27
|
-
></time>
|
|
28
|
-
</div>
|
|
29
|
-
{/each}
|
|
30
|
-
</div>
|
|
31
|
-
{:else}
|
|
32
|
-
<div class="{$theme.time}" role="columnheader">
|
|
33
|
-
<time
|
|
34
|
-
datetime="{toISOString(date, 10)}"
|
|
35
|
-
aria-label="{$_intlDayHeaderAL.format(date)}"
|
|
36
|
-
{@attach contentFrom($_intlDayHeader.format(date))}
|
|
37
|
-
></time>
|
|
38
|
-
</div>
|
|
39
|
-
{/if}
|
|
40
|
-
</div>
|
|
41
|
-
{/each}
|
|
42
|
-
</div>
|
|
43
|
-
<div class="{$theme.hiddenScroll}"></div>
|
|
44
|
-
</div>
|