@event-calendar/core 1.5.1 → 2.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 +85 -63
- package/index.css +20 -20
- package/index.js +214 -255
- package/package.json +1 -1
- package/src/Buttons.svelte +24 -6
- package/src/Calendar.svelte +2 -2
- package/src/index.scss +18 -18
- package/src/lib/a11y.js +0 -24
- package/src/lib/actions.js +4 -10
- package/src/lib/date.js +9 -77
- package/src/lib/dom.js +7 -5
- package/src/lib/events.js +12 -8
- package/src/lib/options.js +28 -0
- package/src/lib/stores.js +6 -7
- package/src/lib/utils.js +4 -4
- package/src/lib.js +1 -0
- package/src/storage/options.js +4 -7
- package/src/storage/state.js +33 -20
- package/src/storage/stores.js +12 -12
package/package.json
CHANGED
package/src/Buttons.svelte
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<script>
|
|
2
2
|
import {getContext} from 'svelte';
|
|
3
|
-
import {createDate, cloneDate, subtractDay, addDuration, subtractDuration, setMidnight} from './lib.js';
|
|
3
|
+
import {createDate, cloneDate, subtractDay, addDuration, setContent, subtractDuration, setMidnight} from './lib.js';
|
|
4
4
|
|
|
5
5
|
export let buttons;
|
|
6
6
|
|
|
@@ -27,14 +27,32 @@
|
|
|
27
27
|
|
|
28
28
|
{#each buttons as button}
|
|
29
29
|
{#if button == 'title'}
|
|
30
|
-
|
|
30
|
+
<!-- svelte-ignore a11y-missing-content -->
|
|
31
|
+
<h2 class="{$theme.title}" use:setContent={$_viewTitle}></h2>
|
|
31
32
|
{:else if button == 'prev'}
|
|
32
|
-
<button
|
|
33
|
+
<button
|
|
34
|
+
class="{$theme.button} ec-{button}"
|
|
35
|
+
aria-label={$buttonText.prev}
|
|
36
|
+
title={$buttonText.prev}
|
|
37
|
+
on:click={prev}
|
|
38
|
+
><i class="{$theme.icon} ec-{button}"></i></button>
|
|
33
39
|
{:else if button == 'next'}
|
|
34
|
-
<button
|
|
40
|
+
<button
|
|
41
|
+
class="{$theme.button} ec-{button}"
|
|
42
|
+
aria-label={$buttonText.next}
|
|
43
|
+
title={$buttonText.next}
|
|
44
|
+
on:click={next}
|
|
45
|
+
><i class="{$theme.icon} ec-{button}"></i></button>
|
|
35
46
|
{:else if button == 'today'}
|
|
36
|
-
<button
|
|
47
|
+
<button
|
|
48
|
+
class="{$theme.button} ec-{button}"
|
|
49
|
+
on:click={() => $date = cloneDate(today)}
|
|
50
|
+
disabled={isToday}
|
|
51
|
+
>{$buttonText[button]}</button>
|
|
37
52
|
{:else if button != ''}
|
|
38
|
-
<button
|
|
53
|
+
<button
|
|
54
|
+
class="{$theme.button}{$view === button ? ' ' + $theme.active : ''} ec-{button}"
|
|
55
|
+
on:click={() => $view = button}
|
|
56
|
+
>{$buttonText[button]}</button>
|
|
39
57
|
{/if}
|
|
40
58
|
{/each}
|
package/src/Calendar.svelte
CHANGED
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
let state = new State(plugins, options);
|
|
27
27
|
setContext('state', state);
|
|
28
28
|
|
|
29
|
-
let {_viewComponent,
|
|
29
|
+
let {_viewComponent, _bodyEl, _interaction, _iClass, _events, _queue, _scrollable,
|
|
30
30
|
events, eventSources, height, theme} = state;
|
|
31
31
|
|
|
32
32
|
// Reactively update options that did change
|
|
@@ -130,7 +130,7 @@
|
|
|
130
130
|
</script>
|
|
131
131
|
|
|
132
132
|
<div
|
|
133
|
-
class="{$theme.calendar}{$
|
|
133
|
+
class="{$theme.calendar} {$theme.view}{$_scrollable ? ' ' + $theme.withScroll : ''}{$_iClass ? ' ' + $theme[$_iClass] : ''}"
|
|
134
134
|
style="height: {$height}"
|
|
135
135
|
>
|
|
136
136
|
<Toolbar/>
|
package/src/index.scss
CHANGED
|
@@ -184,7 +184,7 @@
|
|
|
184
184
|
border-top: none;
|
|
185
185
|
}
|
|
186
186
|
|
|
187
|
-
.ec-
|
|
187
|
+
.ec-day-grid & {
|
|
188
188
|
flex: 1 1 auto;
|
|
189
189
|
}
|
|
190
190
|
}
|
|
@@ -215,12 +215,12 @@
|
|
|
215
215
|
.ec-content {
|
|
216
216
|
display: flex;
|
|
217
217
|
|
|
218
|
-
.ec-
|
|
218
|
+
.ec-day-grid & {
|
|
219
219
|
flex-direction: column;
|
|
220
220
|
height: 100%;
|
|
221
221
|
}
|
|
222
222
|
|
|
223
|
-
.ec-
|
|
223
|
+
.ec-day-grid .ec-uniform & {
|
|
224
224
|
overflow: hidden; // remove scrolling due to hidden events
|
|
225
225
|
}
|
|
226
226
|
|
|
@@ -241,12 +241,12 @@
|
|
|
241
241
|
border-bottom: none;
|
|
242
242
|
}
|
|
243
243
|
|
|
244
|
-
.ec-
|
|
244
|
+
.ec-day-grid &,
|
|
245
245
|
.ec-resource & {
|
|
246
246
|
flex: 1 0 auto;
|
|
247
247
|
}
|
|
248
248
|
|
|
249
|
-
.ec-
|
|
249
|
+
.ec-day-grid .ec-uniform & {
|
|
250
250
|
flex: 1 1 0%; // % is required to work properly for both auto and fixed calendar height
|
|
251
251
|
min-height: 0;
|
|
252
252
|
}
|
|
@@ -263,16 +263,16 @@
|
|
|
263
263
|
background-color: #e5f7fe;
|
|
264
264
|
}
|
|
265
265
|
|
|
266
|
-
.ec-
|
|
266
|
+
.ec-day-grid .ec-body & {
|
|
267
267
|
min-height: 5em;
|
|
268
268
|
position: relative;
|
|
269
269
|
}
|
|
270
270
|
|
|
271
|
-
.ec-
|
|
271
|
+
.ec-day-grid .ec-uniform & {
|
|
272
272
|
min-height: 0;
|
|
273
273
|
}
|
|
274
274
|
|
|
275
|
-
.ec-
|
|
275
|
+
.ec-day-grid &:first-child {
|
|
276
276
|
border-left: none;
|
|
277
277
|
}
|
|
278
278
|
|
|
@@ -296,7 +296,7 @@
|
|
|
296
296
|
}
|
|
297
297
|
}
|
|
298
298
|
|
|
299
|
-
.ec-
|
|
299
|
+
.ec-day-grid {
|
|
300
300
|
.ec-day-head {
|
|
301
301
|
text-align: right;
|
|
302
302
|
padding: 4px 4px 3px;
|
|
@@ -328,7 +328,7 @@
|
|
|
328
328
|
.ec-events {
|
|
329
329
|
margin: 0 6px 0 0;
|
|
330
330
|
|
|
331
|
-
.ec-
|
|
331
|
+
.ec-time-grid &,
|
|
332
332
|
&.ec-preview {
|
|
333
333
|
position: relative;
|
|
334
334
|
}
|
|
@@ -346,12 +346,12 @@
|
|
|
346
346
|
line-height: 1.5;
|
|
347
347
|
z-index: 1; // put it above the pointer event (for multi-day events in month view)
|
|
348
348
|
|
|
349
|
-
.ec-
|
|
349
|
+
.ec-day-grid &,
|
|
350
350
|
.ec-all-day & {
|
|
351
351
|
position: relative;
|
|
352
352
|
}
|
|
353
353
|
|
|
354
|
-
.ec-
|
|
354
|
+
.ec-time-grid .ec-body & {
|
|
355
355
|
position: absolute;
|
|
356
356
|
}
|
|
357
357
|
|
|
@@ -390,7 +390,7 @@
|
|
|
390
390
|
flex-direction: column;
|
|
391
391
|
width: 100%;
|
|
392
392
|
|
|
393
|
-
.ec-
|
|
393
|
+
.ec-day-grid &,
|
|
394
394
|
.ec-all-day & {
|
|
395
395
|
flex-direction: row;
|
|
396
396
|
}
|
|
@@ -408,7 +408,7 @@
|
|
|
408
408
|
margin: 0 0 1px 0;
|
|
409
409
|
flex-shrink: 0;
|
|
410
410
|
|
|
411
|
-
.ec-
|
|
411
|
+
.ec-day-grid & {
|
|
412
412
|
margin: 0 3px 0 0;
|
|
413
413
|
max-width: 100%;
|
|
414
414
|
text-overflow: ellipsis;
|
|
@@ -418,14 +418,14 @@
|
|
|
418
418
|
.ec-event-title {
|
|
419
419
|
overflow: hidden;
|
|
420
420
|
|
|
421
|
-
.ec-
|
|
421
|
+
.ec-day-grid &,
|
|
422
422
|
.ec-all-day & {
|
|
423
423
|
min-height: 1.5em;
|
|
424
424
|
white-space: nowrap;
|
|
425
425
|
text-overflow: ellipsis;
|
|
426
426
|
}
|
|
427
427
|
|
|
428
|
-
.ec-
|
|
428
|
+
.ec-time-grid .ec-body & {
|
|
429
429
|
position: sticky;
|
|
430
430
|
top: 0;
|
|
431
431
|
}
|
|
@@ -557,7 +557,7 @@
|
|
|
557
557
|
position: absolute;
|
|
558
558
|
user-select: none;
|
|
559
559
|
|
|
560
|
-
.ec-
|
|
560
|
+
.ec-day-grid &,
|
|
561
561
|
.ec-all-day & {
|
|
562
562
|
top: 0;
|
|
563
563
|
right: 0;
|
|
@@ -567,7 +567,7 @@
|
|
|
567
567
|
cursor: ew-resize;
|
|
568
568
|
}
|
|
569
569
|
|
|
570
|
-
.ec-
|
|
570
|
+
.ec-time-grid .ec-body & {
|
|
571
571
|
left: 0;
|
|
572
572
|
right: 0;
|
|
573
573
|
bottom: 0;
|
package/src/lib/a11y.js
CHANGED
|
@@ -4,27 +4,3 @@ export function keyEnter(fn) {
|
|
|
4
4
|
return e.key === 'Enter' || e.key === ' ' ? fn.call(this, e) : undefined;
|
|
5
5
|
};
|
|
6
6
|
}
|
|
7
|
-
|
|
8
|
-
export function btnTextDay(text) {
|
|
9
|
-
return btnText(text, 'day');
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export function btnTextWeek(text) {
|
|
13
|
-
return btnText(text, 'week');
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export function btnTextMonth(text) {
|
|
17
|
-
return btnText(text, 'month');
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export function btnTextYear(text) {
|
|
21
|
-
return btnText(text, 'year');
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
function btnText(text, period) {
|
|
25
|
-
return {
|
|
26
|
-
...text,
|
|
27
|
-
next: 'Next ' + period,
|
|
28
|
-
prev: 'Previous ' + period
|
|
29
|
-
};
|
|
30
|
-
}
|
package/src/lib/actions.js
CHANGED
|
@@ -1,18 +1,12 @@
|
|
|
1
|
-
import {isObject} from './utils.js';
|
|
2
1
|
|
|
3
2
|
export function setContent(node, content) {
|
|
4
3
|
let actions = {
|
|
5
4
|
update(content) {
|
|
6
|
-
|
|
7
|
-
node.removeChild(node.lastChild);
|
|
8
|
-
}
|
|
9
|
-
if (!isObject(content)) {
|
|
5
|
+
if (typeof content == 'string') {
|
|
10
6
|
node.innerText = content;
|
|
11
|
-
} else if (content
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
}
|
|
15
|
-
} else if (content.html) {
|
|
7
|
+
} else if (content?.domNodes) {
|
|
8
|
+
node.replaceChildren(...content.domNodes);
|
|
9
|
+
} else if (content?.html) {
|
|
16
10
|
node.innerHTML = content.html;
|
|
17
11
|
}
|
|
18
12
|
}
|
package/src/lib/date.js
CHANGED
|
@@ -91,43 +91,6 @@ export function toISOString(date) {
|
|
|
91
91
|
return date.toISOString().substring(0, 19);
|
|
92
92
|
}
|
|
93
93
|
|
|
94
|
-
export function formatRange(start, end, intl) {
|
|
95
|
-
if (start.getFullYear() !== end.getFullYear()) {
|
|
96
|
-
return intl.format(start) + ' - ' + intl.format(end);
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
let diff = [];
|
|
100
|
-
if (start.getMonth() !== end.getMonth()) {
|
|
101
|
-
diff.push('month');
|
|
102
|
-
}
|
|
103
|
-
if (start.getDate() !== end.getDate()) {
|
|
104
|
-
diff.push('day');
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
if (!diff.length) {
|
|
108
|
-
return intl.format(start);
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
let opts1 = intl.resolvedOptions();
|
|
112
|
-
let opts2 = {};
|
|
113
|
-
for (let key of diff) {
|
|
114
|
-
opts2[key] = opts1[key];
|
|
115
|
-
}
|
|
116
|
-
let intl2 = new Intl.DateTimeFormat(opts1.locale, opts2);
|
|
117
|
-
|
|
118
|
-
let full1 = intl.format(start);
|
|
119
|
-
let full2 = intl.format(end);
|
|
120
|
-
let part1 = intl2.format(start);
|
|
121
|
-
let part2 = intl2.format(end);
|
|
122
|
-
|
|
123
|
-
let common = _commonChunks(full1, part1, full2, part2);
|
|
124
|
-
if (common) {
|
|
125
|
-
return common.head + part1 + ' - ' + part2 + common.tail;
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
return full1 + ' - ' + full2;
|
|
129
|
-
}
|
|
130
|
-
|
|
131
94
|
export function datesEqual(date1, ...dates2) {
|
|
132
95
|
return dates2.every(date2 => date1.getTime() === date2.getTime());
|
|
133
96
|
}
|
|
@@ -151,6 +114,15 @@ export function noTimePart(date) {
|
|
|
151
114
|
return typeof date === 'string' && date.length <= 10;
|
|
152
115
|
}
|
|
153
116
|
|
|
117
|
+
/**
|
|
118
|
+
* Copy time from one date to another
|
|
119
|
+
*/
|
|
120
|
+
export function copyTime(toDate, fromDate) {
|
|
121
|
+
toDate.setUTCHours(fromDate.getUTCHours(), fromDate.getUTCMinutes(), fromDate.getUTCSeconds(), 0);
|
|
122
|
+
|
|
123
|
+
return toDate;
|
|
124
|
+
}
|
|
125
|
+
|
|
154
126
|
/**
|
|
155
127
|
* Private functions
|
|
156
128
|
*/
|
|
@@ -177,43 +149,3 @@ function _fromISOString(str) {
|
|
|
177
149
|
Number(parts[5] || 0)
|
|
178
150
|
));
|
|
179
151
|
}
|
|
180
|
-
|
|
181
|
-
function _commonChunks(str1, substr1, str2, substr2) {
|
|
182
|
-
let i = 0;
|
|
183
|
-
while (i < str1.length) {
|
|
184
|
-
let res1;
|
|
185
|
-
[i, res1] = _cut(str1, substr1, i);
|
|
186
|
-
if (!res1) {
|
|
187
|
-
break;
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
let j = 0;
|
|
191
|
-
while (j < str2.length) {
|
|
192
|
-
let res2;
|
|
193
|
-
[j, res2] = _cut(str2, substr2, j);
|
|
194
|
-
if (!res2) {
|
|
195
|
-
break;
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
if (res1.head === res2.head && res1.tail === res2.tail) {
|
|
199
|
-
return res1;
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
return null
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
function _cut(str, substr, from) {
|
|
208
|
-
let start = str.indexOf(substr, from);
|
|
209
|
-
if (start >= 0) {
|
|
210
|
-
let end = start + substr.length;
|
|
211
|
-
|
|
212
|
-
return [end, {
|
|
213
|
-
head: str.substr(0, start),
|
|
214
|
-
tail: str.substr(end)
|
|
215
|
-
}];
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
return [-1, null];
|
|
219
|
-
}
|
package/src/lib/dom.js
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import {symbol} from './utils.js';
|
|
2
2
|
|
|
3
|
-
export function createElement(tag, className,
|
|
3
|
+
export function createElement(tag, className, content) {
|
|
4
4
|
let el = document.createElement(tag);
|
|
5
5
|
el.className = className;
|
|
6
|
-
if (
|
|
7
|
-
el.
|
|
8
|
-
} else if (
|
|
9
|
-
el.
|
|
6
|
+
if (typeof content == 'string') {
|
|
7
|
+
el.innerText = content;
|
|
8
|
+
} else if (content.domNodes) {
|
|
9
|
+
el.replaceChildren(...content.domNodes);
|
|
10
|
+
} else if (content.html) {
|
|
11
|
+
el.innerHTML = content.html;
|
|
10
12
|
}
|
|
11
13
|
return el;
|
|
12
14
|
}
|
package/src/lib/events.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {addDay, datesEqual, createDate, cloneDate, setMidnight, toLocalDate, noTimePart} from './date';
|
|
1
|
+
import {addDay, datesEqual, createDate, cloneDate, setMidnight, toLocalDate, noTimePart, copyTime} from './date';
|
|
2
2
|
import {createElement} from './dom';
|
|
3
3
|
import {assign} from './utils';
|
|
4
4
|
import {toViewWithLocalDates} from './view';
|
|
@@ -131,10 +131,14 @@ export function repositionEvent(chunk, longChunks, height) {
|
|
|
131
131
|
}
|
|
132
132
|
|
|
133
133
|
export function createEventContent(chunk, displayEventEnd, eventContent, theme, _intlEventTime, _view) {
|
|
134
|
-
let timeText = _intlEventTime.
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
134
|
+
let timeText = _intlEventTime.formatRange(
|
|
135
|
+
chunk.start,
|
|
136
|
+
displayEventEnd && chunk.event.display !== 'pointer'
|
|
137
|
+
? copyTime(cloneDate(chunk.start), chunk.end) // make Intl.formatRange output only the time part
|
|
138
|
+
: chunk.start
|
|
139
|
+
);
|
|
140
|
+
let content;
|
|
141
|
+
|
|
138
142
|
if (eventContent) {
|
|
139
143
|
content = is_function(eventContent)
|
|
140
144
|
? eventContent({
|
|
@@ -150,14 +154,14 @@ export function createEventContent(chunk, displayEventEnd, eventContent, theme,
|
|
|
150
154
|
break;
|
|
151
155
|
case 'pointer':
|
|
152
156
|
content = {
|
|
153
|
-
domNodes: [createElement('div', theme.eventTime,
|
|
157
|
+
domNodes: [createElement('div', theme.eventTime, timeText)]
|
|
154
158
|
};
|
|
155
159
|
break;
|
|
156
160
|
default:
|
|
157
161
|
content = {
|
|
158
162
|
domNodes: [
|
|
159
|
-
...chunk.event.allDay ? [] : [createElement('div', theme.eventTime,
|
|
160
|
-
createElement('div', theme.eventTitle, chunk.event.
|
|
163
|
+
...chunk.event.allDay ? [] : [createElement('div', theme.eventTime, timeText)],
|
|
164
|
+
createElement('div', theme.eventTitle, chunk.event.title)
|
|
161
165
|
]
|
|
162
166
|
};
|
|
163
167
|
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
|
|
2
|
+
export function btnTextDay(text) {
|
|
3
|
+
return btnText(text, 'day');
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
export function btnTextWeek(text) {
|
|
7
|
+
return btnText(text, 'week');
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export function btnTextMonth(text) {
|
|
11
|
+
return btnText(text, 'month');
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function btnTextYear(text) {
|
|
15
|
+
return btnText(text, 'year');
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function btnText(text, period) {
|
|
19
|
+
return {
|
|
20
|
+
...text,
|
|
21
|
+
next: 'Next ' + period,
|
|
22
|
+
prev: 'Previous ' + period
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function themeView(view) {
|
|
27
|
+
return theme => ({...theme, view});
|
|
28
|
+
}
|
package/src/lib/stores.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import {derived, writable, get} from 'svelte/store';
|
|
2
2
|
import {is_function} from 'svelte/internal';
|
|
3
|
-
import {toLocalDate
|
|
3
|
+
import {toLocalDate} from './date';
|
|
4
4
|
|
|
5
5
|
export function writable2(value, parser, start) {
|
|
6
6
|
return {
|
|
7
|
-
...writable(
|
|
7
|
+
...writable(value, start),
|
|
8
8
|
parse: parser
|
|
9
9
|
};
|
|
10
10
|
}
|
|
@@ -43,12 +43,11 @@ export function intl(locale, format) {
|
|
|
43
43
|
|
|
44
44
|
export function intlRange(locale, format) {
|
|
45
45
|
return derived([locale, format], ([$locale, $format]) => {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
let intl = new Intl.DateTimeFormat($locale, $format);
|
|
46
|
+
let intl = is_function($format)
|
|
47
|
+
? {formatRange: $format}
|
|
48
|
+
: new Intl.DateTimeFormat($locale, $format);
|
|
50
49
|
return {
|
|
51
|
-
|
|
50
|
+
formatRange: (start, end) => intl.formatRange(toLocalDate(start), toLocalDate(end))
|
|
52
51
|
};
|
|
53
52
|
});
|
|
54
53
|
}
|
package/src/lib/utils.js
CHANGED
|
@@ -2,6 +2,10 @@ export function assign(...args) {
|
|
|
2
2
|
return Object.assign(...args);
|
|
3
3
|
}
|
|
4
4
|
|
|
5
|
+
export function keys(object) {
|
|
6
|
+
return Object.keys(object);
|
|
7
|
+
}
|
|
8
|
+
|
|
5
9
|
export function floor(value) {
|
|
6
10
|
return Math.floor(value);
|
|
7
11
|
}
|
|
@@ -14,10 +18,6 @@ export function max(...args) {
|
|
|
14
18
|
return Math.max(...args);
|
|
15
19
|
}
|
|
16
20
|
|
|
17
|
-
export function isObject(test) {
|
|
18
|
-
return typeof test === 'object' && test !== null;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
21
|
export function symbol() {
|
|
22
22
|
return Symbol('ec');
|
|
23
23
|
}
|
package/src/lib.js
CHANGED
package/src/storage/options.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import {assign, createDate, createDuration, setMidnight, createEvents, createEventSources} from '../lib.js';
|
|
2
|
-
import {is_function} from 'svelte/internal';
|
|
3
2
|
|
|
4
3
|
export function createOptions(plugins) {
|
|
5
4
|
let options = {
|
|
@@ -92,7 +91,7 @@ export function createOptions(plugins) {
|
|
|
92
91
|
time: 'ec-time',
|
|
93
92
|
title: 'ec-title',
|
|
94
93
|
toolbar: 'ec-toolbar',
|
|
95
|
-
|
|
94
|
+
view: '',
|
|
96
95
|
withScroll: 'ec-with-scroll'
|
|
97
96
|
},
|
|
98
97
|
titleFormat: {
|
|
@@ -112,9 +111,8 @@ export function createOptions(plugins) {
|
|
|
112
111
|
return options;
|
|
113
112
|
}
|
|
114
113
|
|
|
115
|
-
export function createParsers(
|
|
114
|
+
export function createParsers(plugins) {
|
|
116
115
|
let parsers = {
|
|
117
|
-
buttonText: input => is_function(input) ? input(options.buttonText) : input,
|
|
118
116
|
date: date => setMidnight(createDate(date)),
|
|
119
117
|
duration: createDuration,
|
|
120
118
|
events: createEvents,
|
|
@@ -124,12 +122,11 @@ export function createParsers(options, plugins) {
|
|
|
124
122
|
scrollTime: createDuration,
|
|
125
123
|
slotDuration: createDuration,
|
|
126
124
|
slotMaxTime: createDuration,
|
|
127
|
-
slotMinTime: createDuration
|
|
128
|
-
theme: input => is_function(input) ? input(options.theme) : input
|
|
125
|
+
slotMinTime: createDuration
|
|
129
126
|
};
|
|
130
127
|
|
|
131
128
|
for (let plugin of plugins) {
|
|
132
|
-
plugin.createParsers?.(parsers
|
|
129
|
+
plugin.createParsers?.(parsers);
|
|
133
130
|
}
|
|
134
131
|
|
|
135
132
|
return parsers;
|
package/src/storage/state.js
CHANGED
|
@@ -4,15 +4,15 @@ import {createOptions, createParsers} from './options';
|
|
|
4
4
|
import {
|
|
5
5
|
activeRange,
|
|
6
6
|
currentRange,
|
|
7
|
+
dayGrid,
|
|
7
8
|
events,
|
|
8
|
-
monthMode,
|
|
9
9
|
now,
|
|
10
10
|
today,
|
|
11
11
|
viewDates,
|
|
12
12
|
viewTitle,
|
|
13
13
|
view as view2 // hack to avoid a runtime error in SvelteKit dev mode (ReferenceError: view is not defined)
|
|
14
14
|
} from './stores';
|
|
15
|
-
import {
|
|
15
|
+
import {keys, writable2, intl, intlRange} from '../lib.js';
|
|
16
16
|
|
|
17
17
|
export default class {
|
|
18
18
|
constructor(plugins, input) {
|
|
@@ -20,7 +20,11 @@ export default class {
|
|
|
20
20
|
|
|
21
21
|
// Create options
|
|
22
22
|
let options = createOptions(plugins);
|
|
23
|
-
let parsers = createParsers(
|
|
23
|
+
let parsers = createParsers(plugins);
|
|
24
|
+
|
|
25
|
+
// Parse options
|
|
26
|
+
options = parseOpts(options, parsers);
|
|
27
|
+
input = parseOpts(input, parsers);
|
|
24
28
|
|
|
25
29
|
// Create stores for options
|
|
26
30
|
for (let [option, value] of Object.entries(options)) {
|
|
@@ -30,23 +34,22 @@ export default class {
|
|
|
30
34
|
// Private stores
|
|
31
35
|
this._queue = writable(new Map()); // debounce queue
|
|
32
36
|
this._auxiliary = writable([]); // auxiliary components
|
|
33
|
-
this.
|
|
37
|
+
this._dayGrid = dayGrid(this);
|
|
34
38
|
this._currentRange = currentRange(this);
|
|
35
39
|
this._activeRange = activeRange(this);
|
|
36
40
|
this._fetchedRange = writable({start: undefined, end: undefined});
|
|
37
41
|
this._events = events(this);
|
|
38
42
|
this._now = now();
|
|
39
43
|
this._today = today(this);
|
|
40
|
-
this._intlEventTime =
|
|
44
|
+
this._intlEventTime = intlRange(this.locale, this.eventTimeFormat);
|
|
41
45
|
this._intlSlotLabel = intl(this.locale, this.slotLabelFormat);
|
|
42
46
|
this._intlDayHeader = intl(this.locale, this.dayHeaderFormat);
|
|
43
|
-
this.
|
|
47
|
+
this._intlTitle = intlRange(this.locale, this.titleFormat);
|
|
44
48
|
this._bodyEl = writable(undefined);
|
|
45
49
|
this._scrollable = writable(false);
|
|
46
50
|
this._viewTitle = viewTitle(this);
|
|
47
51
|
this._viewDates = viewDates(this);
|
|
48
52
|
this._view = view2(this);
|
|
49
|
-
this._viewClass = writable(undefined);
|
|
50
53
|
this._viewComponent = writable(undefined);
|
|
51
54
|
// Resources
|
|
52
55
|
this._resBgColor = writable(noop);
|
|
@@ -68,13 +71,9 @@ export default class {
|
|
|
68
71
|
}
|
|
69
72
|
|
|
70
73
|
// Set options for each view
|
|
71
|
-
let
|
|
72
|
-
parseOpts(commonOpts, this);
|
|
73
|
-
let views = new Set([...Object.keys(options.views), ...Object.keys(input.views || {})]);
|
|
74
|
+
let views = new Set([...keys(options.views), ...keys(input.views ?? {})]);
|
|
74
75
|
for (let view of views) {
|
|
75
|
-
let
|
|
76
|
-
parseOpts(viewOpts, this);
|
|
77
|
-
let opts = assign({}, commonOpts, viewOpts);
|
|
76
|
+
let opts = mergeOpts(options, options.views[view] ?? {}, input, input.views?.[view] ?? {});
|
|
78
77
|
// Change view component when view changes
|
|
79
78
|
this.view.subscribe(newView => {
|
|
80
79
|
if (newView === view) {
|
|
@@ -85,7 +84,7 @@ export default class {
|
|
|
85
84
|
}
|
|
86
85
|
});
|
|
87
86
|
// Process options
|
|
88
|
-
for (let key of
|
|
87
|
+
for (let key of keys(opts)) {
|
|
89
88
|
if (this.hasOwnProperty(key) && key[0] !== '_') {
|
|
90
89
|
let {set, _set, ...rest} = this[key];
|
|
91
90
|
|
|
@@ -113,12 +112,26 @@ export default class {
|
|
|
113
112
|
}
|
|
114
113
|
}
|
|
115
114
|
|
|
116
|
-
function parseOpts(opts,
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
115
|
+
function parseOpts(opts, parsers) {
|
|
116
|
+
let result = {};
|
|
117
|
+
for (let key of keys(opts)) {
|
|
118
|
+
result[key] = parsers[key] ? parsers[key](opts[key]) : opts[key];
|
|
119
|
+
}
|
|
120
|
+
if (opts.views) {
|
|
121
|
+
for (let view of keys(opts.views)) {
|
|
122
|
+
result.views[view] = parseOpts(opts.views[view], parsers);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
return result;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function mergeOpts(...args) {
|
|
129
|
+
let mergable = ['buttonText', 'theme'];
|
|
130
|
+
let result = {};
|
|
131
|
+
for (let opts of args) {
|
|
132
|
+
for (let key of keys(opts)) {
|
|
133
|
+
result[key] = mergable.includes(key) && is_function(opts[key]) ? opts[key](result[key]) : opts[key];
|
|
122
134
|
}
|
|
123
135
|
}
|
|
136
|
+
return result;
|
|
124
137
|
}
|