@event-calendar/core
Version:
Full-sized drag & drop event calendar with resource & timeline views
1,540 lines • 218 kB
JavaScript
/*!
* EventCalendar v4.5.1
* https://github.com/vkurko/calendar
*/
import { tick, getContext, untrack, setContext, onMount, mount, unmount } from "svelte";
import * as $ from "svelte/internal/client";
import "svelte/internal/disclose-version";
import { derived, writable, readable, get } from "svelte/store";
import "svelte/internal/flags/legacy";
import { SvelteSet } from "svelte/reactivity";
function keyEnter(fn) {
return function(e) {
return e.key === "Enter" || e.key === " " && !e.preventDefault() ? fn.call(this, e) : void 0;
};
}
function setContent(node, content) {
let actions = {
update(content2) {
if (typeof content2 == "string") {
node.innerText = content2;
} else if (content2 == null ? void 0 : content2.domNodes) {
node.replaceChildren(...content2.domNodes);
} else if (content2 == null ? void 0 : content2.html) {
node.innerHTML = content2.html;
}
}
};
actions.update(content);
return actions;
}
function outsideEvent(node, type) {
const handlePointerDown = (jsEvent) => {
if (node && !node.contains(jsEvent.target)) {
node.dispatchEvent(
new CustomEvent(type + "outside", { detail: { jsEvent } })
);
}
};
document.addEventListener(type, handlePointerDown, true);
return {
destroy() {
document.removeEventListener(type, handlePointerDown, true);
}
};
}
function observeResize(node, callback) {
let resizeObserver = new ResizeObserver((entries2) => {
for (let entry of entries2) {
callback(entry);
}
});
resizeObserver.observe(node);
return {
destroy() {
resizeObserver.unobserve(node);
}
};
}
const DAY_IN_SECONDS = 86400;
function createDate(input = void 0) {
if (input !== void 0) {
return input instanceof Date ? _fromLocalDate(input) : _fromISOString(input);
}
return _fromLocalDate(/* @__PURE__ */ new Date());
}
function createDuration(input) {
if (typeof input === "number") {
input = { seconds: input };
} else if (typeof input === "string") {
let seconds = 0, exp = 2;
for (let part of input.split(":", 3)) {
seconds += parseInt(part, 10) * Math.pow(60, exp--);
}
input = { seconds };
} else if (input instanceof Date) {
input = { hours: input.getUTCHours(), minutes: input.getUTCMinutes(), seconds: input.getUTCSeconds() };
}
let weeks = input.weeks || input.week || 0;
return {
years: input.years || input.year || 0,
months: input.months || input.month || 0,
days: weeks * 7 + (input.days || input.day || 0),
seconds: (input.hours || input.hour || 0) * 60 * 60 + (input.minutes || input.minute || 0) * 60 + (input.seconds || input.second || 0),
inWeeks: !!weeks
};
}
function cloneDate(date) {
return new Date(date.getTime());
}
function addDuration(date, duration, x = 1) {
date.setUTCFullYear(date.getUTCFullYear() + x * duration.years);
let month = date.getUTCMonth() + x * duration.months;
date.setUTCMonth(month);
month %= 12;
if (month < 0) {
month += 12;
}
while (date.getUTCMonth() !== month) {
subtractDay(date);
}
date.setUTCDate(date.getUTCDate() + x * duration.days);
date.setUTCSeconds(date.getUTCSeconds() + x * duration.seconds);
return date;
}
function subtractDuration(date, duration, x = 1) {
return addDuration(date, duration, -x);
}
function addDay(date, x = 1) {
date.setUTCDate(date.getUTCDate() + x);
return date;
}
function subtractDay(date, x = 1) {
return addDay(date, -x);
}
function setMidnight(date) {
date.setUTCHours(0, 0, 0, 0);
return date;
}
function toLocalDate(date) {
return new Date(
date.getUTCFullYear(),
date.getUTCMonth(),
date.getUTCDate(),
date.getUTCHours(),
date.getUTCMinutes(),
date.getUTCSeconds()
);
}
function toISOString(date, len = 19) {
return date.toISOString().substring(0, len);
}
function datesEqual(date1, ...dates2) {
return dates2.every((date2) => date1.getTime() === date2.getTime());
}
function nextClosestDay(date, day) {
let diff2 = day - date.getUTCDay();
date.setUTCDate(date.getUTCDate() + (diff2 >= 0 ? diff2 : diff2 + 7));
return date;
}
function prevClosestDay(date, day) {
let diff2 = day - date.getUTCDay();
date.setUTCDate(date.getUTCDate() + (diff2 <= 0 ? diff2 : diff2 - 7));
return date;
}
function noTimePart(date) {
return typeof date === "string" && date.length <= 10;
}
function copyTime(toDate, fromDate) {
toDate.setUTCHours(fromDate.getUTCHours(), fromDate.getUTCMinutes(), fromDate.getUTCSeconds(), 0);
return toDate;
}
function toSeconds(duration) {
return duration.seconds;
}
function nextDate(date, duration) {
addDuration(date, duration);
return date;
}
function prevDate(date, duration, hiddenDays) {
subtractDuration(date, duration);
if (hiddenDays.length && hiddenDays.length < 7) {
while (hiddenDays.includes(date.getUTCDay())) {
subtractDay(date);
}
}
return date;
}
function getWeekNumber(date, firstDay) {
date = cloneDate(date);
if (firstDay == 0) {
date.setUTCDate(date.getUTCDate() + 6 - date.getUTCDay());
} else {
date.setUTCDate(date.getUTCDate() + 4 - (date.getUTCDay() || 7));
}
let yearStart = new Date(Date.UTC(date.getUTCFullYear(), 0, 1));
return Math.ceil(((date - yearStart) / 1e3 / DAY_IN_SECONDS + 1) / 7);
}
function _fromLocalDate(date) {
return new Date(Date.UTC(
date.getFullYear(),
date.getMonth(),
date.getDate(),
date.getHours(),
date.getMinutes(),
date.getSeconds()
));
}
function _fromISOString(str) {
const parts = str.match(/\d+/g);
return new Date(Date.UTC(
Number(parts[0]),
Number(parts[1]) - 1,
Number(parts[2]),
Number(parts[3] || 0),
Number(parts[4] || 0),
Number(parts[5] || 0)
));
}
function assign(...args) {
return Object.assign(...args);
}
function keys(object) {
return Object.keys(object);
}
function entries(object) {
return Object.entries(object);
}
function floor(value) {
return Math.floor(value);
}
function ceil(value) {
return Math.ceil(value);
}
function min(...args) {
return Math.min(...args);
}
function max(...args) {
return Math.max(...args);
}
function symbol() {
return Symbol("ec");
}
function isArray(value) {
return Array.isArray(value);
}
function isFunction(value) {
return typeof value === "function";
}
function run(fn) {
return fn();
}
function runAll(fns) {
fns.forEach(run);
}
function noop() {
}
const identity = (x) => x;
function stopPropagation(fn) {
return function(event) {
event.stopPropagation();
if (fn) {
fn.call(this, event);
}
};
}
function debounce(fn, handle, queueStore) {
queueStore.update((queue) => queue.set(handle, fn));
}
function flushDebounce(queue) {
runAll(queue);
queue.clear();
}
function task(fn, handle, tasks) {
handle ?? (handle = fn);
if (!tasks.has(handle)) {
tasks.set(handle, setTimeout(() => {
tasks.delete(handle);
fn();
}));
}
}
let payloadProp = symbol();
function setPayload(obj, payload) {
obj[payloadProp] = payload;
}
function hasPayload(obj) {
return !!(obj == null ? void 0 : obj[payloadProp]);
}
function getPayload(obj) {
return obj[payloadProp];
}
function createElement(tag, className, content, attrs = []) {
let el = document.createElement(tag);
el.className = className;
if (typeof content == "string") {
el.innerText = content;
} else if (content.domNodes) {
el.replaceChildren(...content.domNodes);
} else if (content.html) {
el.innerHTML = content.html;
}
for (let attr of attrs) {
el.setAttribute(...attr);
}
return el;
}
function hasYScroll(el) {
return el.scrollHeight > el.clientHeight;
}
function rect(el) {
return el.getBoundingClientRect();
}
function ancestor(el, up) {
while (up--) {
el = el.parentElement;
}
return el;
}
function height(el) {
return rect(el).height;
}
function getElementWithPayload(x, y, root2 = document, processed = []) {
processed.push(root2);
for (let el of root2.elementsFromPoint(x, y)) {
if (hasPayload(el)) {
return el;
}
if (el.shadowRoot && !processed.includes(el.shadowRoot)) {
let shadowEl = getElementWithPayload(x, y, el.shadowRoot, processed);
if (shadowEl) {
return shadowEl;
}
}
}
return null;
}
function listen(node, event, handler, options) {
node.addEventListener(event, handler, options);
return () => node.removeEventListener(event, handler, options);
}
function createView(view2, _viewTitle, _currentRange, _activeRange) {
return {
type: view2,
title: _viewTitle,
currentStart: _currentRange.start,
currentEnd: _currentRange.end,
activeStart: _activeRange.start,
activeEnd: _activeRange.end,
calendar: void 0
};
}
function toViewWithLocalDates(view2) {
view2 = assign({}, view2);
view2.currentStart = toLocalDate(view2.currentStart);
view2.currentEnd = toLocalDate(view2.currentEnd);
view2.activeStart = toLocalDate(view2.activeStart);
view2.activeEnd = toLocalDate(view2.activeEnd);
return view2;
}
function listView(view2) {
return view2.startsWith("list");
}
function timelineView(view2) {
return view2.includes("Timeline");
}
let eventId = 1;
function createEvents(input) {
return input.map((event) => {
let result = {
id: "id" in event ? String(event.id) : `{generated-${eventId++}}`,
resourceIds: toArrayProp(event, "resourceId").map(String),
allDay: event.allDay ?? (noTimePart(event.start) && noTimePart(event.end)),
start: createDate(event.start),
end: createDate(event.end),
title: event.title ?? "",
editable: event.editable,
startEditable: event.startEditable,
durationEditable: event.durationEditable,
display: event.display ?? "auto",
extendedProps: event.extendedProps ?? {},
backgroundColor: event.backgroundColor ?? event.color,
textColor: event.textColor,
classNames: toArrayProp(event, "className"),
styles: toArrayProp(event, "style")
};
if (result.allDay) {
setMidnight(result.start);
let end = cloneDate(result.end);
setMidnight(result.end);
if (!datesEqual(result.end, end) || datesEqual(result.end, result.start)) {
addDay(result.end);
}
}
return result;
});
}
function toArrayProp(input, propName) {
let result = input[propName + "s"] ?? input[propName] ?? [];
return isArray(result) ? result : [result];
}
function createEventSources(input) {
return input.map((source) => ({
events: source.events,
url: source.url && source.url.trimEnd("&") || "",
method: source.method && source.method.toUpperCase() || "GET",
extraParams: source.extraParams || {}
}));
}
function createEventChunk(event, start, end) {
let chunk = {
start: event.start > start ? event.start : start,
end: event.end < end ? event.end : end,
event
};
chunk.zeroDuration = datesEqual(chunk.start, chunk.end);
return chunk;
}
function sortEventChunks(chunks) {
chunks.sort((a, b) => a.start - b.start || b.event.allDay - a.event.allDay);
}
function createEventContent(chunk, displayEventEnd, eventContent, theme, _intlEventTime, _view) {
let timeText = _intlEventTime.formatRange(
chunk.start,
displayEventEnd && chunk.event.display !== "pointer" && !chunk.zeroDuration ? copyTime(cloneDate(chunk.start), chunk.end) : chunk.start
);
let content;
if (eventContent) {
content = isFunction(eventContent) ? eventContent({
event: toEventWithLocalDates(chunk.event),
timeText,
view: toViewWithLocalDates(_view)
}) : eventContent;
}
if (content === void 0) {
let domNodes;
switch (chunk.event.display) {
case "background":
domNodes = [];
break;
case "pointer":
domNodes = [createTimeElement(timeText, chunk, theme)];
break;
default:
domNodes = [
...chunk.event.allDay ? [] : [createTimeElement(timeText, chunk, theme)],
createElement("h4", theme.eventTitle, chunk.event.title)
];
}
content = { domNodes };
}
return [timeText, content];
}
function createTimeElement(timeText, chunk, theme) {
return createElement(
"time",
theme.eventTime,
timeText,
[["datetime", toISOString(chunk.start)]]
);
}
function createEventClasses(eventClassNames, event, _view) {
let result = event.classNames;
if (eventClassNames) {
if (isFunction(eventClassNames)) {
eventClassNames = eventClassNames({
event: toEventWithLocalDates(event),
view: toViewWithLocalDates(_view)
});
}
result = [
...isArray(eventClassNames) ? eventClassNames : [eventClassNames],
...result
];
}
return result;
}
function toEventWithLocalDates(event) {
return _cloneEvent(event, toLocalDate);
}
function cloneEvent(event) {
return _cloneEvent(event, cloneDate);
}
function _cloneEvent(event, dateFn) {
event = assign({}, event);
event.start = dateFn(event.start);
event.end = dateFn(event.end);
return event;
}
function prepareEventChunks$1(chunks, hiddenDays) {
let longChunks = {};
if (chunks.length) {
sortEventChunks(chunks);
let prevChunk;
for (let chunk of chunks) {
let dates = [];
let date = setMidnight(cloneDate(chunk.start));
while (chunk.end > date) {
if (!hiddenDays.includes(date.getUTCDay())) {
dates.push(cloneDate(date));
if (dates.length > 1) {
let key = date.getTime();
if (longChunks[key]) {
longChunks[key].chunks.push(chunk);
} else {
longChunks[key] = {
sorted: false,
chunks: [chunk]
};
}
}
}
addDay(date);
}
if (dates.length) {
chunk.date = dates[0];
chunk.days = dates.length;
chunk.dates = dates;
if (chunk.start < dates[0]) {
chunk.start = dates[0];
}
let maxEnd = addDay(cloneDate(dates.at(-1)));
if (chunk.end > maxEnd) {
chunk.end = maxEnd;
}
} else {
chunk.date = setMidnight(cloneDate(chunk.start));
chunk.days = 1;
chunk.dates = [chunk.date];
}
if (prevChunk && datesEqual(prevChunk.date, chunk.date)) {
chunk.prev = prevChunk;
}
prevChunk = chunk;
}
}
return longChunks;
}
function repositionEvent$1(chunk, longChunks, height2) {
chunk.top = 0;
if (chunk.prev) {
chunk.top = chunk.prev.bottom + 1;
}
chunk.bottom = chunk.top + height2;
let margin = 1;
let key = chunk.date.getTime();
if (longChunks[key]) {
if (!longChunks[key].sorted) {
longChunks[key].chunks.sort((a, b) => a.top - b.top);
longChunks[key].sorted = true;
}
for (let longChunk of longChunks[key].chunks) {
if (chunk.top < longChunk.bottom && chunk.bottom > longChunk.top) {
let offset = longChunk.bottom - chunk.top + 1;
margin += offset;
chunk.top += offset;
chunk.bottom += offset;
}
}
}
return margin;
}
function runReposition(refs, data) {
var _a;
refs.length = data.length;
let result = [];
for (let ref of refs) {
result.push((_a = ref == null ? void 0 : ref.reposition) == null ? void 0 : _a.call(ref));
}
return result;
}
function eventIntersects(event, start, end, resources) {
if (event.start < end && event.end > start) {
if (resources) {
if (!isArray(resources)) {
resources = [resources];
}
return resources.some((resource) => event.resourceIds.includes(resource.id));
}
return true;
}
return false;
}
function helperEvent(display) {
return previewEvent(display) || ghostEvent(display) || pointerEvent(display);
}
function bgEvent(display) {
return display === "background";
}
function previewEvent(display) {
return display === "preview";
}
function ghostEvent(display) {
return display === "ghost";
}
function pointerEvent(display) {
return display === "pointer";
}
function btnTextDay(text) {
return btnText(text, "day");
}
function btnTextWeek(text) {
return btnText(text, "week");
}
function btnTextMonth(text) {
return btnText(text, "month");
}
function btnTextYear(text) {
return btnText(text, "year");
}
function btnText(text, period) {
return {
...text,
next: "Next " + period,
prev: "Previous " + period
};
}
function themeView(view2) {
return (theme) => ({ ...theme, view: view2 });
}
function createDateRange(input) {
let start, end;
if (input) {
({ start, end } = input);
if (start) {
start = setMidnight(createDate(start));
}
if (end) {
end = setMidnight(createDate(end));
}
}
return { start, end };
}
function outsideRange(date, range) {
return range.start && date < range.start || range.end && date > range.end;
}
function limitToRange(date, range) {
if (range.start && date < range.start) {
date = range.start;
}
if (range.end && date > range.end) {
date = range.end;
}
return date;
}
function createResources(input) {
let result = [];
_createResources(input, 0, result);
return result;
}
function _createResources(input, level, flat) {
let result = [];
for (let item of input) {
let resource = createResource(item);
result.push(resource);
flat.push(resource);
let payload = {
level,
children: [],
expanded: true,
hidden: false
};
setPayload(resource, payload);
if (item.children) {
payload.children = _createResources(item.children, level + 1, flat);
}
}
return result;
}
function createResource(input) {
return {
id: String(input.id),
title: input.title || "",
eventBackgroundColor: input.eventBackgroundColor,
eventTextColor: input.eventTextColor,
extendedProps: input.extendedProps ?? {}
};
}
function resourceBackgroundColor(event, resources) {
var _a;
return (_a = findResource(event, resources)) == null ? void 0 : _a.eventBackgroundColor;
}
function resourceTextColor(event, resources) {
var _a;
return (_a = findResource(event, resources)) == null ? void 0 : _a.eventTextColor;
}
function findResource(event, resources) {
return resources.find((resource) => event.resourceIds.includes(resource.id));
}
function intl(locale, format) {
return derived([locale, format], ([$locale, $format]) => {
let intl2 = isFunction($format) ? { format: $format } : new Intl.DateTimeFormat($locale, $format);
return {
format: (date) => intl2.format(toLocalDate(date))
};
});
}
function intlRange(locale, format) {
return derived([locale, format], ([$locale, $format]) => {
let formatRange;
if (isFunction($format)) {
formatRange = $format;
} else {
let intl2 = new Intl.DateTimeFormat($locale, $format);
formatRange = (start, end) => {
if (start <= end) {
return intl2.formatRange(start, end);
} else {
let parts = intl2.formatRangeToParts(end, start);
let result = "";
let sources = ["startRange", "endRange"];
let processed = [false, false];
for (let part of parts) {
let i = sources.indexOf(part.source);
if (i >= 0) {
if (!processed[i]) {
result += _getParts(sources[1 - i], parts);
processed[i] = true;
}
} else {
result += part.value;
}
}
return result;
}
};
}
return {
formatRange: (start, end) => formatRange(toLocalDate(start), toLocalDate(end))
};
});
}
function _getParts(source, parts) {
let result = "";
for (let part of parts) {
if (part.source == source) {
result += part.value;
}
}
return result;
}
function viewResources(state) {
return derived(
[state.resources, state.filterResourcesWithEvents, state._filteredEvents, state._activeRange],
([$resources, $filterResourcesWithEvents, $_filteredEvents, $_activeRange]) => {
let result = $resources.filter((resource) => !getPayload(resource).hidden);
if ($filterResourcesWithEvents) {
result = $resources.filter((resource) => {
for (let event of $_filteredEvents) {
if (event.display !== "background" && event.resourceIds.includes(resource.id) && event.start < $_activeRange.end && event.end > $_activeRange.start) {
return true;
}
}
return false;
});
}
if (!result.length) {
result = createResources([{}]);
}
return result;
}
);
}
function createTimes(date, $slotDuration, $slotLabelInterval, $_slotTimeLimits, $_intlSlotLabel) {
date = cloneDate(date);
let times2 = [];
let end = cloneDate(date);
addDuration(date, $_slotTimeLimits.min);
addDuration(end, $_slotTimeLimits.max);
if ($slotLabelInterval === void 0) {
$slotLabelInterval = $slotDuration.seconds < 3600 ? createDuration($slotDuration.seconds * 2) : $slotDuration;
}
let label = cloneDate(date);
while (date < end) {
times2.push([
toISOString(date),
$_intlSlotLabel.format(date),
date >= label
]);
while ($slotLabelInterval.seconds && date >= label) {
addDuration(label, $slotLabelInterval);
}
addDuration(date, $slotDuration);
}
return times2;
}
function createSlotTimeLimits($slotMinTime, $slotMaxTime, $flexibleSlotTimeLimits, $_viewDates, $_filteredEvents) {
let min$1 = createDuration($slotMinTime);
let max$1 = createDuration($slotMaxTime);
if ($flexibleSlotTimeLimits) {
let minMin = createDuration(min(toSeconds(min$1), max(0, toSeconds(max$1) - DAY_IN_SECONDS)));
let maxMax = createDuration(max(toSeconds(max$1), toSeconds(minMin) + DAY_IN_SECONDS));
let filter = isFunction($flexibleSlotTimeLimits == null ? void 0 : $flexibleSlotTimeLimits.eventFilter) ? $flexibleSlotTimeLimits.eventFilter : (event) => !bgEvent(event.display);
loop: for (let date of $_viewDates) {
let start = addDuration(cloneDate(date), min$1);
let end = addDuration(cloneDate(date), max$1);
let minStart = addDuration(cloneDate(date), minMin);
let maxEnd = addDuration(cloneDate(date), maxMax);
for (let event of $_filteredEvents) {
if (!event.allDay && filter(event) && event.start < maxEnd && event.end > minStart) {
if (event.start < start) {
let seconds = max((event.start - date) / 1e3, toSeconds(minMin));
if (seconds < toSeconds(min$1)) {
min$1.seconds = seconds;
}
}
if (event.end > end) {
let seconds = min((event.end - date) / 1e3, toSeconds(maxMax));
if (seconds > toSeconds(max$1)) {
max$1.seconds = seconds;
}
}
if (toSeconds(min$1) === toSeconds(minMin) && toSeconds(max$1) === toSeconds(maxMax)) {
break loop;
}
}
}
}
}
return { min: min$1, max: max$1 };
}
function createOptions(plugins) {
var _a;
let options = {
allDayContent: void 0,
allDaySlot: true,
buttonText: {
today: "today"
},
customButtons: {},
date: /* @__PURE__ */ new Date(),
datesSet: void 0,
dayHeaderFormat: {
weekday: "short",
month: "numeric",
day: "numeric"
},
dayHeaderAriaLabelFormat: {
dateStyle: "full"
},
displayEventEnd: true,
duration: { weeks: 1 },
events: [],
eventAllUpdated: void 0,
eventBackgroundColor: void 0,
eventClassNames: void 0,
eventClick: void 0,
eventColor: void 0,
eventContent: void 0,
eventDidMount: void 0,
eventFilter: void 0,
// ec option
eventMouseEnter: void 0,
eventMouseLeave: void 0,
eventSources: [],
eventTextColor: void 0,
eventTimeFormat: {
hour: "numeric",
minute: "2-digit"
},
filterEventsWithResources: false,
filterResourcesWithEvents: false,
firstDay: 0,
flexibleSlotTimeLimits: false,
// ec option
headerToolbar: {
start: "title",
center: "",
end: "today prev,next"
},
height: void 0,
hiddenDays: [],
highlightedDates: [],
// ec option
lazyFetching: true,
loading: void 0,
locale: void 0,
nowIndicator: false,
resourceLabelContent: void 0,
resourceLabelDidMount: void 0,
resources: [],
selectable: false,
scrollTime: "06:00:00",
slotDuration: "00:30:00",
slotEventOverlap: true,
slotHeight: 24,
// ec option
slotLabelInterval: void 0,
slotLabelFormat: {
hour: "numeric",
minute: "2-digit"
},
slotMaxTime: "24:00:00",
slotMinTime: "00:00:00",
slotWidth: 72,
theme: {
allDay: "ec-all-day",
active: "ec-active",
bgEvent: "ec-bg-event",
bgEvents: "ec-bg-events",
body: "ec-body",
button: "ec-button",
buttonGroup: "ec-button-group",
calendar: "ec",
content: "ec-content",
day: "ec-day",
dayHead: "ec-day-head",
days: "ec-days",
disabled: "ec-disabled",
event: "ec-event",
eventBody: "ec-event-body",
eventTime: "ec-event-time",
eventTitle: "ec-event-title",
events: "ec-events",
extra: "ec-extra",
handle: "ec-handle",
header: "ec-header",
hiddenScroll: "ec-hidden-scroll",
highlight: "ec-highlight",
icon: "ec-icon",
line: "ec-line",
lines: "ec-lines",
minor: "ec-minor",
nowIndicator: "ec-now-indicator",
otherMonth: "ec-other-month",
resource: "ec-resource",
sidebar: "ec-sidebar",
sidebarTitle: "ec-sidebar-title",
today: "ec-today",
time: "ec-time",
title: "ec-title",
toolbar: "ec-toolbar",
view: "",
weekdays: ["ec-sun", "ec-mon", "ec-tue", "ec-wed", "ec-thu", "ec-fri", "ec-sat"],
withScroll: "ec-with-scroll"
},
titleFormat: {
year: "numeric",
month: "short",
day: "numeric"
},
validRange: void 0,
view: void 0,
viewDidMount: void 0,
views: {}
};
for (let plugin of plugins) {
(_a = plugin.createOptions) == null ? void 0 : _a.call(plugin, options);
}
return options;
}
function createParsers(plugins) {
var _a;
let parsers = {
date: (date) => setMidnight(createDate(date)),
duration: createDuration,
events: createEvents,
eventSources: createEventSources,
hiddenDays: (days2) => [...new Set(days2)],
highlightedDates: (dates) => dates.map((date) => setMidnight(createDate(date))),
resources: createResources,
scrollTime: createDuration,
slotDuration: createDuration,
slotLabelInterval: (input) => input !== void 0 ? createDuration(input) : void 0,
slotMaxTime: createDuration,
slotMinTime: createDuration,
validRange: createDateRange
};
for (let plugin of plugins) {
(_a = plugin.createParsers) == null ? void 0 : _a.call(plugin, parsers);
}
return parsers;
}
function diff(options, prevOptions) {
let diff2 = [];
for (let key of keys(options)) {
if (options[key] !== prevOptions[key]) {
diff2.push([key, options[key]]);
}
}
return diff2;
}
function dayGrid(state) {
return derived(state.view, ($view) => $view == null ? void 0 : $view.startsWith("dayGrid"));
}
function activeRange(state) {
return derived(
[state._currentRange, state.firstDay, state.slotMaxTime, state._dayGrid],
([$_currentRange, $firstDay, $slotMaxTime, $_dayGrid]) => {
let start = cloneDate($_currentRange.start);
let end = cloneDate($_currentRange.end);
if ($_dayGrid) {
prevClosestDay(start, $firstDay);
nextClosestDay(end, $firstDay);
} else if ($slotMaxTime.days || $slotMaxTime.seconds > DAY_IN_SECONDS) {
addDuration(subtractDay(end), $slotMaxTime);
let start2 = subtractDay(cloneDate(end));
if (start2 < start) {
start = start2;
}
}
return { start, end };
}
);
}
function currentRange(state) {
return derived(
[state.date, state.duration, state.firstDay],
([$date, $duration, $firstDay]) => {
let start = cloneDate($date), end;
if ($duration.months) {
start.setUTCDate(1);
} else if ($duration.inWeeks) {
prevClosestDay(start, $firstDay);
}
end = addDuration(cloneDate(start), $duration);
return { start, end };
}
);
}
function viewDates(state) {
return derived([state._activeRange, state.hiddenDays], ([$_activeRange, $hiddenDays]) => {
let dates = [];
let date = setMidnight(cloneDate($_activeRange.start));
let end = setMidnight(cloneDate($_activeRange.end));
while (date < end) {
if (!$hiddenDays.includes(date.getUTCDay())) {
dates.push(cloneDate(date));
}
addDay(date);
}
if (!dates.length && $hiddenDays.length && $hiddenDays.length < 7) {
state.date.update((date2) => {
while ($hiddenDays.includes(date2.getUTCDay())) {
addDay(date2);
}
return date2;
});
dates = get(state._viewDates);
}
return dates;
});
}
function viewTitle(state) {
return derived(
[state.date, state._activeRange, state._intlTitle, state._dayGrid],
([$date, $_activeRange, $_intlTitle, $_dayGrid]) => {
return $_dayGrid ? $_intlTitle.formatRange($date, $date) : $_intlTitle.formatRange($_activeRange.start, subtractDay(cloneDate($_activeRange.end)));
}
);
}
function view(state) {
return derived([state.view, state._viewTitle, state._currentRange, state._activeRange], (args) => createView(...args));
}
function events(state) {
let _events = writable([]);
let abortController;
let fetching = 0;
let debounceHandle = {};
derived(
[state.events, state.eventSources, state._activeRange, state._fetchedRange, state.lazyFetching, state.loading],
(values, set) => debounce(() => {
let [$events, $eventSources, $_activeRange, $_fetchedRange, $lazyFetching, $loading] = values;
if (!$eventSources.length) {
set($events);
return;
}
if (!$_fetchedRange.start || $_fetchedRange.start > $_activeRange.start || $_fetchedRange.end < $_activeRange.end || !$lazyFetching) {
if (abortController) {
abortController.abort();
}
abortController = new AbortController();
if (isFunction($loading) && !fetching) {
$loading(true);
}
let stopLoading = () => {
if (--fetching === 0 && isFunction($loading)) {
$loading(false);
}
};
let events2 = [];
let failure = (e) => stopLoading();
let success = (data) => {
events2 = events2.concat(createEvents(data));
set(events2);
stopLoading();
};
let startStr = toISOString($_activeRange.start);
let endStr = toISOString($_activeRange.end);
for (let source of $eventSources) {
if (isFunction(source.events)) {
let result = source.events({
start: toLocalDate($_activeRange.start),
end: toLocalDate($_activeRange.end),
startStr,
endStr
}, success, failure);
if (result !== void 0) {
Promise.resolve(result).then(success, failure);
}
} else {
let params = isFunction(source.extraParams) ? source.extraParams() : assign({}, source.extraParams);
params.start = startStr;
params.end = endStr;
params = new URLSearchParams(params);
let url = source.url, headers = {}, body;
if (["GET", "HEAD"].includes(source.method)) {
url += (url.includes("?") ? "&" : "?") + params;
} else {
headers["content-type"] = "application/x-www-form-urlencoded;charset=UTF-8";
body = String(params);
}
fetch(url, { method: source.method, headers, body, signal: abortController.signal, credentials: "same-origin" }).then((response) => response.json()).then(success).catch(failure);
}
++fetching;
}
$_fetchedRange.start = $_activeRange.start;
$_fetchedRange.end = $_activeRange.end;
}
}, debounceHandle, state._queue),
[]
).subscribe(_events.set);
return _events;
}
function filteredEvents(state) {
let view2;
state._view.subscribe(($_view) => view2 = $_view);
let debounceHandle = {};
return derived(
[state._events, state.eventFilter],
(values, set) => debounce(() => {
let [$_events, $eventFilter] = values;
set(
isFunction($eventFilter) ? $_events.filter((event, index2, events2) => $eventFilter({
event,
index: index2,
events: events2,
view: view2
})) : $_events
);
}, debounceHandle, state._queue),
[]
);
}
function now() {
return readable(createDate(), (set) => {
let interval = setInterval(() => {
set(createDate());
}, 1e3);
return () => clearInterval(interval);
});
}
function today(state) {
return derived(state._now, ($_now) => setMidnight(cloneDate($_now)));
}
class State {
constructor(plugins, input) {
var _a, _b;
plugins = plugins || [];
let options = createOptions(plugins);
let parsers = createParsers(plugins);
options = parseOpts(options, parsers);
input = parseOpts(input, parsers);
for (let [option, value] of Object.entries(options)) {
this[option] = writable(value);
}
this._queue = writable(/* @__PURE__ */ new Map());
this._tasks = /* @__PURE__ */ new Map();
this._auxiliary = writable([]);
this._dayGrid = dayGrid(this);
this._currentRange = currentRange(this);
this._activeRange = activeRange(this);
this._fetchedRange = writable({ start: void 0, end: void 0 });
this._events = events(this);
this._now = now();
this._today = today(this);
this._intlEventTime = intlRange(this.locale, this.eventTimeFormat);
this._intlSlotLabel = intl(this.locale, this.slotLabelFormat);
this._intlDayHeader = intl(this.locale, this.dayHeaderFormat);
this._intlDayHeaderAL = intl(this.locale, this.dayHeaderAriaLabelFormat);
this._intlTitle = intlRange(this.locale, this.titleFormat);
this._bodyEl = writable(void 0);
this._scrollable = writable(false);
this._recheckScrollable = writable(false);
this._viewTitle = viewTitle(this);
this._viewDates = viewDates(this);
this._view = view(this);
this._viewComponent = writable(void 0);
this._filteredEvents = filteredEvents(this);
this._interaction = writable({});
this._iEvents = writable([null, null]);
this._iClasses = writable(identity);
this._iClass = writable(void 0);
this._set = (key, value) => {
if (validKey(key, this)) {
if (parsers[key]) {
value = parsers[key](value);
}
this[key].set(value);
}
};
this._get = (key) => validKey(key, this) ? get(this[key]) : void 0;
for (let plugin of plugins) {
(_a = plugin.createStores) == null ? void 0 : _a.call(plugin, this);
}
if (input.view) {
this.view.set(input.view);
}
let views = /* @__PURE__ */ new Set([...keys(options.views), ...keys(input.views ?? {})]);
for (let view2 of views) {
let defOpts = mergeOpts(options, options.views[view2] ?? {});
let opts = mergeOpts(defOpts, input, ((_b = input.views) == null ? void 0 : _b[view2]) ?? {});
let component = opts.component;
filterOpts(opts, this);
for (let key of keys(opts)) {
let { set, _set = set, ...rest } = this[key];
this[key] = {
// Set value in all views
set: ["buttonText", "theme"].includes(key) ? (value) => {
if (isFunction(value)) {
let result = value(defOpts[key]);
opts[key] = result;
set(set === _set ? result : value);
} else {
opts[key] = value;
set(value);
}
} : (value) => {
opts[key] = value;
set(value);
},
_set,
...rest
};
}
this.view.subscribe((newView) => {
if (newView === view2) {
this._viewComponent.set(component);
if (isFunction(opts.viewDidMount)) {
tick().then(() => opts.viewDidMount({
view: toViewWithLocalDates(get(this._view))
}));
}
for (let key of keys(opts)) {
this[key]._set(opts[key]);
}
}
});
}
}
}
function parseOpts(opts, parsers) {
let result = { ...opts };
for (let key of keys(parsers)) {
if (key in result) {
result[key] = parsers[key](result[key]);
}
}
if (opts.views) {
result.views = {};
for (let view2 of keys(opts.views)) {
result.views[view2] = parseOpts(opts.views[view2], parsers);
}
}
return result;
}
function mergeOpts(...args) {
let result = {};
for (let opts of args) {
let override = {};
for (let key of ["buttonText", "theme"]) {
if (isFunction(opts[key])) {
override[key] = opts[key](result[key]);
}
}
result = {
...result,
...opts,
...override
};
}
return result;
}
function filterOpts(opts, state) {
keys(opts).filter((key) => !validKey(key, state) || key === "view").forEach((key) => delete opts[key]);
}
function validKey(key, state) {
return state.hasOwnProperty(key) && key[0] !== "_";
}
var root_2$7 = $.from_html(`<h2></h2>`);
var root_4$3 = $.from_html(`<button><i></i></button>`);
var root_6$1 = $.from_html(`<button><i></i></button>`);
var root_8$1 = $.from_html(`<button> </button>`);
var root_10$1 = $.from_html(`<button></button>`);
var root_12$1 = $.from_html(`<button> </button>`);
function Buttons($$anchor, $$props) {
$.push($$props, false);
const [$$stores, $$cleanup] = $.setup_stores();
const $validRange = () => $.store_get(validRange, "$validRange", $$stores);
const $date = () => $.store_get(date, "$date", $$stores);
const $duration = () => $.store_get(duration, "$duration", $$stores);
const $hiddenDays = () => $.store_get(hiddenDays, "$hiddenDays", $$stores);
const $_currentRange = () => $.store_get(_currentRange, "$_currentRange", $$stores);
const $_viewDates = () => $.store_get(_viewDates, "$_viewDates", $$stores);
const $theme = () => $.store_get(theme, "$theme", $$stores);
const $_viewTitle = () => $.store_get(_viewTitle, "$_viewTitle", $$stores);
const $buttonText = () => $.store_get(buttonText, "$buttonText", $$stores);
const $customButtons = () => $.store_get(customButtons, "$customButtons", $$stores);
const $view = () => $.store_get(view2, "$view", $$stores);
let buttons = $.prop($$props, "buttons", 8);
let {
_currentRange,
_viewTitle,
_viewDates,
buttonText,
customButtons,
date,
duration,
hiddenDays,
theme,
validRange,
view: view2
} = getContext("state");
let today2 = setMidnight(createDate());
let prevDisabled = $.mutable_source(), nextDisabled = $.mutable_source(), todayDisabled = $.mutable_source();
let running = $.mutable_source(false);
function isRunning() {
return $.get(running);
}
function test() {
return $_viewDates().every((date2) => outsideRange(date2, $validRange()));
}
function prev() {
$.store_set(date, prevDate($date(), $duration(), $hiddenDays()));
}
function next() {
$.store_set(date, nextDate($date(), $duration()));
}
$.legacy_pre_effect(
() => ($validRange(), $date(), $duration(), $hiddenDays(), $.get(todayDisabled), $_currentRange(), tick),
() => {
if (!isRunning()) {
$.set(running, true);
$.set(prevDisabled, false);
$.set(nextDisabled, false);
if ($validRange().start) {
let currentDate = cloneDate($date());
$.store_set(date, prevDate($date(), $duration(), $hiddenDays()));
$.set(prevDisabled, test());
$.store_set(date, currentDate);
}
if ($validRange().end) {
let currentDate = cloneDate($date());
$.store_set(date, nextDate($date(), $duration()));
$.set(nextDisabled, test());
$.store_set(date, currentDate);
}
$.set(todayDisabled, today2 >= $_currentRange().start && today2 < $_currentRange().end);
if (!$.get(todayDisabled) && ($validRange().start || $validRange().end)) {
let currentDate = cloneDate($date());
$.store_set(date, cloneDate(today2));
$.set(todayDisabled, test());
$.store_set(date, currentDate);
}
tick().then(() => $.set(running, false));
}
}
);
$.legacy_pre_effect_reset();
$.init();
var fragment = $.comment();
var node = $.first_child(fragment);
$.each(node, 1, buttons, $.index, ($$anchor2, button) => {
var fragment_1 = $.comment();
var node_1 = $.first_child(fragment_1);
{
var consequent = ($$anchor3) => {
var h2 = root_2$7();
$.action(h2, ($$node, $$action_arg) => setContent == null ? void 0 : setContent($$node, $$action_arg), $_viewTitle);
$.template_effect(() => $.set_class(h2, 1, ($theme(), $.untrack(() => $theme().title))));
$.append($$anchor3, h2);
};
var alternate_4 = ($$anchor3) => {
var fragment_2 = $.comment();
var node_2 = $.first_child(fragment_2);
{
var consequent_1 = ($$anchor4) => {
var button_1 = root_4$3();
var i = $.child(button_1);
$.reset(button_1);
$.template_effect(() => {
$.set_class(button_1, 1, `${($theme(), $.untrack(() => $theme().button)) ?? ""} ec-${$.get(button) ?? ""}`);
$.set_attribute(button_1, "aria-label", ($buttonText(), $.untrack(() => $buttonText().prev)));
$.set_attribute(button_1, "title", ($buttonText(), $.untrack(() => $buttonText().prev)));
button_1.disabled = $.get(prevDisabled);
$.set_class(i, 1, `${($theme(), $.untrack(() => $theme().icon)) ?? ""} ec-${$.get(button) ?? ""}`);
});
$.event("click", button_1, prev);
$.append($$anchor4, button_1);
};
var alternate_3 = ($$anchor4) => {
var fragment_3 = $.comment();
var node_3 = $.first_child(fragment_3);
{
var consequent_2 = ($$anchor5) => {
var button_2 = root_6$1();
var i_1 = $.child(button_2);
$.reset(button_2);
$.template_effect(() => {
$.set_class(button_2, 1, `${($theme(), $.untrack(() => $theme().button)) ?? ""} ec-${$.get(button) ?? ""}`);
$.set_attribute(button_2, "aria-label", ($buttonText(), $.untrack(() => $buttonText().next)));
$.set_attribute(button_2, "title", ($buttonText(), $.untrack(() => $buttonText().next)));
button_2.disabled = $.get(nextDisabled);
$.set_class(i_1, 1, `${($theme(), $.untrack(() => $theme().icon)) ?? ""} ec-${$.get(button) ?? ""}`);
});
$.event("click", button_2, next);
$.append($$anchor5, button_2);
};
var alternate_2 = ($$anchor5) => {
var fragment_4 = $.comment();
var node_4 = $.first_child(fragment_4);
{
var consequent_3 = ($$anchor6) => {
var button_3 = root_8$1();
var text = $.child(button_3, true);
$.reset(button_3);
$.template_effect(() => {
$.set_class(button_3, 1, `${($theme(), $.untrack(() => $theme().button)) ?? ""} ec-${$.get(button) ?? ""}`);
button_3.disabled = $.get(todayDisabled);
$.set_text(text, ($buttonText(), $.get(button), $.untrack(() => $buttonText()[$.get(button)])));
});
$.event("click", button_3, () => $.store_set(date, cloneDate(today2)));
$.append($$anchor6, button_3);
};
var alternate_1 = ($$anchor6) => {
var fragment_5 = $.comment();
var node_5 = $.first_child(fragment_5);
{
var consequent_4 = ($$anchor7) => {
var button_4 = root_10$1();
$.effect(() => $.event("click", button_4, function(...$$args) {
var _a;
(_a = $customButtons()[$.get(button)].click) == null ? void 0 : _a.apply(this, $$args);
}));
$.action(button_4, ($$node, $$action_arg) => setContent == null ? void 0 : setContent($$node, $$action_arg), () => $customButtons()[$.get(button)].text);
$.template_effect(() => $.set_class(button_4, 1, `${($theme(), $.untrack(() => $theme().button)) ?? ""} ec-${$.get(button) ?? ""}${($customButtons(), $.get(button), $theme(), $.untrack(() => $customButtons()[$.get(button)].active ? " " + $theme().active : "")) ?? ""}`));
$.append($$anchor7, button_4);
};
var alternate = ($$anchor7) => {
var fragment_6 = $.comment();
var node_6 = $.first_child(fragment_6);
{
var consequent_5 = ($$anchor8) => {
var button_5 = root_12$1();
var text_1 = $.child(button_5, true);
$.reset(button_5);
$.template_effect(() => {
$.set_class(button_5, 1, `${($theme(), $.untrack(() => $theme().button)) ?? ""}${($view(), $.get(button), $theme(), $.untrack(() => $view() === $.get(button) ? " " + $theme().active : "")) ?? ""} ec-${$.get(button) ?? ""}`);
$.set_text(text_1, ($buttonText(), $.get(button), $.untrack(() => $buttonText()[$.get(button)])));
});
$.event("click", button_5, () => $.store_set(view2, $.get(button)));
$.append($$anchor8, button_5);
};
$.if(
node_6,
($$render) => {
if ($.get(button) != "") $$render(consequent_5);
},
true
);
}
$.append($$anchor7, fragment_6);
};
$.if(
node_5,
($$render) => {
if ($customButtons(), $.get(button), $.untrack(() => $customButtons()[$.get(button)])) $$render(consequent_4);
else $$render(alternate, false);
},
true
);
}
$.append($$anchor6, fragment_5);
};
$.if(
node_4,
($$render) => {
if ($.get(button) == "today") $$render(consequent_3);
else $$render(alternate_1, false);
},
true
);
}
$.append($$anchor5, fragment_4);
};
$.if(
node_3,
($$render) => {
if ($.get(button) == "next") $$render(consequent_2);
else $$render(alternate_2, false);
},
true
);
}
$.append($$anchor4, fragment_3);
};
$.if(
node_2,
($$render) => {
if ($.get(button) == "prev") $$render(consequent_1);
else $$render(alternate_3, false);
},
true
);
}
$.append($$anchor3, fragment_2);
};
$.if(node_1, ($$render) => {
if ($.get(button) == "title") $$render(consequent);
else $$render(alternate_4, false);
});
}
$.append($$anchor2, fragment_1);
});
$.append($$anchor, fragment);
$.pop();
$$cleanup();
}
var root_3$5 = $.from_html(`<div><!></div>`);
var root_1$d = $.from_html(`<div></div>`);
var root$r = $.from_html(`<nav></nav>`);
function Toolbar($$anchor, $$props) {
$.push($$props, true);
const [$$stores, $$cleanup] = $.setup_stores();
const $headerToolbar = () => $.store_get(headerToolbar, "$headerToolbar", $$stores);
const $theme = () => $.store_get(theme, "$theme", $$stores);
let { headerToolbar, theme } = getContext("state");
let sections = $.derived(() => {
var _a;
let sections2 = {};
for (let key of ["start", "center", "end"]) {
sections2[key] = ((_a = $headerToolbar()[key]) == null ? void 0 : _a.split(" ").map((group) => group.split(","))) ?? [];
}
return sections2;
});
var nav = root$r();
$.each(nav, 21, () => keys($.get(sections)), $.index, ($$anchor2, key) => {
var div = root_1$d();
$.each(div, 21, () => $.get(sections)[$.get(key)], $.index, ($$anchor3, buttons) => {
var fragment = $.comment();
var node = $.first_child(fragment);
{
var consequent = ($$anchor4) => {
var div_1 = root_3$5();
var node_1 = $.child(div_1);
Buttons(node_1, {
get buttons() {
return $.get(buttons);
}
});
$.reset(di