@event-calendar/core 4.7.1 → 5.0.1

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 (93) hide show
  1. package/README.md +29 -51
  2. package/dist/index.css +636 -731
  3. package/dist/index.js +2576 -3178
  4. package/package.json +2 -2
  5. package/src/Auxiliary.svelte +2 -13
  6. package/src/Buttons.svelte +62 -52
  7. package/src/Calendar.svelte +9 -3
  8. package/src/lib/a11y.js +2 -2
  9. package/src/lib/attachments.js +61 -0
  10. package/src/lib/chunks.js +117 -0
  11. package/src/lib/components/BaseDay.svelte +50 -0
  12. package/src/lib/components/BaseEvent.svelte +3 -3
  13. package/src/lib/components/ColHead.svelte +34 -0
  14. package/src/lib/components/DayHeader.svelte +14 -0
  15. package/src/lib/components/InteractableEvent.svelte +1 -3
  16. package/src/lib/components/index.js +3 -0
  17. package/src/lib/date.js +1 -1
  18. package/src/lib/dom.js +0 -4
  19. package/src/lib/events.js +10 -134
  20. package/src/lib/index.js +3 -2
  21. package/src/lib/{times.js → slots.js} +14 -19
  22. package/src/lib/stores.js +0 -33
  23. package/src/lib/utils.js +11 -2
  24. package/src/lib/view.js +0 -4
  25. package/src/plugins/day-grid/Day.svelte +36 -129
  26. package/src/plugins/day-grid/Event.svelte +42 -41
  27. package/src/plugins/day-grid/Popup.svelte +65 -48
  28. package/src/plugins/day-grid/View.svelte +76 -4
  29. package/src/plugins/day-grid/index.js +5 -5
  30. package/src/plugins/day-grid/lib.js +61 -0
  31. package/src/plugins/day-grid/stores.js +2 -20
  32. package/src/plugins/interaction/Action.svelte +44 -43
  33. package/src/plugins/interaction/Auxiliary.svelte +4 -4
  34. package/src/plugins/interaction/Pointer.svelte +8 -12
  35. package/src/plugins/interaction/Resizer.svelte +2 -2
  36. package/src/plugins/interaction/lib/utils.js +1 -5
  37. package/src/plugins/list/Day.svelte +8 -24
  38. package/src/plugins/list/View.svelte +39 -2
  39. package/src/plugins/resource-time-grid/Label.svelte +2 -2
  40. package/src/plugins/resource-time-grid/View.svelte +55 -83
  41. package/src/plugins/resource-time-grid/index.js +19 -10
  42. package/src/plugins/resource-time-grid/lib.js +31 -0
  43. package/src/plugins/resource-time-grid/options.js +10 -0
  44. package/src/plugins/resource-time-grid/stores.js +34 -0
  45. package/src/plugins/resource-timeline/Day.svelte +10 -73
  46. package/src/plugins/resource-timeline/Event.svelte +14 -23
  47. package/src/plugins/resource-timeline/Header.svelte +5 -5
  48. package/src/plugins/resource-timeline/Label.svelte +4 -12
  49. package/src/plugins/resource-timeline/NowIndicator.svelte +33 -28
  50. package/src/plugins/resource-timeline/View.svelte +129 -14
  51. package/src/plugins/resource-timeline/index.js +26 -23
  52. package/src/plugins/resource-timeline/lib.js +115 -118
  53. package/src/plugins/resource-timeline/stores.js +11 -7
  54. package/src/plugins/time-grid/AllDayEvent.svelte +31 -0
  55. package/src/plugins/time-grid/Day.svelte +11 -99
  56. package/src/plugins/time-grid/Event.svelte +18 -20
  57. package/src/plugins/time-grid/NowIndicator.svelte +35 -10
  58. package/src/plugins/time-grid/View.svelte +129 -35
  59. package/src/plugins/time-grid/index.js +10 -8
  60. package/src/plugins/time-grid/lib.js +142 -0
  61. package/src/plugins/time-grid/options.js +57 -0
  62. package/src/plugins/time-grid/stores.js +41 -8
  63. package/src/storage/options.js +4 -39
  64. package/src/storage/state.js +1 -4
  65. package/src/storage/stores.js +43 -12
  66. package/src/styles/days.css +91 -0
  67. package/src/styles/events.css +180 -0
  68. package/src/styles/index.css +126 -0
  69. package/src/styles/now-indicator.css +35 -0
  70. package/src/styles/popup.css +30 -0
  71. package/src/styles/sidebar.css +60 -0
  72. package/src/styles/slots.css +42 -0
  73. package/src/styles/theme.css +68 -0
  74. package/src/styles/toolbar.css +88 -0
  75. package/src/lib/actions.js +0 -52
  76. package/src/plugins/day-grid/Body.svelte +0 -54
  77. package/src/plugins/day-grid/Header.svelte +0 -20
  78. package/src/plugins/day-grid/Week.svelte +0 -60
  79. package/src/plugins/list/Body.svelte +0 -44
  80. package/src/plugins/resource-timeline/Body.svelte +0 -67
  81. package/src/plugins/resource-timeline/Days.svelte +0 -72
  82. package/src/plugins/resource-timeline/Sidebar.svelte +0 -35
  83. package/src/plugins/time-grid/Body.svelte +0 -43
  84. package/src/plugins/time-grid/Section.svelte +0 -29
  85. package/src/plugins/time-grid/all-day/Day.svelte +0 -65
  86. package/src/plugins/time-grid/all-day/Event.svelte +0 -37
  87. package/src/plugins/time-grid/all-day/Week.svelte +0 -65
  88. package/src/plugins/time-grid/utils.js +0 -58
  89. package/src/styles/day-grid.scss +0 -51
  90. package/src/styles/index.scss +0 -553
  91. package/src/styles/theme.scss +0 -95
  92. package/src/styles/time-grid.scss +0 -83
  93. package/src/styles/timeline.scss +0 -152
