@event-calendar/core 4.7.0 → 5.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (93) hide show
  1. package/README.md +29 -51
  2. package/dist/index.css +627 -731
  3. package/dist/index.js +2500 -3191
  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 +40 -45
  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 +38 -82
  41. package/src/plugins/resource-time-grid/index.js +18 -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 +32 -10
  58. package/src/plugins/time-grid/View.svelte +127 -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 +42 -11
  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 +59 -0
  72. package/src/styles/slots.css +42 -0
  73. package/src/styles/theme.css +68 -0
  74. package/src/styles/toolbar.css +80 -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,18 +1,15 @@
1
1
  <script>
2
2
  import {getContext} from 'svelte';
3
3
  import {
4
- addDay, bgEvent, cloneDate, createEventChunk, datesEqual, eventIntersects, outsideRange, setContent, setPayload,
5
- sortEventChunks, toISOString
4
+ addDay, bgEvent, cloneDate, createEventChunk, datesEqual, eventIntersects, outsideRange, contentFrom, toISOString
6
5
  } from '#lib';
6
+ import {BaseDay} from '#components';
7
7
  import Event from './Event.svelte';
8
8
 
9
9
  let {date} = $props();
10
10
 
11
- let {_filteredEvents, _interaction, _intlListDay, _intlListDaySide, _today,
12
- resources, eventOrder, filterEventsWithResources, highlightedDates, theme, validRange} = getContext('state');
11
+ let {_filteredEvents, _intlListDay, _intlListDaySide, highlightedDates, theme, validRange} = getContext('state');
13
12
 
14
- let el = $state();
15
- let isToday = $derived(datesEqual(date, $_today));
16
13
  let highlight = $derived($highlightedDates.some(d => datesEqual(d, date)));
17
14
  let disabled = $derived(outsideRange(date, $validRange));
18
15
  let datetime = $derived(toISOString(date, 10));
@@ -23,38 +20,25 @@
23
20
  let start = date;
24
21
  let end = addDay(cloneDate(date));
25
22
  for (let event of $_filteredEvents) {
26
- if (!bgEvent(event.display) && eventIntersects(event, start, end, $filterEventsWithResources ? $resources : undefined)) {
23
+ if (!bgEvent(event.display) && eventIntersects(event, start, end)) {
27
24
  let chunk = createEventChunk(event, start, end);
28
25
  chunks.push(chunk);
29
26
  }
30
27
  }
31
- sortEventChunks(chunks, $eventOrder);
32
28
  }
33
29
  return chunks;
34
30
  });
35
-
36
- // dateFromPoint
37
- $effect(() => {
38
- if (el) {
39
- setPayload(el, () => ({allDay: true, date, resource: undefined, dayEl: el, disabled}));
40
- }
41
- });
42
31
  </script>
43
32
 
