@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
@@ -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,55 +1,42 @@
1
1
  <script>
2
- import {getContext, tick} from 'svelte';
3
- import {
4
- addDuration, cloneDate, contentFrom, DAY_IN_SECONDS, identity, resizeObserver, runReposition, subtractDay,
5
- toSeconds
6
- } from '#lib';
7
- 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';
8
6
  import {ColHead, DayHeader} from '#components';
9
7
  import Day from './Day.svelte';
10
8
  import Event from './Event.svelte';
11
9
  import AllDayEvent from './AllDayEvent.svelte';
12
10
  import NowIndicator from './NowIndicator.svelte';
13
11
 
14
- let {header, nowIndicator, createGridFn} = $props();
12
+ let {header, nowIndicator, viewState} = $props();
15
13
 
16
- let {_activeRangeExt, _mainEl, _filteredEvents, _iEvents, _sidebarWidth, _slotLabelPeriodicity, _slotTimeLimits, _slots,
17
- _viewDates, allDayContent, allDaySlot, columnWidth, highlightedDates, nowIndicator: showNowIndicator,
18
- scrollTime, slotHeight, slotDuration, slotMaxTime, theme, validRange} = getContext('state');
19
-
20
- let headerHeight = $state(0);
21
- 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);
22
21
 
23
- let grid = $derived(createGridFn?.() ?? createGrid($_viewDates, $_slotTimeLimits, $validRange, $highlightedDates));
24
- let {chunks, bgChunks, allDayChunks, allDayBgChunks} = $derived(createEventChunks($_filteredEvents, grid));
25
- 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);
26
26
 
27
- $effect.pre(() => {
28
- $_activeRangeExt = ({start, end}) => {
29
- if ($slotMaxTime.days || $slotMaxTime.seconds > DAY_IN_SECONDS) {
30
- addDuration(subtractDay(end), $slotMaxTime);
31
- let start2 = subtractDay(cloneDate(end));
32
- if (start2 < start) {
33
- start = start2;
34
- }
35
- }
36
- return {start, end};
37
- };
38
- return () => {
39
- $_activeRangeExt = identity;
40
- };
41
- });
27
+ let headerHeight = $state(0);
28
+ let allDayText = $derived(createAllDayContent(allDayContent));
42
29
 
43
30
  // Handle scrollTime
44
31
  $effect(() => {
45
- $_viewDates;
46
- $scrollTime;
32
+ viewDates;
33
+ scrollTime;
47
34
  tick().then(scrollToTime);
48
35
  });
49
36
  function scrollToTime() {
50
- $_mainEl.scrollTop = (
51
- (toSeconds($scrollTime) - toSeconds($_slotTimeLimits.min)) / toSeconds($slotDuration) - 0.5
52
- ) * $slotHeight;
37
+ mainEl.scrollTop = (
38
+ (toSeconds(scrollTime) - toSeconds(slotTimeLimits.min)) / toSeconds(slotDuration) - 0.5
39
+ ) * slotHeight;
53
40
  }
54
41
 
55
42
  // Events reposition
@@ -61,22 +48,22 @@
61
48
  </script>
62
49
 
63
50
  <section
64
- bind:this={$_mainEl}
65
- class="{$theme.main}"
51
+ bind:this={mainState.mainEl}
52
+ class="{theme.main}"
66
53
  style:--ec-grid-cols="{grid.length * grid[0].length}"
67
54
  style:--ec-col-group-span="{grid[0].length}"
68
- style:--ec-col-width="{$columnWidth ?? 'minmax(0, 1fr)'}"
69
- style:--ec-slot-label-periodicity="{$_slotLabelPeriodicity}"
70
- 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"
71
58
  style:--ec-header-height="{headerHeight}px"
72
- style:--ec-sidebar-width="{$_sidebarWidth}px"
59
+ style:--ec-sidebar-width="{sidebarWidth}px"
73
60
  {@attach resizeObserver(reposition)}
74
61
  >
75
- <header bind:offsetHeight={headerHeight} class="{$theme.header}">
76
- <aside class="{$theme.sidebar}" bind:offsetWidth={$_sidebarWidth}></aside>
77
- <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">
78
65
  {#if header}
79
- {@render header(grid)}
66
+ {@render header()}
80
67
  {:else}
81
68
  {#each grid[0] as {dayStart: date, disabled, highlight}, i}
82
69
  <ColHead {date} colIndex={1 + i} {disabled} {highlight}>
@@ -86,17 +73,17 @@
86
73
  {/if}
87
74
  </div>
88
75
 
89
- {#if $allDaySlot}
90
- <div class="{$theme.allDay}">
91
- <aside class="{$theme.sidebar}" {@attach contentFrom(allDayText)}></aside>
92
- <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">
93
80
  {#each grid as days, i}
94
81
  {#each days as day, j}
95
82
  <Day {day} allDay noIeb={i + 1 === grid.length && j + 1 === days.length}/>
96
83
  {/each}
97
84
  {/each}
98
85
  </div>
99
- <div class="{$theme.events}">
86
+ <div class="{theme.events}">
100
87
  {#each allDayChunks as chunk, i}
101
88
  <!-- svelte-ignore binding_property_non_reactive -->
102
89
  <AllDayEvent bind:this={refs[i]} {chunk}/>
@@ -112,11 +99,11 @@
112
99
  {/if}
113
100
  </header>
114
101
 
115
- <div class="{$theme.body}" role="rowgroup">
116
- <aside class="{$theme.sidebar}" aria-hidden="true">
117
- {#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}
118
105
  <div
119
- class={[$theme.slot, !i && $theme.hidden]}
106
+ class={[theme.slot, !i && theme.hidden]}
120
107
  style:--ec-slot-label-periodicity={slot[2]}
121
108
  >
122
109
  <time
@@ -126,14 +113,14 @@
126
113
  </div>
127
114
  {/each}
128
115
  </aside>
129
- <div class="{$theme.grid}" role="row">
116
+ <div class="{theme.grid}" role="row">
130
117
  {#each grid as days, i}
131
118
  {#each days as day, j}
132
119
  <Day {day} noIeb={i + 1 === grid.length && j + 1 === days.length} noBeb/>
133
120
  {/each}
134
121
  {/each}
135
122
  </div>
136
- <div class="{$theme.events}">
123
+ <div class="{theme.events}">
137
124
  {#each chunks as chunk}
138
125
  <Event {chunk}/>
139
126
  {/each}
@@ -146,9 +133,9 @@
146
133
  </div>
147
134
  </div>
148
135
 
149
- {#if $showNowIndicator}
136
+ {#if showNowIndicator}
150
137
  {#if nowIndicator}
151
- {@render nowIndicator(grid)}
138
+ {@render nowIndicator()}
152
139
  {:else}
153
140
  <NowIndicator days={grid[0]}/>
154
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
+ }