@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.
Files changed (79) hide show
  1. package/README.md +15 -4
  2. package/dist/index.css +2 -2
  3. package/dist/index.js +2201 -2128
  4. package/package.json +2 -2
  5. package/src/Buttons.svelte +36 -37
  6. package/src/Calendar.svelte +34 -37
  7. package/src/Toolbar.svelte +4 -4
  8. package/src/lib/components/BaseDay.svelte +13 -10
  9. package/src/lib/components/BaseEvent.svelte +17 -17
  10. package/src/lib/components/ColHead.svelte +6 -6
  11. package/src/lib/components/DayHeader.svelte +3 -3
  12. package/src/lib/components/InteractableEvent.svelte +7 -8
  13. package/src/lib/derived.js +80 -0
  14. package/src/lib/index.js +1 -2
  15. package/src/lib/slots.js +16 -16
  16. package/src/lib/utils.js +4 -9
  17. package/src/lib/view.js +0 -8
  18. package/src/plugins/day-grid/Day.svelte +25 -23
  19. package/src/plugins/day-grid/Event.svelte +15 -13
  20. package/src/plugins/day-grid/Popup.svelte +12 -12
  21. package/src/plugins/day-grid/View.svelte +24 -36
  22. package/src/plugins/day-grid/derived.js +102 -0
  23. package/src/plugins/day-grid/index.js +47 -36
  24. package/src/plugins/day-grid/state.svelte.js +19 -0
  25. package/src/plugins/interaction/Action.svelte +108 -76
  26. package/src/plugins/interaction/Auxiliary.svelte +9 -38
  27. package/src/plugins/interaction/Pointer.svelte +12 -17
  28. package/src/plugins/interaction/Resizer.svelte +9 -7
  29. package/src/plugins/interaction/effects.js +37 -0
  30. package/src/plugins/interaction/index.js +44 -38
  31. package/src/plugins/interaction/lib/utils.js +1 -1
  32. package/src/plugins/interaction/state.svelte.js +12 -0
  33. package/src/plugins/list/Day.svelte +8 -7
  34. package/src/plugins/list/Event.svelte +3 -3
  35. package/src/plugins/list/View.svelte +18 -13
  36. package/src/plugins/list/index.js +51 -43
  37. package/src/plugins/list/state.svelte.js +8 -0
  38. package/src/plugins/resource-time-grid/Label.svelte +8 -8
  39. package/src/plugins/resource-time-grid/View.svelte +38 -17
  40. package/src/plugins/resource-time-grid/derived.js +67 -0
  41. package/src/plugins/resource-time-grid/index.js +34 -28
  42. package/src/plugins/resource-time-grid/state.svelte.js +21 -0
  43. package/src/plugins/resource-timeline/Day.svelte +9 -4
  44. package/src/plugins/resource-timeline/Event.svelte +7 -6
  45. package/src/plugins/resource-timeline/Expander.svelte +7 -6
  46. package/src/plugins/resource-timeline/NowIndicator.svelte +10 -11
  47. package/src/plugins/resource-timeline/View.svelte +45 -63
  48. package/src/plugins/resource-timeline/derived.js +167 -0
  49. package/src/plugins/resource-timeline/index.js +17 -21
  50. package/src/plugins/resource-timeline/lib.js +4 -65
  51. package/src/plugins/resource-timeline/state.svelte.js +18 -0
  52. package/src/plugins/time-grid/Day.svelte +7 -2
  53. package/src/plugins/time-grid/Event.svelte +6 -6
  54. package/src/plugins/time-grid/NowIndicator.svelte +10 -9
  55. package/src/plugins/time-grid/View.svelte +46 -59
  56. package/src/plugins/time-grid/derived.js +162 -0
  57. package/src/plugins/time-grid/index.js +31 -25
  58. package/src/plugins/time-grid/lib.js +18 -74
  59. package/src/plugins/time-grid/options.js +21 -16
  60. package/src/plugins/time-grid/state.svelte.js +44 -0
  61. package/src/storage/derived.js +144 -0
  62. package/src/storage/effects.js +156 -0
  63. package/src/storage/options.svelte.js +275 -0
  64. package/src/storage/state.svelte.js +69 -0
  65. package/src/styles/events.css +1 -1
  66. package/src/Auxiliary.svelte +0 -47
  67. package/src/lib/debounce.js +0 -20
  68. package/src/lib/stores.js +0 -63
  69. package/src/plugins/day-grid/lib.js +0 -61
  70. package/src/plugins/day-grid/stores.js +0 -5
  71. package/src/plugins/resource-time-grid/lib.js +0 -31
  72. package/src/plugins/resource-time-grid/stores.js +0 -34
  73. package/src/plugins/resource-timeline/Header.svelte +0 -44
  74. package/src/plugins/resource-timeline/Label.svelte +0 -38
  75. package/src/plugins/resource-timeline/stores.js +0 -48
  76. package/src/plugins/time-grid/stores.js +0 -49
  77. package/src/storage/options.js +0 -136
  78. package/src/storage/state.js +0 -168
  79. package/src/storage/stores.js +0 -234