@@ -1,109 +1,21 @@
1
1
  <script>
2
- import {getContext, onMount} from 'svelte';
3
- import {
4
- addDuration, bgEvent, cloneDate, createEventChunk, datesEqual, eventIntersects, floor, outsideRange, rect,
5
- setPayload
6
- } from '#lib';
7
- import {groupEventChunks} from './utils.js';
8
- import Event from './Event.svelte';
9
- import NowIndicator from './NowIndicator.svelte';
2
+ import {getContext} from 'svelte';
3
+ import {addDuration, cloneDate, floor, rect} from '#lib';
4
+ import {BaseDay} from '#components';
10
5
 
11
- let {date, resource = undefined} = $props();
6
+ let {day, allDay = false} = $props();
12
7
 
13
- let {_filteredEvents, _iEvents, highlightedDates, nowIndicator, slotDuration, slotHeight, filterEventsWithResources,
14
- eventOrder, theme, resources, validRange, _interaction, _today, _slotTimeLimits} = getContext('state');
8
+ let {slotDuration, slotHeight} = getContext('state');
15
9
 
16
- let el = $state();
17
-
18
- let isToday = $derived(datesEqual(date, $_today));
19
- let highlight = $derived($highlightedDates.some(d => datesEqual(d, date)));
20
- let disabled = $derived(outsideRange(date, $validRange));
21
-
22
- let start = $derived(addDuration(cloneDate(date), $_slotTimeLimits.min));
23
- let end = $derived(addDuration(cloneDate(date), $_slotTimeLimits.max));
24
-
25
- let resourceFilter = $derived(resource ?? ($filterEventsWithResources ? $resources : undefined));
10
+ let {dayStart: date, start, resource, disabled, highlight} = $derived(day);
26
11
 
