@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.
- package/README.md +15 -4
- package/dist/index.css +2 -2
- package/dist/index.js +2200 -2122
- package/package.json +2 -2
- package/src/Buttons.svelte +36 -37
- package/src/Calendar.svelte +34 -37
- package/src/Toolbar.svelte +4 -4
- package/src/lib/components/BaseDay.svelte +13 -10
- package/src/lib/components/BaseEvent.svelte +17 -17
- package/src/lib/components/ColHead.svelte +6 -6
- package/src/lib/components/DayHeader.svelte +3 -3
- package/src/lib/components/InteractableEvent.svelte +7 -8
- package/src/lib/derived.js +80 -0
- package/src/lib/index.js +1 -2
- package/src/lib/slots.js +16 -16
- package/src/lib/utils.js +4 -9
- package/src/lib/view.js +0 -8
- package/src/plugins/day-grid/Day.svelte +25 -23
- package/src/plugins/day-grid/Event.svelte +15 -13
- package/src/plugins/day-grid/Popup.svelte +12 -12
- package/src/plugins/day-grid/View.svelte +24 -33
- package/src/plugins/day-grid/derived.js +102 -0
- package/src/plugins/day-grid/index.js +47 -36
- package/src/plugins/day-grid/state.svelte.js +19 -0
- package/src/plugins/interaction/Action.svelte +108 -76
- package/src/plugins/interaction/Auxiliary.svelte +9 -38
- package/src/plugins/interaction/Pointer.svelte +12 -17
- package/src/plugins/interaction/Resizer.svelte +9 -7
- package/src/plugins/interaction/effects.js +37 -0
- package/src/plugins/interaction/index.js +44 -38
- package/src/plugins/interaction/lib/utils.js +1 -1
- package/src/plugins/interaction/state.svelte.js +12 -0
- package/src/plugins/list/Day.svelte +8 -7
- package/src/plugins/list/Event.svelte +3 -3
- package/src/plugins/list/View.svelte +17 -16
- package/src/plugins/list/index.js +51 -43
- package/src/plugins/list/state.svelte.js +8 -0
- package/src/plugins/resource-time-grid/Label.svelte +8 -8
- package/src/plugins/resource-time-grid/View.svelte +38 -17
- package/src/plugins/resource-time-grid/derived.js +67 -0
- package/src/plugins/resource-time-grid/index.js +34 -28
- package/src/plugins/resource-time-grid/state.svelte.js +21 -0
- package/src/plugins/resource-timeline/Day.svelte +9 -4
- package/src/plugins/resource-timeline/Event.svelte +7 -6
- package/src/plugins/resource-timeline/Expander.svelte +7 -6
- package/src/plugins/resource-timeline/NowIndicator.svelte +10 -11
- package/src/plugins/resource-timeline/View.svelte +45 -60
- package/src/plugins/resource-timeline/derived.js +167 -0
- package/src/plugins/resource-timeline/index.js +17 -21
- package/src/plugins/resource-timeline/lib.js +4 -65
- package/src/plugins/resource-timeline/state.svelte.js +18 -0
- package/src/plugins/time-grid/Day.svelte +7 -2
- package/src/plugins/time-grid/Event.svelte +6 -6
- package/src/plugins/time-grid/NowIndicator.svelte +10 -9
- package/src/plugins/time-grid/View.svelte +46 -55
- package/src/plugins/time-grid/derived.js +162 -0
- package/src/plugins/time-grid/index.js +31 -25
- package/src/plugins/time-grid/lib.js +18 -74
- package/src/plugins/time-grid/options.js +21 -16
- package/src/plugins/time-grid/state.svelte.js +44 -0
- package/src/storage/derived.js +144 -0
- package/src/storage/effects.js +156 -0
- package/src/storage/options.svelte.js +275 -0
- package/src/storage/state.svelte.js +69 -0
- package/src/styles/events.css +1 -1
- package/src/Auxiliary.svelte +0 -47
- package/src/lib/debounce.js +0 -20
- package/src/lib/stores.js +0 -63
- package/src/plugins/day-grid/lib.js +0 -61
- package/src/plugins/day-grid/stores.js +0 -5
- package/src/plugins/resource-time-grid/lib.js +0 -31
- package/src/plugins/resource-time-grid/stores.js +0 -34
- package/src/plugins/resource-timeline/Header.svelte +0 -44
- package/src/plugins/resource-timeline/Label.svelte +0 -38
- package/src/plugins/resource-timeline/stores.js +0 -48
- package/src/plugins/time-grid/stores.js +0 -49
- package/src/storage/options.js +0 -136
- package/src/storage/state.js +0 -168
- package/src/storage/stores.js +0 -234
|
@@ -5,32 +5,34 @@
|
|
|
5
5
|
|
|
6
6
|
let {chunk, axis, forceDate = undefined, forceMargin = undefined, children} = $props();
|
|
7
7
|
|
|
8
|
-
let {
|
|
8
|
+
let {interaction: {action}, options: {editable, eventDurationEditable, eventResizableFromStart, theme}} = $derived(getContext('state'));
|
|
9
|
+
let {snap} = $derived(getContext('view-state')); // timeGrid has snap, others don't
|
|
9
10
|
|
|
10
11
|
let event = $derived(chunk.event);
|
|
11
12
|
let display = $derived(chunk.event.display);
|
|
12
13
|
|
|
13
14
|
let resizable = $derived(
|
|
14
|
-
!bgEvent(display) && !helperEvent(display) && eventResizable(event,
|
|
15
|
+
!bgEvent(display) && !helperEvent(display) && eventResizable(event, eventDurationEditable, editable)
|
|
15
16
|
);
|
|
16
17
|
|
|
17
18
|
function createResizeHandler(start) {
|
|
18
|
-
return jsEvent =>
|
|
19
|
+
return jsEvent => action.resize(
|
|
19
20
|
event,
|
|
20
21
|
jsEvent,
|
|
21
22
|
start,
|
|
22
23
|
axis,
|
|
23
24
|
forceDate,
|
|
24
25
|
forceMargin,
|
|
25
|
-
chunk.zeroDuration
|
|
26
|
+
chunk.zeroDuration,
|
|
27
|
+
snap
|
|
26
28
|
);
|
|
27
29
|
}
|
|
28
30
|
</script>
|
|
29
31
|
|
|
30
|
-
{#if resizable &&
|
|
31
|
-
<div class="{
|
|
32
|
+
{#if resizable && eventResizableFromStart}
|
|
33
|
+
<div class="{theme.resizer} {theme.start}" onpointerdown={createResizeHandler(true)}></div>
|
|
32
34
|
{/if}
|
|
33
35
|
{@render children()}
|
|
34
36
|
{#if resizable}
|
|
35
|
-
<div class="{
|
|
37
|
+
<div class="{theme.resizer}" onpointerdown={createResizeHandler(false)}></div>
|
|
36
38
|
{/if}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import {bgEvent, helperEvent, listen} from '#lib';
|
|
2
|
+
import {eventDraggable} from './lib';
|
|
3
|
+
|
|
4
|
+
export function setIClasses(mainState) {
|
|
5
|
+
return () => {
|
|
6
|
+
// Dependencies
|
|
7
|
+
let {options: {editable, eventStartEditable, theme}} = mainState;
|
|
8
|
+
|
|
9
|
+
mainState.iClasses = (classNames, event) => {
|
|
10
|
+
let {display} = event;
|
|
11
|
+
return [
|
|
12
|
+
...classNames,
|
|
13
|
+
helperEvent(display)
|
|
14
|
+
? [theme[display]]
|
|
15
|
+
: (
|
|
16
|
+
!bgEvent(display) && eventDraggable(event, eventStartEditable, editable)
|
|
17
|
+
? [theme.draggable]
|
|
18
|
+
: []
|
|
19
|
+
)
|
|
20
|
+
];
|
|
21
|
+
};
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function handleScroll(mainState) {
|
|
26
|
+
return () => {
|
|
27
|
+
// Dependencies
|
|
28
|
+
let {interaction, mainEl} = mainState;
|
|
29
|
+
|
|
30
|
+
if (mainEl) {
|
|
31
|
+
return listen(mainEl, 'scroll', () => {
|
|
32
|
+
interaction.action.handleScroll();
|
|
33
|
+
interaction.pointer?.handleScroll();
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
}
|
|
@@ -1,46 +1,52 @@
|
|
|
1
|
+
import {assign} from '#lib';
|
|
1
2
|
import Auxiliary from './Auxiliary.svelte';
|
|
2
3
|
|
|
3
4
|
export default {
|
|
4
5
|
createOptions(options) {
|
|
5
|
-
options
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
options.theme
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
6
|
+
assign(options, {
|
|
7
|
+
dateClick: undefined,
|
|
8
|
+
dragConstraint: undefined,
|
|
9
|
+
dragScroll: true,
|
|
10
|
+
editable: false,
|
|
11
|
+
eventDragMinDistance: 5,
|
|
12
|
+
eventDragStart: undefined,
|
|
13
|
+
eventDragStop: undefined,
|
|
14
|
+
eventDrop: undefined,
|
|
15
|
+
eventDurationEditable: true,
|
|
16
|
+
eventLongPressDelay: undefined,
|
|
17
|
+
eventResizableFromStart: false,
|
|
18
|
+
eventResizeStart: undefined,
|
|
19
|
+
eventResizeStop: undefined,
|
|
20
|
+
eventResize: undefined,
|
|
21
|
+
eventStartEditable: true,
|
|
22
|
+
longPressDelay: 1000,
|
|
23
|
+
pointer: false,
|
|
24
|
+
resizeConstraint: undefined,
|
|
25
|
+
select: undefined,
|
|
26
|
+
selectBackgroundColor: undefined, // ec option
|
|
27
|
+
selectConstraint: undefined,
|
|
28
|
+
selectLongPressDelay: undefined,
|
|
29
|
+
selectMinDistance: 5,
|
|
30
|
+
snapDuration: undefined,
|
|
31
|
+
unselect: undefined,
|
|
32
|
+
unselectAuto: true,
|
|
33
|
+
unselectCancel: ''
|
|
34
|
+
});
|
|
35
|
+
assign(options.theme, {
|
|
36
|
+
draggable: 'ec-draggable',
|
|
37
|
+
ghost: 'ec-ghost',
|
|
38
|
+
preview: 'ec-preview',
|
|
39
|
+
pointer: 'ec-pointer',
|
|
40
|
+
resizer: 'ec-resizer',
|
|
41
|
+
start: 'ec-start',
|
|
42
|
+
dragging: 'ec-dragging',
|
|
43
|
+
resizingY: 'ec-resizing-y',
|
|
44
|
+
resizingX: 'ec-resizing-x',
|
|
45
|
+
selecting: 'ec-selecting'
|
|
46
|
+
});
|
|
41
47
|
},
|
|
42
48
|
|
|
43
|
-
|
|
44
|
-
|
|
49
|
+
initState(mainState) {
|
|
50
|
+
mainState.auxComponents.push(Auxiliary);
|
|
45
51
|
}
|
|
46
52
|
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import {handleScroll, setIClasses} from './effects.js';
|
|
2
|
+
|
|
3
|
+
export default class AuxState {
|
|
4
|
+
constructor(mainState) {
|
|
5
|
+
this.#setupEffects(mainState);
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
#setupEffects(mainState) {
|
|
9
|
+
$effect.pre(setIClasses(mainState));
|
|
10
|
+
$effect(handleScroll(mainState));
|
|
11
|
+
}
|
|
12
|
+
}
|
|
@@ -8,10 +8,11 @@
|
|
|
8
8
|
|
|
9
9
|
let {date} = $props();
|
|
10
10
|
|
|
11
|
-
let {
|
|
11
|
+
let {filteredEvents, options: {highlightedDates, theme, validRange}} = $derived(getContext('state'));
|
|
12
|
+
let {intlListDay, intlListDaySide} = $derived(getContext('view-state'));
|
|
12
13
|
|
|
13
|
-
let highlight = $derived(
|
|
14
|
-
let disabled = $derived(outsideRange(date,
|
|
14
|
+
let highlight = $derived(highlightedDates.some(d => datesEqual(d, date)));
|
|
15
|
+
let disabled = $derived(outsideRange(date, validRange));
|
|
15
16
|
let datetime = $derived(toISOString(date, 10));
|
|
16
17
|
|
|
17
18
|
let chunks = $derived.by(() => {
|
|
@@ -19,7 +20,7 @@
|
|
|
19
20
|
if (!disabled) {
|
|
20
21
|
let start = date;
|
|
21
22
|
let end = addDay(cloneDate(date));
|
|
22
|
-
for (let event of
|
|
23
|
+
for (let event of filteredEvents) {
|
|
23
24
|
if (!bgEvent(event.display) && eventIntersects(event, start, end)) {
|
|
24
25
|
let chunk = createEventChunk(event, start, end);
|
|
25
26
|
chunks.push(chunk);
|
|
@@ -33,9 +34,9 @@
|
|
|
33
34
|
{#if chunks.length}
|
|
34
35
|
<BaseDay {date} allDay role="listitem" {disabled} {highlight}>
|
|
35
36
|
<!-- svelte-ignore a11y_missing_content -->
|
|
36
|
-
<h4 class="{
|
|
37
|
-
<time {datetime} {@attach contentFrom(
|
|
38
|
-
<time class="{
|
|
37
|
+
<h4 class="{theme.dayHead}">
|
|
38
|
+
<time {datetime} {@attach contentFrom(intlListDay.format(date))}></time>
|
|
39
|
+
<time class="{theme.daySide}" {datetime} {@attach contentFrom(intlListDaySide.format(date))}></time>
|
|
39
40
|
</h4>
|
|
40
41
|
{#each chunks as chunk (chunk.event)}
|
|
41
42
|
<Event {chunk}/>
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
let {chunk} = $props();
|
|
6
6
|
|
|
7
|
-
let {
|
|
7
|
+
let {interaction, options: {theme}} = $derived(getContext('state'));
|
|
8
8
|
|
|
9
9
|
// Style
|
|
10
10
|
let styles = $derived(style => {
|
|
@@ -14,9 +14,9 @@
|
|
|
14
14
|
});
|
|
15
15
|
</script>
|
|
16
16
|
|
|
17
|
-
<BaseEvent {chunk} {styles} onpointerdown={
|
|
17
|
+
<BaseEvent {chunk} {styles} onpointerdown={interaction.action?.noAction}>
|
|
18
18
|
{#snippet body(defaultBody, bgColor, txtColor)}
|
|
19
|
-
<div class="{
|
|
19
|
+
<div class="{theme.eventTag}" style:background-color={bgColor}></div>
|
|
20
20
|
{@render defaultBody()}
|
|
21
21
|
{/snippet}
|
|
22
22
|
</BaseEvent>
|
|
@@ -1,20 +1,21 @@
|
|
|
1
1
|
<script>
|
|
2
|
-
import {getContext} from 'svelte';
|
|
3
|
-
import {addDay, cloneDate,
|
|
2
|
+
import {getContext, setContext} from 'svelte';
|
|
3
|
+
import {addDay, cloneDate, contentFrom, bgEvent, isFunction, toViewWithLocalDates} from '#lib';
|
|
4
|
+
import ViewState from './state.svelte.js';
|
|
4
5
|
import Day from './Day.svelte';
|
|
5
6
|
|
|
6
|
-
let
|
|
7
|
+
let mainState = getContext('state');
|
|
8
|
+
let viewState = new ViewState(mainState);
|
|
9
|
+
setContext('view-state', viewState);
|
|
7
10
|
|
|
8
|
-
$
|
|
9
|
-
$_activeRangeExt = identity;
|
|
10
|
-
});
|
|
11
|
+
let {filteredEvents, view, viewDates, options: {noEventsClick, noEventsContent, theme}} = $derived(mainState);
|
|
11
12
|
|
|
12
13
|
let noEvents = $derived.by(() => {
|
|
13
14
|
let noEvents = true;
|
|
14
|
-
if (
|
|
15
|
-
let start =
|
|
16
|
-
let end = addDay(cloneDate(
|
|
17
|
-
for (let event of
|
|
15
|
+
if (viewDates.length) {
|
|
16
|
+
let start = viewDates[0];
|
|
17
|
+
let end = addDay(cloneDate(viewDates.at(-1)));
|
|
18
|
+
for (let event of filteredEvents) {
|
|
18
19
|
if (!bgEvent(event.display) && event.start < end && event.end > start) {
|
|
19
20
|
noEvents = false;
|
|
20
21
|
break;
|
|
@@ -24,22 +25,22 @@
|
|
|
24
25
|
return noEvents;
|
|
25
26
|
});
|
|
26
27
|
|
|
27
|
-
let content = $derived(isFunction(
|
|
28
|
+
let content = $derived(isFunction(noEventsContent) ? noEventsContent() : noEventsContent);
|
|
28
29
|
|
|
29
30
|
function onclick(jsEvent) {
|
|
30
|
-
if (isFunction(
|
|
31
|
-
|
|
31
|
+
if (isFunction(noEventsClick)) {
|
|
32
|
+
noEventsClick({jsEvent, view: toViewWithLocalDates(view)});
|
|
32
33
|
}
|
|
33
34
|
}
|
|
34
35
|
</script>
|
|
35
36
|
|
|
36
|
-
<section bind:this={
|
|
37
|
+
<section bind:this={mainState.mainEl} class="{theme.main}">
|
|
37
38
|
{#if noEvents}
|
|
38
39
|
<!-- svelte-ignore a11y_click_events_have_key_events -->
|
|
39
40
|
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
|
40
|
-
<div {@attach contentFrom(content)} class="{
|
|
41
|
+
<div {@attach contentFrom(content)} class="{theme.noEvents}" {onclick}></div>
|
|
41
42
|
{:else}
|
|
42
|
-
{#each
|
|
43
|
+
{#each viewDates as date}
|
|
43
44
|
<Day {date}/>
|
|
44
45
|
{/each}
|
|
45
46
|
{/if}
|
|
@@ -1,49 +1,57 @@
|
|
|
1
|
-
import {btnTextDay, btnTextWeek, btnTextMonth, btnTextYear,
|
|
1
|
+
import {btnTextDay, btnTextWeek, btnTextMonth, btnTextYear, themeView, assign} from '#lib';
|
|
2
2
|
import View from './View.svelte';
|
|
3
3
|
|
|
4
4
|
export default {
|
|
5
5
|
createOptions(options) {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
options.
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
};
|
|
25
|
-
options.views
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
6
|
+
assign(options, {
|
|
7
|
+
listDayFormat: {weekday: 'long'},
|
|
8
|
+
listDaySideFormat: {year: 'numeric', month: 'long', day: 'numeric'},
|
|
9
|
+
noEventsClick: undefined, // ec option
|
|
10
|
+
noEventsContent: 'No events',
|
|
11
|
+
// Common options
|
|
12
|
+
view: 'listWeek'
|
|
13
|
+
});
|
|
14
|
+
assign(options.buttonText, {
|
|
15
|
+
listDay: 'list',
|
|
16
|
+
listWeek: 'list',
|
|
17
|
+
listMonth: 'list',
|
|
18
|
+
listYear: 'list'
|
|
19
|
+
});
|
|
20
|
+
assign(options.theme, {
|
|
21
|
+
daySide: 'ec-day-side',
|
|
22
|
+
eventTag: 'ec-event-tag',
|
|
23
|
+
noEvents: 'ec-no-events'
|
|
24
|
+
});
|
|
25
|
+
assign(options.views, {
|
|
26
|
+
listDay: {
|
|
27
|
+
buttonText: btnTextDay,
|
|
28
|
+
component: initViewComponent,
|
|
29
|
+
duration: {days: 1},
|
|
30
|
+
theme: themeView('ec-list ec-day-view')
|
|
31
|
+
},
|
|
32
|
+
listWeek: {
|
|
33
|
+
buttonText: btnTextWeek,
|
|
34
|
+
component: initViewComponent,
|
|
35
|
+
duration: {weeks: 1},
|
|
36
|
+
theme: themeView('ec-list ec-week-view')
|
|
37
|
+
},
|
|
38
|
+
listMonth: {
|
|
39
|
+
buttonText: btnTextMonth,
|
|
40
|
+
component: initViewComponent,
|
|
41
|
+
duration: {months: 1},
|
|
42
|
+
theme: themeView('ec-list ec-month-view')
|
|
43
|
+
},
|
|
44
|
+
listYear: {
|
|
45
|
+
buttonText: btnTextYear,
|
|
46
|
+
component: initViewComponent,
|
|
47
|
+
duration: {years: 1},
|
|
48
|
+
theme: themeView('ec-list ec-year-view')
|
|
49
|
+
}
|
|
50
|
+
});
|
|
48
51
|
}
|
|
49
52
|
}
|
|
53
|
+
|
|
54
|
+
function initViewComponent(mainState) {
|
|
55
|
+
mainState.features = ['list'];
|
|
56
|
+
return View;
|
|
57
|
+
}
|
|
@@ -4,18 +4,18 @@
|
|
|
4
4
|
|
|
5
5
|
let {resource, date = undefined, setLabel = undefined} = $props();
|
|
6
6
|
|
|
7
|
-
let {resourceLabelContent, resourceLabelDidMount
|
|
7
|
+
let {intlDayHeaderAL, options: {resourceLabelContent, resourceLabelDidMount}} = $derived(getContext('state'));
|
|
8
8
|
|
|
9
9
|
let el = $state();
|
|
10
10
|
// Content
|
|
11
11
|
let content = $derived.by(() => {
|
|
12
|
-
if (
|
|
13
|
-
return isFunction(
|
|
14
|
-
?
|
|
12
|
+
if (resourceLabelContent) {
|
|
13
|
+
return isFunction(resourceLabelContent)
|
|
14
|
+
? resourceLabelContent({
|
|
15
15
|
resource,
|
|
16
16
|
date: date ? toLocalDate(date) : undefined,
|
|
17
17
|
})
|
|
18
|
-
:
|
|
18
|
+
: resourceLabelContent;
|
|
19
19
|
} else {
|
|
20
20
|
return resource.title;
|
|
21
21
|
}
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
content;
|
|
27
27
|
untrack(() => {
|
|
28
28
|
if (date) {
|
|
29
|
-
ariaLabel =
|
|
29
|
+
ariaLabel = intlDayHeaderAL.format(date) + ', ' + el.innerText;
|
|
30
30
|
} else if (setLabel) {
|
|
31
31
|
ariaLabel = undefined;
|
|
32
32
|
setLabel(el.innerText);
|
|
@@ -35,8 +35,8 @@
|
|
|
35
35
|
});
|
|
36
36
|
|
|
37
37
|
onMount(() => {
|
|
38
|
-
if (isFunction(
|
|
39
|
-
|
|
38
|
+
if (isFunction(resourceLabelDidMount)) {
|
|
39
|
+
resourceLabelDidMount({
|
|
40
40
|
resource,
|
|
41
41
|
date: date ? toLocalDate(date) : undefined,
|
|
42
42
|
el
|
|
@@ -1,34 +1,55 @@
|
|
|
1
1
|
<script>
|
|
2
|
-
import {getContext} from 'svelte';
|
|
3
|
-
import {createGrid} from './lib.js';
|
|
2
|
+
import {getContext, tick} from 'svelte';
|
|
4
3
|
import {ColHead, DayHeader} from '#components';
|
|
4
|
+
import {datesEqual, isRtl} from '#lib';
|
|
5
|
+
import ViewState from './state.svelte.js';
|
|
5
6
|
import Label from './Label.svelte';
|
|
6
7
|
import View from '../time-grid/View.svelte';
|
|
7
8
|
import NowIndicator from '../time-grid/NowIndicator.svelte';
|
|
8
9
|
|
|
9
|
-
let
|
|
10
|
+
let mainState = getContext('state');
|
|
11
|
+
let viewState = new ViewState(mainState);
|
|
12
|
+
|
|
13
|
+
let {today, mainEl, viewDates, options: {scrollTime, datesAboveResources, theme}} = $derived(mainState);
|
|
14
|
+
let {grid, sidebarWidth} = $derived(viewState);
|
|
10
15
|
|
|
11
16
|
let resourceLabels = $state([]);
|
|
17
|
+
|
|
18
|
+
// Handle scrollTime (scroll to today)
|
|
19
|
+
$effect(() => {
|
|
20
|
+
if (datesAboveResources) {
|
|
21
|
+
viewDates;
|
|
22
|
+
scrollTime;
|
|
23
|
+
tick().then(scrollToTime);
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
function scrollToTime() {
|
|
27
|
+
if (today >= viewDates[0] && today <= viewDates.at(-1)) {
|
|
28
|
+
for (let days of grid) {
|
|
29
|
+
let day = days[0];
|
|
30
|
+
if (datesEqual(day.dayStart, today)) {
|
|
31
|
+
mainEl.scrollLeft = (mainEl.scrollWidth - sidebarWidth) / (grid.length * days.length) * (day.gridColumn - 1) * (isRtl() ? -1 : 1);
|
|
32
|
+
break;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
12
37
|
</script>
|
|
13
38
|
|
|
14
|
-
<View
|
|
15
|
-
|
|
16
|
-
$_viewDates, $_viewResources, $_slotTimeLimits, $datesAboveResources, $validRange, $highlightedDates
|
|
17
|
-
)}
|
|
18
|
-
>
|
|
19
|
-
{#snippet header(grid)}
|
|
39
|
+
<View {viewState}>
|
|
40
|
+
{#snippet header()}
|
|
20
41
|
{#each grid as days, i}
|
|
21
42
|
{@const {dayStart: date, resource, disabled, highlight} = days[0]}
|
|
22
43
|
<ColHead
|
|
23
44
|
{date}
|
|
24
|
-
className={grid[0].length > 1 ?
|
|
25
|
-
weekday={
|
|
45
|
+
className={grid[0].length > 1 ? theme.colGroup : undefined}
|
|
46
|
+
weekday={datesAboveResources}
|
|
26
47
|
colSpan={days.length}
|
|
27
48
|
colIndex={1 + i * days.length}
|
|
28
|
-
disabled={
|
|
29
|
-
highlight={
|
|
49
|
+
disabled={datesAboveResources && disabled}
|
|
50
|
+
highlight={datesAboveResources && highlight}
|
|
30
51
|
>
|
|
31
|
-
{#if
|
|
52
|
+
{#if datesAboveResources}
|
|
32
53
|
<DayHeader {date}/>
|
|
33
54
|
{:else}
|
|
34
55
|
<Label {resource} setLabel={label => resourceLabels[i] = label + ', '}/>
|
|
@@ -40,7 +61,7 @@
|
|
|
40
61
|
{#each days as day, j}
|
|
41
62
|
{@const {dayStart: date, resource, disabled, highlight} = day}
|
|
42
63
|
<ColHead {date} colIndex={1 + j + i * days.length} {disabled} {highlight}>
|
|
43
|
-
{#if
|
|
64
|
+
{#if datesAboveResources}
|
|
44
65
|
<Label {resource} {date}/>
|
|
45
66
|
{:else}
|
|
46
67
|
<DayHeader {date} alPrefix={resourceLabels[i]}/>
|
|
@@ -51,8 +72,8 @@
|
|
|
51
72
|
{/if}
|
|
52
73
|
{/snippet}
|
|
53
74
|
|
|
54
|
-
{#snippet nowIndicator(
|
|
55
|
-
{#if
|
|
75
|
+
{#snippet nowIndicator()}
|
|
76
|
+
{#if datesAboveResources}
|
|
56
77
|
<NowIndicator days={grid.flat()} span={grid[0].length}/>
|
|
57
78
|
{:else}
|
|
58
79
|
{#if grid[0].length > 1}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import {untrack} from 'svelte';
|
|
2
|
+
import {
|
|
3
|
+
addDay, addDuration, cloneDate, createResources, datesEqual, eventIntersects, outsideRange
|
|
4
|
+
} from '#lib';
|
|
5
|
+
|
|
6
|
+
export function viewResources(mainState) {
|
|
7
|
+
return () => {
|
|
8
|
+
// Dependencies
|
|
9
|
+
let {
|
|
10
|
+
activeRange, filteredEvents, options: {filterResourcesWithEvents, resources}, extensions: {viewResources}
|
|
11
|
+
} = mainState;
|
|
12
|
+
|
|
13
|
+
let result = viewResources ? viewResources(resources) : resources;
|
|
14
|
+
|
|
15
|
+
untrack(() => {
|
|
16
|
+
if (filterResourcesWithEvents) {
|
|
17
|
+
result = resources.filter(
|
|
18
|
+
resource => filteredEvents.some(
|
|
19
|
+
event => eventIntersects(event, activeRange.start, activeRange.end, resource)
|
|
20
|
+
)
|
|
21
|
+
);
|
|
22
|
+
}
|
|
23
|
+
if (!result.length) {
|
|
24
|
+
result = createResources([{}]);
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
return result;
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function grid(mainState, viewState) {
|
|
33
|
+
return () => {
|
|
34
|
+
// Dependencies
|
|
35
|
+
let {viewDates, options: {datesAboveResources, highlightedDates, validRange}} = mainState;
|
|
36
|
+
let {slotTimeLimits, viewResources} = viewState;
|
|
37
|
+
|
|
38
|
+
let grid = [];
|
|
39
|
+
|
|
40
|
+
untrack(() => {
|
|
41
|
+
let gridColumn = 1;
|
|
42
|
+
let loop = datesAboveResources ? [viewDates, viewResources] : [viewResources, viewDates];
|
|
43
|
+
for (let item0 of loop[0]) {
|
|
44
|
+
let days = [];
|
|
45
|
+
for (let item1 of loop[1]) {
|
|
46
|
+
let date = datesAboveResources ? item0 : item1;
|
|
47
|
+
let resource = datesAboveResources ? item1 : item0;
|
|
48
|
+
days.push({
|
|
49
|
+
gridColumn,
|
|
50
|
+
gridRow: 1,
|
|
51
|
+
resource,
|
|
52
|
+
start: addDuration(cloneDate(date), slotTimeLimits.min),
|
|
53
|
+
end: addDuration(cloneDate(date), slotTimeLimits.max),
|
|
54
|
+
dayStart: date,
|
|
55
|
+
dayEnd: addDay(cloneDate(date)),
|
|
56
|
+
disabled: outsideRange(date, validRange),
|
|
57
|
+
highlight: highlightedDates.some(d => datesEqual(d, date))
|
|
58
|
+
});
|
|
59
|
+
++gridColumn;
|
|
60
|
+
}
|
|
61
|
+
grid.push(days);
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
return grid;
|
|
66
|
+
};
|
|
67
|
+
}
|