@event-calendar/core 5.0.6 → 5.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (79) hide show
  1. package/README.md +15 -4
  2. package/dist/index.css +2 -2
  3. package/dist/index.js +2200 -2122
  4. package/package.json +2 -2
  5. package/src/Buttons.svelte +36 -37
  6. package/src/Calendar.svelte +34 -37
  7. package/src/Toolbar.svelte +4 -4
  8. package/src/lib/components/BaseDay.svelte +13 -10
  9. package/src/lib/components/BaseEvent.svelte +17 -17
  10. package/src/lib/components/ColHead.svelte +6 -6
  11. package/src/lib/components/DayHeader.svelte +3 -3
  12. package/src/lib/components/InteractableEvent.svelte +7 -8
  13. package/src/lib/derived.js +80 -0
  14. package/src/lib/index.js +1 -2
  15. package/src/lib/slots.js +16 -16
  16. package/src/lib/utils.js +4 -9
  17. package/src/lib/view.js +0 -8
  18. package/src/plugins/day-grid/Day.svelte +25 -23
  19. package/src/plugins/day-grid/Event.svelte +15 -13
  20. package/src/plugins/day-grid/Popup.svelte +12 -12
  21. package/src/plugins/day-grid/View.svelte +24 -33
  22. package/src/plugins/day-grid/derived.js +102 -0
  23. package/src/plugins/day-grid/index.js +47 -36
  24. package/src/plugins/day-grid/state.svelte.js +19 -0
  25. package/src/plugins/interaction/Action.svelte +108 -76
  26. package/src/plugins/interaction/Auxiliary.svelte +9 -38
  27. package/src/plugins/interaction/Pointer.svelte +12 -17
  28. package/src/plugins/interaction/Resizer.svelte +9 -7
  29. package/src/plugins/interaction/effects.js +37 -0
  30. package/src/plugins/interaction/index.js +44 -38
  31. package/src/plugins/interaction/lib/utils.js +1 -1
  32. package/src/plugins/interaction/state.svelte.js +12 -0
  33. package/src/plugins/list/Day.svelte +8 -7
  34. package/src/plugins/list/Event.svelte +3 -3
  35. package/src/plugins/list/View.svelte +17 -16
  36. package/src/plugins/list/index.js +51 -43
  37. package/src/plugins/list/state.svelte.js +8 -0
  38. package/src/plugins/resource-time-grid/Label.svelte +8 -8
  39. package/src/plugins/resource-time-grid/View.svelte +38 -17
  40. package/src/plugins/resource-time-grid/derived.js +67 -0
  41. package/src/plugins/resource-time-grid/index.js +34 -28
  42. package/src/plugins/resource-time-grid/state.svelte.js +21 -0
  43. package/src/plugins/resource-timeline/Day.svelte +9 -4
  44. package/src/plugins/resource-timeline/Event.svelte +7 -6
  45. package/src/plugins/resource-timeline/Expander.svelte +7 -6
  46. package/src/plugins/resource-timeline/NowIndicator.svelte +10 -11
  47. package/src/plugins/resource-timeline/View.svelte +45 -60
  48. package/src/plugins/resource-timeline/derived.js +167 -0
  49. package/src/plugins/resource-timeline/index.js +17 -21
  50. package/src/plugins/resource-timeline/lib.js +4 -65
  51. package/src/plugins/resource-timeline/state.svelte.js +18 -0
  52. package/src/plugins/time-grid/Day.svelte +7 -2
  53. package/src/plugins/time-grid/Event.svelte +6 -6
  54. package/src/plugins/time-grid/NowIndicator.svelte +10 -9
  55. package/src/plugins/time-grid/View.svelte +46 -55
  56. package/src/plugins/time-grid/derived.js +162 -0
  57. package/src/plugins/time-grid/index.js +31 -25
  58. package/src/plugins/time-grid/lib.js +18 -74
  59. package/src/plugins/time-grid/options.js +21 -16
  60. package/src/plugins/time-grid/state.svelte.js +44 -0
  61. package/src/storage/derived.js +144 -0
  62. package/src/storage/effects.js +156 -0
  63. package/src/storage/options.svelte.js +275 -0
  64. package/src/storage/state.svelte.js +69 -0
  65. package/src/styles/events.css +1 -1
  66. package/src/Auxiliary.svelte +0 -47
  67. package/src/lib/debounce.js +0 -20
  68. package/src/lib/stores.js +0 -63
  69. package/src/plugins/day-grid/lib.js +0 -61
  70. package/src/plugins/day-grid/stores.js +0 -5
  71. package/src/plugins/resource-time-grid/lib.js +0 -31
  72. package/src/plugins/resource-time-grid/stores.js +0 -34
  73. package/src/plugins/resource-timeline/Header.svelte +0 -44
  74. package/src/plugins/resource-timeline/Label.svelte +0 -38
  75. package/src/plugins/resource-timeline/stores.js +0 -48
  76. package/src/plugins/time-grid/stores.js +0 -49
  77. package/src/storage/options.js +0 -136
  78. package/src/storage/state.js +0 -168
  79. package/src/storage/stores.js +0 -234