package/src/lib/slots.js CHANGED
@@ -2,47 +2,47 @@ import {addDuration, cloneDate, createDuration, DAY_IN_SECONDS, toISOString, toS
2
2
  import {max as maxFn, min as minFn, isFunction, floor} from './utils.js';
3
3
  import {bgEvent} from './events.js';
4
4
 
5
- export function createSlots(date, $slotDuration, $_slotLabelPeriodicity, $_slotTimeLimits, $_intlSlotLabel) {
5
+ export function createSlots(date, slotDuration, slotLabelPeriodicity, slotTimeLimits, intlSlotLabel) {
6
6
  let slots = [];
7
7
  date = cloneDate(date);
8
8
  let end = cloneDate(date);
9
- addDuration(date, $_slotTimeLimits.min);
10
- addDuration(end, $_slotTimeLimits.max);
9
+ addDuration(date, slotTimeLimits.min);
10
+ addDuration(end, slotTimeLimits.max);
11
11
  // Build slots
12
12
  while (date < end) {
13
13
  slots.push([
14
14
  toISOString(date),
15
- $_intlSlotLabel.format(date)
15
+ intlSlotLabel.format(date)
16
16
  ]);
17
- addDuration(date, $slotDuration, $_slotLabelPeriodicity);
17
+ addDuration(date, slotDuration, slotLabelPeriodicity);
18
18
  }
19
19
  // Calculate span for last slot
20
- let span = floor((date - end) / 1000 / toSeconds($slotDuration));
21
- if (span && span !== $_slotLabelPeriodicity) {
22
- slots.at(-1)[2] = $_slotLabelPeriodicity - span;
20
+ let span = floor((date - end) / 1000 / toSeconds(slotDuration));
21
+ if (span && span !== slotLabelPeriodicity) {
22
+ slots.at(-1)[2] = slotLabelPeriodicity - span;
23
23
  }
24
24
 
25
25
  return slots;
26
26
  }
27
27
 
28
- export function createSlotTimeLimits($slotMinTime, $slotMaxTime, $flexibleSlotTimeLimits, $_viewDates, $_filteredEvents) {
28
+ export function createSlotTimeLimits(slotMinTime, slotMaxTime, flexibleSlotTimeLimits, viewDates, filteredEvents) {
29
29
  // Copy values
30
- let min = createDuration($slotMinTime);
31
- let max = createDuration($slotMaxTime);
30
+ let min = createDuration(slotMinTime);
31
+ let max = createDuration(slotMaxTime);
32
32
 
33
- if ($flexibleSlotTimeLimits) {
33
+ if (flexibleSlotTimeLimits) {
34
34
  // If slotMaxTime goes past midnight, then extend it back by a maximum of 24 hours
35
35
  let minMin = createDuration(minFn(toSeconds(min), maxFn(0, toSeconds(max) - DAY_IN_SECONDS)));
36
36
  let maxMax = createDuration(maxFn(toSeconds(max), toSeconds(minMin) + DAY_IN_SECONDS));
37
- let filter = isFunction($flexibleSlotTimeLimits?.eventFilter)
38
- ? $flexibleSlotTimeLimits.eventFilter
37
+ let filter = isFunction(flexibleSlotTimeLimits?.eventFilter)
38
+ ? flexibleSlotTimeLimits.eventFilter
39
39
  : event => !bgEvent(event.display);
40
- loop: for (let date of $_viewDates) {
40
+ loop: for (let date of viewDates) {
41
41
  let start = addDuration(cloneDate(date), min);
42
42
  let end = addDuration(cloneDate(date), max);
43
43
  let minStart = addDuration(cloneDate(date), minMin);
44
44
  let maxEnd = addDuration(cloneDate(date), maxMax);
45
- for (let event of $_filteredEvents) {
45
+ for (let event of filteredEvents) {
46
46
  if (!event.allDay && filter(event) && event.start < maxEnd && event.end > minStart) {
47
47
  if (event.start < start) {
48
48
  let seconds = maxFn((event.start - date) / 1000, toSeconds(minMin));
package/src/lib/utils.js CHANGED
@@ -10,6 +10,10 @@ export function entries(object) {
10
10
  return Object.entries(object);
11
11
  }
12
12
 
13
+ export function hasOwn(object, property) {
14
+ return Object.hasOwn(object, property);
15
+ }
16
+
13
17
  export function floor(value) {
14
18
  return Math.floor(value);
15
19
  }
@@ -38,15 +42,6 @@ export function isFunction(value) {
38
42
  return typeof value === 'function';
39
43
  }
40
44
 
41
- export function isEmpty(obj) {
42
- for (let prop in obj) {
43
- if (Object.hasOwn(obj, prop)) {
44
- return false;
45
- }
46
- }
47
- return true;
48
- }
49
-
50
45
  export function run(fn) {
51
46
  return fn();
52
47
  }
package/src/lib/view.js CHANGED
@@ -22,11 +22,3 @@ export function toViewWithLocalDates(view) {
22
22
 
23
23
  return view;
24
24
  }
25
-
26
- export function listView(view) {
27
- return view.startsWith('list');
28
- }
29
-
30
- export function timelineView(view) {
31
- return view.includes('Timeline');
32
- }
@@ -7,24 +7,26 @@
7
7
 
8
8
  let {day, noIeb, noBeb} = $props();
9
9
 
10
- let {
11
- date, firstDay, moreLinkContent, theme, weekNumbers, weekNumberContent, _hiddenChunks, _intlDayCell, _popupDay
12
- } = getContext('state');
10
+ let mainState = getContext('state');
11
+ let viewState = getContext('view-state');
12
+
13
+ let {options: {date, firstDay, moreLinkContent, theme, weekNumbers, weekNumberContent}} = $derived(mainState);
14
+ let {hiddenChunks, intlDayCell} = $derived(viewState);
13
15
 
14
16
  let {dayStart, disabled, highlight} = $derived(day);
15
- let otherMonth = $derived(dayStart.getUTCMonth() !== $date.getUTCMonth());
16
- let classes = $derived(classNames => [...classNames, otherMonth && $theme.otherMonth]);
17
+ let otherMonth = $derived(dayStart.getUTCMonth() !== date.getUTCMonth());
18
+ let classes = $derived(classNames => [...classNames, otherMonth && theme.otherMonth]);
17
19
 
18
20
  // Week numbers
19
- let showWeekNumber = $derived($weekNumbers && dayStart.getUTCDay() === ($firstDay ? 1 : 0));
21
+ let showWeekNumber = $derived(weekNumbers && dayStart.getUTCDay() === (firstDay ? 1 : 0));
20
22
  let weekNumber = $derived.by(() => {
21
23
  let weekNumber;
22
24
  if (showWeekNumber) {
23
25
  let week = getWeekNumber(dayStart, $firstDay);
24
- if ($weekNumberContent) {
25
- weekNumber = isFunction($weekNumberContent)
26
- ? $weekNumberContent({date: toLocalDate(dayStart), week})
27
- : $weekNumberContent;
26
+ if (weekNumberContent) {
27
+ weekNumber = isFunction(weekNumberContent)
28
+ ? weekNumberContent({date: toLocalDate(dayStart), week})
29
+ : weekNumberContent;
28
30
  } else {
29
31
  weekNumber = 'W' + String(week).padStart(2, '0');
30
32
  }
@@ -33,15 +35,15 @@
33
35
  });
34
36
 
35
37
  // More link
36
- let hiddenChunks = $derived($_hiddenChunks[dayStart.getTime()]);
38
+ let dayHiddenChunks = $derived(hiddenChunks.get(dayStart.getTime()));
37
39
  let moreLink = $derived.by(() => {
38
40
  let moreLink = '';
39
- if (hiddenChunks) {
40
- let text = '+' + hiddenChunks.length + ' more';
41
- if ($moreLinkContent) {
42
- moreLink = isFunction($moreLinkContent)
43
- ? $moreLinkContent({num: hiddenChunks.length, text})
44
- : $moreLinkContent;
41
+ if (dayHiddenChunks) {
42
+ let text = '+' + dayHiddenChunks.length + ' more';
43
+ if (moreLinkContent) {
44
+ moreLink = isFunction(moreLinkContent)
45
+ ? moreLinkContent({num: dayHiddenChunks.length, text})
46
+ : moreLinkContent;
45
47
  } else {
46
48
  moreLink = text;
47
49
  }
@@ -51,26 +53,26 @@
51
53
 
52
54
  // Popup
53
55
  function showMore() {
54
- $_popupDay = day;
56
+ viewState.popupDay = day;
55
57
  }
56
58
  </script>
57
59
 
58
60
  <BaseDay date={dayStart} allDay {classes} {disabled} {highlight} {noIeb} {noBeb}>
59
- <div class="{$theme.dayHead}">
61
+ <div class="{theme.dayHead}">
60
62
  <time
61
63
  datetime="{toISOString(dayStart, 10)}"
62
- {@attach contentFrom($_intlDayCell.format(dayStart))}
64
+ {@attach contentFrom(intlDayCell.format(dayStart))}
63
65
  ></time>
64
66
  {#if showWeekNumber}
65
67
  <span
66
- class="{$theme.weekNumber}"
68
+ class="{theme.weekNumber}"
67
69
  {@attach contentFrom(weekNumber)}
68
70
  ></span>
69
71
  {/if}
70
72
  </div>
71
73
 
72
- <div class="{$theme.dayFoot}">
73
- {#if hiddenChunks}
74
+ <div class="{theme.dayFoot}">
75
+ {#if dayHiddenChunks}
74
76
  <!-- svelte-ignore a11y_missing_attribute -->
75
77
  <!-- svelte-ignore a11y_missing_content -->
76
78
  <!-- svelte-ignore a11y_consider_explicit_label -->
@@ -1,11 +1,12 @@
1
1
  <script>
2
2
  import {getContext} from 'svelte';
3
- import {bgEvent, height, isEmpty, max, repositionEvent} from '#lib';
3
+ import {bgEvent, height, max, repositionEvent} from '#lib';
4
4
  import {InteractableEvent} from '#components';
5
5
 
6
- let {chunk, gridEl, inPopup = false} = $props();
6
+ let {chunk, inPopup = false} = $props();
7
7
 
8
- let {_colsCount, _hiddenChunks, _popupDay, dayMaxEvents} = getContext('state');
8
+ let {options: {dayMaxEvents}} = $derived(getContext('state'));
9
+ let {colsCount, gridEl, hiddenChunks, popupDay} = $derived(getContext('view-state'));
9
10
 
10
11
  let el = $state();
11
12
  let margin = $state(0);
@@ -13,10 +14,10 @@
13
14
 
14
15
  let event = $derived(chunk.event);
15
16
  let display = $derived(chunk.event.display);
16
- let dayEl = $derived(gridEl?.children.item((chunk.gridRow - 1) * $_colsCount + chunk.gridColumn - 1));
17
+ let dayEl = $derived(gridEl.children.item((chunk.gridRow - 1) * colsCount + chunk.gridColumn - 1));
17
18
 
18
19
  $effect(() => {
19
- if (dayEl) {
20
+ if (!inPopup) {
20
21
  margin = height(dayEl.firstElementChild);
21
22
  }
22
23
  });
@@ -47,26 +48,27 @@
47
48
  }
48
49
 
49
50
  export function hide() {
50
- if ($dayMaxEvents === true) {
51
+ if (dayMaxEvents === true) {
51
52
  let h = height(dayEl) - footHeight(dayEl);
52
53
  hidden = chunk.bottom > h;
53
54
  if (hidden) {
54
55
  // Hide the event throughout all days
55
56
  for (let date of chunk.dates) {
56
57
  let key = date.getTime();
57
- if ($_hiddenChunks[key]) {
58
- if (!$_hiddenChunks[key].includes(chunk)) {
59
- $_hiddenChunks[key] = [...$_hiddenChunks[key], chunk];
58
+ if (hiddenChunks.has(key)) {
59
+ let chunks = hiddenChunks.get(key);
60
+ if (!chunks.includes(chunk)) {
61
+ hiddenChunks.set(key, [...chunks, chunk]);
60
62
  }
61
63
  } else {
62
- $_hiddenChunks[key] = [chunk];
64
+ hiddenChunks.set(key, [chunk]);
63
65
  }
64
66
  }
65
67
  }
66
68
  } else {
67
69
  hidden = false;
68
- if (!isEmpty($_hiddenChunks)) {
69
- $_hiddenChunks = {};
70
+ if (hiddenChunks.size) {
71
+ hiddenChunks.clear();
70
72
  }
71
73
  }
72
74
  }
@@ -89,6 +91,6 @@
89
91
  {chunk}
90
92
  {styles}
91
93
  axis="x"
92
- forceDate={inPopup && $_popupDay.dayStart}
94
+ forceDate={inPopup && popupDay.dayStart}
93
95
  forceMargin={[margin, chunk.gridRow]}
94
96
  />
@@ -5,14 +5,14 @@
5
5
  } from '#lib';
6
6
  import Event from './Event.svelte';
7
7
 
8
- let {gridEl, chunks} = $props();
9
-
10
- let {_colsCount, _interaction, _intlDayPopover, _popupDay, buttonText, theme} = getContext('state');
8
+ let viewState = getContext('view-state');
9
+ let {interaction, options: {buttonText, theme}} = $derived(getContext('state'));
10
+ let {colsCount, chunks, gridEl, intlDayPopover, popupDay} = $derived(viewState);
11
11
 
12
12
  let el = $state();
13
13
  let style = $state('');
14
14
 
15
- let {gridColumn, gridRow, dayStart, dayEnd} = $derived($_popupDay);
15
+ let {gridColumn, gridRow, dayStart, dayEnd} = $derived(popupDay);
16
16
 
17
17
  let popupChunks = $derived.by(() => {
18
18
  let result = [];
@@ -38,7 +38,7 @@
38
38
  });
39
39
 
40
40
  function position() {
41
- let dayEl = gridEl.children.item((gridRow - 1) * $_colsCount + gridColumn - 1);
41
+ let dayEl = gridEl.children.item((gridRow - 1) * colsCount + gridColumn - 1);
42
42
  let popupRect = rect(el);
43
43
  let dayRect = rect(dayEl);
44
44
  let gridRect = rect(gridEl);
@@ -76,18 +76,18 @@
76
76
  }
77
77
 
78
78
  function close() {
79
- $_popupDay = null;
79
+ viewState.popupDay = null;
80
80
  }
81
81
 
82
82
  function handlePointerDownOutside() {
83
83
  close();
84
- $_interaction.action?.noClick();
84
+ interaction.action?.noClick();
85
85
  }
86
86
  </script>
87
87
 
88
88
  <dialog
89
89
  bind:this={el}
90
- class="{$theme.popup}"
90
+ class="{theme.popup}"
91
91
  closedby="closerequest"
92
92
  {style}
93
93
  style:grid-area="{`${gridRow + 1} / ${gridColumn}`}"
@@ -95,20 +95,20 @@
95
95
  onpointerdownoutside={handlePointerDownOutside}
96
96
  onclose={close}
97
97
  >
98
- <header class="{$theme.dayHead}">
99
- <time datetime="{toISOString(dayStart, 10)}" {@attach contentFrom($_intlDayPopover.format(dayStart))}></time>
98
+ <header class="{theme.dayHead}">
99
+ <time datetime="{toISOString(dayStart, 10)}" {@attach contentFrom(intlDayPopover.format(dayStart))}></time>
100
100
  <!-- svelte-ignore a11y_missing_attribute -->
101
101
  <!-- svelte-ignore a11y_autofocus -->
102
102
  <a
103
103
  autofocus
104
104
  role="button"
105
105
  tabindex="0"
106
- aria-label={$buttonText.close}
106
+ aria-label={buttonText.close}
107
107
  onclick={stopPropagation(close)}
108
108
  onkeydown={keyEnter(close)}
109
109
  >&times;</a>
110
110
  </header>
111
- <div class="{$theme.events}">
111
+ <div class="{theme.events}">
112
112
  {#each popupChunks as chunk}
113
113
  <Event {chunk} inPopup />
114
114
  {/each}
@@ -1,90 +1,78 @@
1
1
  <script>
2
- import {getContext} from 'svelte';
3
- import {contentFrom, identity, nextClosestDay, prevClosestDay, resizeObserver, runReposition} from '#lib';
2
+ import {getContext, setContext} from 'svelte';
3
+ import {contentFrom, resizeObserver, runReposition} from '#lib';
4
+ import ViewState from './state.svelte.js';
4
5
  import Day from './Day.svelte';
5
6
  import Event from './Event.svelte';
6
7
  import Popup from './Popup.svelte';
7
- import {createEventChunks, createIEventChunks, createGrid} from './lib.js';
8
8
 
9
- let {_activeRangeExt, _mainEl, _colsCount, _filteredEvents, _hiddenChunks, _iEvents, _intlDayHeader,
10
- _intlDayHeaderAL, _popupDay, _viewDates, dayMaxEvents, firstDay, highlightedDates, theme,
11
- validRange} = getContext('state');
9
+ let mainState = getContext('state');
10
+ let viewState = new ViewState(mainState);
11
+ setContext('view-state', viewState);
12
12
 
13
- let gridEl = $state();
14
- let grid = $derived(createGrid($_viewDates, $_colsCount, $validRange, $highlightedDates));
15
- let {chunks, bgChunks} = $derived(createEventChunks($_filteredEvents, grid));
16
- let iChunks = $derived(createIEventChunks($_iEvents, grid));
17
-
18
- $effect.pre(() => {
19
- $_activeRangeExt = ({start, end}) => ({
20
- start: prevClosestDay(start, $firstDay),
21
- end: nextClosestDay(end, $firstDay)
22
- });
23
- return () => {
24
- $_activeRangeExt = identity;
25
- };
26
- });
13
+ let {intlDayHeader, intlDayHeaderAL, options: {dayMaxEvents, theme}} = $derived(mainState);
14
+ let {grid, chunks, bgChunks, iChunks, hiddenChunks, popupDay} = $derived(viewState);
27
15
 
28
16
  // Events reposition
29
17
  let refs = [];
30
18
  function reposition() {
31
- $_hiddenChunks = {};
19
+ hiddenChunks.clear();
32
20
  runReposition(refs, chunks);
33
21
  }
34
22
  $effect(reposition);
35
23
  $effect(() => {
36
- $_hiddenChunks;
24
+ chunks;
37
25
  refs.forEach(ref => ref.hide());
38
26
  });
39
27
  </script>
40
28
 
41
29
  <section
42
- bind:this={$_mainEl}
43
- class={[$theme.main, $dayMaxEvents === true && $theme.uniform]}
30
+ bind:this={mainState.mainEl}
31
+ class={[theme.main, dayMaxEvents === true && theme.uniform]}
44
32
  style:--ec-grid-cols="{grid[0].length}"
45
33
  style:--ec-grid-rows="{grid.length}"
46
34
  {@attach resizeObserver(reposition)}
47
35
  >
48
- <header class="{$theme.header}">
49
- <div class="{$theme.grid}" role="row">
36
+ <header class="{theme.header}">
37
+ <div class="{theme.grid}" role="row">
50
38
  {#each grid[0] as {dayStart}, i}
51
39
  <div
52
- class={[$theme.colHead, $theme.weekdays?.[dayStart.getUTCDay()]]}
40
+ class={[theme.colHead, theme.weekdays?.[dayStart.getUTCDay()]]}
53
41
  role="columnheader"
54
42
  aria-colindex="{1 + i}"
55
43
  >
56
44
  <span
57
- aria-label="{$_intlDayHeaderAL.format(dayStart)}"
58
- {@attach contentFrom($_intlDayHeader.format(dayStart))}
45
+ aria-label="{intlDayHeaderAL.format(dayStart)}"
46
+ {@attach contentFrom(intlDayHeader.format(dayStart))}
59
47
  ></span>
60
48
  </div>
61
49
  {/each}
62
50
  </div>
63
51
  </header>
64
52
 
65
- <div class="{$theme.body}">
66
- <div bind:this={gridEl} class="{$theme.grid}">
53
+ <div class="{theme.body}">
54
+ <div bind:this={viewState.gridEl} class="{theme.grid}">
67
55
  {#each grid as days, i}
68
56
  {#each days as day, j}
69
57
  <Day {day} noIeb={j + 1 === days.length} noBeb={i + 1 === grid.length}/>
70
58
  {/each}
71
59
  {/each}
72
60
  </div>
73
- <div class="{$theme.events}">
61
+ <div class="{theme.events}">
74
62
  {#each chunks as chunk, i}
75
63
  <!-- svelte-ignore binding_property_non_reactive -->
76
- <Event bind:this={refs[i]} {chunk} {gridEl}/>
64
+ <Event bind:this={refs[i]} {chunk}/>
77
65
  {/each}
78
66
  {#each bgChunks as chunk}
79
67
  <Event {chunk}/>
80
68
  {/each}
81
69
  {#each iChunks as chunk}
82
- <Event {chunk} {gridEl}/>
70
+ <Event {chunk}/>
83
71
  {/each}
84
72
  </div>
85
73
  </div>
86
74
 
87
- {#if $_popupDay}
88
- <Popup {gridEl} {chunks}/>
75
+ {#if popupDay}
76
+ <Popup/>
89
77
  {/if}
90
78
  </section>
@@ -0,0 +1,102 @@
1
+ import {untrack} from 'svelte';
2
+ import {addDay, bgEvent, cloneDate, createAllDayChunks, datesEqual, outsideRange, prepareAllDayChunks} from '#lib';
3
+
4
+ export function colsCount(mainState) {
5
+ return () => {
6
+ // Dependencies
7
+ let {options: {hiddenDays}} = mainState;
8
+
9
+ let count;
10
+
11
+ untrack(() => count = 7 - hiddenDays.length);
12
+
13
+ return count;
14
+ };
15
+ }
16
+
17
+ export function grid(mainState, viewState) {
18
+ return () => {
19
+ // Dependencies
20
+ let {options: {highlightedDates, validRange}, viewDates} = mainState;
21
+ let {colsCount} = viewState;
22
+
23
+ let grid = [];
24
+
25
+ untrack(() => {
26
+ let days = [];
27
+ let gridColumn = 1;
28
+ let gridRow = 1;
29
+ for (let date of viewDates) {
30
+ days.push({
31
+ gridColumn,
32
+ gridRow,
33
+ resource: undefined,
34
+ dayStart: date,
35
+ dayEnd: addDay(cloneDate(date)),
36
+ disabled: outsideRange(date, validRange),
37
+ highlight: highlightedDates.some(d => datesEqual(d, date))
38
+ });
39
+ if (gridColumn === colsCount) {
40
+ grid.push(days);
41
+ days = [];
42
+ gridColumn = 0;
43
+ ++ gridRow;
44
+ }
45
+ ++ gridColumn;
46
+ }
47
+ });
48
+
49
+ return grid;
50
+ }
51
+ }
52
+
53
+ export function eventChunks(mainState, viewState) {
54
+ return () => {
55
+ // Dependencies
56
+ let {filteredEvents} = mainState;
57
+ let {grid} = viewState;
58
+
59
+ let chunks = [];
60
+ let bgChunks = [];
61
+
62
+ untrack(() => {
63
+ for (let event of filteredEvents) {
64
+ for (let days of grid) {
65
+ if (bgEvent(event.display)) {
66
+ if (event.allDay) {
67
+ bgChunks = bgChunks.concat(createAllDayChunks(event, days));
68
+ }
69
+ } else {
70
+ chunks = chunks.concat(createAllDayChunks(event, days));
71
+ }
72
+ }
73
+ }
74
+ prepareAllDayChunks(chunks);
75
+ });
76
+
77
+ return {chunks, bgChunks};
78
+ };
79
+ }
80
+
81
+ export function iEventChunks(mainState, viewState) {
82
+ return () => {
83
+ // Dependencies
84
+ let {iEvents} = mainState;
85
+ let {grid} = viewState;
86
+
87
+ let iChunks = [];
88
+
89
+ for (let [, event] of iEvents) {
90
+ if (!event) {
91
+ continue;
92
+ }
93
+ untrack(() => {
94
+ for (let days of grid) {
95
+ iChunks = iChunks.concat(createAllDayChunks(event, days));
96
+ }
97
+ });
98
+ }
99
+
100
+ return iChunks;
101
+ };
102
+ }
@@ -1,42 +1,53 @@
1
- import {writable} from 'svelte/store';
2
- import {btnTextMonth, intl, themeView} from '#lib';
3
- import {colsCount} from './stores.js';
1
+ import {assign, btnTextMonth, nextClosestDay, prevClosestDay, themeView} from '#lib';
4
2
  import View from './View.svelte';
5
3
 
6
4
  export default {
7
5
  createOptions(options) {
8
- options.dayMaxEvents = false;
9
- options.dayCellFormat = {day: 'numeric'};
10
- options.dayPopoverFormat = {month: 'long', day: 'numeric', year: 'numeric'};
11
- options.moreLinkContent = undefined;
12
- options.weekNumbers = false;
13
- options.weekNumberContent = undefined;
14
- // Common options
15
- options.buttonText.dayGridMonth = 'month';
16
- options.buttonText.close = 'Close';
17
- options.theme.uniform = 'ec-uniform';
18
- options.theme.dayFoot = 'ec-day-foot';
19
- options.theme.otherMonth = 'ec-other-month';
20
- options.theme.popup = 'ec-popup';
21
- options.theme.weekNumber = 'ec-week-number';
22
- options.view = 'dayGridMonth';
23
- options.views.dayGridMonth = {
24
- buttonText: btnTextMonth,
25
- component: View,
26
- dayHeaderFormat: {weekday: 'short'},
27
- dayHeaderAriaLabelFormat: {weekday: 'long'},
28
- displayEventEnd: false,
29
- duration: {months: 1},
30
- theme: themeView('ec-day-grid ec-month-view'),
31
- titleFormat: {year: 'numeric', month: 'long'}
32
- };
33
- },
34
-
35
- createStores(state) {
36
- state._colsCount = colsCount(state);
37
- state._intlDayCell = intl(state.locale, state.dayCellFormat);
38
- state._intlDayPopover = intl(state.locale, state.dayPopoverFormat);
39
- state._hiddenChunks = writable({});
40
- state._popupDay = writable(null);
6
+ assign(options, {
7
+ dayMaxEvents: false,
8
+ dayCellFormat: {day: 'numeric'},
9
+ dayPopoverFormat: {month: 'long', day: 'numeric', year: 'numeric'},
10
+ moreLinkContent: undefined,
11
+ weekNumbers: false,
12
+ weekNumberContent: undefined,
13
+ // Common options
14
+ view: 'dayGridMonth'
15
+ });
16
+ assign(options.buttonText, {
17
+ dayGridMonth: 'month',
18
+ close: 'Close'
19
+ });
20
+ assign(options.theme, {
21
+ uniform: 'ec-uniform',
22
+ dayFoot: 'ec-day-foot',
23
+ otherMonth: 'ec-other-month',
24
+ popup: 'ec-popup',
25
+ weekNumber: 'ec-week-number'
26
+ });
27
+ assign(options.views, {
28
+ dayGridMonth: {
29
+ buttonText: btnTextMonth,
30
+ component: initViewComponent,
31
+ dayHeaderFormat: {weekday: 'short'},
32
+ dayHeaderAriaLabelFormat: {weekday: 'long'},
33
+ displayEventEnd: false,
34
+ duration: {months: 1},
35
+ theme: themeView('ec-day-grid ec-month-view'),
36
+ titleFormat: {year: 'numeric', month: 'long'}
37
+ }
38
+ });
41
39
  }
42
40
  }
41
+
42
+ function initViewComponent(mainState) {
43
+ mainState.features = ['day-grid'];
44
+ mainState.extensions.activeRange = (start, end) => {
45
+ // Dependencies
46
+ let {options: {firstDay}} = mainState;
47
+ return {
48
+ start: prevClosestDay(start, firstDay),
49
+ end: nextClosestDay(end, firstDay)
50
+ }
51
+ };
52
+ return View;
53
+ }