27
- let [chunks, bgChunks] = $derived.by(() => {
28
- if (disabled) {
29
- return [[], []];
30
- }
31
- let chunks = [];
32
- let bgChunks = [];
33
- for (let event of $_filteredEvents) {
34
- if ((!event.allDay || bgEvent(event.display)) && eventIntersects(event, start, end, resourceFilter)) {
35
- let chunk = createEventChunk(event, start, end);
36
- switch (event.display) {
37
- case 'background': bgChunks.push(chunk); break;
38
- default: chunks.push(chunk);
39
- }
40
- }
41
- }
42
- groupEventChunks(chunks, $eventOrder);
43
- return [chunks, bgChunks];
44
- });
45
-
46
- let iChunks = $derived.by(() => {
47
- if (disabled) {
48
- return [];
49
- }
50
- return $_iEvents.map(
51
- event => event && eventIntersects(event, start, end, resource) ? createEventChunk(event, start, end) : null
52
- );
53
- });
12
+ let el = $state();
54
13
 
55
14
  function dateFromPoint(x, y) {
56
- y -= rect(el).top;
57
- return {
58
- allDay: false,
59
- date: addDuration(
60
- addDuration(cloneDate(date), $_slotTimeLimits.min),
61
- $slotDuration,
62
- floor(y / $slotHeight)
63
- ),
64
- resource,
65
- dayEl: el,
66
- disabled
67
- };
15
+ return allDay
16
+ ? date
17
+ : addDuration(cloneDate(start), $slotDuration, floor((y - rect(el).top) / $slotHeight));
68
18
  }
69
-
70
- onMount(() => {
71
- setPayload(el, dateFromPoint);
72
- });
73
19
  </script>
74
20
 