@@ -1,16 +1,14 @@
1
- import {btnTextDay, btnTextMonth, btnTextWeek, themeView} from '#lib';
2
- import {dayTimeLimits, daySlots, nestedResources, monthView} from './stores.js';
1
+ import {btnTextDay, btnTextMonth, btnTextWeek, getPayload, themeView} from '#lib';
2
+ import {setExtensions} from '../time-grid/lib.js';
3
3
  import {createTRROptions, createTRRParsers} from '../time-grid/options.js';
4
- import {createTRRStores} from '../time-grid/stores.js';
5
4
  import {createRROptions} from '../resource-time-grid/options.js';
6
- import {createRRStores} from '../resource-time-grid/stores.js';
7
5
  import View from './View.svelte';
8
6
 
9
7
  export default {
10
8
  createOptions(options) {
11
9
  createTRROptions(options);
12
10
  createRROptions(options);
13
- options.slotWidth = 16;
11
+ options.slotWidth = 32;
14
12
  // Common options
15
13
  options.buttonText.resourceTimelineDay = 'timeline';
16
14
  options.buttonText.resourceTimelineWeek = 'timeline';
@@ -21,27 +19,23 @@ export default {
21
19
  options.view = 'resourceTimelineWeek';
22
20
  options.views.resourceTimelineDay = {
23
21
  buttonText: btnTextDay,
24
- component: View,
22
+ component: initViewComponent,
25
23
  displayEventEnd: false,
26
24
  dayHeaderFormat: {weekday: 'long'},
27
25
  duration: {days: 1},
28
- slotLabelInterval: '01:00',
29
- slotDuration: '00:15',
30
26
  theme: themeView('ec-resource ec-timeline ec-day-view'),
31
27
  titleFormat: {year: 'numeric', month: 'long', day: 'numeric'}
32
28
  };
33
29
  options.views.resourceTimelineWeek = {
34
30
  buttonText: btnTextWeek,
35
- component: View,
31
+ component: initViewComponent,
36
32
  displayEventEnd: false,
37
33
  duration: {weeks: 1},
38
- slotLabelInterval: '01:00',
39
- slotDuration: '00:15',
40
34
  theme: themeView('ec-resource ec-timeline ec-week-view')
41
35
  };
42
36
  options.views.resourceTimelineMonth = {
43
37
  buttonText: btnTextMonth,
44
- component: View,
38
+ component: initMonthViewComponent,
45
39
  displayEventEnd: false,
46
40
  dayHeaderFormat: {
47
41
  weekday: 'short',
@@ -56,14 +50,16 @@ export default {
56
50
 
57
51
  createParsers(parsers) {
58
52
  createTRRParsers(parsers);
59
- },
53
+ }
54
+ }
55
+
56
+ function initViewComponent(mainState) {
57
+ setExtensions(mainState);
58
+ return initMonthViewComponent(mainState);
59
+ }
60
60
 
61
- createStores(state) {
62
- createTRRStores(state);
63
- createRRStores(state);
64
- state._dayTimeLimits = dayTimeLimits(state); // flexible time limits per day
65
- state._daySlots = daySlots(state);
66
- state._monthView = monthView(state);
67
- state._nestedResources = nestedResources(state);
68
- }
61
+ function initMonthViewComponent(mainState) {
62
+ mainState.features = ['timeline'];
63
+ mainState.extensions.viewResources = resources => resources.filter(resource => !getPayload(resource).hidden);
64
+ return View;
69
65
  }
@@ -1,67 +1,6 @@
1
- import {
2
- addDay, addDuration, assign, bgEvent, cloneDate, createDuration, createEventChunk, datesEqual, eventIntersects, max,
3
- min, outsideRange
4
- } from '#lib';
1
+ import {assign, createDuration, createEventChunk, eventIntersects, max, min} from '#lib';
5
2
 
6
- export function createGrid($_viewDates, $_viewResources, $_dayTimeLimits, $validRange, $highlightedDates) {
7
- let grid = [];
8
- let gridRow = 1
9
- for (let resource of $_viewResources) {
10
- let days = [];
11
- let gridColumn = 1;
12
- for (let date of $_viewDates) {
13
- let slotTimeLimits = $_dayTimeLimits[date.getTime()];
14
- days.push({
15
- gridColumn,
16
- gridRow,
17
- resource,
18
- start: addDuration(cloneDate(date), slotTimeLimits.min),
19
- end: addDuration(cloneDate(date), slotTimeLimits.max),
20
- dayStart: date,
21
- dayEnd: addDay(cloneDate(date)),
22
- disabled: outsideRange(date, $validRange),
23
- highlight: $highlightedDates.some(d => datesEqual(d, date))
24
- });
25
- ++ gridColumn;
26
- }
27
- grid.push(days);
28
- ++ gridRow;
29
- }
30
- return grid;
31
- }
32
-
33
- export function createEventChunks($_filteredEvents, grid) {
34
- let chunks = [];
35
- let bgChunks = [];
36
- for (let event of $_filteredEvents) {
37
- for (let days of grid) {
38
- if (bgEvent(event.display)) {
39
- bgChunks = bgChunks.concat(createChunks(event, days));
40
- } else {
41
- chunks = chunks.concat(createChunks(event, days));
42
- }
43
- }
44
- }
45
- prepareChunks(chunks);
46
-
47
- return {chunks, bgChunks};
48
- }
49
-
50
- export function createIEventChunks($_iEvents, grid) {
51
- let iChunks = [];
52
- for (let event of $_iEvents) {
53
- if (!event) {
54
- continue;
55
- }
56
- for (let days of grid) {
57
- iChunks = iChunks.concat(createChunks(event, days));
58
- }
59
- }
60
-
61
- return iChunks;
62
- }
63
-
64
- function createChunks(event, days) {
3
+ export function createChunks(event, days) {
65
4
  let dates = [];
66
5
  let firstStart;
67
6
  let lastEnd;
@@ -131,6 +70,6 @@ export function repositionEvent(chunk, height, monthView) {
131
70
  return top;
132
71
  }
133
72
 
134
- export function getSlotTimeLimits($_dayTimeLimits, date) {
135
- return $_dayTimeLimits[date.getTime()] ?? {min: createDuration(0), max: createDuration('24:00:00')};
73
+ export function getSlotTimeLimits(dayTimeLimits, date) {
74
+ return dayTimeLimits[date.getTime()] ?? {min: createDuration(0), max: createDuration('24:00:00')};
136
75
  }
@@ -0,0 +1,18 @@
1
+ import {TRRState} from '../time-grid/state.svelte.js';
2
+ import {RRState} from '../resource-time-grid/state.svelte.js';
3
+ import {daySlots, dayTimeLimits, eventChunks, grid, iEventChunks, monthView, nestedResources} from './derived.js';
4
+
5
+ export default class ViewState extends RRState(TRRState()) {
6
+ constructor(mainState) {
7
+ super(mainState);
8
+ this.dayTimeLimits = $derived.by(dayTimeLimits(mainState)); // flexible time limits per day
9
+ this.daySlots = $derived.by(daySlots(mainState, this));
10
+ this.grid = $derived.by(grid(mainState, this));
11
+ let {chunks, bgChunks} = $derived.by(eventChunks(mainState, this));
12
+ this.chunks = $derived(chunks);
13
+ this.bgChunks = $derived(bgChunks);
14
+ this.iChunks = $derived.by(iEventChunks(mainState, this));
15
+ this.monthView = $derived.by(monthView(mainState));
16
+ this.nestedResources = $derived.by(nestedResources(mainState));
17
+ }
18
+ }
@@ -5,7 +5,8 @@
5
5
 
6
6
  let {day, allDay = false, noIeb, noBeb} = $props();
7
7
 
8
- let {slotDuration, slotHeight} = getContext('state');
8
+ let {options: {slotHeight}} = $derived(getContext('state'));
9
+ let {snap} = $derived(getContext('view-state'));
9
10
 
10
11
  let {dayStart: date, start, resource, disabled, highlight} = $derived(day);
11
12
 
@@ -17,7 +18,11 @@
17
18
  } else {
18
19
  let dayRect = rect(el);
19
20
  let scaleY = dayRect.height / el.offsetHeight;
20
- return addDuration(cloneDate(start), $slotDuration, floor((y - dayRect.top) / ($slotHeight * scaleY)));
21
+ return addDuration(
22
+ cloneDate(start),
23
+ snap.duration,
24
+ floor((y - dayRect.top) / (slotHeight * snap.ratio * scaleY))
25
+ );
21
26
  }
22
27
  }
23
28
  </script>
@@ -5,14 +5,14 @@
5
5
 
6
6
  let {chunk} = $props();
7
7
 
8
- let {slotEventOverlap, slotDuration, slotHeight} = getContext('state');
8
+ let {options: {slotEventOverlap, slotDuration, slotHeight}} = $derived(getContext('state'));
9
9
 
10
10
  // Style
11
11
  let styles = $derived(style => {
12
- let step = toSeconds($slotDuration);
13
- let top = chunk.top / step * $slotHeight;
14
- let height = chunk.height / step * $slotHeight || $slotHeight;
15
- let maxHeight = chunk.maxHeight / step * $slotHeight;
12
+ let step = toSeconds(slotDuration);
13
+ let top = chunk.top / step * slotHeight;
14
+ let height = chunk.height / step * slotHeight || slotHeight;
15
+ let maxHeight = chunk.maxHeight / step * slotHeight;
16
16
  style['grid-column'] = chunk.gridColumn;
17
17
  style['inset-block-start'] = `${top}px`;
18
18
  style['min-block-size'] = `${height}px`;
@@ -23,7 +23,7 @@
23
23
  let groupColumns = chunk.group.columns.length;
24
24
  style['z-index'] = `${chunk.groupColumn + 1}`;
25
25
  style['inset-inline-start'] = `calc((${maxWidth}) / ${groupColumns} * ${chunk.groupColumn})`;
26
- style['inline-size'] = `calc((${maxWidth}) / ${groupColumns} * ${($slotEventOverlap ? 0.5 * (1 + groupColumns - chunk.groupColumn) : 1)})`;
26
+ style['inline-size'] = `calc((${maxWidth}) / ${groupColumns} * ${(slotEventOverlap ? 0.5 * (1 + groupColumns - chunk.groupColumn) : 1)})`;
27
27
  }
28
28
  return style;
29
29
  });
@@ -4,39 +4,40 @@
4
4
 
5
5
  let {days, span = 1} = $props();
6
6
 
7
- let {_mainEl, _now, _today, _sidebarWidth, slotDuration, slotHeight, theme} = getContext('state');
7
+ let {mainEl, now, today, options: {slotDuration, slotHeight, theme}} = $derived(getContext('state'));
8
+ let {sidebarWidth} = $derived(getContext('view-state'));
8
9
 
9
10
  // Layout
10
11
  let {gridColumn, start, end} = $derived.by(() => {
11
12
  for (let day of days) {
12
- if (datesEqual(day.dayStart, $_today)) {
13
+ if (datesEqual(day.dayStart, today)) {
13
14
  return day;
14
15
  }
15
16
  }
16
17
  return {};
17
18
  });
18
19
  let top = $derived.by(() => {
19
- if ($_now < start || $_now > end) {
20
+ if (now < start || now > end) {
20
21
  return null;
21
22
  }
22
- let step = toSeconds($slotDuration);
23
- return ($_now - start) / 1000 / step * $slotHeight;
23
+ let step = toSeconds(slotDuration);
24
+ return (now - start) / 1000 / step * slotHeight;
24
25
  });
25
26
 
26
27
  // Observe intersections
27
28
  let observerOptions = $derived({
28
- root: $_mainEl,
29
- rootMargin: isRtl() ? `0px -${$_sidebarWidth + 5.5}px 0px 0px` : `0px 0px 0px -${$_sidebarWidth + 5.5}px`,
29
+ root: mainEl,
30
+ rootMargin: isRtl() ? `0px -${sidebarWidth + 5.5}px 0px 0px` : `0px 0px 0px -${sidebarWidth + 5.5}px`,
30
31
  threshold: 0.0,
31
32
  });
32
33
  function onIntersect(el, entry) {
33
- el.classList.toggle($theme.hidden, !entry.isIntersecting);
34
+ el.classList.toggle(theme.hidden, !entry.isIntersecting);
34
35
  }
35
36
  </script>
36
37
 
37
38
  {#if gridColumn && top !== null}
38
39
  <div {@attach intersectionObserver(onIntersect, observerOptions)}
39
- class="{$theme.nowIndicator}"
40
+ class="{theme.nowIndicator}"
40
41
  style:grid-column="{gridColumn + 1} / span {span}"
41
42
  style:inset-block-start="{top}px"
42
43
  ></div>
@@ -1,51 +1,42 @@
1
1
  <script>
2
- import {getContext, tick} from 'svelte';
3
- import {
4
- addDuration, cloneDate, contentFrom, DAY_IN_SECONDS, resizeObserver, runReposition, subtractDay, toSeconds
5
- } from '#lib';
6
- import {createAllDayContent, createGrid, createEventChunks, createIEventChunks} from './lib.js';
2
+ import {getContext, setContext, tick} from 'svelte';
3
+ import {contentFrom, resizeObserver, runReposition, toSeconds} from '#lib';
4
+ import {createAllDayContent} from './lib.js';
5
+ import ViewState from './state.svelte.js';
7
6
  import {ColHead, DayHeader} from '#components';
8
7
  import Day from './Day.svelte';
9
8
  import Event from './Event.svelte';
10
9
  import AllDayEvent from './AllDayEvent.svelte';
11
10
  import NowIndicator from './NowIndicator.svelte';
12
11
 
13
- let {header, nowIndicator, createGridFn} = $props();
12
+ let {header, nowIndicator, viewState} = $props();
14
13
 
15
- let {_activeRangeExt, _mainEl, _filteredEvents, _iEvents, _sidebarWidth, _slotLabelPeriodicity, _slotTimeLimits, _slots,
16
- _viewDates, allDayContent, allDaySlot, columnWidth, highlightedDates, nowIndicator: showNowIndicator,
17
- scrollTime, slotHeight, slotDuration, slotMaxTime, theme, validRange} = getContext('state');
18
-
19
- let headerHeight = $state(0);
20
- let allDayText = $derived(createAllDayContent($allDayContent));
14
+ let mainState = getContext('state');
15
+ // svelte-ignore state_referenced_locally
16
+ if (!viewState) {
17
+ viewState = new ViewState(mainState);
18
+ }
19
+ // svelte-ignore state_referenced_locally
20
+ setContext('view-state', viewState);
21
21
 
22
- let grid = $derived(createGridFn?.() ?? createGrid($_viewDates, $_slotTimeLimits, $validRange, $highlightedDates));
23
- let {chunks, bgChunks, allDayChunks, allDayBgChunks} = $derived(createEventChunks($_filteredEvents, grid));
24
- let {iChunks, allDayIChunks} = $derived(createIEventChunks($_iEvents, grid));
22
+ let {mainEl, viewDates, options: {allDayContent, allDaySlot, columnWidth, nowIndicator: showNowIndicator,
23
+ scrollTime, slotHeight, slotDuration, theme}} = $derived(mainState);
24
+ let {allDayChunks, allDayBgChunks, allDayIChunks, bgChunks, chunks, iChunks, grid, sidebarWidth, slots,
25
+ slotLabelPeriodicity, slotTimeLimits} = $derived(viewState);
25
26
 
26
- $effect.pre(() => {
27
- $_activeRangeExt = ({start, end}) => {
28
- if ($slotMaxTime.days || $slotMaxTime.seconds > DAY_IN_SECONDS) {
29
- addDuration(subtractDay(end), $slotMaxTime);
30
- let start2 = subtractDay(cloneDate(end));
31
- if (start2 < start) {
32
- start = start2;
33
- }
34
- }
35
- return {start, end};
36
- };
37
- });
27
+ let headerHeight = $state(0);
28
+ let allDayText = $derived(createAllDayContent(allDayContent));
38
29
 
39
30
  // Handle scrollTime
40
31
  $effect(() => {
41
- $_viewDates;
42
- $scrollTime;
32
+ viewDates;
33
+ scrollTime;
43
34
  tick().then(scrollToTime);
44
35
  });
45
36
  function scrollToTime() {
46
- $_mainEl.scrollTop = (
47
- (toSeconds($scrollTime) - toSeconds($_slotTimeLimits.min)) / toSeconds($slotDuration) - 0.5
48
- ) * $slotHeight;
37
+ mainEl.scrollTop = (
38
+ (toSeconds(scrollTime) - toSeconds(slotTimeLimits.min)) / toSeconds(slotDuration) - 0.5
39
+ ) * slotHeight;
49
40
  }
50
41
 
51
42
  // Events reposition
@@ -57,22 +48,22 @@
57
48
  </script>
58
49
 
59
50
  <section
60
- bind:this={$_mainEl}
61
- class="{$theme.main}"
51
+ bind:this={mainState.mainEl}
52
+ class="{theme.main}"
62
53
  style:--ec-grid-cols="{grid.length * grid[0].length}"
63
54
  style:--ec-col-group-span="{grid[0].length}"
64
- style:--ec-col-width="{$columnWidth ?? 'minmax(0, 1fr)'}"
65
- style:--ec-slot-label-periodicity="{$_slotLabelPeriodicity}"
66
- style:--ec-slot-height="{$slotHeight}px"
55
+ style:--ec-col-width="{columnWidth ?? 'minmax(0, 1fr)'}"
56
+ style:--ec-slot-label-periodicity="{slotLabelPeriodicity}"
57
+ style:--ec-slot-height="{slotHeight}px"
67
58
  style:--ec-header-height="{headerHeight}px"
68
- style:--ec-sidebar-width="{$_sidebarWidth}px"
59
+ style:--ec-sidebar-width="{sidebarWidth}px"
69
60
  {@attach resizeObserver(reposition)}
70
61
  >
71
- <header bind:offsetHeight={headerHeight} class="{$theme.header}">
72
- <aside class="{$theme.sidebar}" bind:offsetWidth={$_sidebarWidth}></aside>
73
- <div class="{$theme.grid}" role="row">
62
+ <header bind:offsetHeight={headerHeight} class="{theme.header}">
63
+ <aside class="{theme.sidebar}" bind:offsetWidth={viewState.sidebarWidth}></aside>
64
+ <div class="{theme.grid}" role="row">
74
65
  {#if header}
75
- {@render header(grid)}
66
+ {@render header()}
76
67
  {:else}
77
68
  {#each grid[0] as {dayStart: date, disabled, highlight}, i}
78
69
  <ColHead {date} colIndex={1 + i} {disabled} {highlight}>
@@ -82,17 +73,17 @@
82
73
  {/if}
83
74
  </div>
84
75
 
85
- {#if $allDaySlot}
86
- <div class="{$theme.allDay}">
87
- <aside class="{$theme.sidebar}" {@attach contentFrom(allDayText)}></aside>
88
- <div class="{$theme.grid}" role="row">
76
+ {#if allDaySlot}
77
+ <div class="{theme.allDay}">
78
+ <aside class="{theme.sidebar}" {@attach contentFrom(allDayText)}></aside>
79
+ <div class="{theme.grid}" role="row">
89
80
  {#each grid as days, i}
90
81
  {#each days as day, j}
91
82
  <Day {day} allDay noIeb={i + 1 === grid.length && j + 1 === days.length}/>
92
83
  {/each}
93
84
  {/each}
94
85
  </div>
95
- <div class="{$theme.events}">
86
+ <div class="{theme.events}">
96
87
  {#each allDayChunks as chunk, i}
97
88
  <!-- svelte-ignore binding_property_non_reactive -->
98
89
  <AllDayEvent bind:this={refs[i]} {chunk}/>
@@ -108,11 +99,11 @@
108
99
  {/if}
109
100
  </header>
110
101
 
111
- <div class="{$theme.body}" role="rowgroup">
112
- <aside class="{$theme.sidebar}" aria-hidden="true">
113
- {#each $_slots as slot, i}
102
+ <div class="{theme.body}" role="rowgroup">
103
+ <aside class="{theme.sidebar}" aria-hidden="true">
104
+ {#each slots as slot, i}
114
105
  <div
115
- class={[$theme.slot, !i && $theme.hidden]}
106
+ class={[theme.slot, !i && theme.hidden]}
116
107
  style:--ec-slot-label-periodicity={slot[2]}
117
108
  >
118
109
  <time
@@ -122,14 +113,14 @@
122
113
  </div>
123
114
  {/each}
124
115
  </aside>
125
- <div class="{$theme.grid}" role="row">
116
+ <div class="{theme.grid}" role="row">
126
117
  {#each grid as days, i}
127
118
  {#each days as day, j}
128
119
  <Day {day} noIeb={i + 1 === grid.length && j + 1 === days.length} noBeb/>
129
120
  {/each}
130
121
  {/each}
131
122
  </div>
132
- <div class="{$theme.events}">
123
+ <div class="{theme.events}">
133
124
  {#each chunks as chunk}
134
125
  <Event {chunk}/>
135
126
  {/each}
@@ -142,9 +133,9 @@
142
133
  </div>
143
134
  </div>
144
135
 
145
- {#if $showNowIndicator}
136
+ {#if showNowIndicator}
146
137
  {#if nowIndicator}
147
- {@render nowIndicator(grid)}
138
+ {@render nowIndicator()}
148
139
  {:else}
149
140
  <NowIndicator days={grid[0]}/>
150
141
  {/if}
@@ -0,0 +1,162 @@
1
+ import {untrack} from 'svelte';
2
+ import {
3
+ addDay, addDuration, bgEvent, ceil, cloneDate, createAllDayChunks, createDate, createSlots, createSlotTimeLimits,
4
+ datesEqual, outsideRange, prepareAllDayChunks, setMidnight, toSeconds
5
+ } from '#lib';
6
+ import {createChunks, groupChunks} from './lib.js';
7
+
8
+ export function grid(mainState, viewState) {
9
+ return () => {
10
+ // Dependencies
11
+ let {viewDates, options: {highlightedDates, validRange}} = mainState;
12
+ let {slotTimeLimits} = viewState;
13
+
14
+ let days = [];
15
+
16
+ untrack(() => {
17
+ let gridColumn = 1;
18
+ for (let date of viewDates) {
19
+ days.push({
20
+ gridColumn,
21
+ gridRow: 1,
22
+ resource: undefined,
23
+ start: addDuration(cloneDate(date), slotTimeLimits.min),
24
+ end: addDuration(cloneDate(date), slotTimeLimits.max),
25
+ dayStart: date,
26
+ dayEnd: addDay(cloneDate(date)),
27
+ disabled: outsideRange(date, validRange),
28
+ highlight: highlightedDates.some(d => datesEqual(d, date))
29
+ });
30
+ ++gridColumn;
31
+ }
32
+ });
33
+
34
+ return [days];
35
+ };
36
+ }
37
+
38
+ export function eventChunks(mainState, viewState) {
39
+ return () => {
40
+ // Dependencies
41
+ let {filteredEvents} = mainState;
42
+ let {grid} = viewState;
43
+
44
+ let chunks = [];
45
+ let bgChunks = [];
46
+ let allDayChunks = [];
47
+ let allDayBgChunks = [];
48
+
49
+ untrack(() => {
50
+ for (let event of filteredEvents) {
51
+ for (let days of grid) {
52
+ if (bgEvent(event.display)) {
53
+ bgChunks = bgChunks.concat(createChunks(event, days));
54
+ if (event.allDay) {
55
+ allDayBgChunks = allDayBgChunks.concat(createAllDayChunks(event, days));
56
+ }
57
+ } else {
58
+ if (event.allDay) {
59
+ allDayChunks = allDayChunks.concat(createAllDayChunks(event, days));
60
+ } else {
61
+ chunks = chunks.concat(createChunks(event, days));
62
+ }
63
+ }
64
+ }
65
+ }
66
+ groupChunks(chunks);
67
+ prepareAllDayChunks(allDayChunks);
68
+ });
69
+
70
+ return {chunks, bgChunks, allDayChunks, allDayBgChunks};
71
+ };
72
+ }
73
+
74
+ export function iEventChunks(mainState, viewState) {
75
+ return () => {
76
+ // Dependencies
77
+ let {iEvents} = mainState;
78
+ let {grid} = viewState;
79
+
80
+ let iChunks = [];
81
+ let allDayIChunks = [];
82
+
83
+ for (let [, event] of iEvents) {
84
+ if (!event) {
85
+ continue;
86
+ }
87
+ untrack(() => {
88
+ for (let days of grid) {
89
+ if (event.allDay) {
90
+ allDayIChunks = allDayIChunks.concat(createAllDayChunks(event, days));
91
+ } else {
92
+ iChunks = iChunks.concat(createChunks(event, days));
93
+ }
94
+ }
95
+ });
96
+ }
97
+
98
+ return {iChunks, allDayIChunks};
99
+ };
100
+ }
101
+
102
+ export function slotTimeLimits(mainState) {
103
+ return () => {
104
+ // Dependencies
105
+ let {filteredEvents, viewDates, options: {flexibleSlotTimeLimits, slotMinTime, slotMaxTime}} = mainState;
106
+
107
+ let limits;
108
+
109
+ untrack(() => {
110
+ limits = createSlotTimeLimits(slotMinTime, slotMaxTime, flexibleSlotTimeLimits, viewDates, filteredEvents);
111
+ });
112
+
113
+ return limits;
114
+ };
115
+ }
116
+
117
+ export function slotLabelPeriodicity(mainState) {
118
+ return () => {
119
+ // Dependencies
120
+ let {options: {slotDuration, slotLabelInterval}} = mainState;
121
+
122
+ let periodicity;
123
+
124
+ untrack(() => {
125
+ periodicity = slotLabelInterval === undefined
126
+ ? toSeconds(slotDuration) < 3600 ? 2 : 1
127
+ : (ceil(toSeconds(slotLabelInterval) / toSeconds(slotDuration)) || 1)
128
+ });
129
+
130
+ return periodicity;
131
+ };
132
+ }
133
+
134
+ export function slots(mainState, viewState) {
135
+ return () => {
136
+ // Dependencies
137
+ let {options: {slotDuration}} = mainState;
138
+ let {intlSlotLabel, slotLabelPeriodicity, slotTimeLimits} = viewState;
139
+
140
+ let slots;
141
+
142
+ untrack(() => {
143
+ slots = createSlots(setMidnight(createDate()), slotDuration, slotLabelPeriodicity, slotTimeLimits, intlSlotLabel);
144
+ });
145
+
146
+ return slots;
147
+ };
148
+ }
149
+
150
+ export function snap(mainState) {
151
+ return () => {
152
+ // Dependencies
153
+ let {options: {slotDuration, snapDuration}} = mainState;
154
+
155
+ snapDuration ??= slotDuration;
156
+
157
+ return {
158
+ duration: snapDuration,
159
+ ratio: toSeconds(snapDuration) / toSeconds(slotDuration)
160
+ };
161
+ };
162
+ }