@event-calendar/core 1.5.1 → 2.0.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 CHANGED
@@ -4,7 +4,7 @@ See [demo](https://vkurko.github.io/calendar/) and [changelog](CHANGELOG.md).
4
4
 
5
5
  Full-sized drag & drop JavaScript event calendar with resource view:
6
6
 
7
- * Lightweight (28kb [br](https://en.wikipedia.org/wiki/Brotli) compressed)
7
+ * Lightweight (31kb [br](https://en.wikipedia.org/wiki/Brotli) compressed)
8
8
  * Zero-dependency (pre-built bundle)
9
9
  * Used on over 70,000 websites with [Bookly](https://wordpress.org/plugins/bookly-responsive-appointment-booking-tool/)
10
10
 
@@ -194,8 +194,8 @@ import '@event-calendar/core/index.css';
194
194
  ### Pre-built browser ready bundle
195
195
  Include the following lines of code in the `<head>` section of your page:
196
196
  ```html
197
- <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@event-calendar/build@1.5.1/event-calendar.min.css">
198
- <script src="https://cdn.jsdelivr.net/npm/@event-calendar/build@1.5.1/event-calendar.min.js"></script>
197
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@event-calendar/build@2.0.0/event-calendar.min.css">
198
+ <script src="https://cdn.jsdelivr.net/npm/@event-calendar/build@2.0.0/event-calendar.min.js"></script>
199
199
  ```
200
200
 
201
201
  <details>
@@ -248,16 +248,16 @@ In Svelte, you can simply update the original `options` object.
248
248
  ## Options
249
249
 
250
250
  ### allDayContent
251
- - Type `string`, `object`or `function`
251
+ - Type `Content` or `function`
252
252
  - Default `'all-day'`
253
253
 
254
254
  Defines the content that is displayed as a title of the `all-day` slot.
255
255
 
256
- This value can be either a string containing text `'...'`, an object containing the HTML string `{html: '<p>...</p>'}`, an object containing an array of DOM nodes `{domNodes: [node1, node2, ...]}` or a function that returns any of the above formats:
256
+ This value can be either a [Content](#content) or a function that returns content:
257
257
 
258
258
  ```js
259
259
  function (arg) {
260
- // return string or object
260
+ // return Content
261
261
  }
262
262
  ```
263
263
  `arg` is an object with the following properties:
@@ -461,11 +461,11 @@ The current [View](#view-object) object
461
461
 
462
462
  Defines the text that is displayed on the calendar’s column headings.
463
463
 
464
- This value can be either an object with options for the native JavaScript [Intl.DateTimeFormat](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat/DateTimeFormat) object, or a callback function that returns formatted string:
464
+ This value can be either an object with options for the native JavaScript [Intl.DateTimeFormat](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat/DateTimeFormat) object, or a callback function that returns a [Content](#content) with the formatted string:
465
465
 
466
466
  ```js
467
467
  function (date) {
468
- // return formatted date string
468
+ // return Content with the formatted date string
469
469
  }
470
470
  ```
471
471
  <table>
@@ -494,8 +494,13 @@ Currently, only the value `true` is supported, which limits the number of events
494
494
 
495
495
  Defines the date format of title of the popover created by the [dayMaxEvents](#daymaxevents) option.
496
496
 
497
- This value can be either an object with options for the native JavaScript [Intl.DateTimeFormat](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat/DateTimeFormat) object, or a callback function that returns formatted string:
497
+ This value can be either an object with options for the native JavaScript [Intl.DateTimeFormat](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat/DateTimeFormat) object, or a callback function that returns a [Content](#content) with the formatted string:
498
498
 
499
+ ```js
500
+ function (date) {
501
+ // return Content with the formatted date string
502
+ }
503
+ ```
499
504
  ### displayEventEnd
500
505
  - Type `boolean`
501
506
  - Default `true`
@@ -645,16 +650,16 @@ The current [View](#view-object) object
645
650
  This is currently an alias for the `eventBackgroundColor`.
646
651
 
647
652
  ### eventContent
648
- - Type `string`, `object` or `function`
653
+ - Type `Content` or `function`
649
654
  - Default `undefined`
650
655
 
651
656
  Defines the content that is rendered inside an event’s element.
652
657
 
653
- This value can be either a string containing text `'...'`, an object containing the HTML string `{html: '<p>...</p>'}`, an object containing an array of DOM nodes `{domNodes: [node1, node2, ...]}` or a function that returns any of the above formats:
658
+ This value can be either a [Content](#content) or a function that returns content:
654
659
 
655
660
  ```js
656
661
  function (info) {
657
- // return string or object
662
+ // return Content
658
663
  }
659
664
  ```
660
665
  `info` is an object with the following properties:
@@ -1298,20 +1303,27 @@ Determines whether the events on the calendar can be dragged.
1298
1303
 
1299
1304
  Defines the time-text that is displayed on each event.
1300
1305
 
1301
- This value can be either an object with options for the native JavaScript [Intl.DateTimeFormat](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat/DateTimeFormat) object, or a callback function that returns formatted string:
1306
+ This value can be either an object with options for the native JavaScript [Intl.DateTimeFormat](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat/DateTimeFormat) object, or a callback function that returns a [Content](#content) with formatted string:
1302
1307
 
1303
1308
  ```js
1304
- function (time) {
1305
- // return formatted time string
1309
+ function (start, end) {
1310
+ // return Content with the formatted time string
1306
1311
  }
1307
1312
  ```
1308
1313
  <table>
1309
1314
  <tr>
1310
1315
  <td>
1311
1316
 
1312
- `time`
1317
+ `start`
1313
1318
  </td>
1314
- <td>JavaScript Date object that needs to be formatted</td>
1319
+ <td>JavaScript Date object containing the beginning of the time span to be formatted</td>
1320
+ </tr>
1321
+ <tr>
1322
+ <td>
1323
+
1324
+ `end`
1325
+ </td>
1326
+ <td>JavaScript Date object containing the end of the time span to be formatted</td>
1315
1327
  </tr>
1316
1328
  </table>
1317
1329
 
@@ -1462,11 +1474,11 @@ When set to `false`, the calendar will fetch events any time the view is switche
1462
1474
 
1463
1475
  Defines the text on the left side of the day headings in list view.
1464
1476
 
1465
- This value can be either an object with options for the native JavaScript [Intl.DateTimeFormat](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat/DateTimeFormat) object, or a callback function that returns formatted string:
1477
+ This value can be either an object with options for the native JavaScript [Intl.DateTimeFormat](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat/DateTimeFormat) object, or a callback function that returns a [Content](#content) with the formatted string:
1466
1478
 
1467
1479
  ```js
1468
1480
  function (date) {
1469
- // return formatted date string
1481
+ // return Content with the formatted date string
1470
1482
  }
1471
1483
  ```
1472
1484
  <table>
@@ -1485,11 +1497,11 @@ function (date) {
1485
1497
 
1486
1498
  Defines the text on the right side of the day headings in list view.
1487
1499
 
1488
- This value can be either an object with options for the native JavaScript [Intl.DateTimeFormat](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat/DateTimeFormat) object, or a callback function that returns formatted string:
1500
+ This value can be either an object with options for the native JavaScript [Intl.DateTimeFormat](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat/DateTimeFormat) object, or a callback function that returns a [Content](#content) with the formatted string:
1489
1501
 
1490
1502
  ```js
1491
1503
  function (date) {
1492
- // return formatted date string
1504
+ // return Content with the formatted date string
1493
1505
  }
1494
1506
  ```
1495
1507
  <table>
@@ -1539,16 +1551,16 @@ For touch devices, the amount of time (in milliseconds) the user must hold down
1539
1551
  For a more granular configuration, see [eventLongPressDelay](#eventlongpressdelay) and [selectLongPressDelay](#selectlongpressdelay).
1540
1552
 
1541
1553
  ### moreLinkContent
1542
- - Type `string`, `object`or `function`
1554
+ - Type `Content` or `function`
1543
1555
  - Default `undefined`
1544
1556
 
1545
1557
  Defines the text that is displayed instead of the default `+2 more` created by the [dayMaxEvents](#daymaxevents) option.
1546
1558
 
1547
- This value can be either a string containing text `'...'`, an object containing the HTML string `{html: '<p>...</p>'}`, an object containing an array of DOM nodes `{domNodes: [node1, node2, ...]}` or a function that returns any of the above formats:
1559
+ This value can be either a [Content](#content) or a function that returns content:
1548
1560
 
1549
1561
  ```js
1550
1562
  function (arg) {
1551
- // return string or object
1563
+ // return Content
1552
1564
  }
1553
1565
  ```
1554
1566
  `arg` is an object with the following properties:
@@ -1603,16 +1615,16 @@ The current [View](#view-object) object
1603
1615
  </table>
1604
1616
 
1605
1617
  ### noEventsContent
1606
- - Type `string`, `object`or `function`
1618
+ - Type `Content` or `function`
1607
1619
  - Default `'No events'`
1608
1620
 
1609
1621
  Defines the text that is displayed in list view when there are no events to display.
1610
1622
 
1611
- This value can be either a string containing text `'...'`, an object containing the HTML string `{html: '<p>...</p>'}`, an object containing an array of DOM nodes `{domNodes: [node1, node2, ...]}` or a function that returns any of the above formats:
1623
+ This value can be either a [Content](#content) or a function that returns content:
1612
1624
 
1613
1625
  ```js
1614
1626
  function () {
1615
- // return string or object
1627
+ // return Content
1616
1628
  }
1617
1629
  ```
1618
1630
 
@@ -1641,11 +1653,11 @@ Array of plain objects that will be parsed into [Resource](#resource-object) obj
1641
1653
 
1642
1654
  Defines the content that is rendered inside an element with a resource title.
1643
1655
 
1644
- This value can be either a string containing text `'...'`, an object containing the HTML string `{html: '<p>...</p>'}`, an object containing an array of DOM nodes `{domNodes: [node1, node2, ...]}` or a function that returns any of the above formats:
1656
+ This value can be either a [Content](#content) or a function that returns content:
1645
1657
 
1646
1658
  ```js
1647
1659
  function (info) {
1648
- // return string or object
1660
+ // return Content
1649
1661
  }
1650
1662
  ```
1651
1663
  `info` is an object with the following properties:
@@ -1858,11 +1870,11 @@ Defines the time slot height in pixels. When changing the setting, you must addi
1858
1870
 
1859
1871
  Defines the text that will be displayed within a time slot.
1860
1872
 
1861
- This value can be either an object with options for the native JavaScript [Intl.DateTimeFormat](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat/DateTimeFormat) object, or a callback function that returns formatted string:
1873
+ This value can be either an object with options for the native JavaScript [Intl.DateTimeFormat](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat/DateTimeFormat) object, or a callback function that returns a [Content](#content) with the formatted string:
1862
1874
 
1863
1875
  ```js
1864
1876
  function (time) {
1865
- // return formatted time string
1877
+ // return Content with the formatted time string
1866
1878
  }
1867
1879
  ```
1868
1880
  <table>
@@ -1923,23 +1935,40 @@ function (theme) {
1923
1935
 
1924
1936
  Defines the text that is displayed in the header toolbar’s title.
1925
1937
 
1926
- This value can be either an object with options for the native JavaScript [Intl.DateTimeFormat](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat/DateTimeFormat) object, or a callback function that returns formatted string:
1938
+ This value can be either an object with options for the native JavaScript [Intl.DateTimeFormat](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat/DateTimeFormat) object, or a callback function that returns a [Content](#content) with the formatted string:
1927
1939
 
1928
1940
  ```js
1929
- function (date) {
1930
- // return formatted date string
1941
+ function (start, end) {
1942
+ // return Content with the formatted date string
1931
1943
  }
1932
1944
  ```
1933
1945
  <table>
1934
1946
  <tr>
1935
1947
  <td>
1936
1948
 
1937
- `date`
1949
+ `start`
1938
1950
  </td>
1939
- <td>JavaScript Date object that needs to be formatted</td>
1951
+ <td>JavaScript Date object containing the beginning of the time span to be formatted</td>
1952
+ </tr>
1953
+ <tr>
1954
+ <td>
1955
+
1956
+ `end`
1957
+ </td>
1958
+ <td>JavaScript Date object containing the end of the time span to be formatted</td>
1940
1959
  </tr>
1941
1960
  </table>
1942
1961
 
1962
+ The callback function can return HTML markup. If you want to use HTML entities in the title, you must use the callback function:
1963
+
1964
+ ```js
1965
+ function (date) {
1966
+ let month = date.toLocaleDateString('en-US', { month: 'long' })
1967
+ let year = date.toLocaleDateString('en-US', { year: 'numeric' })
1968
+ return `<span class="month">${month}</span> <span class="year">${year}</span>`
1969
+ }
1970
+ ```
1971
+
1943
1972
  ### unselect
1944
1973
  - Type `function`
1945
1974
  - Default `undefined`
@@ -2189,6 +2218,13 @@ Returns the [View](#view-object) object for the current view.
2189
2218
 
2190
2219
  Clears the current selection. See [selectable](#selectable).
2191
2220
 
2221
+ ## Content
2222
+ The content can be presented in the following forms:
2223
+
2224
+ * a string containing text `'some text'`
2225
+ * an object containing the HTML string `{html: '<p>some HTML</p>'}`
2226
+ * an object containing an array of DOM nodes `{domNodes: [node1, node2, ...]}`
2227
+
2192
2228
  ## Event object
2193
2229
  This is a JavaScript object that the Event Calendar uses to store information about a calendar event.
2194
2230
 
@@ -2236,14 +2272,9 @@ Here are all properties that exist in Event object:
2236
2272
 
2237
2273
  `title`
2238
2274
  </td>
2239
- <td>The text appearing on the event</td>
2240
- </tr>
2241
- <tr>
2242
2275
  <td>
2243
2276
 
2244
- `titleHTML`
2245
- </td>
2246
- <td>The HTML version of the title</td>
2277
+ The text appearing on the event. See [Content](#content)</td>
2247
2278
  </tr>
2248
2279
  <tr>
2249
2280
  <td>
@@ -2391,17 +2422,7 @@ Here are all admissible fields for the event’s input object:
2391
2422
  </td>
2392
2423
  <td>
2393
2424
 
2394
- `string` The text that will appear on the event. Default `''`
2395
- </td>
2396
- </tr>
2397
- <tr>
2398
- <td>
2399
-
2400
- `titleHTML`
2401
- </td>
2402
- <td>
2403
-
2404
- `string` The HTML version of the title to be displayed instead of the text version. Default `''`
2425
+ `Content` The text that will appear on the event. See [Content](#content). Default `''`
2405
2426
  </td>
2406
2427
  </tr>
2407
2428
  <tr>
package/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { run_all, is_function, noop, identity, tick, SvelteComponent, init, safe_not_equal, ensure_array_like, empty, insert, detach, destroy_each, component_subscribe, set_store_value, element, text, attr, append, listen, set_data, transition_in, group_outros, check_outros, transition_out, space, create_component, mount_component, destroy_component, construct_svelte_component, set_style, get_current_component } from 'svelte/internal';
1
+ import { run_all, is_function, noop, identity, tick, SvelteComponent, init, safe_not_equal, ensure_array_like, empty, insert, detach, destroy_each, component_subscribe, set_store_value, element, text, attr, append, listen, set_data, action_destroyer, transition_in, group_outros, check_outros, transition_out, space, create_component, mount_component, destroy_component, construct_svelte_component, set_style, get_current_component } from 'svelte/internal';
2
2
  import { getContext, setContext, beforeUpdate } from 'svelte';
3
3
  import { writable, derived, get, readable } from 'svelte/store';
4
4
 
@@ -32,43 +32,14 @@ function btnText(text, period) {
32
32
  };
33
33
  }
34
34
 
35
- function assign(...args) {
36
- return Object.assign(...args);
37
- }
38
-
39
- function floor(value) {
40
- return Math.floor(value);
41
- }
42
-
43
- function min(...args) {
44
- return Math.min(...args);
45
- }
46
-
47
- function max(...args) {
48
- return Math.max(...args);
49
- }
50
-
51
- function isObject(test) {
52
- return typeof test === 'object' && test !== null;
53
- }
54
-
55
- function symbol() {
56
- return Symbol('ec');
57
- }
58
-
59
35
  function setContent(node, content) {
60
36
  let actions = {
61
37
  update(content) {
62
- while (node.firstChild) {
63
- node.removeChild(node.lastChild);
64
- }
65
- if (!isObject(content)) {
38
+ if (typeof content == 'string') {
66
39
  node.innerText = content;
67
- } else if (content.domNodes) {
68
- for (let child of content.domNodes) {
69
- node.appendChild(child);
70
- }
71
- } else if (content.html) {
40
+ } else if (content?.domNodes) {
41
+ node.replaceChildren(...content.domNodes);
42
+ } else if (content?.html) {
72
43
  node.innerHTML = content.html;
73
44
  }
74
45
  }
@@ -191,43 +162,6 @@ function toISOString(date) {
191
162
  return date.toISOString().substring(0, 19);
192
163
  }
193
164
 
194
- function formatRange(start, end, intl) {
195
- if (start.getFullYear() !== end.getFullYear()) {
196
- return intl.format(start) + ' - ' + intl.format(end);
197
- }
198
-
199
- let diff = [];
200
- if (start.getMonth() !== end.getMonth()) {
201
- diff.push('month');
202
- }
203
- if (start.getDate() !== end.getDate()) {
204
- diff.push('day');
205
- }
206
-
207
- if (!diff.length) {
208
- return intl.format(start);
209
- }
210
-
211
- let opts1 = intl.resolvedOptions();
212
- let opts2 = {};
213
- for (let key of diff) {
214
- opts2[key] = opts1[key];
215
- }
216
- let intl2 = new Intl.DateTimeFormat(opts1.locale, opts2);
217
-
218
- let full1 = intl.format(start);
219
- let full2 = intl.format(end);
220
- let part1 = intl2.format(start);
221
- let part2 = intl2.format(end);
222
-
223
- let common = _commonChunks(full1, part1, full2, part2);
224
- if (common) {
225
- return common.head + part1 + ' - ' + part2 + common.tail;
226
- }
227
-
228
- return full1 + ' - ' + full2;
229
- }
230
-
231
165
  function datesEqual(date1, ...dates2) {
232
166
  return dates2.every(date2 => date1.getTime() === date2.getTime());
233
167
  }
@@ -251,6 +185,15 @@ function noTimePart(date) {
251
185
  return typeof date === 'string' && date.length <= 10;
252
186
  }
253
187
 
188
+ /**
189
+ * Copy time from one date to another
190
+ */
191
+ function copyTime(toDate, fromDate) {
192
+ toDate.setUTCHours(fromDate.getUTCHours(), fromDate.getUTCMinutes(), fromDate.getUTCSeconds(), 0);
193
+
194
+ return toDate;
195
+ }
196
+
254
197
  /**
255
198
  * Private functions
256
199
  */
@@ -278,62 +221,48 @@ function _fromISOString(str) {
278
221
  ));
279
222
  }
280
223
 
281
- function _commonChunks(str1, substr1, str2, substr2) {
282
- let i = 0;
283
- while (i < str1.length) {
284
- let res1;
285
- [i, res1] = _cut(str1, substr1, i);
286
- if (!res1) {
287
- break;
288
- }
289
-
290
- let j = 0;
291
- while (j < str2.length) {
292
- let res2;
293
- [j, res2] = _cut(str2, substr2, j);
294
- if (!res2) {
295
- break;
296
- }
224
+ function debounce(fn, handle, queueStore) {
225
+ queueStore.update(queue => queue.set(handle, fn));
226
+ }
297
227
 
298
- if (res1.head === res2.head && res1.tail === res2.tail) {
299
- return res1;
300
- }
301
- }
302
- }
228
+ function flushDebounce(queue) {
229
+ run_all(queue);
230
+ queue.clear();
231
+ }
303
232
 
304
- return null
233
+ function assign(...args) {
234
+ return Object.assign(...args);
305
235
  }
306
236
 
307
- function _cut(str, substr, from) {
308
- let start = str.indexOf(substr, from);
309
- if (start >= 0) {
310
- let end = start + substr.length;
237
+ function keys(object) {
238
+ return Object.keys(object);
239
+ }
311
240
 
312
- return [end, {
313
- head: str.substr(0, start),
314
- tail: str.substr(end)
315
- }];
316
- }
241
+ function floor(value) {
242
+ return Math.floor(value);
243
+ }
317
244
 
318
- return [-1, null];
245
+ function min(...args) {
246
+ return Math.min(...args);
319
247
  }
320
248
 
321
- function debounce(fn, handle, queueStore) {
322
- queueStore.update(queue => queue.set(handle, fn));
249
+ function max(...args) {
250
+ return Math.max(...args);
323
251
  }
324
252
 
325
- function flushDebounce(queue) {
326
- run_all(queue);
327
- queue.clear();
253
+ function symbol() {
254
+ return Symbol('ec');
328
255
  }
329
256
 
330
- function createElement(tag, className, html, text) {
257
+ function createElement(tag, className, content) {
331
258
  let el = document.createElement(tag);
332
259
  el.className = className;
333
- if (html) {
334
- el.innerHTML = html;
335
- } else if (text) {
336
- el.innerText = text;
260
+ if (typeof content == 'string') {
261
+ el.innerText = content;
262
+ } else if (content.domNodes) {
263
+ el.replaceChildren(...content.domNodes);
264
+ } else if (content.html) {
265
+ el.innerHTML = content.html;
337
266
  }
338
267
  return el;
339
268
  }
@@ -535,10 +464,14 @@ function repositionEvent(chunk, longChunks, height) {
535
464
  }
536
465
 
537
466
  function createEventContent(chunk, displayEventEnd, eventContent, theme, _intlEventTime, _view) {
538
- let timeText = _intlEventTime.format(chunk.start), content;
539
- if (displayEventEnd && chunk.event.display !== 'pointer') {
540
- timeText += ` - ${_intlEventTime.format(chunk.end)}`;
541
- }
467
+ let timeText = _intlEventTime.formatRange(
468
+ chunk.start,
469
+ displayEventEnd && chunk.event.display !== 'pointer'
470
+ ? copyTime(cloneDate(chunk.start), chunk.end) // make Intl.formatRange output only the time part
471
+ : chunk.start
472
+ );
473
+ let content;
474
+
542
475
  if (eventContent) {
543
476
  content = is_function(eventContent)
544
477
  ? eventContent({
@@ -554,14 +487,14 @@ function createEventContent(chunk, displayEventEnd, eventContent, theme, _intlEv
554
487
  break;
555
488
  case 'pointer':
556
489
  content = {
557
- domNodes: [createElement('div', theme.eventTime, null, timeText)]
490
+ domNodes: [createElement('div', theme.eventTime, timeText)]
558
491
  };
559
492
  break;
560
493
  default:
561
494
  content = {
562
495
  domNodes: [
563
- ...chunk.event.allDay ? [] : [createElement('div', theme.eventTime, null, timeText)],
564
- createElement('div', theme.eventTitle, chunk.event.titleHTML, chunk.event.title)
496
+ ...chunk.event.allDay ? [] : [createElement('div', theme.eventTime, timeText)],
497
+ createElement('div', theme.eventTitle, chunk.event.title)
565
498
  ]
566
499
  };
567
500
  }
@@ -638,7 +571,7 @@ function pointerEvent(display) {
638
571
 
639
572
  function writable2(value, parser, start) {
640
573
  return {
641
- ...writable(parser ? parser(value) : value, start),
574
+ ...writable(value, start),
642
575
  parse: parser
643
576
  };
644
577
  }
@@ -677,12 +610,11 @@ function intl(locale, format) {
677
610
 
678
611
  function intlRange(locale, format) {
679
612
  return derived([locale, format], ([$locale, $format]) => {
680
- if (is_function($format)) {
681
- return {format: (start, end) => $format(toLocalDate(start), toLocalDate(end))};
682
- }
683
- let intl = new Intl.DateTimeFormat($locale, $format);
613
+ let intl = is_function($format)
614
+ ? {formatRange: $format}
615
+ : new Intl.DateTimeFormat($locale, $format);
684
616
  return {
685
- format: (start, end) => formatRange(toLocalDate(start), toLocalDate(end), intl)
617
+ formatRange: (start, end) => intl.formatRange(toLocalDate(start), toLocalDate(end))
686
618
  };
687
619
  });
688
620
  }
@@ -910,11 +842,11 @@ function viewDates(state) {
910
842
 
911
843
  function viewTitle(state) {
912
844
  return derived(
913
- [state.date, state._activeRange, state._titleIntlRange, state._monthMode],
914
- ([$date, $_activeRange, $_titleIntlRange, $_monthMode]) => {
845
+ [state.date, state._activeRange, state._intlTitle, state._monthMode],
846
+ ([$date, $_activeRange, $_intlTitle, $_monthMode]) => {
915
847
  return $_monthMode
916
- ? $_titleIntlRange.format($date, $date)
917
- : $_titleIntlRange.format($_activeRange.start, subtractDay(cloneDate($_activeRange.end)));
848
+ ? $_intlTitle.formatRange($date, $date)
849
+ : $_intlTitle.formatRange($_activeRange.start, subtractDay(cloneDate($_activeRange.end)));
918
850
  }
919
851
  );
920
852
  }
@@ -1030,9 +962,13 @@ class State {
1030
962
  plugins = plugins || [];
1031
963
 
1032
964
  // Create options
1033
- let options = createOptions(plugins);
965
+ let options= createOptions(plugins);
1034
966
  let parsers = createParsers(options, plugins);
1035
967
 
968
+ // Parse options
969
+ options = parseOpts(options, parsers);
970
+ input = parseOpts(input, parsers);
971
+
1036
972
  // Create stores for options
1037
973
  for (let [option, value] of Object.entries(options)) {
1038
974
  this[option] = writable2(value, parsers[option]);
@@ -1048,10 +984,10 @@ class State {
1048
984
  this._events = events(this);
1049
985
  this._now = now();
1050
986
  this._today = today(this);
1051
- this._intlEventTime = intl(this.locale, this.eventTimeFormat);
987
+ this._intlEventTime = intlRange(this.locale, this.eventTimeFormat);
1052
988
  this._intlSlotLabel = intl(this.locale, this.slotLabelFormat);
1053
989
  this._intlDayHeader = intl(this.locale, this.dayHeaderFormat);
1054
- this._titleIntlRange = intlRange(this.locale, this.titleFormat);
990
+ this._intlTitle = intlRange(this.locale, this.titleFormat);
1055
991
  this._bodyEl = writable(undefined);
1056
992
  this._scrollable = writable(false);
1057
993
  this._viewTitle = viewTitle(this);
@@ -1079,13 +1015,9 @@ class State {
1079
1015
  }
1080
1016
 
1081
1017
  // Set options for each view
1082
- let commonOpts = assign({}, options, input);
1083
- parseOpts(commonOpts, this);
1084
- let views = new Set([...Object.keys(options.views), ...Object.keys(input.views || {})]);
1018
+ let views = new Set([...keys(options.views), ...keys(input.views ?? {})]);
1085
1019
  for (let view of views) {
1086
- let viewOpts = assign({}, options.views[view] ?? {}, input.views?.[view] ?? {});
1087
- parseOpts(viewOpts, this);
1088
- let opts = assign({}, commonOpts, viewOpts);
1020
+ let opts = assign({}, options, options.views[view] ?? {}, input, input.views?.[view] ?? {});
1089
1021
  // Change view component when view changes
1090
1022
  this.view.subscribe(newView => {
1091
1023
  if (newView === view) {
@@ -1096,7 +1028,7 @@ class State {
1096
1028
  }
1097
1029
  });
1098
1030
  // Process options
1099
- for (let key of Object.keys(opts)) {
1031
+ for (let key of keys(opts)) {
1100
1032
  if (this.hasOwnProperty(key) && key[0] !== '_') {
1101
1033
  let {set, _set, ...rest} = this[key];
1102
1034
 
@@ -1124,14 +1056,17 @@ class State {
1124
1056
  }
1125
1057
  }
1126
1058
 
1127
- function parseOpts(opts, state) {
1128
- for (let key of Object.keys(opts)) {
1129
- if (state.hasOwnProperty(key) && key[0] !== '_') {
1130
- if (state[key].parse) {
1131
- opts[key] = state[key].parse(opts[key]);
1132
- }
1059
+ function parseOpts(opts, parsers) {
1060
+ let result = {};
1061
+ for (let key of keys(opts)) {
1062
+ result[key] = parsers[key] ? parsers[key](opts[key]) : opts[key];
1063
+ }
1064
+ if (opts.views) {
1065
+ for (let view of keys(opts.views)) {
1066
+ result.views[view] = parseOpts(opts.views[view], parsers);
1133
1067
  }
1134
1068
  }
1069
+ return result;
1135
1070
  }
1136
1071
 
1137
1072
  /* packages/core/src/Buttons.svelte generated by Svelte v4.1.1 */
@@ -1142,7 +1077,7 @@ function get_each_context$2(ctx, list, i) {
1142
1077
  return child_ctx;
1143
1078
  }
1144
1079
 
1145
- // (37:27)
1080
+ // (38:27)
1146
1081
  function create_if_block_4(ctx) {
1147
1082
  let button_1;
1148
1083
  let t_value = /*$buttonText*/ ctx[5][/*button*/ ctx[23]] + "";
@@ -1194,7 +1129,7 @@ function create_if_block_4(ctx) {
1194
1129
  };
1195
1130
  }
1196
1131
 
1197
- // (35:32)
1132
+ // (36:32)
1198
1133
  function create_if_block_3(ctx) {
1199
1134
  let button_1;
1200
1135
  let t_value = /*$buttonText*/ ctx[5][/*button*/ ctx[23]] + "";
@@ -1241,7 +1176,7 @@ function create_if_block_3(ctx) {
1241
1176
  };
1242
1177
  }
1243
1178
 
1244
- // (33:31)
1179
+ // (34:31)
1245
1180
  function create_if_block_2(ctx) {
1246
1181
  let button_1;
1247
1182
  let i;
@@ -1292,7 +1227,7 @@ function create_if_block_2(ctx) {
1292
1227
  };
1293
1228
  }
1294
1229
 
1295
- // (31:31)
1230
+ // (32:31)
1296
1231
  function create_if_block_1(ctx) {
1297
1232
  let button_1;
1298
1233
  let i;
@@ -1346,30 +1281,38 @@ function create_if_block_1(ctx) {
1346
1281
  // (29:4) {#if button == 'title'}
1347
1282
  function create_if_block$1(ctx) {
1348
1283
  let h2;
1349
- let t;
1350
1284
  let h2_class_value;
1285
+ let setContent_action;
1286
+ let mounted;
1287
+ let dispose;
1351
1288
 
1352
1289
  return {
1353
1290
  c() {
1354
1291
  h2 = element("h2");
1355
- t = text(/*$_viewTitle*/ ctx[4]);
1356
1292
  attr(h2, "class", h2_class_value = /*$theme*/ ctx[3].title);
1357
1293
  },
1358
1294
  m(target, anchor) {
1359
1295
  insert(target, h2, anchor);
1360
- append(h2, t);
1296
+
1297
+ if (!mounted) {
1298
+ dispose = action_destroyer(setContent_action = setContent.call(null, h2, /*$_viewTitle*/ ctx[4]));
1299
+ mounted = true;
1300
+ }
1361
1301
  },
1362
1302
  p(ctx, dirty) {
1363
- if (dirty & /*$_viewTitle*/ 16) set_data(t, /*$_viewTitle*/ ctx[4]);
1364
-
1365
1303
  if (dirty & /*$theme*/ 8 && h2_class_value !== (h2_class_value = /*$theme*/ ctx[3].title)) {
1366
1304
  attr(h2, "class", h2_class_value);
1367
1305
  }
1306
+
1307
+ if (setContent_action && is_function(setContent_action.update) && dirty & /*$_viewTitle*/ 16) setContent_action.update.call(null, /*$_viewTitle*/ ctx[4]);
1368
1308
  },
1369
1309
  d(detaching) {
1370
1310
  if (detaching) {
1371
1311
  detach(h2);
1372
1312
  }
1313
+
1314
+ mounted = false;
1315
+ dispose();
1373
1316
  }
1374
1317
  };
1375
1318
  }
@@ -2552,4 +2495,4 @@ class Calendar extends SvelteComponent {
2552
2495
  }
2553
2496
  }
2554
2497
 
2555
- export { DAY_IN_SECONDS, addDay, addDuration, ancestor, assign, bgEvent, btnTextDay, btnTextMonth, btnTextWeek, btnTextYear, cloneDate, cloneEvent, createDate, createDuration, createElement, createEventChunk, createEventClasses, createEventContent, createEventSources, createEvents, createView, datesEqual, debounce, Calendar as default, derived2, eventIntersects, floor, flushDebounce, formatRange, getElementWithPayload, getPayload, ghostEvent, hasPayload, hasYScroll, height, helperEvent, intl, intlRange, isObject, keyEnter, max, min, nextClosestDay, noTimePart, outsideEvent, pointerEvent, prepareEventChunks, prevClosestDay, previewEvent, rect, repositionEvent, setContent, setMidnight, setPayload, sortEventChunks, subtractDay, subtractDuration, symbol, toEventWithLocalDates, toISOString, toLocalDate, toViewWithLocalDates, writable2 };
2498
+ export { DAY_IN_SECONDS, addDay, addDuration, ancestor, assign, bgEvent, btnTextDay, btnTextMonth, btnTextWeek, btnTextYear, cloneDate, cloneEvent, copyTime, createDate, createDuration, createElement, createEventChunk, createEventClasses, createEventContent, createEventSources, createEvents, createView, datesEqual, debounce, Calendar as default, derived2, eventIntersects, floor, flushDebounce, getElementWithPayload, getPayload, ghostEvent, hasPayload, hasYScroll, height, helperEvent, intl, intlRange, keyEnter, keys, max, min, nextClosestDay, noTimePart, outsideEvent, pointerEvent, prepareEventChunks, prevClosestDay, previewEvent, rect, repositionEvent, setContent, setMidnight, setPayload, sortEventChunks, subtractDay, subtractDuration, symbol, toEventWithLocalDates, toISOString, toLocalDate, toViewWithLocalDates, writable2 };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@event-calendar/core",
3
- "version": "1.5.1",
3
+ "version": "2.0.0",
4
4
  "title": "Event Calendar Core package",
5
5
  "description": "Full-sized drag & drop event calendar with resource view",
6
6
  "keywords": [
@@ -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,7 +27,8 @@
27
27
 
28
28
  {#each buttons as button}
29
29
  {#if button == 'title'}
30
- <h2 class="{$theme.title}">{$_viewTitle}</h2>
30
+ <!-- svelte-ignore a11y-missing-content -->
31
+ <h2 class="{$theme.title}" use:setContent={$_viewTitle}></h2>
31
32
  {:else if button == 'prev'}
32
33
  <button class="{$theme.button} ec-{button}" aria-label={$buttonText.prev} on:click={prev}><i class="{$theme.icon} ec-{button}"></i></button>
33
34
  {:else if button == 'next'}
@@ -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
- while (node.firstChild) {
7
- node.removeChild(node.lastChild);
8
- }
9
- if (!isObject(content)) {
5
+ if (typeof content == 'string') {
10
6
  node.innerText = content;
11
- } else if (content.domNodes) {
12
- for (let child of content.domNodes) {
13
- node.appendChild(child);
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, html, text) {
3
+ export function createElement(tag, className, content) {
4
4
  let el = document.createElement(tag);
5
5
  el.className = className;
6
- if (html) {
7
- el.innerHTML = html;
8
- } else if (text) {
9
- el.innerText = text;
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.format(chunk.start), content;
135
- if (displayEventEnd && chunk.event.display !== 'pointer') {
136
- timeText += ` - ${_intlEventTime.format(chunk.end)}`;
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, null, timeText)]
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, null, timeText)],
160
- createElement('div', theme.eventTitle, chunk.event.titleHTML, chunk.event.title)
163
+ ...chunk.event.allDay ? [] : [createElement('div', theme.eventTime, timeText)],
164
+ createElement('div', theme.eventTitle, chunk.event.title)
161
165
  ]
162
166
  };
163
167
  }
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, formatRange} from './date';
3
+ import {toLocalDate} from './date';
4
4
 
5
5
  export function writable2(value, parser, start) {
6
6
  return {
7
- ...writable(parser ? parser(value) : value, start),
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
- if (is_function($format)) {
47
- return {format: (start, end) => $format(toLocalDate(start), toLocalDate(end))};
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
- format: (start, end) => formatRange(toLocalDate(start), toLocalDate(end), intl)
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
  }
@@ -12,16 +12,20 @@ import {
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 {assign, writable2, intl, intlRange} from '../lib.js';
15
+ import {assign, keys, writable2, intl, intlRange} from '../lib.js';
16
16
 
17
17
  export default class {
18
18
  constructor(plugins, input) {
19
19
  plugins = plugins || [];
20
20
 
21
21
  // Create options
22
- let options = createOptions(plugins);
22
+ let options= createOptions(plugins);
23
23
  let parsers = createParsers(options, plugins);
24
24
 
25
+ // Parse options
26
+ options = parseOpts(options, parsers);
27
+ input = parseOpts(input, parsers);
28
+
25
29
  // Create stores for options
26
30
  for (let [option, value] of Object.entries(options)) {
27
31
  this[option] = writable2(value, parsers[option]);
@@ -37,10 +41,10 @@ export default class {
37
41
  this._events = events(this);
38
42
  this._now = now();
39
43
  this._today = today(this);
40
- this._intlEventTime = intl(this.locale, this.eventTimeFormat);
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._titleIntlRange = intlRange(this.locale, this.titleFormat);
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);
@@ -68,13 +72,9 @@ export default class {
68
72
  }
69
73
 
70
74
  // Set options for each view
71
- let commonOpts = assign({}, options, input);
72
- parseOpts(commonOpts, this);
73
- let views = new Set([...Object.keys(options.views), ...Object.keys(input.views || {})]);
75
+ let views = new Set([...keys(options.views), ...keys(input.views ?? {})]);
74
76
  for (let view of views) {
75
- let viewOpts = assign({}, options.views[view] ?? {}, input.views?.[view] ?? {});
76
- parseOpts(viewOpts, this);
77
- let opts = assign({}, commonOpts, viewOpts);
77
+ let opts = assign({}, options, options.views[view] ?? {}, input, input.views?.[view] ?? {});
78
78
  // Change view component when view changes
79
79
  this.view.subscribe(newView => {
80
80
  if (newView === view) {
@@ -85,7 +85,7 @@ export default class {
85
85
  }
86
86
  });
87
87
  // Process options
88
- for (let key of Object.keys(opts)) {
88
+ for (let key of keys(opts)) {
89
89
  if (this.hasOwnProperty(key) && key[0] !== '_') {
90
90
  let {set, _set, ...rest} = this[key];
91
91
 
@@ -113,12 +113,15 @@ export default class {
113
113
  }
114
114
  }
115
115
 
116
- function parseOpts(opts, state) {
117
- for (let key of Object.keys(opts)) {
118
- if (state.hasOwnProperty(key) && key[0] !== '_') {
119
- if (state[key].parse) {
120
- opts[key] = state[key].parse(opts[key]);
121
- }
116
+ function parseOpts(opts, parsers) {
117
+ let result = {};
118
+ for (let key of keys(opts)) {
119
+ result[key] = parsers[key] ? parsers[key](opts[key]) : opts[key];
120
+ }
121
+ if (opts.views) {
122
+ for (let view of keys(opts.views)) {
123
+ result.views[view] = parseOpts(opts.views[view], parsers);
122
124
  }
123
125
  }
126
+ return result;
124
127
  }
@@ -93,11 +93,11 @@ export function viewDates(state) {
93
93
 
94
94
  export function viewTitle(state) {
95
95
  return derived(
96
- [state.date, state._activeRange, state._titleIntlRange, state._monthMode],
97
- ([$date, $_activeRange, $_titleIntlRange, $_monthMode]) => {
96
+ [state.date, state._activeRange, state._intlTitle, state._monthMode],
97
+ ([$date, $_activeRange, $_intlTitle, $_monthMode]) => {
98
98
  return $_monthMode
99
- ? $_titleIntlRange.format($date, $date)
100
- : $_titleIntlRange.format($_activeRange.start, subtractDay(cloneDate($_activeRange.end)));
99
+ ? $_intlTitle.formatRange($date, $date)
100
+ : $_intlTitle.formatRange($_activeRange.start, subtractDay(cloneDate($_activeRange.end)));
101
101
  }
102
102
  );
103
103
  }