75
- <div
76
- bind:this={el}
77
- class="{$theme.day} {$theme.weekdays?.[date.getUTCDay()]}{isToday ? ' ' + $theme.today : ''}{highlight ? ' ' + $theme.highlight : ''}{disabled ? ' ' + $theme.disabled : ''}"
78
- role="cell"
79
- onpointerdown={!disabled ? $_interaction.action?.select : undefined}
80
- >
81
- <div class="{$theme.bgEvents}">
82
- {#if !disabled}
83
- {#each bgChunks as chunk (chunk.event)}
84
- <Event {date} {chunk}/>
85
- {/each}
86
- {/if}
87
- </div>
88
- <div class="{$theme.events}">
89
- {#if !disabled}
90
- <!-- Pointer -->
91
- {#if iChunks[1]}
92
- <Event {date} chunk={iChunks[1]}/>
93
- {/if}
94
- {#each chunks as chunk (chunk.event)}
95
- <Event {date} {chunk}/>
96
- {/each}
97
- <!-- Drag, Resize & Select -->
98
- {#if iChunks[0] && !iChunks[0].event.allDay}
99
- <Event {date} chunk={iChunks[0]}/>
100
- {/if}
101
- {/if}
102
- </div>
103
- <div class="{$theme.extra}">
104
- <!-- Now indicator -->
105
- {#if $nowIndicator && isToday && !disabled}
106
- <NowIndicator />
107
- {/if}
108
- </div>
109
- </div>
21
+ <BaseDay bind:el {date} {allDay} {resource} {dateFromPoint} {disabled} {highlight}/>
@@ -1,31 +1,29 @@
1
1
  <script>
2
2
  import {getContext} from 'svelte';
3
- import {bgEvent, ghostEvent, helperEvent} from '#lib';
3
+ import {toSeconds} from '#lib';
4
4
  import {InteractableEvent} from '#components';
5
5
 
6
- let {date, chunk} = $props();
6
+ let {chunk} = $props();
7
7
 
8
- let {slotEventOverlap, slotDuration, slotHeight, _slotTimeLimits} = getContext('state');
9
-
10
- let display = $derived(chunk.event.display);
8
+ let {slotEventOverlap, slotDuration, slotHeight} = getContext('state');
11
9
 
12
10
  // Style
13
11
  let styles = $derived(style => {
14
- let step = $slotDuration.seconds;
15
- let offset = $_slotTimeLimits.min.seconds;
16
- let start = (chunk.start - date) / 1000;
17
- let end = (chunk.end - date) / 1000;
18
- let top = (start - offset) / step * $slotHeight;
19
- let height = (end - start) / step * $slotHeight || $slotHeight;
20
- let maxHeight = ($_slotTimeLimits.max.seconds - start) / step * $slotHeight;
21
- style['top'] = `${top}px`;
22
- style['min-height'] = `${height}px`;
23
- style['height'] = `${height}px`;
24
- style['max-height'] = `${maxHeight}px`;
25
- if (!bgEvent(display) && !helperEvent(display) || ghostEvent(display)) {
26
- style['z-index'] = `${chunk.column + 1}`;
27
- style['left'] = `${100 / chunk.group.columns.length * chunk.column}%`;
28
- style['width'] = `${100 / chunk.group.columns.length * ($slotEventOverlap ? 0.5 * (1 + chunk.group.columns.length - chunk.column) : 1)}%`;
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
+ style['grid-column'] = chunk.gridColumn;
17
+ style['inset-block-start'] = `${top}px`;
18
+ style['min-block-size'] = `${height}px`;
19
+ style['block-size'] = `${height}px`;
20
+ style['max-block-size'] = `${maxHeight}px`;
21
+ let maxWidth = '100% - var(--ec-event-col-gap)';
22
+ if (chunk.group) {
23
+ let groupColumns = chunk.group.columns.length;
24
+ style['z-index'] = `${chunk.groupColumn + 1}`;
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)})`;
29
27
  }
30
28
  return style;
31
29
  });
@@ -1,18 +1,43 @@
1
1
  <script>
2
2
  import {getContext} from 'svelte';
3
+ import {datesEqual, toSeconds, intersectionObserver} from '#lib';
3
4
 
4
- let {slotDuration, slotHeight, theme, _now, _today, _slotTimeLimits} = getContext('state');
5
+ let {days, span = 1} = $props();
5
6
 
6
- let start = $derived(($_now - $_today) / 1000);
7
- // Style
7
+ let {_mainEl, _now, _today, _sidebarWidth, slotDuration, slotHeight, theme} = getContext('state');
8
+
9
+ // Layout
10
+ let {gridColumn, start, end} = $derived.by(() => {
11
+ for (let day of days) {
12
+ if (datesEqual(day.dayStart, $_today)) {
13
+ return day;
14
+ }
15
+ }
16
+ return {};
17
+ });
8
18
  let top = $derived.by(() => {
9
- let step = $slotDuration.seconds;
10
- let offset = $_slotTimeLimits.min.seconds;
11
- return (start - offset) / step * $slotHeight;
19
+ if ($_now < start || $_now > end) {
20
+ return null;
21
+ }
22
+ let step = toSeconds($slotDuration);
23
+ return ($_now - start) / 1000 / step * $slotHeight;
24
+ });
25
+
26
+ // Observe intersections
27
+ let observerOptions = $derived({
28
+ root: $_mainEl,
29
+ rootMargin: `0px 0px 0px -${$_sidebarWidth + 5.5}px`,
30
+ threshold: 0.0,
12
31
  });
32
+ function onIntersect(el, entry) {
33
+ el.classList.toggle($theme.hidden, !entry.isIntersecting);
34
+ }
13
35
  </script>
14
36
 
15
- <div
16
- class="{$theme.nowIndicator}"
17
- style="top:{top}px"
18
- ></div>
37
+ {#if gridColumn && top !== null}
38
+ <div {@attach intersectionObserver(onIntersect, observerOptions)}
39
+ class="{$theme.nowIndicator}"
40
+ style:grid-column="{gridColumn + 1} / span {span}"
41
+ style:inset-block-start="{top}px"
42
+ ></div>
43
+ {/if}
@@ -1,43 +1,137 @@
1
1
  <script>
2
- import {getContext} from 'svelte';
3
- import {datesEqual, setContent, toISOString} from '#lib';
4
- import Section from './Section.svelte';
5
- import Body from './Body.svelte';
2
+ import {getContext, tick} from 'svelte';
3
+ import {contentFrom, resizeObserver, runReposition, toSeconds} from '#lib';
4
+ import {createAllDayContent, createGrid, createEventChunks, createIEventChunks} from './lib.js';
5
+ import {ColHead, DayHeader} from '#components';
6
6
  import Day from './Day.svelte';
7
- import Week from './all-day/Week.svelte';
7
+ import Event from './Event.svelte';
8
+ import AllDayEvent from './AllDayEvent.svelte';
9
+ import NowIndicator from './NowIndicator.svelte';
8
10
 
9
- let {_viewDates, _intlDayHeader, _intlDayHeaderAL, _today, allDaySlot, theme} = getContext('state');
11
+ let {header, nowIndicator, createGridFn} = $props();
12
+
13
+ let {_mainEl, _filteredEvents, _iEvents, _sidebarWidth, _slotLabelPeriodicity, _slotTimeLimits, _slots,
14
+ _viewDates, allDayContent, allDaySlot, columnWidth, highlightedDates, nowIndicator: showNowIndicator,
15
+ scrollTime, slotHeight, slotDuration, theme, validRange} = getContext('state');
16
+
17
+ let headerHeight = $state(0);
18
+ let allDayText = $derived(createAllDayContent($allDayContent));
19
+
20
+ let grid = $derived(createGridFn?.() ?? createGrid($_viewDates, $_slotTimeLimits, $validRange, $highlightedDates));
21
+ let {chunks, bgChunks, allDayChunks, allDayBgChunks} = $derived(createEventChunks($_filteredEvents, grid));
22
+ let {iChunks, allDayIChunks} = $derived(createIEventChunks($_iEvents, grid));
23
+
24
+ // Handle scrollTime
25
+ $effect(() => {
26
+ $_viewDates;
27
+ $scrollTime;
28
+ tick().then(scrollToTime);
29
+ });
30
+ function scrollToTime() {
31
+ $_mainEl.scrollTop = (
32
+ (toSeconds($scrollTime) - toSeconds($_slotTimeLimits.min)) / toSeconds($slotDuration) - 0.5
33
+ ) * $slotHeight;
34
+ }
35
+
36
+ // Events reposition
37
+ let refs = [];
38
+ function reposition() {
39
+ runReposition(refs, allDayChunks);
40
+ }
41
+ $effect(reposition);
10
42
  </script>
11
43
 
12
- <div class="{$theme.header}">
13
- <Section>
14
- {#each $_viewDates as date}
15
- <div
16
- class="{$theme.day} {$theme.weekdays?.[date.getUTCDay()]}{datesEqual(date, $_today) ? ' ' + $theme.today : ''}"
17
- role="columnheader"
18
- >
19
- <time
20
- datetime="{toISOString(date, 10)}"
21
- aria-label="{$_intlDayHeaderAL.format(date)}"
22
- use:setContent={$_intlDayHeader.format(date)}
23
- ></time>
44
+ <section
45
+ bind:this={$_mainEl}
46
+ class="{$theme.main}"
47
+ style:--ec-grid-cols="{grid.length * grid[0].length}"
48
+ style:--ec-col-group-span="{grid[0].length}"
49
+ style:--ec-col-width="{$columnWidth ?? 'minmax(0, 1fr)'}"
50
+ style:--ec-slot-label-periodicity="{$_slotLabelPeriodicity}"
51
+ style:--ec-slot-height="{$slotHeight}px"
52
+ style:--ec-header-height="{headerHeight}px"
53
+ style:--ec-sidebar-width="{$_sidebarWidth}px"
54
+ {@attach resizeObserver(reposition)}
55
+ >
56
+ <header bind:offsetHeight={headerHeight} class="{$theme.header}">
57
+ <aside class="{$theme.sidebar}" bind:offsetWidth={$_sidebarWidth}></aside>
58
+ <div class="{$theme.grid}" role="row">
59
+ {#if header}
60
+ {@render header(grid)}
61
+ {:else}
62
+ {#each grid[0] as {dayStart: date, disabled, highlight}, i}
63
+ <ColHead {date} colIndex={1 + i} {disabled} {highlight}>
64
+ <DayHeader {date}/>
65
+ </ColHead>
66
+ {/each}
67
+ {/if}
68
+ </div>
69
+
70
+ {#if $allDaySlot}
71
+ <div class="{$theme.allDay}">
72
+ <aside class="{$theme.sidebar}" {@attach contentFrom(allDayText)}></aside>
73
+ <div class="{$theme.grid}" role="row">
74
+ {#each grid as days}
75
+ {#each days as day}
76
+ <Day {day} allDay/>
77
+ {/each}
78
+ {/each}
79
+ </div>
80
+ <div class="{$theme.events}">
81
+ {#each allDayChunks as chunk, i}
82
+ <!-- svelte-ignore binding_property_non_reactive -->
83
+ <AllDayEvent bind:this={refs[i]} {chunk}/>
84
+ {/each}
85
+ {#each allDayBgChunks as chunk}
86
+ <AllDayEvent {chunk}/>
87
+ {/each}
88
+ {#each allDayIChunks as chunk}
89
+ <AllDayEvent {chunk}/>
90
+ {/each}
91
+ </div>
24
92
  </div>
25
- {/each}
26
- </Section>
27
- <div class="{$theme.hiddenScroll}"></div>
28
- </div>
29
- {#if $allDaySlot}
30
- <div class="{$theme.allDay}">
31
- <div class="{$theme.content}">
32
- <Section>
33
- <Week dates={$_viewDates}/>
34
- </Section>
35
- <div class="{$theme.hiddenScroll}"></div>
93
+ {/if}
94
+ </header>
95
+
96
+ <div class="{$theme.body}" role="rowgroup">
97
+ <aside class="{$theme.sidebar}" aria-hidden="true">
98
+ {#each $_slots as slot, i}
99
+ <div
100
+ class={[$theme.slot, !i && $theme.hidden]}
101
+ style:--ec-slot-label-periodicity={slot[2]}
102
+ >
103
+ <time
104
+ datetime="{slot[0]}"
105
+ {@attach contentFrom(slot[1])}
106
+ ></time>
107
+ </div>
108
+ {/each}
109
+ </aside>
110
+ <div class="{$theme.grid}" role="row">
111
+ {#each grid as days}
112
+ {#each days as day}
113
+ <Day {day}/>
114
+ {/each}
115
+ {/each}
116
+ </div>
117
+ <div class="{$theme.events}">
118
+ {#each chunks as chunk}
119
+ <Event {chunk}/>
120
+ {/each}
121
+ {#each bgChunks as chunk}
122
+ <Event {chunk}/>
123
+ {/each}
124
+ {#each iChunks as chunk}
125
+ <Event {chunk}/>
126
+ {/each}
36
127
  </div>
37
128
  </div>
38
- {/if}
39
- <Body>
40
- {#each $_viewDates as date}
41
- <Day {date}/>
42
- {/each}
43
- </Body>
129
+
130
+ {#if $showNowIndicator}
131
+ {#if nowIndicator}
132
+ {@render nowIndicator(grid)}
133
+ {:else}
134
+ <NowIndicator days={grid[0]}/>
135
+ {/if}
136
+ {/if}
137
+ </section>
@@ -1,14 +1,12 @@
1
1
  import {btnTextDay, btnTextWeek, themeView} from '#lib';
2
- import {slotTimeLimits, times} from './stores.js';
2
+ import {createTROptions, createTRROptions, createTRRParsers} from './options.js';
3
+ import {createTRRStores, createTRStores} from './stores.js';
3
4
  import View from './View.svelte';
4
5
 
5
- export {default as Section} from './Section.svelte';
6
- export {default as Body} from './Body.svelte';
7
- export {default as Day} from './Day.svelte';
8
- export {default as Week} from './all-day/Week.svelte';
9
-
10
6
  export default {
11
7
  createOptions(options) {
8
+ createTROptions(options);
9
+ createTRROptions(options);
12
10
  // Common options
13
11
  options.buttonText.timeGridDay = 'day';
14
12
  options.buttonText.timeGridWeek = 'week';
@@ -29,8 +27,12 @@ export default {
29
27
  };
30
28
  },
31
29
 
30
+ createParsers(parsers) {
31
+ createTRRParsers(parsers);
32
+ },
33
+
32
34
  createStores(state) {
33
- state._slotTimeLimits = slotTimeLimits(state); // flexible limits
34
- state._times = times(state);
35
+ createTRRStores(state);
36
+ createTRStores(state);
35
37
  }
36
38
  }
@@ -0,0 +1,142 @@
1
+ import {
2
+ addDay, addDuration, assign, bgEvent, cloneDate, createAllDayChunks, createEventChunk, datesEqual, eventIntersects,
3
+ isFunction, outsideRange, prepareAllDayChunks,
4
+ } from '#lib';
5
+
6
+ /**
7
+ * Days with prepared start and end times
8
+ */
9
+ export function createGrid($_viewDates, $_slotTimeLimits, $validRange, $highlightedDates) {
10
+ let days = [];
11
+ let gridColumn = 1;
12
+ for (let date of $_viewDates) {
13
+ days.push({
14
+ gridColumn,
15
+ gridRow: 1,
16
+ resource: undefined,
17
+ start: addDuration(cloneDate(date), $_slotTimeLimits.min),
18
+ end: addDuration(cloneDate(date), $_slotTimeLimits.max),
19
+ dayStart: date,
20
+ dayEnd: addDay(cloneDate(date)),
21
+ disabled: outsideRange(date, $validRange),
22
+ highlight: $highlightedDates.some(d => datesEqual(d, date))
23
+ });
24
+ ++ gridColumn;
25
+ }
26
+
27
+ return [days];
28
+ }
29
+
30
+ export function createEventChunks($_filteredEvents, grid) {
31
+ let chunks = [];
32
+ let bgChunks = [];
33
+ let allDayChunks = [];
34
+ let allDayBgChunks = [];
35
+ for (let event of $_filteredEvents) {
36
+ for (let days of grid) {
37
+ if (bgEvent(event.display)) {
38
+ bgChunks = bgChunks.concat(createChunks(event, days));
39
+ if (event.allDay) {
40
+ allDayBgChunks = allDayBgChunks.concat(createAllDayChunks(event, days));
41
+ }
42
+ } else {
43
+ if (event.allDay) {
44
+ allDayChunks = allDayChunks.concat(createAllDayChunks(event, days));
45
+ } else {
46
+ chunks = chunks.concat(createChunks(event, days));
47
+ }
48
+ }
49
+ }
50
+ }
51
+ groupChunks(chunks);
52
+ prepareAllDayChunks(allDayChunks);
53
+
54
+ return {chunks, bgChunks, allDayChunks, allDayBgChunks};
55
+ }
56
+
57
+ export function createIEventChunks($_iEvents, grid) {
58
+ let iChunks = [];
59
+ let allDayIChunks = [];
60
+ for (let event of $_iEvents) {
61
+ if (!event) {
62
+ continue;
63
+ }
64
+ for (let days of grid) {
65
+ if (event.allDay) {
66
+ allDayIChunks = allDayIChunks.concat(createAllDayChunks(event, days));
67
+ } else {
68
+ iChunks = iChunks.concat(createChunks(event, days));
69
+ }
70
+ }
71
+ }
72
+
73
+ return {iChunks, allDayIChunks};
74
+ }
75
+
76
+ function createChunks(event, days) {
77
+ let chunks = [];
78
+ for (let {gridColumn, gridRow, resource, start, end, disabled} of days) {
79
+ if (!disabled && eventIntersects(event, start, end, resource)) {
80
+ let chunk = createEventChunk(event, start, end);
81
+ // Chunk layout
82
+ assign(chunk, {
83
+ gridColumn,
84
+ gridRow,
85
+ top: (chunk.start - start) / 1000,
86
+ height: (chunk.end - chunk.start) / 1000,
87
+ maxHeight: (end - chunk.start) / 1000
88
+ });
89
+ chunks.push(chunk);
90
+ }
91
+ }
92
+ return chunks;
93
+ }
94
+
95
+ function groupChunks(chunks) {
96
+ let groups = {};
97
+ for (let chunk of chunks) {
98
+ let {gridColumn} = chunk;
99
+ let group = groups[gridColumn];
100
+ let column = 0;
101
+ if (group && chunk.start < group.end) {
102
+ for (; column < group.columns.length; ++ column) {
103
+ if (group.columns[column].at(-1).end <= chunk.start) {
104
+ break;
105
+ }
106
+ }
107
+ if (chunk.end > group.end) {
108
+ group.end = chunk.end;
109
+ }
110
+ } else {
111
+ group = {
112
+ columns: [],
113
+ end: chunk.end
114
+ };
115
+ }
116
+ if (group.columns.length < column + 1) {
117
+ group.columns.push([]);
118
+ }
119
+ group.columns[column].push(chunk);
120
+ groups[gridColumn] = group;
121
+ // Chunk layout
122
+ chunk.group = group;
123
+ chunk.groupColumn = column;
124
+ }
125
+ }
126
+
127
+ export function createAllDayContent(allDayContent) {
128
+ let text = 'all-day';
129
+ let content;
130
+ if (allDayContent) {
131
+ content = isFunction(allDayContent) ? allDayContent({text}) : allDayContent;
132
+ if (typeof content === 'string') {
133
+ content = {html: content};
134
+ }
135
+ } else {
136
+ content = {
137
+ html: text
138
+ };
139
+ }
140
+
141
+ return content;
142
+ }
@@ -0,0 +1,57 @@
1
+ import {assign, createDuration} from '#lib';
2
+
3
+ /**
4
+ * TimeGrid + ResourceTimeGrid
5
+ */
6
+ export function createTROptions(options) {
7
+ if (!('allDaySlot' in options)) {
8
+ assign(options, {
9
+ allDayContent: undefined,
10
+ allDaySlot: true,
11
+ slotEventOverlap: true
12
+ });
13
+ }
14
+ }
15
+
16
+ /**
17
+ * TimeGrid + ResourceTimeGrid + ResourceTimeline
18
+ */
19
+ export function createTRROptions(options) {
20
+ if (!('scrollTime' in options)) {
21
+ assign(options, {
22
+ columnWidth: undefined, // ec option
23
+ flexibleSlotTimeLimits: false, // ec option
24
+ nowIndicator: false,
25
+ scrollTime: '06:00:00',
26
+ slotDuration: '00:30:00',
27
+ slotHeight: 24, // ec option
28
+ slotLabelInterval: undefined,
29
+ slotLabelFormat: {
30
+ hour: 'numeric',
31
+ minute: '2-digit'
32
+ },
33
+ slotMaxTime: '24:00:00',
34
+ slotMinTime: '00:00:00'
35
+ });
36
+ assign(options.theme, {
37
+ nowIndicator: 'ec-now-indicator',
38
+ sidebar: 'ec-sidebar',
39
+ slot: 'ec-slot',
40
+ });
41
+ }
42
+ }
43
+
44
+ /**
45
+ * TimeGrid + ResourceTimeGrid + ResourceTimeline
46
+ */
47
+ export function createTRRParsers(parsers) {
48
+ if (!('scrollTime' in parsers)) {
49
+ assign(parsers, {
50
+ scrollTime: createDuration,
51
+ slotDuration: createDuration,
52
+ slotLabelInterval: input => input !== undefined ? createDuration(input) : undefined,
53
+ slotMaxTime: createDuration,
54
+ slotMinTime: createDuration
55
+ });
56
+ }
57
+ }