44
33
  {#if chunks.length}
45
- <div
46
- bind:this={el}
47
- class="{$theme.day} {$theme.weekdays?.[date.getUTCDay()]}{isToday ? ' ' + $theme.today : ''}{highlight ? ' ' + $theme.highlight : ''}"
48
- role="listitem"
49
- onpointerdown={$_interaction.action?.select}
50
- >
34
+ <BaseDay {date} allDay role="listitem" {disabled} {highlight}>
51
35
  <!-- svelte-ignore a11y_missing_content -->
52
36
  <h4 class="{$theme.dayHead}">
53
- <time {datetime} use:setContent={$_intlListDay.format(date)}></time>
54
- <time class="{$theme.daySide}" {datetime} use:setContent={$_intlListDaySide.format(date)}></time>
37
+ <time {datetime} {@attach contentFrom($_intlListDay.format(date))}></time>
38
+ <time class="{$theme.daySide}" {datetime} {@attach contentFrom($_intlListDaySide.format(date))}></time>
55
39
  </h4>
56
40
  {#each chunks as chunk (chunk.event)}
57
41
  <Event {chunk}/>
58
42
  {/each}
59
- </div>
43
+ </BaseDay>
60
44
  {/if}
@@ -1,5 +1,42 @@
1
1
  <script>
2
- import Body from './Body.svelte';
2
+ import {getContext} from 'svelte';
3
+ import {addDay, cloneDate, toViewWithLocalDates, contentFrom, bgEvent, isFunction} from '#lib';
4
+ import Day from './Day.svelte';
5
+
6
+ let {_mainEl, _filteredEvents, _view, _viewDates, noEventsClick, noEventsContent, theme} = getContext('state');
7
+
8
+ let noEvents = $derived.by(() => {
9
+ let noEvents = true;
10
+ if ($_viewDates.length) {
11
+ let start = $_viewDates[0];
12
+ let end = addDay(cloneDate($_viewDates.at(-1)));
13
+ for (let event of $_filteredEvents) {
14
+ if (!bgEvent(event.display) && event.start < end && event.end > start) {
15
+ noEvents = false;
16
+ break;
17
+ }
18
+ }
19
+ }
20
+ return noEvents;
21
+ });
22
+
23
+ let content = $derived(isFunction($noEventsContent) ? $noEventsContent() : $noEventsContent);
24
+
25
+ function onclick(jsEvent) {
26
+ if (isFunction($noEventsClick)) {
27
+ $noEventsClick({jsEvent, view: toViewWithLocalDates($_view)});
28
+ }
29
+ }
3
30
  </script>
4
31
 
5
- <Body/>
32
+ <section bind:this={$_mainEl} class="{$theme.main}">
33
+ {#if noEvents}
34
+ <!-- svelte-ignore a11y_click_events_have_key_events -->
35
+ <!-- svelte-ignore a11y_no_static_element_interactions -->
36
+ <div {@attach contentFrom(content)} class="{$theme.noEvents}" {onclick}></div>
37
+ {:else}
38
+ {#each $_viewDates as date}
39
+ <Day {date}/>
40
+ {/each}
41
+ {/if}
42
+ </section>
@@ -1,6 +1,6 @@
1
1
  <script>
2
2
  import {getContext, onMount, untrack} from 'svelte';
3
- import {setContent, toLocalDate, isFunction} from '#lib';
3
+ import {contentFrom, toLocalDate, isFunction} from '#lib';
4
4
 
5
5
  let {resource, date = undefined, setLabel = undefined} = $props();
6
6
 
@@ -48,5 +48,5 @@
48
48
  <span
49
49
  bind:this={el}
50
50
  aria-label="{ariaLabel}"
51
- use:setContent={content}
51
+ {@attach contentFrom(content)}
52
52
  ></span>
@@ -1,95 +1,51 @@
1
1
  <script>
2
2
  import {getContext} from 'svelte';
3
- import {datesEqual, setContent, toISOString} from '#lib';
4
- import {Section, Body, Day, Week} from '../time-grid/index.js';
3
+ import {createGrid} from './lib.js';
4
+ import {ColHead, DayHeader} from '#components';
5
5
  import Label from './Label.svelte';
6
+ import View from '../time-grid/View.svelte';
6
7
 
7
- let {
8
- datesAboveResources, _today, _viewDates, _viewResources, _intlDayHeader, _intlDayHeaderAL, allDaySlot, theme
9
- } = getContext('state');
10
-
11
- let loops = $derived($datesAboveResources ? [$_viewDates, $_viewResources] : [$_viewResources, $_viewDates]);
8
+ let {_viewDates, _viewResources, _slotTimeLimits, datesAboveResources, highlightedDates, validRange, theme} = getContext('state');
12
9
 
13
10
  let resourceLabels = $state([]);
14
11
  </script>
15
12
 
16
- <div class="{$theme.header}">
17
- <Section>
18
- {#each loops[0] as item0, i}
19
- <div class="{$theme.resource}">
13
+ <View
14
+ createGridFn={() => createGrid(
15
+ $_viewDates, $_viewResources, $_slotTimeLimits, $datesAboveResources, $validRange, $highlightedDates
16
+ )}
17
+ fullwidthNowIndicator={$datesAboveResources}
18
+ >
19
+ {#snippet header(grid)}
20
+ {#each grid as days, i}
21
+ {@const {dayStart: date, resource, disabled, highlight} = days[0]}
22
+ <ColHead
23
+ {date}
24
+ className={$theme.colGroup}
25
+ weekday={$datesAboveResources}
26
+ colSpan={days.length}
27
+ colIndex={1 + i * days.length}
28
+ disabled={$datesAboveResources && disabled}
29
+ highlight={$datesAboveResources && highlight}
30
+ >
20
31
  {#if $datesAboveResources}
21
- <div class="{$theme.day} {$theme.weekdays?.[item0.getUTCDay()]}{datesEqual(item0, $_today) ? ' ' + $theme.today : ''}">
22
- <time
23
- datetime="{toISOString(item0, 10)}"
24
- aria-label="{$_intlDayHeaderAL.format(item0)}"
25
- use:setContent={$_intlDayHeader.format(item0)}
26
- ></time>
27
- </div>
32
+ <DayHeader {date}/>
28
33
  {:else}
29
- <div class="{$theme.day}">
30
- <Label resource={item0} setLabel={e => resourceLabels[i] = e.detail + ', '} />
31
- </div>
32
- {/if}
33
- {#if loops[1].length > 1}
34
- <div class="{$theme.days}">
35
- {#each loops[1] as item1}
36
- {#if $datesAboveResources}
37
- <div class="{$theme.day}" role="columnheader">
38
- <Label resource={item1} date={item0} />
39
- </div>
40
- {:else}
41
- <div
42
- class="{$theme.day} {$theme.weekdays?.[item1.getUTCDay()]}{datesEqual(item1, $_today) ? ' ' + $theme.today : ''}"
43
- role="columnheader"
44
- >
45
- <time
46
- datetime="{toISOString(item1, 10)}"
47
- aria-label="{resourceLabels[i]}{$_intlDayHeaderAL.format(item1)}"
48
- use:setContent={$_intlDayHeader.format(item1)}
49
- ></time>
50
- </div>
51
- {/if}
52
- {/each}
53
- </div>
34
+ <Label {resource} setLabel={label => resourceLabels[i] = label + ', '}/>
54
35
  {/if}
55
- </div>
36
+ </ColHead>
56
37
  {/each}
57
- </Section>
58
- <div class="{$theme.hiddenScroll}"></div>
59
- </div>
60
- {#if $allDaySlot}
61
- <div class="{$theme.allDay}">
62
- <div class="{$theme.content}">
63
- <Section>
64
- {#if $datesAboveResources}
65
- {#each $_viewDates as date}
66
- <div class="{$theme.resource}">
67
- {#each $_viewResources as resource}
68
- <Week dates={[date]} {resource}/>
69
- {/each}
70
- </div>
71
- {/each}
72
- {:else}
73
- {#each $_viewResources as resource}
74
- <div class="{$theme.resource}">
75
- <Week dates={$_viewDates} {resource}/>
76
- </div>
77
- {/each}
78
- {/if}
79
- </Section>
80
- <div class="{$theme.hiddenScroll}"></div>
81
- </div>
82
- </div>
83
- {/if}
84
- <Body>
85
- {#each loops[0] as item0}
86
- <div class="{$theme.resource}">
87
- {#each loops[1] as item1}
88
- <Day
89
- date={$datesAboveResources ? item0 : item1}
90
- resource={$datesAboveResources ? item1 : item0}
91
- />
38
+ {#each grid as days, i}
39
+ {#each days as day, j}
40
+ {@const {dayStart: date, resource, disabled, highlight} = day}
41
+ <ColHead {date} colIndex={1 + j + i * days.length} {disabled} {highlight}>
42
+ {#if $datesAboveResources}
43
+ <Label {resource} {date}/>
44
+ {:else}
45
+ <DayHeader {date} alPrefix={resourceLabels[i]}/>
46
+ {/if}
47
+ </ColHead>
48
+ {/each}
92
49
  {/each}
93
- </div>
94
- {/each}
95
- </Body>
50
+ {/snippet}
51
+ </View>
@@ -1,34 +1,42 @@
1
- import {btnTextDay, btnTextWeek, themeView, viewResources} from '#lib';
2
- import TimeGrid from '../time-grid/index.js';
1
+ import {btnTextDay, btnTextWeek, themeView} from '#lib';
2
+ import {createTROptions, createTRROptions, createTRRParsers} from '../time-grid/options.js';
3
+ import {createTRRStores, createTRStores} from '../time-grid/stores.js';
4
+ import {createRROptions} from './options.js';
5
+ import {createRRStores} from './stores.js';
3
6
  import View from './View.svelte';
4
7
 
5
8
  export default {
6
9
  createOptions(options) {
10
+ createTROptions(options);
11
+ createTRROptions(options);
12
+ createRROptions(options);
7
13
  options.datesAboveResources = false;
8
14
  // Common options
9
15
  options.buttonText.resourceTimeGridDay = 'resources';
10
16
  options.buttonText.resourceTimeGridWeek = 'resources';
17
+ options.theme.colGroup = 'ec-col-group';
11
18
  options.view = 'resourceTimeGridWeek';
12
19
  options.views.resourceTimeGridDay = {
13
20
  buttonText: btnTextDay,
14
21
  component: View,
15
22
  duration: {days: 1},
16
- theme: themeView('ec-time-grid ec-resource-day-view')
23
+ theme: themeView('ec-resource ec-time-grid ec-day-view')
17
24
  };
18
25
  options.views.resourceTimeGridWeek = {
19
26
  buttonText: btnTextWeek,
20
27
  component: View,
21
28
  duration: {weeks: 1},
22
- theme: themeView('ec-time-grid ec-resource-week-view')
29
+ theme: themeView('ec-resource ec-time-grid ec-week-view')
23
30
  };
24
31
  },
25
32
 
33
+ createParsers(parsers) {
34
+ createTRRParsers(parsers);
35
+ },
36
+
26
37
  createStores(state) {
27
- if (!('_times' in state)) {
28
- TimeGrid.createStores(state);
29
- }
30
- if (!('_viewResources' in state)) {
31
- state._viewResources = viewResources(state);
32
- }
38
+ createTRRStores(state);
39
+ createTRStores(state);
40
+ createRRStores(state);
33
41
  }
34
42
  }
@@ -0,0 +1,31 @@
1
+ import {
2
+ addDay, addDuration, cloneDate, datesEqual, outsideRange
3
+ } from '#lib';
4
+
5
+ export function createGrid($_viewDates, $_viewResources, $_slotTimeLimits, $datesAboveResources, $validRange, $highlightedDates) {
6
+ let grid = [];
7
+ let gridColumn = 1;
8
+ let loop = $datesAboveResources ? [$_viewDates, $_viewResources] : [$_viewResources, $_viewDates];
9
+ for (let item0 of loop[0]) {
10
+ let days = [];
11
+ for (let item1 of loop[1]) {
12
+ let date = $datesAboveResources ? item0 : item1;
13
+ let resource = $datesAboveResources ? item1 : item0;
14
+ days.push({
15
+ gridColumn,
16
+ gridRow: 1,
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
+ }
29
+
30
+ return grid;
31
+ }
@@ -0,0 +1,10 @@
1
+ /**
2
+ * ResourceTimeGrid + ResourceTimeline
3
+ */
4
+ export function createRROptions(options) {
5
+ if (!('resourceLabelContent' in options)) {
6
+ options.filterResourcesWithEvents = false;
7
+ options.resourceLabelContent = undefined;
8
+ options.resourceLabelDidMount = undefined;
9
+ }
10
+ }
@@ -0,0 +1,34 @@
1
+ import {derived} from 'svelte/store';
2
+ import {createResources, eventIntersects, getPayload} from '#lib';
3
+
4
+ function viewResources(state) {
5
+ return derived(
6
+ [state.resources, state.filterResourcesWithEvents, state._filteredEvents, state._activeRange],
7
+ ([$resources, $filterResourcesWithEvents, $_filteredEvents, $_activeRange]) => {
8
+ let result = $resources.filter(resource => !getPayload(resource).hidden);
9
+
10
+ if ($filterResourcesWithEvents) {
11
+ result = $resources.filter(
12
+ resource => $_filteredEvents.some(
13
+ event => eventIntersects(event, $_activeRange.start, $_activeRange.end, resource)
14
+ )
15
+ );
16
+ }
17
+
18
+ if (!result.length) {
19
+ result = createResources([{}]);
20
+ }
21
+
22
+ return result;
23
+ }
24
+ );
25
+ }
26
+
27
+ /**
28
+ * ResourceTimeGrid + ResourceTimeline
29
+ */
30
+ export function createRRStores(state) {
31
+ if (!('_viewResources' in state)) {
32
+ state._viewResources = viewResources(state);
33
+ }
34
+ }
@@ -1,84 +1,21 @@
1
1
  <script>
2
2
  import {getContext} from 'svelte';
3
- import {
4
- addDuration, ceil, cloneDate, datesEqual, floor, max, outsideRange, rect, runReposition, setPayload, toSeconds
5
- } from '#lib';
6
- import {getSlotTimeLimits} from './lib.js';
7
- import Event from './Event.svelte';
3
+ import {addDuration, cloneDate, floor, rect} from '#lib';
4
+ import {BaseDay} from '#components';
8
5
 
9
- let {date, resource, chunks, bgChunks, longChunks, iChunks = []} = $props();
6
+ let {day} = $props();
10
7
 
11
- let {
12
- highlightedDates, slotDuration, slotWidth, theme, validRange, _interaction, _today, _dayTimeLimits
13
- } = getContext('state');
8
+ let {_monthView, slotDuration, slotWidth} = getContext('state');
14
9
 
15
- let el = $state();
16
- let refs = [];
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 slotTimeLimits = $derived(getSlotTimeLimits($_dayTimeLimits, date));
23
- let allDay = $derived(!toSeconds($slotDuration));
24
- let pointerIdx = $derived(allDay ? 2 : 1);
25
-
26
- let dayChunks = $derived(chunks.filter(chunkIntersects));
27
- let dayBgChunks = $derived(bgChunks.filter(bgChunk => (!allDay || bgChunk.event.allDay) && chunkIntersects(bgChunk)));
10
+ let {dayStart: date, start, resource, disabled, highlight} = $derived(day);
28
11
 
29
- function chunkIntersects(chunk) {
30
- return datesEqual(chunk.date, date);
31
- }
12
+ let el = $state();
32
13
 
33
14
  function dateFromPoint(x, y) {
34
- x -= rect(el).left;
35
- return {
36
- allDay,
37
- date: allDay
38
- ? cloneDate(date)
39
- : addDuration(
40
- addDuration(cloneDate(date), slotTimeLimits.min),
41
- $slotDuration,
42
- floor(x / $slotWidth)
43
- ),
44
- resource,
45
- dayEl: el,
46
- disabled
47
- };
48
- }
49
- $effect(() => {
50
- setPayload(el, dateFromPoint);
51
- });
52
-
53
- export function reposition() {
54
- return max(...runReposition(refs, dayChunks));
15
+ return $_monthView
16
+ ? date
17
+ : addDuration(cloneDate(start), $slotDuration, floor((x - rect(el).left)/ $slotWidth));
55
18
  }
56
19
  </script>
57
20
 
58
- <div
59
- bind:this={el}
60
- class="{$theme.day} {$theme.weekdays?.[date.getUTCDay()]}{isToday ? ' ' + $theme.today : ''}{highlight ? ' ' + $theme.highlight : ''}{disabled ? ' ' + $theme.disabled : ''}"
61
- style="flex-grow: {allDay ? null : ceil((toSeconds(slotTimeLimits.max) - toSeconds(slotTimeLimits.min)) / toSeconds($slotDuration))}"
62
- role="cell"
63
- onpointerdown={$_interaction.action?.select}
64
- >
65
- <div class="{$theme.events}">
66
- {#if !disabled}
67
- {#each dayBgChunks as chunk (chunk.event)}
68
- <Event {chunk}/>
69
- {/each}
70
- <!-- Pointer -->
71
- {#if iChunks[pointerIdx] && chunkIntersects(iChunks[pointerIdx])}
72
- <Event chunk={iChunks[pointerIdx]}/>
73
- {/if}
74
- {#each dayChunks as chunk, i (chunk.event)}
75
- <!-- svelte-ignore binding_property_non_reactive -->
76
- <Event {chunk} {dayChunks} {longChunks} {resource} bind:this={refs[i]}/>
77
- {/each}
78
- <!-- Drag, Resize & Select -->
79
- {#if iChunks[0] && chunkIntersects(iChunks[0])}
80
- <Event chunk={iChunks[0]} {resource}/>
81
- {/if}
82
- {/if}
83
- </div>
84
- </div>
21
+ <BaseDay bind:el allDay={$_monthView} {date} {resource} {dateFromPoint} {disabled} {highlight}/>
@@ -4,46 +4,37 @@
4
4
  import {repositionEvent} from './lib.js';
5
5
  import {InteractableEvent} from '#components';
6
6
 
7
- let {chunk, dayChunks = [], longChunks = {}, resource = undefined} = $props();
7
+ let {chunk} = $props();
8
8
 
9
- let {slotDuration, slotWidth} = getContext('state');
9
+ let {slotDuration, slotWidth, _monthView} = getContext('state');
10
10
 
11
11
  let el = $state();
12
- let margin = $state(helperEvent(chunk.event.display) ? 1 : 0);
12
+ let margin = $state(1);
13
13
  let event = $derived(chunk.event);
14
14
  // Style
15
- let width = $derived('slots' in chunk ? chunk.slots * $slotWidth : chunk.days * 100);
16
15
  let styles = $derived(style => {
17
- if ('slots' in chunk) {
18
- let left = chunk.offset * $slotWidth;
19
- style['left'] = `${left}px`;
20
- style['width'] = `${width}px`;
21
- } else {
22
- // Month view
23
- style['width'] = `${width}%`;
16
+ style['grid-column'] = `${chunk.gridColumn} / span ${chunk.dates.length}`;
17
+ style['grid-row'] = chunk.gridRow;
18
+ if (!$_monthView) {
19
+ let left = chunk.left / toSeconds($slotDuration) * $slotWidth;
20
+ style['inset-inline-start'] = `${left}px`;
21
+ style['inline-size'] = `${chunk.width / toSeconds($slotDuration) * $slotWidth + chunk.dates.length - 1}px`;
24
22
  }
25
23
  let marginTop = margin;
26
24
  if (event._margin) {
27
25
  // Force margin for helper events
28
- let [_margin, _resource] = event._margin;
29
- if (resource === _resource) {
26
+ let [_margin, _gridRow] = event._margin;
27
+ if (chunk.gridRow === _gridRow) {
30
28
  marginTop = _margin;
31
29
  }
32
30
  }
33
- style['margin-top'] = `${marginTop}px`;
31
+ style['margin-block-start'] = `${marginTop}px`;
34
32
  return style;
35
33
  });
36
34
 
37
35
  export function reposition() {
38
- if (!el) {
39
- return 0;
40
- }
41
- let h = height(el);
42
- margin = repositionEvent(chunk, dayChunks, longChunks, h, !toSeconds($slotDuration));
43
- return margin + h;
36
+ margin = repositionEvent(chunk, height(el), $_monthView);
44
37
  }
45
38
  </script>
46
39
 
47
- {#if width > 0}
48
- <InteractableEvent bind:el {chunk} {styles} axis="x" forceMargin={() => [margin, resource]} />
49
- {/if}
40
+ <InteractableEvent bind:el {chunk} {styles} axis="x" forceMargin={[margin, chunk.gridRow]} />
@@ -1,12 +1,12 @@
1
1
  <script>
2
2
  import {getContext} from 'svelte';
3
- import {datesEqual, setContent, toISOString, toSeconds, observeResize} from '#lib';
3
+ import {datesEqual, contentFrom, toISOString, toSeconds, resizeObserver} from '#lib';
4
4
 
5
5
  let {_headerEl, _headerHeight, _intlDayHeader, _intlDayHeaderAL, _dayTimes, _today, _viewDates,
6
6
  slotDuration, theme} = getContext('state');
7
7
  </script>
8
8
 
9
- <div class="{$theme.header}" bind:this={$_headerEl} use:observeResize={() => $_headerHeight = $_headerEl.clientHeight}>
9
+ <div class="{$theme.header}" bind:this={$_headerEl} {@attach resizeObserver(() => $_headerHeight = $_headerEl.clientHeight)}>
10
10
  <div class="{$theme.days}" role="row">
11
11
  {#each $_viewDates as date}
12
12
  <div class="{$theme.day} {$theme.weekdays?.[date.getUTCDay()]}{datesEqual(date, $_today) ? ' ' + $theme.today : ''}">
@@ -15,7 +15,7 @@
15
15
  <time
16
16
  datetime="{toISOString(date, 10)}"
17
17
  aria-label="{$_intlDayHeaderAL.format(date)}"
18
- use:setContent={$_intlDayHeader.format(date)}
18
+ {@attach contentFrom($_intlDayHeader.format(date))}
19
19
  ></time>
20
20
  </div>
21
21
  <div class="{$theme.times}">
@@ -23,7 +23,7 @@
23
23
  <div class="{$theme.time}{time[2] ? '' : ' ' + $theme.minor}" role="columnheader">
24
24
  <time
25
25
  datetime="{time[0]}"
26
- use:setContent={time[1]}
26
+ {@attach contentFrom(time[1])}
27
27
  ></time>
28
28
  </div>
29
29
  {/each}
@@ -33,7 +33,7 @@
33
33
  <time
34
34
  datetime="{toISOString(date, 10)}"
35
35
  aria-label="{$_intlDayHeaderAL.format(date)}"
36
- use:setContent={$_intlDayHeader.format(date)}
36
+ {@attach contentFrom($_intlDayHeader.format(date))}
37
37
  ></time>
38
38
  </div>
39
39
  {/if}
@@ -1,10 +1,10 @@
1
1
  <script>
2
- import {getContext, onMount, untrack} from 'svelte';
3
- import {ceil, height, setContent, toLocalDate, isFunction} from '#lib';
2
+ import {getContext, onMount} from 'svelte';
3
+ import {contentFrom, toLocalDate, isFunction} from '#lib';
4
4
 
5
5
  let {resource, date = undefined} = $props();
6
6
 
7
- let {resourceLabelContent, resourceLabelDidMount, _resHs} = getContext('state');
7
+ let {resourceLabelContent, resourceLabelDidMount} = getContext('state');
8
8
 
9
9
  let el = $state();
10
10
  // Content
@@ -21,14 +21,6 @@
21
21
  }
22
22
  });
23
23
 
24
- $effect(() => {
25
- content;
26
- untrack(() => {
27
- $_resHs.set(resource, ceil(height(el) + 10));
28
- $_resHs = $_resHs;
29
- });
30
- });
31
-
32
24
  onMount(() => {
33
25
  if (isFunction($resourceLabelDidMount)) {
34
26
  $resourceLabelDidMount({
@@ -42,5 +34,5 @@
42
34
 
43
35
  <span
44
36
  bind:this={el}
45
- use:setContent={content}
37
+ {@attach contentFrom(content)}
46
38
  ></span>