routie dev init since i didn't adhere to any proper guidance up until now

This commit is contained in:
2026-04-29 22:27:29 -06:00
commit e1dabb71e2
15301 changed files with 3562618 additions and 0 deletions
File diff suppressed because it is too large Load Diff
+330
View File
@@ -0,0 +1,330 @@
import { mergeProps as _mergeProps, createVNode as _createVNode, withDirectives as _withDirectives } from "vue";
// Styles
import "./VCalendarCategory.css";
import "./VCalendarDaily.css";
import "./VCalendarWeekly.css";
// Components
import { VCalendarCategory } from "./VCalendarCategory.js";
import { VCalendarDaily } from "./VCalendarDaily.js";
import { VCalendarWeekly } from "./VCalendarWeekly.js"; // Composables
import { makeCalendarBaseProps } from "./composables/calendarBase.js";
import { makeCalendarWithEventsProps, useCalendarWithEvents } from "./composables/calendarWithEvents.js";
import { forwardRefs } from "../../composables/forwardRefs.js"; // Directives
import vResize from "../../directives/resize/index.js"; // Utilities
import { computed, onMounted, onUpdated, ref, watch } from 'vue';
import { getParsedCategories } from "./util/parser.js";
import { copyTimestamp, DAY_MIN, DAYS_IN_MONTH_MAX, DAYS_IN_WEEK, getEndOfMonth, getStartOfMonth, nextDay, prevDay, relativeDays, timestampToDate, updateFormatted, updateRelative, updateWeekday, validateTimestamp } from "./util/timestamp.js";
import { genericComponent, useRender } from "../../util/index.js"; // Types
// Types
export const VCalendar = genericComponent()({
name: 'VCalendar',
directives: {
vResize
},
props: {
modelValue: {
type: [String, Number, Date],
validate: validateTimestamp
},
categoryDays: {
type: [Number, String],
default: 1,
validate: x => isFinite(parseInt(x)) && parseInt(x) > 0
},
categories: {
type: [Array, String],
default: ''
},
categoryText: {
type: [String, Function]
},
maxDays: {
type: Number,
default: 7
},
categoryHideDynamic: {
type: Boolean
},
categoryShowAll: {
type: Boolean
},
categoryForInvalid: {
type: String,
default: ''
},
...makeCalendarBaseProps(),
...makeCalendarWithEventsProps()
},
setup(props, {
slots,
attrs,
emit
}) {
const root = ref();
const base = useCalendarWithEvents(props, slots, attrs);
const lastStart = ref(null);
const lastEnd = ref(null);
const parsedCategoryDays = computed(() => {
return parseInt(String(props.categoryDays)) || 1;
});
const parsedCategories = computed(() => {
return getParsedCategories(props.categories, props.categoryText);
});
const renderProps = computed(() => {
const around = base.parsedValue.value;
let component = null;
let maxDays = props.maxDays;
let categories = parsedCategories.value;
let start = around;
let end = around;
switch (props.type) {
case 'month':
component = VCalendarWeekly;
start = getStartOfMonth(around);
end = getEndOfMonth(around);
break;
case 'week':
component = VCalendarDaily;
start = base.getStartOfWeek(around);
end = base.getEndOfWeek(around);
maxDays = 7;
break;
case 'day':
component = VCalendarDaily;
maxDays = 1;
break;
case '4day':
component = VCalendarDaily;
end = relativeDays(copyTimestamp(end), nextDay, 3);
updateFormatted(end);
maxDays = 4;
break;
case 'custom-weekly':
component = VCalendarWeekly;
start = base.parsedStart.value || around;
end = base.parsedEnd.value;
break;
case 'custom-daily':
component = VCalendarDaily;
start = base.parsedStart.value || around;
end = base.parsedEnd.value;
break;
case 'category':
const days = parsedCategoryDays.value;
component = VCalendarCategory;
end = relativeDays(copyTimestamp(end), nextDay, days);
updateFormatted(end);
maxDays = days;
categories = getCategoryList(categories);
break;
default:
const type = props.type;
throw new Error(`${type} is not a valid Calendar type`);
}
return {
component,
start,
end,
maxDays,
categories
};
});
const eventWeekdays = computed(() => {
return base.effectiveWeekdays.value;
});
const categoryMode = computed(() => {
return props.type === 'category';
});
const monthLongFormatter = computed(() => {
return base.getFormatter({
timeZone: 'UTC',
month: 'long'
});
});
const monthShortFormatter = computed(() => {
return base.getFormatter({
timeZone: 'UTC',
month: 'short'
});
});
const title = computed(() => {
const {
start,
end
} = renderProps.value;
const spanYears = start.year !== end.year;
const spanMonths = spanYears || start.month !== end.month;
if (spanYears) {
return monthShortFormatter.value(start, true) + ' ' + start.year + ' - ' + monthShortFormatter.value(end, true) + ' ' + end.year;
}
if (spanMonths) {
return monthShortFormatter.value(start, true) + ' - ' + monthShortFormatter.value(end, true) + ' ' + end.year;
} else {
return monthLongFormatter.value(start, false) + ' ' + start.year;
}
});
function checkChange() {
const {
start,
end
} = renderProps.value;
if (!lastStart.value || !lastEnd.value || start.date !== lastStart.value.date || end.date !== lastEnd.value.date) {
lastStart.value = start;
lastEnd.value = end;
emit('change', {
start,
end
});
}
}
function move(amount = 1) {
const moved = copyTimestamp(base.parsedValue.value);
const forward = amount > 0;
const mover = forward ? nextDay : prevDay;
const limit = forward ? DAYS_IN_MONTH_MAX : DAY_MIN;
let times = forward ? amount : -amount;
while (--times >= 0) {
switch (props.type) {
case 'month':
moved.day = limit;
mover(moved);
break;
case 'week':
relativeDays(moved, mover, DAYS_IN_WEEK);
break;
case 'day':
relativeDays(moved, mover, 1);
break;
case '4day':
relativeDays(moved, mover, 4);
break;
case 'category':
relativeDays(moved, mover, parsedCategoryDays.value);
break;
}
}
updateWeekday(moved);
updateFormatted(moved);
updateRelative(moved, base.times.now);
if (props.modelValue instanceof Date) {
emit('update:modelValue', timestampToDate(moved));
} else if (typeof props.modelValue === 'number') {
emit('update:modelValue', timestampToDate(moved).getTime());
} else {
emit('update:modelValue', moved.date);
}
emit('moved', moved);
}
function next(amount = 1) {
move(amount);
}
function prev(amount = 1) {
move(-amount);
}
function getCategoryList(categories) {
if (!base.noEvents.value) {
const categoryMap = categories.reduce((map, category, index) => {
if (typeof category === 'object' && category.categoryName) map[category.categoryName] = {
index,
count: 0
};else if (typeof category === 'string') map[category] = {
index,
count: 0
};
return map;
}, {});
if (!props.categoryHideDynamic || !props.categoryShowAll) {
let categoryLength = categories.length;
base.parsedEvents.value.forEach(ev => {
let category = ev.category;
if (typeof category !== 'string') {
category = props.categoryForInvalid;
}
if (!category) {
return;
}
if (category in categoryMap) {
categoryMap[category].count++;
} else if (!props.categoryHideDynamic) {
categoryMap[category] = {
index: categoryLength++,
count: 1
};
}
});
}
if (!props.categoryShowAll) {
for (const category in categoryMap) {
if (categoryMap[category].count === 0) {
delete categoryMap[category];
}
}
}
categories = categories.filter(category => {
if (typeof category === 'object' && category.categoryName) {
return categoryMap.hasOwnProperty(category.categoryName);
} else if (typeof category === 'string') {
return categoryMap.hasOwnProperty(category);
}
return false;
});
}
return categories;
}
watch(renderProps, checkChange);
onMounted(() => {
base.updateEventVisibility();
checkChange();
});
onUpdated(() => {
window.requestAnimationFrame(base.updateEventVisibility);
});
useRender(() => {
const {
start,
end,
maxDays,
component: Component,
categories
} = renderProps.value;
return _withDirectives(_createVNode(Component, _mergeProps({
"ref": root,
"class": ['v-calendar', {
'v-calendar-events': !base.noEvents.value
}],
"role": "grid"
}, Component.filterProps(props), {
"start": start.date,
"end": end.date,
"maxDays": maxDays,
"weekdays": base.effectiveWeekdays.value,
"categories": categories,
"onClick:date": (e, day) => {
if (attrs['onUpdate:modelValue']) emit('update:modelValue', day.date);
}
}), base.getScopedSlots()), [[vResize, base.updateEventVisibility, void 0, {
quiet: true
}]]);
});
return forwardRefs({
...base,
lastStart,
lastEnd,
parsedCategoryDays,
renderProps,
eventWeekdays,
categoryMode,
title,
monthLongFormatter,
monthShortFormatter,
parsedCategories,
checkChange,
move,
next,
prev,
getCategoryList
}, root);
}
});
//# sourceMappingURL=VCalendar.js.map
File diff suppressed because one or more lines are too long
@@ -0,0 +1,103 @@
@layer vuetify-components {
.v-calendar-category .v-calendar-category__column,
.v-calendar-category .v-calendar-category__column-header {
border-right: rgba(var(--v-border-color), var(--v-border-opacity)) 1px solid;
}
.v-calendar-category .v-calendar-daily__head {
background: rgb(var(--v-theme-surface));
color: rgb(var(--v-theme-on-surface));
}
.v-calendar-category .v-calendar-daily__intervals-head {
background: rgb(var(--v-theme-surface));
color: rgb(var(--v-theme-on-surface));
}
.v-calendar-category .v-calendar-daily__intervals-body {
background: rgb(var(--v-theme-surface));
color: rgb(var(--v-theme-on-surface));
}
.v-calendar-category {
overflow: auto;
position: relative;
}
.v-calendar-category .v-calendar-category__category {
text-align: center;
}
.v-calendar-category .v-calendar-daily__day-container {
width: min-content;
}
.v-calendar-category .v-calendar-daily__day-container .v-calendar-category__columns {
position: absolute;
height: 100%;
width: 100%;
top: 0;
}
.v-calendar-category .v-calendar-daily__day-body {
display: flex;
flex: 1;
width: 100%;
height: 100%;
}
.v-calendar-category .v-calendar-daily__head {
flex-direction: row;
width: min-content;
min-width: 100%;
position: sticky;
top: 0;
z-index: 2;
}
.v-calendar-category .v-calendar-daily_head-day {
width: auto;
position: unset;
}
.v-calendar-category .v-calendar-daily__intervals-head {
position: sticky;
left: 0;
top: 0;
z-index: 2;
}
.v-calendar-category .v-calendar-daily_head-weekday {
position: sticky;
left: 50%;
width: 50px;
}
.v-calendar-category .v-calendar-daily_head-day-label {
width: 56px;
position: sticky;
left: 50%;
}
.v-calendar-category .v-calendar-daily__day {
min-width: 200px;
}
.v-calendar-category .v-calendar-daily__intervals-body {
position: sticky;
left: 0;
z-index: 1;
}
.v-calendar-category .v-calendar-daily__interval:last-of-type::after {
display: none;
}
.v-calendar-category .v-calendar-daily__body {
overflow: visible;
}
.v-calendar-category .v-calendar-daily__body .v-calendar-daily__scroll-area {
overflow-y: visible;
flex: none;
}
.v-calendar-category .v-calendar-daily__pane {
overflow-y: visible;
}
.v-calendar-category .v-calendar-category__columns {
display: flex;
width: min-content;
min-width: 100%;
}
.v-calendar-category .v-calendar-category__columns .v-calendar-category__column,
.v-calendar-category .v-calendar-category__columns .v-calendar-category__column-header {
flex: 1 1 auto;
width: 0;
position: relative;
}
.v-calendar-category .v-calendar-category__columns .v-calendar-category__column-header {
min-width: 200px;
}
}
@@ -0,0 +1,789 @@
import type { PropType } from 'vue';
import type { CalendarCategory, CalendarCategoryTextFunction, CalendarTimestamp } from './types.js';
export declare const VCalendarCategory: {
new (...args: any[]): import("vue").CreateComponentPublicInstanceWithMixins<Readonly<import("vue").ExtractPropTypes<{
start: {
type: (DateConstructor | NumberConstructor | StringConstructor)[];
validate: typeof import("./util/timestamp.js").validateTimestamp;
default: () => string;
};
end: {
type: (DateConstructor | NumberConstructor | StringConstructor)[];
validate: typeof import("./util/timestamp.js").validateTimestamp;
};
weekdays: {
type: PropType<number[] | string>;
default: () => number[];
validate: typeof import("./util/timestamp.js").validateWeekdays;
};
firstDayOfWeek: (NumberConstructor | StringConstructor)[];
firstDayOfYear: (NumberConstructor | StringConstructor)[];
weekdayFormat: {
type: PropType<import("./types.js").CalendarFormatter>;
default: null;
};
dayFormat: {
type: PropType<import("./types.js").CalendarFormatter>;
default: null;
};
locale: StringConstructor;
now: {
type: StringConstructor;
validator: typeof import("./util/timestamp.js").validateTimestamp;
};
type: {
type: PropType<'month' | 'week' | 'day' | '4day' | 'custom-weekly' | 'custom-daily' | 'category'>;
default: string;
};
maxDays: {
type: NumberConstructor;
default: number;
};
intervalHeight: {
type: (NumberConstructor | StringConstructor)[];
default: number;
validate: typeof import("./util/timestamp.js").validateNumber;
};
intervalWidth: {
type: (NumberConstructor | StringConstructor)[];
default: number;
validate: typeof import("./util/timestamp.js").validateNumber;
};
intervalMinutes: {
type: (NumberConstructor | StringConstructor)[];
default: number;
validate: typeof import("./util/timestamp.js").validateNumber;
};
firstInterval: {
type: (NumberConstructor | StringConstructor)[];
default: number;
validate: typeof import("./util/timestamp.js").validateNumber;
};
firstTime: {
type: PropType<import("./util/timestamp.js").VTime>;
validate: typeof import("./util/timestamp.js").validateTime;
};
intervalCount: {
type: (NumberConstructor | StringConstructor)[];
default: number;
validate: typeof import("./util/timestamp.js").validateNumber;
};
intervalFormat: {
type: PropType<import("./types.js").CalendarFormatter>;
default: null;
};
intervalStyle: {
type: PropType<(interval: CalendarTimestamp) => import("vue").StyleValue>;
default: null;
};
showIntervalLabel: {
type: PropType<(interval: CalendarTimestamp) => boolean>;
default: null;
};
categories: {
type: PropType<CalendarCategory[] | string>;
default: string;
};
categoryText: PropType<string | CalendarCategoryTextFunction>;
categoryForInvalid: {
type: StringConstructor;
default: string;
};
}>>, {
times: {
now: {
date: string;
time: string;
year: number;
month: number;
day: number;
weekday: number;
hour: number;
minute: number;
hasDay: boolean;
hasTime: boolean;
past: boolean;
present: boolean;
future: boolean;
category?: CalendarCategory;
};
today: {
date: string;
time: string;
year: number;
month: number;
day: number;
weekday: number;
hour: number;
minute: number;
hasDay: boolean;
hasTime: boolean;
past: boolean;
present: boolean;
future: boolean;
category?: CalendarCategory;
};
};
locale: {
name: string;
decimalSeparator: import("vue").ShallowRef<string>;
messages: import("vue").Ref<import("../../types.js").LocaleMessages, import("../../types.js").LocaleMessages>;
current: import("vue").Ref<string, string>;
fallback: import("vue").Ref<string, string>;
t: (key: string, ...params: unknown[]) => string;
n: (value: number) => string;
provide: (props: import("../../types.js").LocaleOptions) => import("../../types.js").LocaleInstance;
isRtl: import("vue").Ref<boolean, boolean>;
rtl: import("vue").Ref<Record<string, boolean>, Record<string, boolean>>;
rtlClasses: import("vue").Ref<string, string>;
};
parsedValue: import("vue").ComputedRef<CalendarTimestamp>;
parsedWeekdays: import("vue").ComputedRef<number[]>;
effectiveWeekdays: import("vue").ComputedRef<number[]>;
weekdaySkips: import("vue").ComputedRef<number[]>;
parsedStart: import("vue").ComputedRef<CalendarTimestamp>;
parsedEnd: import("vue").ComputedRef<CalendarTimestamp>;
dayFormatter: import("vue").ComputedRef<import("./types.js").CalendarFormatter>;
weekdayFormatter: import("vue").ComputedRef<import("./types.js").CalendarFormatter>;
getColorProps: (colors: {
background?: import("../../composables/color.js").ColorValue;
text?: import("../../composables/color.js").ColorValue;
}) => {
class: string[];
style: import("vue").CSSProperties;
};
getRelativeClasses: (timestamp: CalendarTimestamp, outside?: boolean) => {
'v-present': boolean;
'v-past': boolean;
'v-future': boolean;
'v-outside': boolean;
};
getWeekNumber: (timestamp: CalendarTimestamp) => number;
getStartOfWeek: (timestamp: CalendarTimestamp) => CalendarTimestamp;
getEndOfWeek: (timestamp: CalendarTimestamp) => CalendarTimestamp;
getFormatter: (options: Intl.DateTimeFormatOptions) => import("./types.js").CalendarFormatter;
updateTimes: () => void;
scrollAreaRef: import("vue").ShallowRef<HTMLElement | undefined, HTMLElement | undefined>;
parsedFirstInterval: import("vue").ComputedRef<number>;
parsedIntervalMinutes: import("vue").ComputedRef<number>;
parsedIntervalCount: import("vue").ComputedRef<number>;
parsedIntervalHeight: import("vue").ComputedRef<number>;
parsedFirstTime: import("vue").ComputedRef<number | false>;
firstMinute: import("vue").ComputedRef<number>;
bodyHeight: import("vue").ComputedRef<number>;
days: import("vue").ComputedRef<CalendarTimestamp[]>;
intervals: import("vue").ComputedRef<CalendarTimestamp[][]>;
intervalFormatter: import("vue").ComputedRef<import("./types.js").CalendarFormatter>;
showIntervalLabelDefault: (interval: CalendarTimestamp) => boolean;
intervalStyleDefault: (_interval: CalendarTimestamp) => import("vue").StyleValue;
getTimestampAtEvent: (e: Event, day: CalendarTimestamp) => CalendarTimestamp;
getSlotScope: (timestamp: CalendarTimestamp) => import("./types.js").CalendarDayBodySlotScope;
scrollToTime: (time: import("./util/timestamp.js").VTime) => boolean;
minutesToPixels: (minutes: number) => number;
timeToY: (time: import("./util/timestamp.js").VTime | CalendarTimestamp, targetDateOrClamp?: CalendarTimestamp | boolean) => number | false;
timeDelta: (time: import("./util/timestamp.js").VTime | CalendarTimestamp, targetDate?: CalendarTimestamp) => number | false;
parsedCategories: import("vue").ComputedRef<CalendarCategory[]>;
}, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, import("vue").PublicProps, {
start: string | number | Date;
weekdays: string | number[];
weekdayFormat: import("./types.js").CalendarFormatter;
dayFormat: import("./types.js").CalendarFormatter;
type: "4day" | "category" | "custom-daily" | "custom-weekly" | "day" | "month" | "week";
maxDays: number;
intervalHeight: string | number;
intervalWidth: string | number;
intervalMinutes: string | number;
firstInterval: string | number;
intervalCount: string | number;
intervalFormat: import("./types.js").CalendarFormatter;
intervalStyle: (interval: CalendarTimestamp) => import("vue").StyleValue;
showIntervalLabel: (interval: CalendarTimestamp) => boolean;
categories: string | CalendarCategory[];
categoryForInvalid: string;
}, true, {}, {}, import("vue").GlobalComponents, import("vue").GlobalDirectives, string, {}, any, import("vue").ComponentProvideOptions, {
P: {};
B: {};
D: {};
C: {};
M: {};
Defaults: {};
}, Readonly<import("vue").ExtractPropTypes<{
start: {
type: (DateConstructor | NumberConstructor | StringConstructor)[];
validate: typeof import("./util/timestamp.js").validateTimestamp;
default: () => string;
};
end: {
type: (DateConstructor | NumberConstructor | StringConstructor)[];
validate: typeof import("./util/timestamp.js").validateTimestamp;
};
weekdays: {
type: PropType<number[] | string>;
default: () => number[];
validate: typeof import("./util/timestamp.js").validateWeekdays;
};
firstDayOfWeek: (NumberConstructor | StringConstructor)[];
firstDayOfYear: (NumberConstructor | StringConstructor)[];
weekdayFormat: {
type: PropType<import("./types.js").CalendarFormatter>;
default: null;
};
dayFormat: {
type: PropType<import("./types.js").CalendarFormatter>;
default: null;
};
locale: StringConstructor;
now: {
type: StringConstructor;
validator: typeof import("./util/timestamp.js").validateTimestamp;
};
type: {
type: PropType<'month' | 'week' | 'day' | '4day' | 'custom-weekly' | 'custom-daily' | 'category'>;
default: string;
};
maxDays: {
type: NumberConstructor;
default: number;
};
intervalHeight: {
type: (NumberConstructor | StringConstructor)[];
default: number;
validate: typeof import("./util/timestamp.js").validateNumber;
};
intervalWidth: {
type: (NumberConstructor | StringConstructor)[];
default: number;
validate: typeof import("./util/timestamp.js").validateNumber;
};
intervalMinutes: {
type: (NumberConstructor | StringConstructor)[];
default: number;
validate: typeof import("./util/timestamp.js").validateNumber;
};
firstInterval: {
type: (NumberConstructor | StringConstructor)[];
default: number;
validate: typeof import("./util/timestamp.js").validateNumber;
};
firstTime: {
type: PropType<import("./util/timestamp.js").VTime>;
validate: typeof import("./util/timestamp.js").validateTime;
};
intervalCount: {
type: (NumberConstructor | StringConstructor)[];
default: number;
validate: typeof import("./util/timestamp.js").validateNumber;
};
intervalFormat: {
type: PropType<import("./types.js").CalendarFormatter>;
default: null;
};
intervalStyle: {
type: PropType<(interval: CalendarTimestamp) => import("vue").StyleValue>;
default: null;
};
showIntervalLabel: {
type: PropType<(interval: CalendarTimestamp) => boolean>;
default: null;
};
categories: {
type: PropType<CalendarCategory[] | string>;
default: string;
};
categoryText: PropType<string | CalendarCategoryTextFunction>;
categoryForInvalid: {
type: StringConstructor;
default: string;
};
}>>, {
times: {
now: {
date: string;
time: string;
year: number;
month: number;
day: number;
weekday: number;
hour: number;
minute: number;
hasDay: boolean;
hasTime: boolean;
past: boolean;
present: boolean;
future: boolean;
category?: CalendarCategory;
};
today: {
date: string;
time: string;
year: number;
month: number;
day: number;
weekday: number;
hour: number;
minute: number;
hasDay: boolean;
hasTime: boolean;
past: boolean;
present: boolean;
future: boolean;
category?: CalendarCategory;
};
};
locale: {
name: string;
decimalSeparator: import("vue").ShallowRef<string>;
messages: import("vue").Ref<import("../../types.js").LocaleMessages, import("../../types.js").LocaleMessages>;
current: import("vue").Ref<string, string>;
fallback: import("vue").Ref<string, string>;
t: (key: string, ...params: unknown[]) => string;
n: (value: number) => string;
provide: (props: import("../../types.js").LocaleOptions) => import("../../types.js").LocaleInstance;
isRtl: import("vue").Ref<boolean, boolean>;
rtl: import("vue").Ref<Record<string, boolean>, Record<string, boolean>>;
rtlClasses: import("vue").Ref<string, string>;
};
parsedValue: import("vue").ComputedRef<CalendarTimestamp>;
parsedWeekdays: import("vue").ComputedRef<number[]>;
effectiveWeekdays: import("vue").ComputedRef<number[]>;
weekdaySkips: import("vue").ComputedRef<number[]>;
parsedStart: import("vue").ComputedRef<CalendarTimestamp>;
parsedEnd: import("vue").ComputedRef<CalendarTimestamp>;
dayFormatter: import("vue").ComputedRef<import("./types.js").CalendarFormatter>;
weekdayFormatter: import("vue").ComputedRef<import("./types.js").CalendarFormatter>;
getColorProps: (colors: {
background?: import("../../composables/color.js").ColorValue;
text?: import("../../composables/color.js").ColorValue;
}) => {
class: string[];
style: import("vue").CSSProperties;
};
getRelativeClasses: (timestamp: CalendarTimestamp, outside?: boolean) => {
'v-present': boolean;
'v-past': boolean;
'v-future': boolean;
'v-outside': boolean;
};
getWeekNumber: (timestamp: CalendarTimestamp) => number;
getStartOfWeek: (timestamp: CalendarTimestamp) => CalendarTimestamp;
getEndOfWeek: (timestamp: CalendarTimestamp) => CalendarTimestamp;
getFormatter: (options: Intl.DateTimeFormatOptions) => import("./types.js").CalendarFormatter;
updateTimes: () => void;
scrollAreaRef: import("vue").ShallowRef<HTMLElement | undefined, HTMLElement | undefined>;
parsedFirstInterval: import("vue").ComputedRef<number>;
parsedIntervalMinutes: import("vue").ComputedRef<number>;
parsedIntervalCount: import("vue").ComputedRef<number>;
parsedIntervalHeight: import("vue").ComputedRef<number>;
parsedFirstTime: import("vue").ComputedRef<number | false>;
firstMinute: import("vue").ComputedRef<number>;
bodyHeight: import("vue").ComputedRef<number>;
days: import("vue").ComputedRef<CalendarTimestamp[]>;
intervals: import("vue").ComputedRef<CalendarTimestamp[][]>;
intervalFormatter: import("vue").ComputedRef<import("./types.js").CalendarFormatter>;
showIntervalLabelDefault: (interval: CalendarTimestamp) => boolean;
intervalStyleDefault: (_interval: CalendarTimestamp) => import("vue").StyleValue;
getTimestampAtEvent: (e: Event, day: CalendarTimestamp) => CalendarTimestamp;
getSlotScope: (timestamp: CalendarTimestamp) => import("./types.js").CalendarDayBodySlotScope;
scrollToTime: (time: import("./util/timestamp.js").VTime) => boolean;
minutesToPixels: (minutes: number) => number;
timeToY: (time: import("./util/timestamp.js").VTime | CalendarTimestamp, targetDateOrClamp?: CalendarTimestamp | boolean) => number | false;
timeDelta: (time: import("./util/timestamp.js").VTime | CalendarTimestamp, targetDate?: CalendarTimestamp) => number | false;
parsedCategories: import("vue").ComputedRef<CalendarCategory[]>;
}, {}, {}, {}, {
start: string | number | Date;
weekdays: string | number[];
weekdayFormat: import("./types.js").CalendarFormatter;
dayFormat: import("./types.js").CalendarFormatter;
type: "4day" | "category" | "custom-daily" | "custom-weekly" | "day" | "month" | "week";
maxDays: number;
intervalHeight: string | number;
intervalWidth: string | number;
intervalMinutes: string | number;
firstInterval: string | number;
intervalCount: string | number;
intervalFormat: import("./types.js").CalendarFormatter;
intervalStyle: (interval: CalendarTimestamp) => import("vue").StyleValue;
showIntervalLabel: (interval: CalendarTimestamp) => boolean;
categories: string | CalendarCategory[];
categoryForInvalid: string;
}>;
__isFragment?: never;
__isTeleport?: never;
__isSuspense?: never;
} & import("vue").ComponentOptionsBase<Readonly<import("vue").ExtractPropTypes<{
start: {
type: (DateConstructor | NumberConstructor | StringConstructor)[];
validate: typeof import("./util/timestamp.js").validateTimestamp;
default: () => string;
};
end: {
type: (DateConstructor | NumberConstructor | StringConstructor)[];
validate: typeof import("./util/timestamp.js").validateTimestamp;
};
weekdays: {
type: PropType<number[] | string>;
default: () => number[];
validate: typeof import("./util/timestamp.js").validateWeekdays;
};
firstDayOfWeek: (NumberConstructor | StringConstructor)[];
firstDayOfYear: (NumberConstructor | StringConstructor)[];
weekdayFormat: {
type: PropType<import("./types.js").CalendarFormatter>;
default: null;
};
dayFormat: {
type: PropType<import("./types.js").CalendarFormatter>;
default: null;
};
locale: StringConstructor;
now: {
type: StringConstructor;
validator: typeof import("./util/timestamp.js").validateTimestamp;
};
type: {
type: PropType<'month' | 'week' | 'day' | '4day' | 'custom-weekly' | 'custom-daily' | 'category'>;
default: string;
};
maxDays: {
type: NumberConstructor;
default: number;
};
intervalHeight: {
type: (NumberConstructor | StringConstructor)[];
default: number;
validate: typeof import("./util/timestamp.js").validateNumber;
};
intervalWidth: {
type: (NumberConstructor | StringConstructor)[];
default: number;
validate: typeof import("./util/timestamp.js").validateNumber;
};
intervalMinutes: {
type: (NumberConstructor | StringConstructor)[];
default: number;
validate: typeof import("./util/timestamp.js").validateNumber;
};
firstInterval: {
type: (NumberConstructor | StringConstructor)[];
default: number;
validate: typeof import("./util/timestamp.js").validateNumber;
};
firstTime: {
type: PropType<import("./util/timestamp.js").VTime>;
validate: typeof import("./util/timestamp.js").validateTime;
};
intervalCount: {
type: (NumberConstructor | StringConstructor)[];
default: number;
validate: typeof import("./util/timestamp.js").validateNumber;
};
intervalFormat: {
type: PropType<import("./types.js").CalendarFormatter>;
default: null;
};
intervalStyle: {
type: PropType<(interval: CalendarTimestamp) => import("vue").StyleValue>;
default: null;
};
showIntervalLabel: {
type: PropType<(interval: CalendarTimestamp) => boolean>;
default: null;
};
categories: {
type: PropType<CalendarCategory[] | string>;
default: string;
};
categoryText: PropType<string | CalendarCategoryTextFunction>;
categoryForInvalid: {
type: StringConstructor;
default: string;
};
}>>, {
times: {
now: {
date: string;
time: string;
year: number;
month: number;
day: number;
weekday: number;
hour: number;
minute: number;
hasDay: boolean;
hasTime: boolean;
past: boolean;
present: boolean;
future: boolean;
category?: CalendarCategory;
};
today: {
date: string;
time: string;
year: number;
month: number;
day: number;
weekday: number;
hour: number;
minute: number;
hasDay: boolean;
hasTime: boolean;
past: boolean;
present: boolean;
future: boolean;
category?: CalendarCategory;
};
};
locale: {
name: string;
decimalSeparator: import("vue").ShallowRef<string>;
messages: import("vue").Ref<import("../../types.js").LocaleMessages, import("../../types.js").LocaleMessages>;
current: import("vue").Ref<string, string>;
fallback: import("vue").Ref<string, string>;
t: (key: string, ...params: unknown[]) => string;
n: (value: number) => string;
provide: (props: import("../../types.js").LocaleOptions) => import("../../types.js").LocaleInstance;
isRtl: import("vue").Ref<boolean, boolean>;
rtl: import("vue").Ref<Record<string, boolean>, Record<string, boolean>>;
rtlClasses: import("vue").Ref<string, string>;
};
parsedValue: import("vue").ComputedRef<CalendarTimestamp>;
parsedWeekdays: import("vue").ComputedRef<number[]>;
effectiveWeekdays: import("vue").ComputedRef<number[]>;
weekdaySkips: import("vue").ComputedRef<number[]>;
parsedStart: import("vue").ComputedRef<CalendarTimestamp>;
parsedEnd: import("vue").ComputedRef<CalendarTimestamp>;
dayFormatter: import("vue").ComputedRef<import("./types.js").CalendarFormatter>;
weekdayFormatter: import("vue").ComputedRef<import("./types.js").CalendarFormatter>;
getColorProps: (colors: {
background?: import("../../composables/color.js").ColorValue;
text?: import("../../composables/color.js").ColorValue;
}) => {
class: string[];
style: import("vue").CSSProperties;
};
getRelativeClasses: (timestamp: CalendarTimestamp, outside?: boolean) => {
'v-present': boolean;
'v-past': boolean;
'v-future': boolean;
'v-outside': boolean;
};
getWeekNumber: (timestamp: CalendarTimestamp) => number;
getStartOfWeek: (timestamp: CalendarTimestamp) => CalendarTimestamp;
getEndOfWeek: (timestamp: CalendarTimestamp) => CalendarTimestamp;
getFormatter: (options: Intl.DateTimeFormatOptions) => import("./types.js").CalendarFormatter;
updateTimes: () => void;
scrollAreaRef: import("vue").ShallowRef<HTMLElement | undefined, HTMLElement | undefined>;
parsedFirstInterval: import("vue").ComputedRef<number>;
parsedIntervalMinutes: import("vue").ComputedRef<number>;
parsedIntervalCount: import("vue").ComputedRef<number>;
parsedIntervalHeight: import("vue").ComputedRef<number>;
parsedFirstTime: import("vue").ComputedRef<number | false>;
firstMinute: import("vue").ComputedRef<number>;
bodyHeight: import("vue").ComputedRef<number>;
days: import("vue").ComputedRef<CalendarTimestamp[]>;
intervals: import("vue").ComputedRef<CalendarTimestamp[][]>;
intervalFormatter: import("vue").ComputedRef<import("./types.js").CalendarFormatter>;
showIntervalLabelDefault: (interval: CalendarTimestamp) => boolean;
intervalStyleDefault: (_interval: CalendarTimestamp) => import("vue").StyleValue;
getTimestampAtEvent: (e: Event, day: CalendarTimestamp) => CalendarTimestamp;
getSlotScope: (timestamp: CalendarTimestamp) => import("./types.js").CalendarDayBodySlotScope;
scrollToTime: (time: import("./util/timestamp.js").VTime) => boolean;
minutesToPixels: (minutes: number) => number;
timeToY: (time: import("./util/timestamp.js").VTime | CalendarTimestamp, targetDateOrClamp?: CalendarTimestamp | boolean) => number | false;
timeDelta: (time: import("./util/timestamp.js").VTime | CalendarTimestamp, targetDate?: CalendarTimestamp) => number | false;
parsedCategories: import("vue").ComputedRef<CalendarCategory[]>;
}, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, {
start: string | number | Date;
weekdays: string | number[];
weekdayFormat: import("./types.js").CalendarFormatter;
dayFormat: import("./types.js").CalendarFormatter;
type: "4day" | "category" | "custom-daily" | "custom-weekly" | "day" | "month" | "week";
maxDays: number;
intervalHeight: string | number;
intervalWidth: string | number;
intervalMinutes: string | number;
firstInterval: string | number;
intervalCount: string | number;
intervalFormat: import("./types.js").CalendarFormatter;
intervalStyle: (interval: CalendarTimestamp) => import("vue").StyleValue;
showIntervalLabel: (interval: CalendarTimestamp) => boolean;
categories: string | CalendarCategory[];
categoryForInvalid: string;
}, {}, string, {}, import("vue").GlobalComponents, import("vue").GlobalDirectives, string, import("vue").ComponentProvideOptions> & import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps & import("../../util/index.js").FilterPropsOptions<{
start: {
type: (DateConstructor | NumberConstructor | StringConstructor)[];
validate: typeof import("./util/timestamp.js").validateTimestamp;
default: () => string;
};
end: {
type: (DateConstructor | NumberConstructor | StringConstructor)[];
validate: typeof import("./util/timestamp.js").validateTimestamp;
};
weekdays: {
type: PropType<number[] | string>;
default: () => number[];
validate: typeof import("./util/timestamp.js").validateWeekdays;
};
firstDayOfWeek: (NumberConstructor | StringConstructor)[];
firstDayOfYear: (NumberConstructor | StringConstructor)[];
weekdayFormat: {
type: PropType<import("./types.js").CalendarFormatter>;
default: null;
};
dayFormat: {
type: PropType<import("./types.js").CalendarFormatter>;
default: null;
};
locale: StringConstructor;
now: {
type: StringConstructor;
validator: typeof import("./util/timestamp.js").validateTimestamp;
};
type: {
type: PropType<'month' | 'week' | 'day' | '4day' | 'custom-weekly' | 'custom-daily' | 'category'>;
default: string;
};
maxDays: {
type: NumberConstructor;
default: number;
};
intervalHeight: {
type: (NumberConstructor | StringConstructor)[];
default: number;
validate: typeof import("./util/timestamp.js").validateNumber;
};
intervalWidth: {
type: (NumberConstructor | StringConstructor)[];
default: number;
validate: typeof import("./util/timestamp.js").validateNumber;
};
intervalMinutes: {
type: (NumberConstructor | StringConstructor)[];
default: number;
validate: typeof import("./util/timestamp.js").validateNumber;
};
firstInterval: {
type: (NumberConstructor | StringConstructor)[];
default: number;
validate: typeof import("./util/timestamp.js").validateNumber;
};
firstTime: {
type: PropType<import("./util/timestamp.js").VTime>;
validate: typeof import("./util/timestamp.js").validateTime;
};
intervalCount: {
type: (NumberConstructor | StringConstructor)[];
default: number;
validate: typeof import("./util/timestamp.js").validateNumber;
};
intervalFormat: {
type: PropType<import("./types.js").CalendarFormatter>;
default: null;
};
intervalStyle: {
type: PropType<(interval: CalendarTimestamp) => import("vue").StyleValue>;
default: null;
};
showIntervalLabel: {
type: PropType<(interval: CalendarTimestamp) => boolean>;
default: null;
};
categories: {
type: PropType<CalendarCategory[] | string>;
default: string;
};
categoryText: PropType<string | CalendarCategoryTextFunction>;
categoryForInvalid: {
type: StringConstructor;
default: string;
};
}, import("vue").ExtractPropTypes<{
start: {
type: (DateConstructor | NumberConstructor | StringConstructor)[];
validate: typeof import("./util/timestamp.js").validateTimestamp;
default: () => string;
};
end: {
type: (DateConstructor | NumberConstructor | StringConstructor)[];
validate: typeof import("./util/timestamp.js").validateTimestamp;
};
weekdays: {
type: PropType<number[] | string>;
default: () => number[];
validate: typeof import("./util/timestamp.js").validateWeekdays;
};
firstDayOfWeek: (NumberConstructor | StringConstructor)[];
firstDayOfYear: (NumberConstructor | StringConstructor)[];
weekdayFormat: {
type: PropType<import("./types.js").CalendarFormatter>;
default: null;
};
dayFormat: {
type: PropType<import("./types.js").CalendarFormatter>;
default: null;
};
locale: StringConstructor;
now: {
type: StringConstructor;
validator: typeof import("./util/timestamp.js").validateTimestamp;
};
type: {
type: PropType<'month' | 'week' | 'day' | '4day' | 'custom-weekly' | 'custom-daily' | 'category'>;
default: string;
};
maxDays: {
type: NumberConstructor;
default: number;
};
intervalHeight: {
type: (NumberConstructor | StringConstructor)[];
default: number;
validate: typeof import("./util/timestamp.js").validateNumber;
};
intervalWidth: {
type: (NumberConstructor | StringConstructor)[];
default: number;
validate: typeof import("./util/timestamp.js").validateNumber;
};
intervalMinutes: {
type: (NumberConstructor | StringConstructor)[];
default: number;
validate: typeof import("./util/timestamp.js").validateNumber;
};
firstInterval: {
type: (NumberConstructor | StringConstructor)[];
default: number;
validate: typeof import("./util/timestamp.js").validateNumber;
};
firstTime: {
type: PropType<import("./util/timestamp.js").VTime>;
validate: typeof import("./util/timestamp.js").validateTime;
};
intervalCount: {
type: (NumberConstructor | StringConstructor)[];
default: number;
validate: typeof import("./util/timestamp.js").validateNumber;
};
intervalFormat: {
type: PropType<import("./types.js").CalendarFormatter>;
default: null;
};
intervalStyle: {
type: PropType<(interval: CalendarTimestamp) => import("vue").StyleValue>;
default: null;
};
showIntervalLabel: {
type: PropType<(interval: CalendarTimestamp) => boolean>;
default: null;
};
categories: {
type: PropType<CalendarCategory[] | string>;
default: string;
};
categoryText: PropType<string | CalendarCategoryTextFunction>;
categoryForInvalid: {
type: StringConstructor;
default: string;
};
}>>;
export type VCalendarCategory = InstanceType<typeof VCalendarCategory>;
@@ -0,0 +1,122 @@
import { createElementVNode as _createElementVNode, mergeProps as _mergeProps, normalizeStyle as _normalizeStyle, createVNode as _createVNode } from "vue";
// Components
import { VCalendarDaily } from "./VCalendarDaily.js"; // Composables
import { makeCalendarBaseProps } from "./composables/calendarBase.js";
import { makeCalendarWithIntervalsProps, useCalendarWithIntervals } from "./composables/calendarWithIntervals.js"; // Utilities
import { computed } from 'vue';
import { getParsedCategories } from "./util/parser.js";
import { convertToUnit, defineComponent, getPrefixedEventHandlers, useRender } from "../../util/index.js"; // Types
export const VCalendarCategory = defineComponent({
name: 'VCalendarCategory',
props: {
categories: {
type: [Array, String],
default: ''
},
categoryText: [String, Function],
categoryForInvalid: {
type: String,
default: ''
},
...makeCalendarBaseProps(),
...makeCalendarWithIntervalsProps()
},
setup(props, {
slots,
attrs
}) {
const base = useCalendarWithIntervals(props);
const parsedCategories = computed(() => {
return getParsedCategories(props.categories, props.categoryText);
});
function getCategoryScope(scope, category) {
const cat = typeof category === 'object' && category && category.categoryName === props.categoryForInvalid ? null : category;
return {
...scope,
category: cat
};
}
function genDayHeader(scope) {
return _createElementVNode("div", {
"class": "v-calendar-category__columns"
}, [parsedCategories.value.map(category => {
return genDayHeaderCategory(scope, getCategoryScope(scope, category));
})]);
}
function genDayHeaderCategory(day, scope) {
const headerTitle = typeof scope.category === 'object' ? scope.category.categoryName : scope.category;
const events = getPrefixedEventHandlers(attrs, ':dayCategory', () => {
return getCategoryScope(base.getSlotScope(day) || day, scope.category);
});
return _createElementVNode("div", _mergeProps({
"class": "v-calendar-category__column-header"
}, events), [slots.category?.(scope) ?? genDayHeaderCategoryTitle(headerTitle), slots['day-header']?.(scope)]);
}
function genDayHeaderCategoryTitle(categoryName) {
return _createElementVNode("div", {
"class": "v-calendar-category__category"
}, [categoryName === null ? props.categoryForInvalid : categoryName]);
}
function genDays() {
const days = [];
base.days.value.forEach((d, j) => {
const day = new Array(parsedCategories.value.length || 1);
day.fill(d);
days.push(...day.map((v, i) => genDay(v, j, i)));
});
return days;
}
function genDay(day, index, categoryIndex) {
const category = parsedCategories.value[categoryIndex];
const events = getPrefixedEventHandlers(attrs, ':time', e => {
return base.getSlotScope(base.getTimestampAtEvent(e, day));
});
return _createElementVNode("div", _mergeProps({
"key": day.date + '-' + categoryIndex,
"class": ['v-calendar-daily__day', base.getRelativeClasses(day)]
}, events), [genDayIntervals(index, category), genDayBody(day, category)]);
}
function genDayIntervals(index, category) {
return base.intervals.value[index].map(v => genDayInterval(v, category));
}
function genDayInterval(interval, category) {
const height = convertToUnit(props.intervalHeight);
const styler = props.intervalStyle || base.intervalStyleDefault;
return _createElementVNode("div", {
"key": interval.time,
"class": "v-calendar-daily__day-interval",
"style": _normalizeStyle([{
height
}, styler({
...interval,
category
})])
}, [slots.interval?.(getCategoryScope(base.getSlotScope(interval), category))]);
}
function genDayBody(day, category) {
return _createElementVNode("div", {
"class": "v-calendar-category__columns"
}, [genDayBodyCategory(day, category)]);
}
function genDayBodyCategory(day, category) {
const events = getPrefixedEventHandlers(attrs, ':timeCategory', e => {
return getCategoryScope(base.getSlotScope(base.getTimestampAtEvent(e, day)), category);
});
return _createElementVNode("div", _mergeProps({
"class": "v-calendar-category__column"
}, events), [slots['day-body']?.(getCategoryScope(base.getSlotScope(day), category))]);
}
useRender(() => _createVNode(VCalendarDaily, _mergeProps({
"class": ['v-calendar-daily', 'v-calendar-category']
}, props), {
...slots,
days: genDays,
'day-header': genDayHeader
}));
return {
...base,
parsedCategories
};
}
});
//# sourceMappingURL=VCalendarCategory.js.map
File diff suppressed because one or more lines are too long
@@ -0,0 +1,105 @@
@use '../../styles/tools'
@use '../../styles/settings'
@use './variables' as *
@include tools.layer('components')
.v-calendar-category
.v-calendar-category__column,
.v-calendar-category__column-header
border-right: $calendar-grid-color $calendar-line-width solid
.v-calendar-daily__head
background: $calendar-background
color: $calendar-on-background
.v-calendar-daily__intervals-head
background: $calendar-background
color: $calendar-on-background
.v-calendar-daily__intervals-body
background: $calendar-background
color: $calendar-on-background
.v-calendar-category
overflow: auto
position: relative
.v-calendar-category__category
text-align: center
.v-calendar-daily__day-container
width: min-content
.v-calendar-category__columns
position: absolute
height: 100%
width: 100%
top: 0
.v-calendar-daily__day-body
display: flex
flex: 1
width: 100%
height: 100%
.v-calendar-daily__head
flex-direction: row
width: min-content
min-width: 100%
position: sticky
top: 0
z-index: 2
.v-calendar-daily_head-day
width: auto
position: unset
.v-calendar-daily__intervals-head
position: sticky
left: 0
top: 0
z-index: 2
.v-calendar-daily_head-weekday
position: sticky
left: 50%
width: $calendar-daily-head-weekday-size
.v-calendar-daily_head-day-label
width: $calendar-daily-head-day-label-size
position: sticky
left: 50%
.v-calendar-daily__day
min-width: $calendar-category-column-min-width
.v-calendar-daily__intervals-body
position: sticky
left: 0
z-index: 1
.v-calendar-daily__interval
&:last-of-type::after
display: none
.v-calendar-daily__body
overflow: visible
.v-calendar-daily__scroll-area
overflow-y: visible
flex: none
.v-calendar-daily__pane
overflow-y: visible
.v-calendar-category__columns
display: flex
width: min-content
min-width: 100%
.v-calendar-category__column,
.v-calendar-category__column-header
flex: 1 1 auto
width: 0
position: relative
.v-calendar-category__column-header
min-width: $calendar-category-column-min-width
@@ -0,0 +1,139 @@
@layer vuetify-components {
.v-calendar-daily {
background-color: rgb(var(--v-theme-surface));
color: rgb(var(--v-theme-on-surface));
border-left: rgba(var(--v-border-color), var(--v-border-opacity)) 1px solid;
border-top: rgba(var(--v-border-color), var(--v-border-opacity)) 1px solid;
}
.v-calendar-daily .v-calendar-daily__intervals-head {
border-right: rgba(var(--v-border-color), var(--v-border-opacity)) 1px solid;
}
.v-calendar-daily .v-calendar-daily__intervals-head::after {
background: rgba(var(--v-border-color), var(--v-border-opacity));
background: linear-gradient(90deg, transparent, rgba(var(--v-border-color), var(--v-border-opacity)));
}
.v-calendar-daily .v-calendar-daily_head-day {
border-right: rgba(var(--v-border-color), var(--v-border-opacity)) 1px solid;
border-bottom: rgba(var(--v-border-color), var(--v-border-opacity)) 1px solid;
}
.v-calendar-daily .v-calendar-daily_head-day.v-past .v-calendar-daily_head-weekday,
.v-calendar-daily .v-calendar-daily_head-day.v-past .v-calendar-daily_head-day-label {
color: rgb(var(--v-theme-on-surface));
}
.v-calendar-daily .v-calendar-daily__intervals-body {
border-right: rgba(var(--v-border-color), var(--v-border-opacity)) 1px solid;
}
.v-calendar-daily .v-calendar-daily__intervals-body .v-calendar-daily__interval-text {
color: rgb(var(--v-theme-on-surface));
}
.v-calendar-daily .v-calendar-daily__day {
border-right: rgba(var(--v-border-color), var(--v-border-opacity)) 1px solid;
border-bottom: rgba(var(--v-border-color), var(--v-border-opacity)) 1px solid;
}
.v-calendar-daily .v-calendar-daily__day-interval {
border-top: rgba(var(--v-border-color), var(--v-border-opacity)) 1px solid;
}
.v-calendar-daily .v-calendar-daily__day-interval:first-child {
border-top: none;
}
.v-calendar-daily .v-calendar-daily__interval::after {
border-top: rgba(var(--v-border-color), var(--v-border-opacity)) 1px solid;
}
.v-calendar-daily {
display: flex;
flex-direction: column;
overflow: hidden;
height: 100%;
}
.v-calendar-daily__head {
flex: none;
display: flex;
}
.v-calendar-daily__intervals-head {
flex: none;
position: relative;
}
.v-calendar-daily__intervals-head::after {
position: absolute;
bottom: 0px;
height: 1px;
left: 0;
right: 0;
content: "";
}
.v-calendar-daily_head-day {
flex: 1 1 auto;
width: 0;
position: relative;
}
.v-calendar-daily_head-weekday {
user-select: none;
padding: 3px 0px 0px 0px;
font-size: 11px;
text-align: center;
text-transform: uppercase;
}
.v-calendar-daily_head-day-label {
user-select: none;
padding: 0px 0px 3px 0px;
cursor: pointer;
text-align: center;
}
.v-calendar-daily__body {
flex: 1 1 60%;
overflow: hidden;
display: flex;
position: relative;
flex-direction: column;
}
.v-calendar-daily__scroll-area {
overflow-y: scroll;
flex: 1 1 auto;
display: flex;
align-items: flex-start;
}
.v-calendar-daily__pane {
width: 100%;
overflow-y: hidden;
flex: none;
display: flex;
align-items: flex-start;
}
.v-calendar-daily__day-container {
display: flex;
flex: 1;
width: 100%;
height: 100%;
}
.v-calendar-daily__intervals-body {
flex: none;
user-select: none;
}
.v-calendar-daily__interval {
text-align: right;
padding-right: 8px;
border-bottom: none;
position: relative;
}
.v-calendar-daily__interval::after {
width: 8px;
position: absolute;
height: 1px;
display: block;
content: "";
right: 0;
bottom: -1px;
}
.v-calendar-daily__interval-text {
display: block;
position: relative;
top: -6px;
font-size: 10px;
padding-right: 4px;
}
.v-calendar-daily__day {
flex: 1;
width: 0;
position: relative;
}
}
@@ -0,0 +1,808 @@
import type { CalendarTimestamp } from './types.js';
export declare const VCalendarDaily: {
new (...args: any[]): import("vue").CreateComponentPublicInstanceWithMixins<Readonly<import("vue").ExtractPropTypes<{
start: {
type: (DateConstructor | NumberConstructor | StringConstructor)[];
validate: typeof import("./util/timestamp.js").validateTimestamp;
default: () => string;
};
end: {
type: (DateConstructor | NumberConstructor | StringConstructor)[];
validate: typeof import("./util/timestamp.js").validateTimestamp;
};
weekdays: {
type: import("vue").PropType<string | number[]>;
default: () => number[];
validate: typeof import("./util/timestamp.js").validateWeekdays;
};
firstDayOfWeek: (NumberConstructor | StringConstructor)[];
firstDayOfYear: (NumberConstructor | StringConstructor)[];
weekdayFormat: {
type: import("vue").PropType<import("./types.js").CalendarFormatter>;
default: null;
};
dayFormat: {
type: import("vue").PropType<import("./types.js").CalendarFormatter>;
default: null;
};
locale: StringConstructor;
now: {
type: StringConstructor;
validator: typeof import("./util/timestamp.js").validateTimestamp;
};
type: {
type: import("vue").PropType<"4day" | "category" | "custom-daily" | "custom-weekly" | "day" | "month" | "week">;
default: string;
};
maxDays: {
type: NumberConstructor;
default: number;
};
intervalHeight: {
type: (NumberConstructor | StringConstructor)[];
default: number;
validate: typeof import("./util/timestamp.js").validateNumber;
};
intervalWidth: {
type: (NumberConstructor | StringConstructor)[];
default: number;
validate: typeof import("./util/timestamp.js").validateNumber;
};
intervalMinutes: {
type: (NumberConstructor | StringConstructor)[];
default: number;
validate: typeof import("./util/timestamp.js").validateNumber;
};
firstInterval: {
type: (NumberConstructor | StringConstructor)[];
default: number;
validate: typeof import("./util/timestamp.js").validateNumber;
};
firstTime: {
type: import("vue").PropType<import("./util/timestamp.js").VTime>;
validate: typeof import("./util/timestamp.js").validateTime;
};
intervalCount: {
type: (NumberConstructor | StringConstructor)[];
default: number;
validate: typeof import("./util/timestamp.js").validateNumber;
};
intervalFormat: {
type: import("vue").PropType<import("./types.js").CalendarFormatter>;
default: null;
};
intervalStyle: {
type: import("vue").PropType<(interval: CalendarTimestamp) => import("vue").StyleValue>;
default: null;
};
showIntervalLabel: {
type: import("vue").PropType<(interval: CalendarTimestamp) => boolean>;
default: null;
};
color: StringConstructor;
shortWeekdays: {
type: BooleanConstructor;
default: boolean;
};
shortIntervals: {
type: BooleanConstructor;
default: boolean;
};
hideHeader: BooleanConstructor;
}>>, {
times: {
now: {
date: string;
time: string;
year: number;
month: number;
day: number;
weekday: number;
hour: number;
minute: number;
hasDay: boolean;
hasTime: boolean;
past: boolean;
present: boolean;
future: boolean;
category?: import("./types.js").CalendarCategory;
};
today: {
date: string;
time: string;
year: number;
month: number;
day: number;
weekday: number;
hour: number;
minute: number;
hasDay: boolean;
hasTime: boolean;
past: boolean;
present: boolean;
future: boolean;
category?: import("./types.js").CalendarCategory;
};
};
locale: {
name: string;
decimalSeparator: import("vue").ShallowRef<string>;
messages: import("vue").Ref<import("../../types.js").LocaleMessages, import("../../types.js").LocaleMessages>;
current: import("vue").Ref<string, string>;
fallback: import("vue").Ref<string, string>;
t: (key: string, ...params: unknown[]) => string;
n: (value: number) => string;
provide: (props: import("../../types.js").LocaleOptions) => import("../../types.js").LocaleInstance;
isRtl: import("vue").Ref<boolean, boolean>;
rtl: import("vue").Ref<Record<string, boolean>, Record<string, boolean>>;
rtlClasses: import("vue").Ref<string, string>;
};
parsedValue: import("vue").ComputedRef<CalendarTimestamp>;
parsedWeekdays: import("vue").ComputedRef<number[]>;
effectiveWeekdays: import("vue").ComputedRef<number[]>;
weekdaySkips: import("vue").ComputedRef<number[]>;
parsedStart: import("vue").ComputedRef<CalendarTimestamp>;
parsedEnd: import("vue").ComputedRef<CalendarTimestamp>;
dayFormatter: import("vue").ComputedRef<import("./types.js").CalendarFormatter>;
weekdayFormatter: import("vue").ComputedRef<import("./types.js").CalendarFormatter>;
getColorProps: (colors: {
background?: import("../../composables/color.js").ColorValue;
text?: import("../../composables/color.js").ColorValue;
}) => {
class: string[];
style: import("vue").CSSProperties;
};
getRelativeClasses: (timestamp: CalendarTimestamp, outside?: boolean) => {
'v-present': boolean;
'v-past': boolean;
'v-future': boolean;
'v-outside': boolean;
};
getWeekNumber: (timestamp: CalendarTimestamp) => number;
getStartOfWeek: (timestamp: CalendarTimestamp) => CalendarTimestamp;
getEndOfWeek: (timestamp: CalendarTimestamp) => CalendarTimestamp;
getFormatter: (options: Intl.DateTimeFormatOptions) => import("./types.js").CalendarFormatter;
updateTimes: () => void;
scrollAreaRef: import("vue").ShallowRef<HTMLElement | undefined, HTMLElement | undefined>;
parsedFirstInterval: import("vue").ComputedRef<number>;
parsedIntervalMinutes: import("vue").ComputedRef<number>;
parsedIntervalCount: import("vue").ComputedRef<number>;
parsedIntervalHeight: import("vue").ComputedRef<number>;
parsedFirstTime: import("vue").ComputedRef<number | false>;
firstMinute: import("vue").ComputedRef<number>;
bodyHeight: import("vue").ComputedRef<number>;
days: import("vue").ComputedRef<CalendarTimestamp[]>;
intervals: import("vue").ComputedRef<CalendarTimestamp[][]>;
intervalFormatter: import("vue").ComputedRef<import("./types.js").CalendarFormatter>;
showIntervalLabelDefault: (interval: CalendarTimestamp) => boolean;
intervalStyleDefault: (_interval: CalendarTimestamp) => import("vue").StyleValue;
getTimestampAtEvent: (e: Event, day: CalendarTimestamp) => CalendarTimestamp;
getSlotScope: (timestamp: CalendarTimestamp) => import("./types.js").CalendarDayBodySlotScope;
scrollToTime: (time: import("./util/timestamp.js").VTime) => boolean;
minutesToPixels: (minutes: number) => number;
timeToY: (time: import("./util/timestamp.js").VTime | CalendarTimestamp, targetDateOrClamp?: CalendarTimestamp | boolean) => number | false;
timeDelta: (time: import("./util/timestamp.js").VTime | CalendarTimestamp, targetDate?: CalendarTimestamp) => number | false;
scrollPush: import("vue").Ref<number, number>;
pane: import("vue").Ref<HTMLElement | undefined, HTMLElement | undefined>;
init: () => void;
onResize: () => void;
getScrollPush: () => number;
}, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, import("vue").PublicProps, {
start: string | number | Date;
weekdays: string | number[];
weekdayFormat: import("./types.js").CalendarFormatter;
dayFormat: import("./types.js").CalendarFormatter;
type: "4day" | "category" | "custom-daily" | "custom-weekly" | "day" | "month" | "week";
maxDays: number;
intervalHeight: string | number;
intervalWidth: string | number;
intervalMinutes: string | number;
firstInterval: string | number;
intervalCount: string | number;
intervalFormat: import("./types.js").CalendarFormatter;
intervalStyle: (interval: CalendarTimestamp) => import("vue").StyleValue;
showIntervalLabel: (interval: CalendarTimestamp) => boolean;
shortWeekdays: boolean;
shortIntervals: boolean;
hideHeader: boolean;
}, true, {}, {}, import("vue").GlobalComponents, import("vue").GlobalDirectives, string, {}, any, import("vue").ComponentProvideOptions, {
P: {};
B: {};
D: {};
C: {};
M: {};
Defaults: {};
}, Readonly<import("vue").ExtractPropTypes<{
start: {
type: (DateConstructor | NumberConstructor | StringConstructor)[];
validate: typeof import("./util/timestamp.js").validateTimestamp;
default: () => string;
};
end: {
type: (DateConstructor | NumberConstructor | StringConstructor)[];
validate: typeof import("./util/timestamp.js").validateTimestamp;
};
weekdays: {
type: import("vue").PropType<string | number[]>;
default: () => number[];
validate: typeof import("./util/timestamp.js").validateWeekdays;
};
firstDayOfWeek: (NumberConstructor | StringConstructor)[];
firstDayOfYear: (NumberConstructor | StringConstructor)[];
weekdayFormat: {
type: import("vue").PropType<import("./types.js").CalendarFormatter>;
default: null;
};
dayFormat: {
type: import("vue").PropType<import("./types.js").CalendarFormatter>;
default: null;
};
locale: StringConstructor;
now: {
type: StringConstructor;
validator: typeof import("./util/timestamp.js").validateTimestamp;
};
type: {
type: import("vue").PropType<"4day" | "category" | "custom-daily" | "custom-weekly" | "day" | "month" | "week">;
default: string;
};
maxDays: {
type: NumberConstructor;
default: number;
};
intervalHeight: {
type: (NumberConstructor | StringConstructor)[];
default: number;
validate: typeof import("./util/timestamp.js").validateNumber;
};
intervalWidth: {
type: (NumberConstructor | StringConstructor)[];
default: number;
validate: typeof import("./util/timestamp.js").validateNumber;
};
intervalMinutes: {
type: (NumberConstructor | StringConstructor)[];
default: number;
validate: typeof import("./util/timestamp.js").validateNumber;
};
firstInterval: {
type: (NumberConstructor | StringConstructor)[];
default: number;
validate: typeof import("./util/timestamp.js").validateNumber;
};
firstTime: {
type: import("vue").PropType<import("./util/timestamp.js").VTime>;
validate: typeof import("./util/timestamp.js").validateTime;
};
intervalCount: {
type: (NumberConstructor | StringConstructor)[];
default: number;
validate: typeof import("./util/timestamp.js").validateNumber;
};
intervalFormat: {
type: import("vue").PropType<import("./types.js").CalendarFormatter>;
default: null;
};
intervalStyle: {
type: import("vue").PropType<(interval: CalendarTimestamp) => import("vue").StyleValue>;
default: null;
};
showIntervalLabel: {
type: import("vue").PropType<(interval: CalendarTimestamp) => boolean>;
default: null;
};
color: StringConstructor;
shortWeekdays: {
type: BooleanConstructor;
default: boolean;
};
shortIntervals: {
type: BooleanConstructor;
default: boolean;
};
hideHeader: BooleanConstructor;
}>>, {
times: {
now: {
date: string;
time: string;
year: number;
month: number;
day: number;
weekday: number;
hour: number;
minute: number;
hasDay: boolean;
hasTime: boolean;
past: boolean;
present: boolean;
future: boolean;
category?: import("./types.js").CalendarCategory;
};
today: {
date: string;
time: string;
year: number;
month: number;
day: number;
weekday: number;
hour: number;
minute: number;
hasDay: boolean;
hasTime: boolean;
past: boolean;
present: boolean;
future: boolean;
category?: import("./types.js").CalendarCategory;
};
};
locale: {
name: string;
decimalSeparator: import("vue").ShallowRef<string>;
messages: import("vue").Ref<import("../../types.js").LocaleMessages, import("../../types.js").LocaleMessages>;
current: import("vue").Ref<string, string>;
fallback: import("vue").Ref<string, string>;
t: (key: string, ...params: unknown[]) => string;
n: (value: number) => string;
provide: (props: import("../../types.js").LocaleOptions) => import("../../types.js").LocaleInstance;
isRtl: import("vue").Ref<boolean, boolean>;
rtl: import("vue").Ref<Record<string, boolean>, Record<string, boolean>>;
rtlClasses: import("vue").Ref<string, string>;
};
parsedValue: import("vue").ComputedRef<CalendarTimestamp>;
parsedWeekdays: import("vue").ComputedRef<number[]>;
effectiveWeekdays: import("vue").ComputedRef<number[]>;
weekdaySkips: import("vue").ComputedRef<number[]>;
parsedStart: import("vue").ComputedRef<CalendarTimestamp>;
parsedEnd: import("vue").ComputedRef<CalendarTimestamp>;
dayFormatter: import("vue").ComputedRef<import("./types.js").CalendarFormatter>;
weekdayFormatter: import("vue").ComputedRef<import("./types.js").CalendarFormatter>;
getColorProps: (colors: {
background?: import("../../composables/color.js").ColorValue;
text?: import("../../composables/color.js").ColorValue;
}) => {
class: string[];
style: import("vue").CSSProperties;
};
getRelativeClasses: (timestamp: CalendarTimestamp, outside?: boolean) => {
'v-present': boolean;
'v-past': boolean;
'v-future': boolean;
'v-outside': boolean;
};
getWeekNumber: (timestamp: CalendarTimestamp) => number;
getStartOfWeek: (timestamp: CalendarTimestamp) => CalendarTimestamp;
getEndOfWeek: (timestamp: CalendarTimestamp) => CalendarTimestamp;
getFormatter: (options: Intl.DateTimeFormatOptions) => import("./types.js").CalendarFormatter;
updateTimes: () => void;
scrollAreaRef: import("vue").ShallowRef<HTMLElement | undefined, HTMLElement | undefined>;
parsedFirstInterval: import("vue").ComputedRef<number>;
parsedIntervalMinutes: import("vue").ComputedRef<number>;
parsedIntervalCount: import("vue").ComputedRef<number>;
parsedIntervalHeight: import("vue").ComputedRef<number>;
parsedFirstTime: import("vue").ComputedRef<number | false>;
firstMinute: import("vue").ComputedRef<number>;
bodyHeight: import("vue").ComputedRef<number>;
days: import("vue").ComputedRef<CalendarTimestamp[]>;
intervals: import("vue").ComputedRef<CalendarTimestamp[][]>;
intervalFormatter: import("vue").ComputedRef<import("./types.js").CalendarFormatter>;
showIntervalLabelDefault: (interval: CalendarTimestamp) => boolean;
intervalStyleDefault: (_interval: CalendarTimestamp) => import("vue").StyleValue;
getTimestampAtEvent: (e: Event, day: CalendarTimestamp) => CalendarTimestamp;
getSlotScope: (timestamp: CalendarTimestamp) => import("./types.js").CalendarDayBodySlotScope;
scrollToTime: (time: import("./util/timestamp.js").VTime) => boolean;
minutesToPixels: (minutes: number) => number;
timeToY: (time: import("./util/timestamp.js").VTime | CalendarTimestamp, targetDateOrClamp?: CalendarTimestamp | boolean) => number | false;
timeDelta: (time: import("./util/timestamp.js").VTime | CalendarTimestamp, targetDate?: CalendarTimestamp) => number | false;
scrollPush: import("vue").Ref<number, number>;
pane: import("vue").Ref<HTMLElement | undefined, HTMLElement | undefined>;
init: () => void;
onResize: () => void;
getScrollPush: () => number;
}, {}, {}, {}, {
start: string | number | Date;
weekdays: string | number[];
weekdayFormat: import("./types.js").CalendarFormatter;
dayFormat: import("./types.js").CalendarFormatter;
type: "4day" | "category" | "custom-daily" | "custom-weekly" | "day" | "month" | "week";
maxDays: number;
intervalHeight: string | number;
intervalWidth: string | number;
intervalMinutes: string | number;
firstInterval: string | number;
intervalCount: string | number;
intervalFormat: import("./types.js").CalendarFormatter;
intervalStyle: (interval: CalendarTimestamp) => import("vue").StyleValue;
showIntervalLabel: (interval: CalendarTimestamp) => boolean;
shortWeekdays: boolean;
shortIntervals: boolean;
hideHeader: boolean;
}>;
__isFragment?: never;
__isTeleport?: never;
__isSuspense?: never;
} & import("vue").ComponentOptionsBase<Readonly<import("vue").ExtractPropTypes<{
start: {
type: (DateConstructor | NumberConstructor | StringConstructor)[];
validate: typeof import("./util/timestamp.js").validateTimestamp;
default: () => string;
};
end: {
type: (DateConstructor | NumberConstructor | StringConstructor)[];
validate: typeof import("./util/timestamp.js").validateTimestamp;
};
weekdays: {
type: import("vue").PropType<string | number[]>;
default: () => number[];
validate: typeof import("./util/timestamp.js").validateWeekdays;
};
firstDayOfWeek: (NumberConstructor | StringConstructor)[];
firstDayOfYear: (NumberConstructor | StringConstructor)[];
weekdayFormat: {
type: import("vue").PropType<import("./types.js").CalendarFormatter>;
default: null;
};
dayFormat: {
type: import("vue").PropType<import("./types.js").CalendarFormatter>;
default: null;
};
locale: StringConstructor;
now: {
type: StringConstructor;
validator: typeof import("./util/timestamp.js").validateTimestamp;
};
type: {
type: import("vue").PropType<"4day" | "category" | "custom-daily" | "custom-weekly" | "day" | "month" | "week">;
default: string;
};
maxDays: {
type: NumberConstructor;
default: number;
};
intervalHeight: {
type: (NumberConstructor | StringConstructor)[];
default: number;
validate: typeof import("./util/timestamp.js").validateNumber;
};
intervalWidth: {
type: (NumberConstructor | StringConstructor)[];
default: number;
validate: typeof import("./util/timestamp.js").validateNumber;
};
intervalMinutes: {
type: (NumberConstructor | StringConstructor)[];
default: number;
validate: typeof import("./util/timestamp.js").validateNumber;
};
firstInterval: {
type: (NumberConstructor | StringConstructor)[];
default: number;
validate: typeof import("./util/timestamp.js").validateNumber;
};
firstTime: {
type: import("vue").PropType<import("./util/timestamp.js").VTime>;
validate: typeof import("./util/timestamp.js").validateTime;
};
intervalCount: {
type: (NumberConstructor | StringConstructor)[];
default: number;
validate: typeof import("./util/timestamp.js").validateNumber;
};
intervalFormat: {
type: import("vue").PropType<import("./types.js").CalendarFormatter>;
default: null;
};
intervalStyle: {
type: import("vue").PropType<(interval: CalendarTimestamp) => import("vue").StyleValue>;
default: null;
};
showIntervalLabel: {
type: import("vue").PropType<(interval: CalendarTimestamp) => boolean>;
default: null;
};
color: StringConstructor;
shortWeekdays: {
type: BooleanConstructor;
default: boolean;
};
shortIntervals: {
type: BooleanConstructor;
default: boolean;
};
hideHeader: BooleanConstructor;
}>>, {
times: {
now: {
date: string;
time: string;
year: number;
month: number;
day: number;
weekday: number;
hour: number;
minute: number;
hasDay: boolean;
hasTime: boolean;
past: boolean;
present: boolean;
future: boolean;
category?: import("./types.js").CalendarCategory;
};
today: {
date: string;
time: string;
year: number;
month: number;
day: number;
weekday: number;
hour: number;
minute: number;
hasDay: boolean;
hasTime: boolean;
past: boolean;
present: boolean;
future: boolean;
category?: import("./types.js").CalendarCategory;
};
};
locale: {
name: string;
decimalSeparator: import("vue").ShallowRef<string>;
messages: import("vue").Ref<import("../../types.js").LocaleMessages, import("../../types.js").LocaleMessages>;
current: import("vue").Ref<string, string>;
fallback: import("vue").Ref<string, string>;
t: (key: string, ...params: unknown[]) => string;
n: (value: number) => string;
provide: (props: import("../../types.js").LocaleOptions) => import("../../types.js").LocaleInstance;
isRtl: import("vue").Ref<boolean, boolean>;
rtl: import("vue").Ref<Record<string, boolean>, Record<string, boolean>>;
rtlClasses: import("vue").Ref<string, string>;
};
parsedValue: import("vue").ComputedRef<CalendarTimestamp>;
parsedWeekdays: import("vue").ComputedRef<number[]>;
effectiveWeekdays: import("vue").ComputedRef<number[]>;
weekdaySkips: import("vue").ComputedRef<number[]>;
parsedStart: import("vue").ComputedRef<CalendarTimestamp>;
parsedEnd: import("vue").ComputedRef<CalendarTimestamp>;
dayFormatter: import("vue").ComputedRef<import("./types.js").CalendarFormatter>;
weekdayFormatter: import("vue").ComputedRef<import("./types.js").CalendarFormatter>;
getColorProps: (colors: {
background?: import("../../composables/color.js").ColorValue;
text?: import("../../composables/color.js").ColorValue;
}) => {
class: string[];
style: import("vue").CSSProperties;
};
getRelativeClasses: (timestamp: CalendarTimestamp, outside?: boolean) => {
'v-present': boolean;
'v-past': boolean;
'v-future': boolean;
'v-outside': boolean;
};
getWeekNumber: (timestamp: CalendarTimestamp) => number;
getStartOfWeek: (timestamp: CalendarTimestamp) => CalendarTimestamp;
getEndOfWeek: (timestamp: CalendarTimestamp) => CalendarTimestamp;
getFormatter: (options: Intl.DateTimeFormatOptions) => import("./types.js").CalendarFormatter;
updateTimes: () => void;
scrollAreaRef: import("vue").ShallowRef<HTMLElement | undefined, HTMLElement | undefined>;
parsedFirstInterval: import("vue").ComputedRef<number>;
parsedIntervalMinutes: import("vue").ComputedRef<number>;
parsedIntervalCount: import("vue").ComputedRef<number>;
parsedIntervalHeight: import("vue").ComputedRef<number>;
parsedFirstTime: import("vue").ComputedRef<number | false>;
firstMinute: import("vue").ComputedRef<number>;
bodyHeight: import("vue").ComputedRef<number>;
days: import("vue").ComputedRef<CalendarTimestamp[]>;
intervals: import("vue").ComputedRef<CalendarTimestamp[][]>;
intervalFormatter: import("vue").ComputedRef<import("./types.js").CalendarFormatter>;
showIntervalLabelDefault: (interval: CalendarTimestamp) => boolean;
intervalStyleDefault: (_interval: CalendarTimestamp) => import("vue").StyleValue;
getTimestampAtEvent: (e: Event, day: CalendarTimestamp) => CalendarTimestamp;
getSlotScope: (timestamp: CalendarTimestamp) => import("./types.js").CalendarDayBodySlotScope;
scrollToTime: (time: import("./util/timestamp.js").VTime) => boolean;
minutesToPixels: (minutes: number) => number;
timeToY: (time: import("./util/timestamp.js").VTime | CalendarTimestamp, targetDateOrClamp?: CalendarTimestamp | boolean) => number | false;
timeDelta: (time: import("./util/timestamp.js").VTime | CalendarTimestamp, targetDate?: CalendarTimestamp) => number | false;
scrollPush: import("vue").Ref<number, number>;
pane: import("vue").Ref<HTMLElement | undefined, HTMLElement | undefined>;
init: () => void;
onResize: () => void;
getScrollPush: () => number;
}, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, {
start: string | number | Date;
weekdays: string | number[];
weekdayFormat: import("./types.js").CalendarFormatter;
dayFormat: import("./types.js").CalendarFormatter;
type: "4day" | "category" | "custom-daily" | "custom-weekly" | "day" | "month" | "week";
maxDays: number;
intervalHeight: string | number;
intervalWidth: string | number;
intervalMinutes: string | number;
firstInterval: string | number;
intervalCount: string | number;
intervalFormat: import("./types.js").CalendarFormatter;
intervalStyle: (interval: CalendarTimestamp) => import("vue").StyleValue;
showIntervalLabel: (interval: CalendarTimestamp) => boolean;
shortWeekdays: boolean;
shortIntervals: boolean;
hideHeader: boolean;
}, {}, string, {}, import("vue").GlobalComponents, import("vue").GlobalDirectives, string, import("vue").ComponentProvideOptions> & import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps & import("../../util/index.js").FilterPropsOptions<{
start: {
type: (DateConstructor | NumberConstructor | StringConstructor)[];
validate: typeof import("./util/timestamp.js").validateTimestamp;
default: () => string;
};
end: {
type: (DateConstructor | NumberConstructor | StringConstructor)[];
validate: typeof import("./util/timestamp.js").validateTimestamp;
};
weekdays: {
type: import("vue").PropType<string | number[]>;
default: () => number[];
validate: typeof import("./util/timestamp.js").validateWeekdays;
};
firstDayOfWeek: (NumberConstructor | StringConstructor)[];
firstDayOfYear: (NumberConstructor | StringConstructor)[];
weekdayFormat: {
type: import("vue").PropType<import("./types.js").CalendarFormatter>;
default: null;
};
dayFormat: {
type: import("vue").PropType<import("./types.js").CalendarFormatter>;
default: null;
};
locale: StringConstructor;
now: {
type: StringConstructor;
validator: typeof import("./util/timestamp.js").validateTimestamp;
};
type: {
type: import("vue").PropType<"4day" | "category" | "custom-daily" | "custom-weekly" | "day" | "month" | "week">;
default: string;
};
maxDays: {
type: NumberConstructor;
default: number;
};
intervalHeight: {
type: (NumberConstructor | StringConstructor)[];
default: number;
validate: typeof import("./util/timestamp.js").validateNumber;
};
intervalWidth: {
type: (NumberConstructor | StringConstructor)[];
default: number;
validate: typeof import("./util/timestamp.js").validateNumber;
};
intervalMinutes: {
type: (NumberConstructor | StringConstructor)[];
default: number;
validate: typeof import("./util/timestamp.js").validateNumber;
};
firstInterval: {
type: (NumberConstructor | StringConstructor)[];
default: number;
validate: typeof import("./util/timestamp.js").validateNumber;
};
firstTime: {
type: import("vue").PropType<import("./util/timestamp.js").VTime>;
validate: typeof import("./util/timestamp.js").validateTime;
};
intervalCount: {
type: (NumberConstructor | StringConstructor)[];
default: number;
validate: typeof import("./util/timestamp.js").validateNumber;
};
intervalFormat: {
type: import("vue").PropType<import("./types.js").CalendarFormatter>;
default: null;
};
intervalStyle: {
type: import("vue").PropType<(interval: CalendarTimestamp) => import("vue").StyleValue>;
default: null;
};
showIntervalLabel: {
type: import("vue").PropType<(interval: CalendarTimestamp) => boolean>;
default: null;
};
color: StringConstructor;
shortWeekdays: {
type: BooleanConstructor;
default: boolean;
};
shortIntervals: {
type: BooleanConstructor;
default: boolean;
};
hideHeader: BooleanConstructor;
}, import("vue").ExtractPropTypes<{
start: {
type: (DateConstructor | NumberConstructor | StringConstructor)[];
validate: typeof import("./util/timestamp.js").validateTimestamp;
default: () => string;
};
end: {
type: (DateConstructor | NumberConstructor | StringConstructor)[];
validate: typeof import("./util/timestamp.js").validateTimestamp;
};
weekdays: {
type: import("vue").PropType<string | number[]>;
default: () => number[];
validate: typeof import("./util/timestamp.js").validateWeekdays;
};
firstDayOfWeek: (NumberConstructor | StringConstructor)[];
firstDayOfYear: (NumberConstructor | StringConstructor)[];
weekdayFormat: {
type: import("vue").PropType<import("./types.js").CalendarFormatter>;
default: null;
};
dayFormat: {
type: import("vue").PropType<import("./types.js").CalendarFormatter>;
default: null;
};
locale: StringConstructor;
now: {
type: StringConstructor;
validator: typeof import("./util/timestamp.js").validateTimestamp;
};
type: {
type: import("vue").PropType<"4day" | "category" | "custom-daily" | "custom-weekly" | "day" | "month" | "week">;
default: string;
};
maxDays: {
type: NumberConstructor;
default: number;
};
intervalHeight: {
type: (NumberConstructor | StringConstructor)[];
default: number;
validate: typeof import("./util/timestamp.js").validateNumber;
};
intervalWidth: {
type: (NumberConstructor | StringConstructor)[];
default: number;
validate: typeof import("./util/timestamp.js").validateNumber;
};
intervalMinutes: {
type: (NumberConstructor | StringConstructor)[];
default: number;
validate: typeof import("./util/timestamp.js").validateNumber;
};
firstInterval: {
type: (NumberConstructor | StringConstructor)[];
default: number;
validate: typeof import("./util/timestamp.js").validateNumber;
};
firstTime: {
type: import("vue").PropType<import("./util/timestamp.js").VTime>;
validate: typeof import("./util/timestamp.js").validateTime;
};
intervalCount: {
type: (NumberConstructor | StringConstructor)[];
default: number;
validate: typeof import("./util/timestamp.js").validateNumber;
};
intervalFormat: {
type: import("vue").PropType<import("./types.js").CalendarFormatter>;
default: null;
};
intervalStyle: {
type: import("vue").PropType<(interval: CalendarTimestamp) => import("vue").StyleValue>;
default: null;
};
showIntervalLabel: {
type: import("vue").PropType<(interval: CalendarTimestamp) => boolean>;
default: null;
};
color: StringConstructor;
shortWeekdays: {
type: BooleanConstructor;
default: boolean;
};
shortIntervals: {
type: BooleanConstructor;
default: boolean;
};
hideHeader: BooleanConstructor;
}>>;
export type VCalendarDaily = InstanceType<typeof VCalendarDaily>;
@@ -0,0 +1,213 @@
import { createElementVNode as _createElementVNode, mergeProps as _mergeProps, createVNode as _createVNode, normalizeStyle as _normalizeStyle, normalizeClass as _normalizeClass, withDirectives as _withDirectives } from "vue";
// Components
import { VIconBtn } from "../../labs/VIconBtn/index.js"; // Composables
import { makeCalendarBaseProps } from "./composables/calendarBase.js";
import { makeCalendarWithIntervalsProps, useCalendarWithIntervals } from "./composables/calendarWithIntervals.js"; // Directives
import vResize from "../../directives/resize/index.js"; // Utilities
import { nextTick, onMounted, ref } from 'vue';
import { convertToUnit, defineComponent, getPrefixedEventHandlers, noop, useRender } from "../../util/index.js"; // Types
export const VCalendarDaily = defineComponent({
name: 'VCalendarDaily',
directives: {
vResize
},
props: {
color: String,
shortWeekdays: {
type: Boolean,
default: true
},
shortIntervals: {
type: Boolean,
default: true
},
hideHeader: Boolean,
...makeCalendarBaseProps(),
...makeCalendarWithIntervalsProps()
},
setup(props, {
slots,
attrs
}) {
const scrollPush = ref(0);
const pane = ref();
const base = useCalendarWithIntervals(props);
function init() {
nextTick(onResize);
}
function onResize() {
scrollPush.value = getScrollPush();
}
function getScrollPush() {
return base.scrollAreaRef.value && pane.value ? base.scrollAreaRef.value.offsetWidth - pane.value.offsetWidth : 0;
}
function genHead() {
return _createElementVNode("div", {
"class": "v-calendar-daily__head",
"style": {
marginRight: scrollPush.value + 'px'
}
}, [genHeadIntervals(), genHeadDays()]);
}
function genHeadIntervals() {
const width = convertToUnit(props.intervalWidth);
return _createElementVNode("div", {
"class": "v-calendar-daily__intervals-head",
"style": {
width
}
}, [slots['interval-header']?.()]);
}
function genHeadDays() {
return base.days.value.map(genHeadDay);
}
function genHeadDay(day, index) {
const events = getPrefixedEventHandlers(attrs, ':day', nativeEvent => ({
nativeEvent,
...base.getSlotScope(day)
}));
return _createElementVNode("div", _mergeProps({
"key": day.date,
"class": ['v-calendar-daily_head-day', base.getRelativeClasses(day)]
}, events), [genHeadWeekday(day), genHeadDayLabel(day), genDayHeader(day, index)]);
}
function genDayHeader(day, index) {
return slots['day-header']?.({
week: base.days.value,
...day,
index
}) ?? [];
}
function genHeadWeekday(day) {
const color = day.present ? props.color : undefined;
return _createElementVNode("div", _mergeProps(base.getColorProps({
text: color
}), {
"class": "v-calendar-daily_head-weekday"
}), [base.weekdayFormatter.value(day, props.shortWeekdays)]);
}
function genHeadDayLabel(day) {
return _createElementVNode("div", {
"class": "v-calendar-daily_head-day-label"
}, [slots['day-label-header']?.(day) ?? genHeadDayButton(day)]);
}
function genHeadDayButton(day) {
const events = getPrefixedEventHandlers(attrs, ':date', nativeEvent => ({
nativeEvent,
...day
}));
return _createVNode(VIconBtn, _mergeProps({
"active": day.present,
"activeColor": props.color,
"variant": "outlined",
"baseVariant": "text",
"onUpdate:active": noop
}, events), {
default: () => [base.dayFormatter.value(day, false)]
});
}
function genBody() {
return _createElementVNode("div", {
"class": "v-calendar-daily__body"
}, [genScrollArea()]);
}
function genScrollArea() {
return _createElementVNode("div", {
"ref": base.scrollAreaRef,
"class": "v-calendar-daily__scroll-area"
}, [genPane()]);
}
function genPane() {
return _createElementVNode("div", {
"ref": pane,
"class": "v-calendar-daily__pane",
"style": {
height: convertToUnit(base.bodyHeight.value)
}
}, [genDayContainer()]);
}
function genDayContainer() {
return _createElementVNode("div", {
"class": "v-calendar-daily__day-container"
}, [genBodyIntervals(), slots.days?.() ?? genDays()]);
}
function genDays() {
return base.days.value.map((day, index) => {
const events = getPrefixedEventHandlers(attrs, ':time', nativeEvent => ({
nativeEvent,
...base.getSlotScope(base.getTimestampAtEvent(nativeEvent, day))
}));
return _createElementVNode("div", _mergeProps({
"key": day.date,
"class": ['v-calendar-daily__day', base.getRelativeClasses(day)]
}, events), [genDayIntervals(index), genDayBody(day)]);
});
}
function genDayBody(day) {
return slots['day-body']?.(base.getSlotScope(day)) ?? [];
}
function genDayIntervals(index) {
return base.intervals.value[index].map(genDayInterval);
}
function genDayInterval(interval) {
const height = convertToUnit(props.intervalHeight);
const styler = props.intervalStyle || base.intervalStyleDefault;
return _createElementVNode("div", {
"class": "v-calendar-daily__day-interval",
"key": interval.time,
"style": _normalizeStyle([{
height
}, styler(interval)])
}, [slots.interval?.(base.getSlotScope(interval))]);
}
function genBodyIntervals() {
const width = convertToUnit(props.intervalWidth);
const events = getPrefixedEventHandlers(attrs, ':interval', nativeEvent => ({
nativeEvent,
...base.getTimestampAtEvent(nativeEvent, base.parsedStart.value)
}));
return _createElementVNode("div", _mergeProps({
"class": "v-calendar-daily__intervals-body",
"style": {
width
}
}, events), [genIntervalLabels()]);
}
function genIntervalLabels() {
if (!base.intervals.value.length) return null;
return base.intervals.value[0].map(genIntervalLabel);
}
function genIntervalLabel(interval) {
const height = convertToUnit(props.intervalHeight);
const short = props.shortIntervals;
const shower = props.showIntervalLabel || base.showIntervalLabelDefault;
const show = shower(interval);
const label = show ? base.intervalFormatter.value(interval, short) : undefined;
return _createElementVNode("div", {
"key": interval.time,
"class": "v-calendar-daily__interval",
"style": {
height
}
}, [_createElementVNode("div", {
"class": "v-calendar-daily__interval-text"
}, [label])]);
}
onMounted(init);
useRender(() => _withDirectives(_createElementVNode("div", {
"class": _normalizeClass(['v-calendar-daily', attrs.class]),
"onDragstart": e => e.preventDefault()
}, [!props.hideHeader ? genHead() : undefined, genBody()]), [[vResize, onResize, void 0, {
quiet: true
}]]));
return {
...base,
scrollPush,
pane,
init,
onResize,
getScrollPush
};
}
});
//# sourceMappingURL=VCalendarDaily.js.map
File diff suppressed because one or more lines are too long
@@ -0,0 +1,142 @@
@use '../../styles/tools'
@use '../../styles/settings'
@use './variables' as *
@include tools.layer('components')
.v-calendar-daily
background-color: $calendar-background
color: $calendar-on-background
border-left: $calendar-outline-color $calendar-line-width solid
border-top: $calendar-outline-color $calendar-line-width solid
.v-calendar-daily__intervals-head
border-right: $calendar-grid-color $calendar-line-width solid
&::after
background: $calendar-grid-color
background: linear-gradient(90deg, transparent, $calendar-grid-color)
.v-calendar-daily_head-day
border-right: $calendar-grid-color $calendar-line-width solid
border-bottom: $calendar-grid-color $calendar-line-width solid
&.v-past
.v-calendar-daily_head-weekday,
.v-calendar-daily_head-day-label
color: $calendar-past-color
.v-calendar-daily__intervals-body
border-right: $calendar-grid-color $calendar-line-width solid
.v-calendar-daily__interval-text
color: $calendar-interval-text-color
.v-calendar-daily__day
border-right: $calendar-grid-color $calendar-line-width solid
border-bottom: $calendar-grid-color $calendar-line-width solid
.v-calendar-daily__day-interval
border-top: $calendar-grid-color $calendar-line-width solid
&:first-child
border-top: none
.v-calendar-daily__interval::after
border-top: $calendar-grid-color $calendar-line-width solid
.v-calendar-daily
display: flex
flex-direction: column
overflow: hidden
height: 100%
.v-calendar-daily__head
flex: none
display: flex
.v-calendar-daily__intervals-head
flex: none
position: relative
&::after
position: absolute
bottom: 0px
height: $calendar-line-width
left: 0
right: 0
content: ''
.v-calendar-daily_head-day
flex: 1 1 auto
width: 0
position: relative
.v-calendar-daily_head-weekday
user-select: none
padding: $calendar-daily-weekday-padding
font-size: $calendar-daily-weekday-font-size
text-align: center
text-transform: uppercase
.v-calendar-daily_head-day-label
user-select: none
padding: $calendar-daily-day-padding
cursor: pointer
text-align: center
.v-calendar-daily__body
flex: 1 1 60%
overflow: hidden
display: flex
position: relative
flex-direction: column
.v-calendar-daily__scroll-area
overflow-y: scroll
flex: 1 1 auto
display: flex
align-items: flex-start
.v-calendar-daily__pane
width: 100%
overflow-y: hidden
flex: none
display: flex
align-items: flex-start
.v-calendar-daily__day-container
display: flex
flex: 1
width: 100%
height: 100%
.v-calendar-daily__intervals-body
flex: none
user-select: none
.v-calendar-daily__interval
text-align: $calendar-daily-interval-gutter-align
padding-right: $calendar-daily-interval-gutter-line-width
border-bottom: none
position: relative
&::after
width: $calendar-daily-interval-gutter-line-width
position: absolute
height: $calendar-line-width
display: block
content: ''
right: 0
bottom: -$calendar-line-width
.v-calendar-daily__interval-text
display: block
position: relative
top: $calendar-daily-interval-gutter-top
font-size: $calendar-daily-interval-gutter-font-size
padding-right: $calendar-daily-interval-gutter-width
.v-calendar-daily__day
flex: 1
width: 0
position: relative
@@ -0,0 +1,113 @@
@layer vuetify-components {
.v-calendar-weekly {
background-color: rgb(var(--v-theme-surface));
color: rgb(var(--v-theme-on-surface));
border-top: rgba(var(--v-border-color), var(--v-border-opacity)) 1px solid;
border-left: rgba(var(--v-border-color), var(--v-border-opacity)) 1px solid;
}
.v-calendar-weekly .v-calendar-weekly__head-weekday {
border-right: rgba(var(--v-border-color), var(--v-border-opacity)) 1px solid;
}
.v-calendar-weekly .v-calendar-weekly__head-weekday.v-past {
color: rgb(var(--v-theme-on-surface));
}
.v-calendar-weekly .v-calendar-weekly__head-weekday.v-outside {
background-color: rgb(var(--v-theme-surface-light));
color: rgb(var(--v-theme-on-surface-light));
}
.v-calendar-weekly .v-calendar-weekly__head-weeknumber {
background-color: rgb(var(--v-theme-surface));
color: rgb(var(--v-theme-on-surface));
border-right: rgba(var(--v-border-color), var(--v-border-opacity)) 1px solid;
}
.v-calendar-weekly .v-calendar-weekly__day {
border-right: rgba(var(--v-border-color), var(--v-border-opacity)) 1px solid;
border-bottom: rgba(var(--v-border-color), var(--v-border-opacity)) 1px solid;
}
.v-calendar-weekly .v-calendar-weekly__day.v-outside {
background-color: rgb(var(--v-theme-surface-light));
color: rgb(var(--v-theme-on-surface-light));
}
.v-calendar-weekly .v-calendar-weekly__weeknumber {
background-color: rgb(var(--v-theme-surface));
color: rgb(var(--v-theme-on-surface));
border-right: rgba(var(--v-border-color), var(--v-border-opacity)) 1px solid;
border-bottom: rgba(var(--v-border-color), var(--v-border-opacity)) 1px solid;
}
.v-calendar-weekly {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
min-height: 0;
}
.v-calendar-weekly__head {
display: flex;
user-select: none;
}
.v-calendar-weekly__head-weekday {
flex: 1 0 20px;
user-select: none;
padding: 0px 4px 0px 4px;
font-size: 11px;
overflow: hidden;
text-align: center;
text-overflow: ellipsis;
text-transform: uppercase;
white-space: nowrap;
}
.v-calendar-weekly__head-weeknumber {
position: relative;
flex: 0 0 24px;
}
.v-calendar-weekly__week {
display: flex;
flex: 1;
height: unset;
min-height: 0;
}
.v-calendar-weekly__weeknumber {
display: flex;
flex: 0 0 24px;
height: unset;
min-height: 0;
padding-top: 14.5px;
text-align: center;
}
.v-calendar-weekly__weeknumber > small {
width: 100%;
}
.v-calendar-weekly__day {
flex: 1;
width: 0;
overflow: hidden;
user-select: none;
position: relative;
padding: 0px 0px 0px 0px;
min-width: 0;
}
.v-calendar-weekly__day.v-present .v-calendar-weekly__day-month {
color: currentColor;
}
.v-calendar-weekly__day-label {
text-decoration: none;
user-select: none;
cursor: pointer;
box-shadow: none;
text-align: center;
margin: 4px 0 0 0;
}
.v-calendar-weekly__day-label .v-icon-btn {
font-size: 12px;
}
.v-calendar-weekly__day-month {
position: absolute;
text-decoration: none;
user-select: none;
box-shadow: none;
top: 0;
left: 36px;
height: 32px;
line-height: 32px;
}
}
@@ -0,0 +1,557 @@
import { validateNumber } from './util/timestamp.js';
import type { PropType } from 'vue';
import type { CalendarFormatter, CalendarTimestamp } from './types.js';
export declare const VCalendarWeekly: {
new (...args: any[]): import("vue").CreateComponentPublicInstanceWithMixins<Readonly<import("vue").ExtractPropTypes<{
start: {
type: (DateConstructor | NumberConstructor | StringConstructor)[];
validate: typeof import("./util/timestamp.js").validateTimestamp;
default: () => string;
};
end: {
type: (DateConstructor | NumberConstructor | StringConstructor)[];
validate: typeof import("./util/timestamp.js").validateTimestamp;
};
weekdays: {
type: PropType<number[] | string>;
default: () => number[];
validate: typeof import("./util/timestamp.js").validateWeekdays;
};
firstDayOfWeek: (NumberConstructor | StringConstructor)[];
firstDayOfYear: (NumberConstructor | StringConstructor)[];
weekdayFormat: {
type: PropType<CalendarFormatter>;
default: null;
};
dayFormat: {
type: PropType<CalendarFormatter>;
default: null;
};
locale: StringConstructor;
now: {
type: StringConstructor;
validator: typeof import("./util/timestamp.js").validateTimestamp;
};
type: {
type: PropType<'month' | 'week' | 'day' | '4day' | 'custom-weekly' | 'custom-daily' | 'category'>;
default: string;
};
minWeeks: {
validate: typeof validateNumber;
default: number;
};
monthFormat: PropType<CalendarFormatter>;
showWeek: BooleanConstructor;
color: StringConstructor;
shortWeekdays: {
type: BooleanConstructor;
default: boolean;
};
showMonthOnFirst: {
type: BooleanConstructor;
default: boolean;
};
shortMonths: {
type: BooleanConstructor;
default: boolean;
};
hideHeader: BooleanConstructor;
}>>, {
times: {
now: {
date: string;
time: string;
year: number;
month: number;
day: number;
weekday: number;
hour: number;
minute: number;
hasDay: boolean;
hasTime: boolean;
past: boolean;
present: boolean;
future: boolean;
category?: import("./types.js").CalendarCategory;
};
today: {
date: string;
time: string;
year: number;
month: number;
day: number;
weekday: number;
hour: number;
minute: number;
hasDay: boolean;
hasTime: boolean;
past: boolean;
present: boolean;
future: boolean;
category?: import("./types.js").CalendarCategory;
};
};
locale: {
name: string;
decimalSeparator: import("vue").ShallowRef<string>;
messages: import("vue").Ref<import("../../types.js").LocaleMessages, import("../../types.js").LocaleMessages>;
current: import("vue").Ref<string, string>;
fallback: import("vue").Ref<string, string>;
t: (key: string, ...params: unknown[]) => string;
n: (value: number) => string;
provide: (props: import("../../types.js").LocaleOptions) => import("../../types.js").LocaleInstance;
isRtl: import("vue").Ref<boolean, boolean>;
rtl: import("vue").Ref<Record<string, boolean>, Record<string, boolean>>;
rtlClasses: import("vue").Ref<string, string>;
};
parsedValue: import("vue").ComputedRef<CalendarTimestamp>;
parsedWeekdays: import("vue").ComputedRef<number[]>;
effectiveWeekdays: import("vue").ComputedRef<number[]>;
weekdaySkips: import("vue").ComputedRef<number[]>;
parsedStart: import("vue").ComputedRef<CalendarTimestamp>;
parsedEnd: import("vue").ComputedRef<CalendarTimestamp>;
dayFormatter: import("vue").ComputedRef<CalendarFormatter>;
weekdayFormatter: import("vue").ComputedRef<CalendarFormatter>;
getColorProps: (colors: {
background?: import("../../composables/color.js").ColorValue;
text?: import("../../composables/color.js").ColorValue;
}) => {
class: string[];
style: import("vue").CSSProperties;
};
getRelativeClasses: (timestamp: CalendarTimestamp, outside?: boolean) => {
'v-present': boolean;
'v-past': boolean;
'v-future': boolean;
'v-outside': boolean;
};
getWeekNumber: (timestamp: CalendarTimestamp) => number;
getStartOfWeek: (timestamp: CalendarTimestamp) => CalendarTimestamp;
getEndOfWeek: (timestamp: CalendarTimestamp) => CalendarTimestamp;
getFormatter: (options: Intl.DateTimeFormatOptions) => CalendarFormatter;
updateTimes: () => void;
days: import("vue").ComputedRef<CalendarTimestamp[]>;
todayWeek: import("vue").ComputedRef<CalendarTimestamp[]>;
monthFormatter: import("vue").ComputedRef<CalendarFormatter>;
isOutside: (day: CalendarTimestamp) => boolean;
}, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, import("vue").PublicProps, {
start: string | number | Date;
weekdays: string | number[];
weekdayFormat: CalendarFormatter;
dayFormat: CalendarFormatter;
type: "4day" | "category" | "custom-daily" | "custom-weekly" | "day" | "month" | "week";
minWeeks: number;
showWeek: boolean;
shortWeekdays: boolean;
showMonthOnFirst: boolean;
shortMonths: boolean;
hideHeader: boolean;
}, true, {}, {}, import("vue").GlobalComponents, import("vue").GlobalDirectives, string, {}, any, import("vue").ComponentProvideOptions, {
P: {};
B: {};
D: {};
C: {};
M: {};
Defaults: {};
}, Readonly<import("vue").ExtractPropTypes<{
start: {
type: (DateConstructor | NumberConstructor | StringConstructor)[];
validate: typeof import("./util/timestamp.js").validateTimestamp;
default: () => string;
};
end: {
type: (DateConstructor | NumberConstructor | StringConstructor)[];
validate: typeof import("./util/timestamp.js").validateTimestamp;
};
weekdays: {
type: PropType<number[] | string>;
default: () => number[];
validate: typeof import("./util/timestamp.js").validateWeekdays;
};
firstDayOfWeek: (NumberConstructor | StringConstructor)[];
firstDayOfYear: (NumberConstructor | StringConstructor)[];
weekdayFormat: {
type: PropType<CalendarFormatter>;
default: null;
};
dayFormat: {
type: PropType<CalendarFormatter>;
default: null;
};
locale: StringConstructor;
now: {
type: StringConstructor;
validator: typeof import("./util/timestamp.js").validateTimestamp;
};
type: {
type: PropType<'month' | 'week' | 'day' | '4day' | 'custom-weekly' | 'custom-daily' | 'category'>;
default: string;
};
minWeeks: {
validate: typeof validateNumber;
default: number;
};
monthFormat: PropType<CalendarFormatter>;
showWeek: BooleanConstructor;
color: StringConstructor;
shortWeekdays: {
type: BooleanConstructor;
default: boolean;
};
showMonthOnFirst: {
type: BooleanConstructor;
default: boolean;
};
shortMonths: {
type: BooleanConstructor;
default: boolean;
};
hideHeader: BooleanConstructor;
}>>, {
times: {
now: {
date: string;
time: string;
year: number;
month: number;
day: number;
weekday: number;
hour: number;
minute: number;
hasDay: boolean;
hasTime: boolean;
past: boolean;
present: boolean;
future: boolean;
category?: import("./types.js").CalendarCategory;
};
today: {
date: string;
time: string;
year: number;
month: number;
day: number;
weekday: number;
hour: number;
minute: number;
hasDay: boolean;
hasTime: boolean;
past: boolean;
present: boolean;
future: boolean;
category?: import("./types.js").CalendarCategory;
};
};
locale: {
name: string;
decimalSeparator: import("vue").ShallowRef<string>;
messages: import("vue").Ref<import("../../types.js").LocaleMessages, import("../../types.js").LocaleMessages>;
current: import("vue").Ref<string, string>;
fallback: import("vue").Ref<string, string>;
t: (key: string, ...params: unknown[]) => string;
n: (value: number) => string;
provide: (props: import("../../types.js").LocaleOptions) => import("../../types.js").LocaleInstance;
isRtl: import("vue").Ref<boolean, boolean>;
rtl: import("vue").Ref<Record<string, boolean>, Record<string, boolean>>;
rtlClasses: import("vue").Ref<string, string>;
};
parsedValue: import("vue").ComputedRef<CalendarTimestamp>;
parsedWeekdays: import("vue").ComputedRef<number[]>;
effectiveWeekdays: import("vue").ComputedRef<number[]>;
weekdaySkips: import("vue").ComputedRef<number[]>;
parsedStart: import("vue").ComputedRef<CalendarTimestamp>;
parsedEnd: import("vue").ComputedRef<CalendarTimestamp>;
dayFormatter: import("vue").ComputedRef<CalendarFormatter>;
weekdayFormatter: import("vue").ComputedRef<CalendarFormatter>;
getColorProps: (colors: {
background?: import("../../composables/color.js").ColorValue;
text?: import("../../composables/color.js").ColorValue;
}) => {
class: string[];
style: import("vue").CSSProperties;
};
getRelativeClasses: (timestamp: CalendarTimestamp, outside?: boolean) => {
'v-present': boolean;
'v-past': boolean;
'v-future': boolean;
'v-outside': boolean;
};
getWeekNumber: (timestamp: CalendarTimestamp) => number;
getStartOfWeek: (timestamp: CalendarTimestamp) => CalendarTimestamp;
getEndOfWeek: (timestamp: CalendarTimestamp) => CalendarTimestamp;
getFormatter: (options: Intl.DateTimeFormatOptions) => CalendarFormatter;
updateTimes: () => void;
days: import("vue").ComputedRef<CalendarTimestamp[]>;
todayWeek: import("vue").ComputedRef<CalendarTimestamp[]>;
monthFormatter: import("vue").ComputedRef<CalendarFormatter>;
isOutside: (day: CalendarTimestamp) => boolean;
}, {}, {}, {}, {
start: string | number | Date;
weekdays: string | number[];
weekdayFormat: CalendarFormatter;
dayFormat: CalendarFormatter;
type: "4day" | "category" | "custom-daily" | "custom-weekly" | "day" | "month" | "week";
minWeeks: number;
showWeek: boolean;
shortWeekdays: boolean;
showMonthOnFirst: boolean;
shortMonths: boolean;
hideHeader: boolean;
}>;
__isFragment?: never;
__isTeleport?: never;
__isSuspense?: never;
} & import("vue").ComponentOptionsBase<Readonly<import("vue").ExtractPropTypes<{
start: {
type: (DateConstructor | NumberConstructor | StringConstructor)[];
validate: typeof import("./util/timestamp.js").validateTimestamp;
default: () => string;
};
end: {
type: (DateConstructor | NumberConstructor | StringConstructor)[];
validate: typeof import("./util/timestamp.js").validateTimestamp;
};
weekdays: {
type: PropType<number[] | string>;
default: () => number[];
validate: typeof import("./util/timestamp.js").validateWeekdays;
};
firstDayOfWeek: (NumberConstructor | StringConstructor)[];
firstDayOfYear: (NumberConstructor | StringConstructor)[];
weekdayFormat: {
type: PropType<CalendarFormatter>;
default: null;
};
dayFormat: {
type: PropType<CalendarFormatter>;
default: null;
};
locale: StringConstructor;
now: {
type: StringConstructor;
validator: typeof import("./util/timestamp.js").validateTimestamp;
};
type: {
type: PropType<'month' | 'week' | 'day' | '4day' | 'custom-weekly' | 'custom-daily' | 'category'>;
default: string;
};
minWeeks: {
validate: typeof validateNumber;
default: number;
};
monthFormat: PropType<CalendarFormatter>;
showWeek: BooleanConstructor;
color: StringConstructor;
shortWeekdays: {
type: BooleanConstructor;
default: boolean;
};
showMonthOnFirst: {
type: BooleanConstructor;
default: boolean;
};
shortMonths: {
type: BooleanConstructor;
default: boolean;
};
hideHeader: BooleanConstructor;
}>>, {
times: {
now: {
date: string;
time: string;
year: number;
month: number;
day: number;
weekday: number;
hour: number;
minute: number;
hasDay: boolean;
hasTime: boolean;
past: boolean;
present: boolean;
future: boolean;
category?: import("./types.js").CalendarCategory;
};
today: {
date: string;
time: string;
year: number;
month: number;
day: number;
weekday: number;
hour: number;
minute: number;
hasDay: boolean;
hasTime: boolean;
past: boolean;
present: boolean;
future: boolean;
category?: import("./types.js").CalendarCategory;
};
};
locale: {
name: string;
decimalSeparator: import("vue").ShallowRef<string>;
messages: import("vue").Ref<import("../../types.js").LocaleMessages, import("../../types.js").LocaleMessages>;
current: import("vue").Ref<string, string>;
fallback: import("vue").Ref<string, string>;
t: (key: string, ...params: unknown[]) => string;
n: (value: number) => string;
provide: (props: import("../../types.js").LocaleOptions) => import("../../types.js").LocaleInstance;
isRtl: import("vue").Ref<boolean, boolean>;
rtl: import("vue").Ref<Record<string, boolean>, Record<string, boolean>>;
rtlClasses: import("vue").Ref<string, string>;
};
parsedValue: import("vue").ComputedRef<CalendarTimestamp>;
parsedWeekdays: import("vue").ComputedRef<number[]>;
effectiveWeekdays: import("vue").ComputedRef<number[]>;
weekdaySkips: import("vue").ComputedRef<number[]>;
parsedStart: import("vue").ComputedRef<CalendarTimestamp>;
parsedEnd: import("vue").ComputedRef<CalendarTimestamp>;
dayFormatter: import("vue").ComputedRef<CalendarFormatter>;
weekdayFormatter: import("vue").ComputedRef<CalendarFormatter>;
getColorProps: (colors: {
background?: import("../../composables/color.js").ColorValue;
text?: import("../../composables/color.js").ColorValue;
}) => {
class: string[];
style: import("vue").CSSProperties;
};
getRelativeClasses: (timestamp: CalendarTimestamp, outside?: boolean) => {
'v-present': boolean;
'v-past': boolean;
'v-future': boolean;
'v-outside': boolean;
};
getWeekNumber: (timestamp: CalendarTimestamp) => number;
getStartOfWeek: (timestamp: CalendarTimestamp) => CalendarTimestamp;
getEndOfWeek: (timestamp: CalendarTimestamp) => CalendarTimestamp;
getFormatter: (options: Intl.DateTimeFormatOptions) => CalendarFormatter;
updateTimes: () => void;
days: import("vue").ComputedRef<CalendarTimestamp[]>;
todayWeek: import("vue").ComputedRef<CalendarTimestamp[]>;
monthFormatter: import("vue").ComputedRef<CalendarFormatter>;
isOutside: (day: CalendarTimestamp) => boolean;
}, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, {
start: string | number | Date;
weekdays: string | number[];
weekdayFormat: CalendarFormatter;
dayFormat: CalendarFormatter;
type: "4day" | "category" | "custom-daily" | "custom-weekly" | "day" | "month" | "week";
minWeeks: number;
showWeek: boolean;
shortWeekdays: boolean;
showMonthOnFirst: boolean;
shortMonths: boolean;
hideHeader: boolean;
}, {}, string, {}, import("vue").GlobalComponents, import("vue").GlobalDirectives, string, import("vue").ComponentProvideOptions> & import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps & import("../../util/index.js").FilterPropsOptions<{
start: {
type: (DateConstructor | NumberConstructor | StringConstructor)[];
validate: typeof import("./util/timestamp.js").validateTimestamp;
default: () => string;
};
end: {
type: (DateConstructor | NumberConstructor | StringConstructor)[];
validate: typeof import("./util/timestamp.js").validateTimestamp;
};
weekdays: {
type: PropType<number[] | string>;
default: () => number[];
validate: typeof import("./util/timestamp.js").validateWeekdays;
};
firstDayOfWeek: (NumberConstructor | StringConstructor)[];
firstDayOfYear: (NumberConstructor | StringConstructor)[];
weekdayFormat: {
type: PropType<CalendarFormatter>;
default: null;
};
dayFormat: {
type: PropType<CalendarFormatter>;
default: null;
};
locale: StringConstructor;
now: {
type: StringConstructor;
validator: typeof import("./util/timestamp.js").validateTimestamp;
};
type: {
type: PropType<'month' | 'week' | 'day' | '4day' | 'custom-weekly' | 'custom-daily' | 'category'>;
default: string;
};
minWeeks: {
validate: typeof validateNumber;
default: number;
};
monthFormat: PropType<CalendarFormatter>;
showWeek: BooleanConstructor;
color: StringConstructor;
shortWeekdays: {
type: BooleanConstructor;
default: boolean;
};
showMonthOnFirst: {
type: BooleanConstructor;
default: boolean;
};
shortMonths: {
type: BooleanConstructor;
default: boolean;
};
hideHeader: BooleanConstructor;
}, import("vue").ExtractPropTypes<{
start: {
type: (DateConstructor | NumberConstructor | StringConstructor)[];
validate: typeof import("./util/timestamp.js").validateTimestamp;
default: () => string;
};
end: {
type: (DateConstructor | NumberConstructor | StringConstructor)[];
validate: typeof import("./util/timestamp.js").validateTimestamp;
};
weekdays: {
type: PropType<number[] | string>;
default: () => number[];
validate: typeof import("./util/timestamp.js").validateWeekdays;
};
firstDayOfWeek: (NumberConstructor | StringConstructor)[];
firstDayOfYear: (NumberConstructor | StringConstructor)[];
weekdayFormat: {
type: PropType<CalendarFormatter>;
default: null;
};
dayFormat: {
type: PropType<CalendarFormatter>;
default: null;
};
locale: StringConstructor;
now: {
type: StringConstructor;
validator: typeof import("./util/timestamp.js").validateTimestamp;
};
type: {
type: PropType<'month' | 'week' | 'day' | '4day' | 'custom-weekly' | 'custom-daily' | 'category'>;
default: string;
};
minWeeks: {
validate: typeof validateNumber;
default: number;
};
monthFormat: PropType<CalendarFormatter>;
showWeek: BooleanConstructor;
color: StringConstructor;
shortWeekdays: {
type: BooleanConstructor;
default: boolean;
};
showMonthOnFirst: {
type: BooleanConstructor;
default: boolean;
};
shortMonths: {
type: BooleanConstructor;
default: boolean;
};
hideHeader: BooleanConstructor;
}>>;
export type VCalendarWeekly = InstanceType<typeof VCalendarWeekly>;
@@ -0,0 +1,176 @@
import { createElementVNode as _createElementVNode, mergeProps as _mergeProps, createVNode as _createVNode, normalizeClass as _normalizeClass } from "vue";
// Components
import { VIconBtn } from "../../labs/VIconBtn/index.js"; // Composables
import { makeCalendarBaseProps, useCalendarBase } from "./composables/calendarBase.js";
import { useTheme } from "../../composables/index.js"; // Utilities
import { computed } from 'vue';
import { createDayList, createNativeLocaleFormatter, getDayIdentifier, validateNumber } from "./util/timestamp.js";
import { defineComponent, getPrefixedEventHandlers, noop, useRender } from "../../util/index.js"; // Types
export const VCalendarWeekly = defineComponent({
name: 'VCalendarWeekly',
props: {
minWeeks: {
validate: validateNumber,
default: 1
},
monthFormat: Function,
showWeek: Boolean,
color: String,
shortWeekdays: {
type: Boolean,
default: true
},
showMonthOnFirst: {
type: Boolean,
default: true
},
shortMonths: {
type: Boolean,
default: true
},
hideHeader: Boolean,
...makeCalendarBaseProps()
},
setup(props, {
slots,
attrs
}) {
const base = useCalendarBase(props);
const theme = useTheme();
const parsedMinWeeks = computed(() => {
return parseInt(String(props.minWeeks));
});
const days = computed(() => {
const minDays = parsedMinWeeks.value * base.parsedWeekdays.value.length;
const start = base.getStartOfWeek(base.parsedStart.value);
const end = base.getEndOfWeek(base.parsedEnd.value);
return createDayList(start, end, base.times.today, base.weekdaySkips.value, Number.MAX_SAFE_INTEGER, minDays);
});
const todayWeek = computed(() => {
const today = base.times.today;
const start = base.getStartOfWeek(today);
const end = base.getEndOfWeek(today);
return createDayList(start, end, today, base.weekdaySkips.value, base.parsedWeekdays.value.length, base.parsedWeekdays.value.length);
});
const monthFormatter = computed(() => {
if (props.monthFormat) {
// TODO: what happens when this is a string?
return props.monthFormat;
}
return createNativeLocaleFormatter(base.locale.current.value, (_tms, short) => ({
timeZone: 'UTC',
month: short ? 'short' : 'long'
}));
});
function isOutside(day) {
const dayIdentifier = getDayIdentifier(day);
return dayIdentifier < getDayIdentifier(base.parsedStart.value) || dayIdentifier > getDayIdentifier(base.parsedEnd.value);
}
function genHead() {
return _createElementVNode("div", {
"class": "v-calendar-weekly__head",
"role": "row"
}, [genHeadDays()]);
}
function genHeadDays() {
const header = todayWeek.value.map(genHeadDay);
if (props.showWeek) {
header.unshift(_createElementVNode("div", {
"class": "v-calendar-weekly__head-weeknumber"
}, null));
}
return header;
}
function genHeadDay(day, index) {
const outside = isOutside(days.value[index]);
const color = day.present ? props.color : undefined;
return _createElementVNode("div", _mergeProps(base.getColorProps({
text: color
}), {
"key": day.date,
"class": ['v-calendar-weekly__head-weekday', base.getRelativeClasses(day, outside)],
"role": "columnheader"
}), [base.weekdayFormatter.value(day, props.shortWeekdays)]);
}
function genWeeks() {
const daysValue = days.value;
const weekDays = base.parsedWeekdays.value.length;
const weeks = [];
for (let i = 0; i < daysValue.length; i += weekDays) {
weeks.push(genWeek(daysValue.slice(i, i + weekDays), getWeekNumber(daysValue[i])));
}
return weeks;
}
function genWeek(week, weekNumber) {
const weekNodes = week.map((day, index) => genDay(day, index, week));
if (props.showWeek) {
weekNodes.unshift(genWeekNumber(weekNumber));
}
return _createElementVNode("div", {
"key": week[0].date,
"class": "v-calendar-weekly__week",
"role": "row"
}, [weekNodes]);
}
function getWeekNumber(determineDay) {
return base.getWeekNumber(determineDay);
}
function genWeekNumber(weekNumber) {
return _createElementVNode("div", {
"class": "v-calendar-weekly__weeknumber"
}, [_createElementVNode("small", null, [String(weekNumber)])]);
}
function genDay(day, index, week) {
const outside = isOutside(day);
const events = getPrefixedEventHandlers(attrs, ':day', nativeEvent => {
return {
nativeEvent,
...day
};
});
return _createElementVNode("div", _mergeProps({
"key": day.date,
"class": ['v-calendar-weekly__day', base.getRelativeClasses(day, outside)],
"role": "cell"
}, events), [genDayLabel(day), slots.day?.({
outside,
index,
week,
...day
})]);
}
function genDayLabel(day) {
return _createElementVNode("div", {
"class": "v-calendar-weekly__day-label"
}, [slots['day-label']?.(day) ?? genDayLabelButton(day)]);
}
function genDayLabelButton(day) {
const hasMonth = day.day === 1 && props.showMonthOnFirst;
const events = getPrefixedEventHandlers(attrs, ':date', nativeEvent => ({
nativeEvent,
...day
}));
return _createVNode(VIconBtn, _mergeProps({
"active": day.present,
"activeColor": props.color,
"variant": "outlined",
"baseVariant": "text",
"onUpdate:active": noop
}, events), {
default: () => [hasMonth ? monthFormatter.value(day, props.shortMonths) + ' ' + base.dayFormatter.value(day, false) : base.dayFormatter.value(day, false)]
});
}
useRender(() => _createElementVNode("div", {
"class": _normalizeClass(['v-calendar-weekly', theme.themeClasses.value]),
"onDragstart": e => e.preventDefault()
}, [!props.hideHeader ? genHead() : undefined, genWeeks()]));
return {
...base,
days,
todayWeek,
monthFormatter,
isOutside
};
}
});
//# sourceMappingURL=VCalendarWeekly.js.map
File diff suppressed because one or more lines are too long
@@ -0,0 +1,120 @@
@use '../../styles/tools'
@use '../../styles/settings'
@use './variables' as *
@include tools.layer('components')
.v-calendar-weekly
background-color: $calendar-background
color: $calendar-on-background
border-top: $calendar-outline-color $calendar-line-width solid
border-left: $calendar-outline-color $calendar-line-width solid
.v-calendar-weekly__head-weekday
border-right: $calendar-grid-color $calendar-line-width solid
&.v-past
color: $calendar-past-color
&.v-outside
background-color: $calendar-outside-background
color: $calendar-on-outside-background
.v-calendar-weekly__head-weeknumber
background-color: $calendar-weeknumber-background
color: $calendar-on-weeknumber-background
border-right: $calendar-grid-color $calendar-line-width solid
.v-calendar-weekly__day
border-right: $calendar-grid-color $calendar-line-width solid
border-bottom: $calendar-grid-color $calendar-line-width solid
&.v-outside
background-color: $calendar-outside-background
color: $calendar-on-outside-background
.v-calendar-weekly__weeknumber
background-color: $calendar-weeknumber-background
color: $calendar-on-weeknumber-background
border-right: $calendar-grid-color $calendar-line-width solid
border-bottom: $calendar-grid-color $calendar-line-width solid
.v-calendar-weekly
width: 100%
height: 100%
display: flex
flex-direction: column
// https://github.com/vuetifyjs/vuetify/issues/8319
min-height: 0
.v-calendar-weekly__head
display: flex
user-select: none
.v-calendar-weekly__head-weekday
flex: 1 0 20px
user-select: none
padding: $calendar-weekly-weekday-padding
font-size: $calendar-weekly-weekday-font-size
overflow: hidden
text-align: center
text-overflow: ellipsis
text-transform: uppercase
white-space: nowrap
.v-calendar-weekly__head-weeknumber
position: relative
flex: 0 0 $calendar-weekly-weeknumber-flex-basis
.v-calendar-weekly__week
display: flex
flex: 1
height: unset
// https://github.com/vuetifyjs/vuetify/issues/8319
min-height: 0
.v-calendar-weekly__weeknumber
display: flex
flex: 0 0 $calendar-weekly-weeknumber-flex-basis
height: unset
min-height: 0
padding-top: $calendar-weekly-weeknumber-padding-top
text-align: center
> small
width: 100%
.v-calendar-weekly__day
flex: 1
width: 0
overflow: hidden
user-select: none
position: relative
padding: $calendar-weekly-day-padding
// https://github.com/vuetifyjs/vuetify/issues/9058
// https://bugzilla.mozilla.org/show_bug.cgi?id=1114904
min-width: 0
&.v-present
.v-calendar-weekly__day-month
color: currentColor
.v-calendar-weekly__day-label
text-decoration: none
user-select: none
cursor: pointer
box-shadow: none
text-align: center
margin: $calendar-weekly-day-label-margin
.v-icon-btn
font-size: $calendar-weekly-day-label-font-size
.v-calendar-weekly__day-month
position: absolute
text-decoration: none
user-select: none
box-shadow: none
top: 0
left: $calendar-weekly-day-month-left
height: $calendar-weekly-day-label-size
line-height: $calendar-weekly-day-label-size
+45
View File
@@ -0,0 +1,45 @@
@use '../../styles/settings';
$calendar-line-width: 1px !default;
$calendar-daily-head-day-label-size: 56px !default;
$calendar-daily-head-weekday-size: 50px !default;
$calendar-daily-weekday-padding: 3px 0px 0px 0px !default;
$calendar-daily-weekday-font-size: 11px !default;
$calendar-daily-day-padding: 0px 0px 3px 0px !default;
$calendar-daily-day-font-size: 40px !default;
$calendar-daily-interval-gutter-top: -6px !default;
$calendar-daily-interval-gutter-width: 4px !default;
$calendar-daily-interval-gutter-align: right !default;
$calendar-daily-interval-gutter-line-width: 8px !default;
$calendar-daily-interval-gutter-font-size: 10px !default;
$calendar-category-column-min-width: 200px !default;
$calendar-weekly-weekday-padding: 0px 4px 0px 4px !default;
$calendar-weekly-weekday-font-size: 11px !default;
$calendar-weekly-day-padding: 0px 0px 0px 0px !default;
$calendar-weekly-day-label-size: 32px !default;
$calendar-weekly-day-label-font-size: 12px !default;
$calendar-weekly-day-label-margin: 4px 0 0 0 !default;
$calendar-weekly-day-month-left: 36px !default;
$calendar-weekly-weeknumber-flex-basis: 24px !default;
$calendar-weekly-weeknumber-padding-top: 14.5px !default;
$calendar-event-bottom-space: 1px !default;
$calendar-event-border-width: 1px !default;
$calendar-event-border-radius: settings.$border-radius-root !default;
$calendar-event-font-size: 12px !default;
$calendar-event-line-height: 20px !default;
$calendar-event-right-empty: 10px !default;
$calendar-background: rgb(var(--v-theme-surface)) !default;
$calendar-on-background: rgb(var(--v-theme-on-surface)) !default;
$calendar-outside-background: rgb(var(--v-theme-surface-light)) !default;
$calendar-on-outside-background: rgb(var(--v-theme-on-surface-light)) !default;
$calendar-weeknumber-background: rgb(var(--v-theme-surface)) !default;
$calendar-on-weeknumber-background: rgb(var(--v-theme-on-surface)) !default;
$calendar-outline-color: rgba(var(--v-border-color), var(--v-border-opacity)) !default;
$calendar-grid-color: rgba(var(--v-border-color), var(--v-border-opacity)) !default;
$calendar-past-color: rgb(var(--v-theme-on-surface)) !default;
$calendar-interval-text-color: rgb(var(--v-theme-on-surface)) !default;
@@ -0,0 +1,193 @@
import { validateTimestamp, validateWeekdays } from '../util/timestamp.js';
import type { PropType } from 'vue';
import type { CalendarFormatter, CalendarTimestamp } from '../types.js';
import type { ColorValue } from '../../../composables/color.js';
export declare const makeCalendarBaseProps: <Defaults extends {
start?: unknown;
end?: unknown;
weekdays?: unknown;
firstDayOfWeek?: unknown;
firstDayOfYear?: unknown;
weekdayFormat?: unknown;
dayFormat?: unknown;
locale?: unknown;
now?: unknown;
type?: unknown;
} = {}>(defaults?: Defaults | undefined) => {
start: unknown extends Defaults["start"] ? {
type: (DateConstructor | NumberConstructor | StringConstructor)[];
validate: typeof validateTimestamp;
default: () => string;
} : Omit<{
type: (DateConstructor | NumberConstructor | StringConstructor)[];
validate: typeof validateTimestamp;
default: () => string;
}, "default" | "type"> & {
type: PropType<unknown extends Defaults["start"] ? string | number | Date : string | number | Date | Defaults["start"]>;
default: unknown extends Defaults["start"] ? string | number | Date : Defaults["start"] | NonNullable<string | number | Date>;
};
end: unknown extends Defaults["end"] ? {
type: (DateConstructor | NumberConstructor | StringConstructor)[];
validate: typeof validateTimestamp;
} : Omit<{
type: (DateConstructor | NumberConstructor | StringConstructor)[];
validate: typeof validateTimestamp;
}, "default" | "type"> & {
type: PropType<unknown extends Defaults["end"] ? string | number | Date : string | number | Date | Defaults["end"]>;
default: unknown extends Defaults["end"] ? string | number | Date : Defaults["end"] | NonNullable<string | number | Date>;
};
weekdays: unknown extends Defaults["weekdays"] ? {
type: PropType<number[] | string>;
default: () => number[];
validate: typeof validateWeekdays;
} : Omit<{
type: PropType<number[] | string>;
default: () => number[];
validate: typeof validateWeekdays;
}, "default" | "type"> & {
type: PropType<unknown extends Defaults["weekdays"] ? string | number[] : string | number[] | Defaults["weekdays"]>;
default: unknown extends Defaults["weekdays"] ? string | number[] : Defaults["weekdays"] | NonNullable<string | number[]>;
};
firstDayOfWeek: unknown extends Defaults["firstDayOfWeek"] ? (NumberConstructor | StringConstructor)[] : {
type: PropType<unknown extends Defaults["firstDayOfWeek"] ? string | number : string | number | Defaults["firstDayOfWeek"]>;
default: unknown extends Defaults["firstDayOfWeek"] ? string | number : Defaults["firstDayOfWeek"] | NonNullable<string | number>;
};
firstDayOfYear: unknown extends Defaults["firstDayOfYear"] ? (NumberConstructor | StringConstructor)[] : {
type: PropType<unknown extends Defaults["firstDayOfYear"] ? string | number : string | number | Defaults["firstDayOfYear"]>;
default: unknown extends Defaults["firstDayOfYear"] ? string | number : Defaults["firstDayOfYear"] | NonNullable<string | number>;
};
weekdayFormat: unknown extends Defaults["weekdayFormat"] ? {
type: PropType<CalendarFormatter>;
default: null;
} : Omit<{
type: PropType<CalendarFormatter>;
default: null;
}, "default" | "type"> & {
type: PropType<unknown extends Defaults["weekdayFormat"] ? CalendarFormatter : CalendarFormatter | Defaults["weekdayFormat"]>;
default: unknown extends Defaults["weekdayFormat"] ? CalendarFormatter : CalendarFormatter | Defaults["weekdayFormat"];
};
dayFormat: unknown extends Defaults["dayFormat"] ? {
type: PropType<CalendarFormatter>;
default: null;
} : Omit<{
type: PropType<CalendarFormatter>;
default: null;
}, "default" | "type"> & {
type: PropType<unknown extends Defaults["dayFormat"] ? CalendarFormatter : CalendarFormatter | Defaults["dayFormat"]>;
default: unknown extends Defaults["dayFormat"] ? CalendarFormatter : CalendarFormatter | Defaults["dayFormat"];
};
locale: unknown extends Defaults["locale"] ? StringConstructor : {
type: PropType<unknown extends Defaults["locale"] ? string : string | Defaults["locale"]>;
default: unknown extends Defaults["locale"] ? string : string | Defaults["locale"];
};
now: unknown extends Defaults["now"] ? {
type: StringConstructor;
validator: typeof validateTimestamp;
} : Omit<{
type: StringConstructor;
validator: typeof validateTimestamp;
}, "default" | "type"> & {
type: PropType<unknown extends Defaults["now"] ? string : string | Defaults["now"]>;
default: unknown extends Defaults["now"] ? string : string | Defaults["now"];
};
type: unknown extends Defaults["type"] ? {
type: PropType<'month' | 'week' | 'day' | '4day' | 'custom-weekly' | 'custom-daily' | 'category'>;
default: string;
} : Omit<{
type: PropType<'month' | 'week' | 'day' | '4day' | 'custom-weekly' | 'custom-daily' | 'category'>;
default: string;
}, "default" | "type"> & {
type: PropType<unknown extends Defaults["type"] ? "4day" | "category" | "custom-daily" | "custom-weekly" | "day" | "month" | "week" : "4day" | "category" | "custom-daily" | "custom-weekly" | "day" | "month" | "week" | Defaults["type"]>;
default: unknown extends Defaults["type"] ? "4day" | "category" | "custom-daily" | "custom-weekly" | "day" | "month" | "week" : Defaults["type"] | NonNullable<"4day" | "category" | "custom-daily" | "custom-weekly" | "day" | "month" | "week">;
};
};
export interface CalendarBaseProps {
modelValue?: string | number | Date;
categoryDays?: string | number;
start: string | number | Date;
end: string | number | Date | undefined;
weekdays: string | number[];
firstDayOfWeek: number | string | undefined;
firstDayOfYear: number | string | undefined;
weekdayFormat: CalendarFormatter | string | undefined;
dayFormat: CalendarFormatter | string | undefined;
locale: string | undefined;
now: string | undefined;
type: 'month' | 'week' | 'day' | '4day' | 'custom-weekly' | 'custom-daily' | 'category';
}
export declare function useCalendarBase(props: CalendarBaseProps): {
times: {
now: {
date: string;
time: string;
year: number;
month: number;
day: number;
weekday: number;
hour: number;
minute: number;
hasDay: boolean;
hasTime: boolean;
past: boolean;
present: boolean;
future: boolean;
category?: import("../types.js").CalendarCategory;
};
today: {
date: string;
time: string;
year: number;
month: number;
day: number;
weekday: number;
hour: number;
minute: number;
hasDay: boolean;
hasTime: boolean;
past: boolean;
present: boolean;
future: boolean;
category?: import("../types.js").CalendarCategory;
};
};
locale: {
name: string;
decimalSeparator: import("vue").ShallowRef<string>;
messages: import("vue").Ref<import("../../../types.js").LocaleMessages, import("../../../types.js").LocaleMessages>;
current: import("vue").Ref<string, string>;
fallback: import("vue").Ref<string, string>;
t: (key: string, ...params: unknown[]) => string;
n: (value: number) => string;
provide: (props: import("../../../types.js").LocaleOptions) => import("../../../types.js").LocaleInstance;
isRtl: import("vue").Ref<boolean, boolean>;
rtl: import("vue").Ref<Record<string, boolean>, Record<string, boolean>>;
rtlClasses: import("vue").Ref<string, string>;
};
parsedValue: import("vue").ComputedRef<CalendarTimestamp>;
parsedWeekdays: import("vue").ComputedRef<number[]>;
effectiveWeekdays: import("vue").ComputedRef<number[]>;
weekdaySkips: import("vue").ComputedRef<number[]>;
parsedStart: import("vue").ComputedRef<CalendarTimestamp>;
parsedEnd: import("vue").ComputedRef<CalendarTimestamp>;
days: import("vue").ComputedRef<CalendarTimestamp[]>;
dayFormatter: import("vue").ComputedRef<CalendarFormatter>;
weekdayFormatter: import("vue").ComputedRef<CalendarFormatter>;
getColorProps: (colors: {
background?: ColorValue;
text?: ColorValue;
}) => {
class: string[];
style: import("vue").CSSProperties;
};
getRelativeClasses: (timestamp: CalendarTimestamp, outside?: boolean) => {
'v-present': boolean;
'v-past': boolean;
'v-future': boolean;
'v-outside': boolean;
};
getWeekNumber: (timestamp: CalendarTimestamp) => number;
getStartOfWeek: (timestamp: CalendarTimestamp) => CalendarTimestamp;
getEndOfWeek: (timestamp: CalendarTimestamp) => CalendarTimestamp;
getFormatter: (options: Intl.DateTimeFormatOptions) => CalendarFormatter;
updateTimes: () => void;
};
@@ -0,0 +1,160 @@
// Composables
import { useTimes } from "./times.js";
import { computeColor } from "../../../composables/color.js";
import { useDate } from "../../../composables/date/index.js";
import { provideLocale } from "../../../composables/locale.js"; // Utilities
import { computed } from 'vue';
import { createDayList, createNativeLocaleFormatter, getEndOfMonth, getEndOfWeek, getStartOfMonth, getStartOfWeek, getTimestampIdentifier, getWeekdaySkips, parseDate, parseTimestamp, validateTimestamp, validateWeekdays } from "../util/timestamp.js";
import { propsFactory } from "../../../util/index.js"; // Types
export const makeCalendarBaseProps = propsFactory({
start: {
type: [String, Number, Date],
validate: validateTimestamp,
default: () => parseDate(new Date()).date
},
end: {
type: [String, Number, Date],
validate: validateTimestamp
},
weekdays: {
type: [Array, String],
default: () => [0, 1, 2, 3, 4, 5, 6],
validate: validateWeekdays
},
firstDayOfWeek: [Number, String],
firstDayOfYear: [Number, String],
weekdayFormat: {
type: Function,
default: null
},
dayFormat: {
type: Function,
default: null
},
locale: String,
now: {
type: String,
validator: validateTimestamp
},
type: {
type: String,
default: 'month'
}
}, 'VCalendar-base');
export function useCalendarBase(props) {
const {
times,
updateTimes
} = useTimes({
now: props.now
});
const locale = provideLocale(props);
const adapter = useDate();
const parsedStart = computed(() => {
if (props.type === 'month') {
return getStartOfMonth(parseTimestamp(props.start, true));
}
return parseTimestamp(props.start, true);
});
const parsedEnd = computed(() => {
const start = parsedStart.value;
const end = props.end ? parseTimestamp(props.end) || start : start;
const value = getTimestampIdentifier(end) < getTimestampIdentifier(start) ? start : end;
if (props.type === 'month') {
return getEndOfMonth(value);
}
return value;
});
const parsedValue = computed(() => {
return validateTimestamp(props.modelValue) ? parseTimestamp(props.modelValue, true) : parsedStart.value || times.today;
});
const parsedWeekdays = computed(() => {
const weekdays = Array.isArray(props.weekdays) ? props.weekdays : (props.weekdays || '').split(',').map(x => parseInt(x, 10));
const first = adapter.toJsDate(adapter.startOfWeek(adapter.date(), props.firstDayOfWeek)).getDay();
return [...weekdays.toSorted().filter(v => v >= first), ...weekdays.toSorted().filter(v => v < first)];
});
const effectiveWeekdays = computed(() => {
const start = parsedValue.value;
const days = parseInt(String(props.categoryDays)) || 1;
switch (props.type) {
case 'day':
return [start.weekday];
case '4day':
return [start.weekday, (start.weekday + 1) % 7, (start.weekday + 2) % 7, (start.weekday + 3) % 7];
case 'category':
return Array.from({
length: days
}, (_, i) => (start.weekday + i) % 7);
default:
return parsedWeekdays.value;
}
});
const weekdaySkips = computed(() => {
return getWeekdaySkips(parsedWeekdays.value);
});
const days = computed(() => {
return createDayList(parsedStart.value, parsedEnd.value, times.today, weekdaySkips.value);
});
const dayFormatter = computed(() => {
if (props.dayFormat) {
return props.dayFormat;
}
return createNativeLocaleFormatter(locale.current.value, () => ({
timeZone: 'UTC',
day: 'numeric'
}));
});
const weekdayFormatter = computed(() => {
if (props.weekdayFormat) {
return props.weekdayFormat;
}
return createNativeLocaleFormatter(locale.current.value, (_tms, short) => ({
timeZone: 'UTC',
weekday: short ? 'short' : 'long'
}));
});
function getColorProps(colors) {
return computeColor(colors);
}
function getRelativeClasses(timestamp, outside = false) {
return {
'v-present': timestamp.present,
'v-past': timestamp.past,
'v-future': timestamp.future,
'v-outside': outside
};
}
function getWeekNumber(timestamp) {
return adapter.getWeek(adapter.date(timestamp.date), props.firstDayOfWeek, props.firstDayOfYear);
}
function _getStartOfWeek(timestamp) {
return getStartOfWeek(timestamp, parsedWeekdays.value, times.today);
}
function _getEndOfWeek(timestamp) {
return getEndOfWeek(timestamp, parsedWeekdays.value, times.today);
}
function getFormatter(options) {
return createNativeLocaleFormatter(locale.current.value, () => options);
}
return {
times,
locale,
parsedValue,
parsedWeekdays,
effectiveWeekdays,
weekdaySkips,
parsedStart,
parsedEnd,
days,
dayFormatter,
weekdayFormatter,
getColorProps,
getRelativeClasses,
getWeekNumber,
getStartOfWeek: _getStartOfWeek,
getEndOfWeek: _getEndOfWeek,
getFormatter,
updateTimes
};
}
//# sourceMappingURL=calendarBase.js.map
File diff suppressed because one or more lines are too long
@@ -0,0 +1,65 @@
@layer vuetify-components {
.v-calendar-events .v-event-more {
background-color: rgb(var(--v-theme-surface));
color: rgb(var(--v-theme-on-surface));
}
.v-calendar-events .v-event-more.v-outside {
background-color: rgb(var(--v-theme-surface-light));
color: rgb(var(--v-theme-on-surface-light));
}
.v-calendar .v-event {
position: relative;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
font-size: 12px;
cursor: pointer;
line-height: 20px;
margin-right: -1px;
z-index: 1;
border-radius: 4px;
}
.v-calendar .v-event-more {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
font-size: 12px;
cursor: pointer;
font-weight: bold;
z-index: 1;
position: relative;
}
.v-calendar .v-event-timed-container {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
margin-right: 10px;
pointer-events: none;
}
.v-calendar .v-event-timed {
position: absolute;
white-space: nowrap;
text-overflow: ellipsis;
font-size: 12px;
cursor: pointer;
border: 1px solid rgb(var(--v-theme-surface));
border-radius: 4px;
pointer-events: all;
}
.v-calendar .v-event-summary {
display: inline-block;
overflow: hidden;
text-overflow: ellipsis;
width: 100%;
white-space: nowrap;
}
.v-calendar.v-calendar-events .v-calendar-weekly__head-weekday {
margin-right: -1px;
}
.v-calendar.v-calendar-events .v-calendar-weekly__day {
overflow: visible;
margin-right: -1px;
}
}
@@ -0,0 +1,307 @@
import type { PropType, VNode } from 'vue';
import type { CalendarBaseProps } from './calendarBase.js';
import type { CalendarCategory, CalendarDayBodySlotScope, CalendarDaySlotScope, CalendarEvent, CalendarEventCategoryFunction, CalendarEventColorFunction, CalendarEventNameFunction, CalendarEventOverlapMode, CalendarEventParsed, CalendarEventTimedFunction, CalendarEventVisual, CalendarTimestamp } from '../types.js';
type VDailyEventsMap = {
[date: string]: {
parent: HTMLElement;
more: HTMLElement | null;
events: HTMLElement[];
};
};
export interface VEventScopeInput {
eventParsed: CalendarEventParsed;
day: CalendarDaySlotScope;
start: boolean;
end: boolean;
timed: boolean;
}
export declare const makeCalendarWithEventsProps: <Defaults extends {
events?: unknown;
eventStart?: unknown;
eventEnd?: unknown;
eventTimed?: unknown;
eventCategory?: unknown;
eventHeight?: unknown;
eventColor?: unknown;
eventTextColor?: unknown;
eventName?: unknown;
eventOverlapThreshold?: unknown;
eventOverlapMode?: unknown;
eventMore?: unknown;
eventMoreText?: unknown;
eventRipple?: unknown;
eventMarginBottom?: unknown;
} = {}>(defaults?: Defaults | undefined) => {
events: unknown extends Defaults["events"] ? {
type: PropType<CalendarEvent[]>;
default: () => never[];
} : Omit<{
type: PropType<CalendarEvent[]>;
default: () => never[];
}, "default" | "type"> & {
type: PropType<unknown extends Defaults["events"] ? CalendarEvent[] : CalendarEvent[] | Defaults["events"]>;
default: unknown extends Defaults["events"] ? CalendarEvent[] : CalendarEvent[] | Defaults["events"];
};
eventStart: unknown extends Defaults["eventStart"] ? {
type: StringConstructor;
default: string;
} : Omit<{
type: StringConstructor;
default: string;
}, "default" | "type"> & {
type: PropType<unknown extends Defaults["eventStart"] ? string : string | Defaults["eventStart"]>;
default: unknown extends Defaults["eventStart"] ? string : string | Defaults["eventStart"];
};
eventEnd: unknown extends Defaults["eventEnd"] ? {
type: StringConstructor;
default: string;
} : Omit<{
type: StringConstructor;
default: string;
}, "default" | "type"> & {
type: PropType<unknown extends Defaults["eventEnd"] ? string : string | Defaults["eventEnd"]>;
default: unknown extends Defaults["eventEnd"] ? string : string | Defaults["eventEnd"];
};
eventTimed: unknown extends Defaults["eventTimed"] ? {
type: PropType<string | CalendarEventTimedFunction>;
default: string;
} : Omit<{
type: PropType<string | CalendarEventTimedFunction>;
default: string;
}, "default" | "type"> & {
type: PropType<unknown extends Defaults["eventTimed"] ? string | CalendarEventTimedFunction : string | CalendarEventTimedFunction | Defaults["eventTimed"]>;
default: unknown extends Defaults["eventTimed"] ? string | CalendarEventTimedFunction : Defaults["eventTimed"] | NonNullable<string | CalendarEventTimedFunction>;
};
eventCategory: unknown extends Defaults["eventCategory"] ? {
type: PropType<string | CalendarEventCategoryFunction>;
default: string;
} : Omit<{
type: PropType<string | CalendarEventCategoryFunction>;
default: string;
}, "default" | "type"> & {
type: PropType<unknown extends Defaults["eventCategory"] ? string | CalendarEventCategoryFunction : string | CalendarEventCategoryFunction | Defaults["eventCategory"]>;
default: unknown extends Defaults["eventCategory"] ? string | CalendarEventCategoryFunction : Defaults["eventCategory"] | NonNullable<string | CalendarEventCategoryFunction>;
};
eventHeight: unknown extends Defaults["eventHeight"] ? {
type: NumberConstructor;
default: number;
} : Omit<{
type: NumberConstructor;
default: number;
}, "default" | "type"> & {
type: PropType<unknown extends Defaults["eventHeight"] ? number : number | Defaults["eventHeight"]>;
default: unknown extends Defaults["eventHeight"] ? number : number | Defaults["eventHeight"];
};
eventColor: unknown extends Defaults["eventColor"] ? {
type: PropType<string | CalendarEventColorFunction>;
default: string;
} : Omit<{
type: PropType<string | CalendarEventColorFunction>;
default: string;
}, "default" | "type"> & {
type: PropType<unknown extends Defaults["eventColor"] ? string | CalendarEventColorFunction : string | CalendarEventColorFunction | Defaults["eventColor"]>;
default: unknown extends Defaults["eventColor"] ? string | CalendarEventColorFunction : Defaults["eventColor"] | NonNullable<string | CalendarEventColorFunction>;
};
eventTextColor: unknown extends Defaults["eventTextColor"] ? {
type: PropType<string | CalendarEventColorFunction>;
} : Omit<{
type: PropType<string | CalendarEventColorFunction>;
}, "default" | "type"> & {
type: PropType<unknown extends Defaults["eventTextColor"] ? string | CalendarEventColorFunction : string | CalendarEventColorFunction | Defaults["eventTextColor"]>;
default: unknown extends Defaults["eventTextColor"] ? string | CalendarEventColorFunction : Defaults["eventTextColor"] | NonNullable<string | CalendarEventColorFunction>;
};
eventName: unknown extends Defaults["eventName"] ? {
type: PropType<string | CalendarEventNameFunction>;
default: string;
} : Omit<{
type: PropType<string | CalendarEventNameFunction>;
default: string;
}, "default" | "type"> & {
type: PropType<unknown extends Defaults["eventName"] ? string | CalendarEventNameFunction : string | CalendarEventNameFunction | Defaults["eventName"]>;
default: unknown extends Defaults["eventName"] ? string | CalendarEventNameFunction : Defaults["eventName"] | NonNullable<string | CalendarEventNameFunction>;
};
eventOverlapThreshold: unknown extends Defaults["eventOverlapThreshold"] ? {
type: (NumberConstructor | StringConstructor)[];
default: number;
} : Omit<{
type: (NumberConstructor | StringConstructor)[];
default: number;
}, "default" | "type"> & {
type: PropType<unknown extends Defaults["eventOverlapThreshold"] ? string | number : string | number | Defaults["eventOverlapThreshold"]>;
default: unknown extends Defaults["eventOverlapThreshold"] ? string | number : Defaults["eventOverlapThreshold"] | NonNullable<string | number>;
};
eventOverlapMode: unknown extends Defaults["eventOverlapMode"] ? {
type: PropType<'stack' | 'column' | CalendarEventOverlapMode>;
default: string;
validate: (mode: any) => boolean;
} : Omit<{
type: PropType<'stack' | 'column' | CalendarEventOverlapMode>;
default: string;
validate: (mode: any) => boolean;
}, "default" | "type"> & {
type: PropType<unknown extends Defaults["eventOverlapMode"] ? "column" | "stack" | CalendarEventOverlapMode : "column" | "stack" | CalendarEventOverlapMode | Defaults["eventOverlapMode"]>;
default: unknown extends Defaults["eventOverlapMode"] ? "column" | "stack" | CalendarEventOverlapMode : Defaults["eventOverlapMode"] | NonNullable<"column" | "stack" | CalendarEventOverlapMode>;
};
eventMore: unknown extends Defaults["eventMore"] ? {
type: BooleanConstructor;
default: boolean;
} : Omit<{
type: BooleanConstructor;
default: boolean;
}, "default" | "type"> & {
type: PropType<unknown extends Defaults["eventMore"] ? boolean : boolean | Defaults["eventMore"]>;
default: unknown extends Defaults["eventMore"] ? boolean : boolean | Defaults["eventMore"];
};
eventMoreText: unknown extends Defaults["eventMoreText"] ? {
type: StringConstructor;
default: string;
} : Omit<{
type: StringConstructor;
default: string;
}, "default" | "type"> & {
type: PropType<unknown extends Defaults["eventMoreText"] ? string : string | Defaults["eventMoreText"]>;
default: unknown extends Defaults["eventMoreText"] ? string : string | Defaults["eventMoreText"];
};
eventRipple: unknown extends Defaults["eventRipple"] ? {
type: (BooleanConstructor | ObjectConstructor)[];
default: null;
} : Omit<{
type: (BooleanConstructor | ObjectConstructor)[];
default: null;
}, "default" | "type"> & {
type: PropType<unknown extends Defaults["eventRipple"] ? boolean | Record<string, any> : boolean | Record<string, any> | Defaults["eventRipple"]>;
default: unknown extends Defaults["eventRipple"] ? boolean | Record<string, any> : Defaults["eventRipple"] | NonNullable<boolean | Record<string, any>>;
};
eventMarginBottom: unknown extends Defaults["eventMarginBottom"] ? {
type: NumberConstructor;
default: number;
} : Omit<{
type: NumberConstructor;
default: number;
}, "default" | "type"> & {
type: PropType<unknown extends Defaults["eventMarginBottom"] ? number : number | Defaults["eventMarginBottom"]>;
default: unknown extends Defaults["eventMarginBottom"] ? number : number | Defaults["eventMarginBottom"];
};
};
interface CalendarWithEventsProps extends CalendarBaseProps {
events: CalendarEvent[];
eventStart: string;
eventEnd: string;
eventTimed: string | CalendarEventTimedFunction;
eventCategory: string | CalendarEventCategoryFunction;
eventHeight: number;
eventColor: string | CalendarEventColorFunction;
eventTextColor: string | CalendarEventColorFunction | undefined;
eventName: string | CalendarEventNameFunction;
eventOverlapThreshold: string | number;
eventOverlapMode: string | CalendarEventOverlapMode;
eventMore: boolean;
eventMoreText: string;
eventRipple: boolean | object | null | undefined;
eventMarginBottom: number;
type: 'month' | 'week' | 'day' | '4day' | 'custom-weekly' | 'custom-daily' | 'category';
}
export declare function useCalendarWithEvents(props: CalendarWithEventsProps, slots: any, attrs: any): {
times: {
now: {
date: string;
time: string;
year: number;
month: number;
day: number;
weekday: number;
hour: number;
minute: number;
hasDay: boolean;
hasTime: boolean;
past: boolean;
present: boolean;
future: boolean;
category?: CalendarCategory;
};
today: {
date: string;
time: string;
year: number;
month: number;
day: number;
weekday: number;
hour: number;
minute: number;
hasDay: boolean;
hasTime: boolean;
past: boolean;
present: boolean;
future: boolean;
category?: CalendarCategory;
};
};
locale: {
name: string;
decimalSeparator: import("vue").ShallowRef<string>;
messages: import("vue").Ref<import("../../../types.js").LocaleMessages, import("../../../types.js").LocaleMessages>;
current: import("vue").Ref<string, string>;
fallback: import("vue").Ref<string, string>;
t: (key: string, ...params: unknown[]) => string;
n: (value: number) => string;
provide: (props: import("../../../types.js").LocaleOptions) => import("../../../types.js").LocaleInstance;
isRtl: import("vue").Ref<boolean, boolean>;
rtl: import("vue").Ref<Record<string, boolean>, Record<string, boolean>>;
rtlClasses: import("vue").Ref<string, string>;
};
parsedValue: import("vue").ComputedRef<CalendarTimestamp>;
parsedWeekdays: import("vue").ComputedRef<number[]>;
effectiveWeekdays: import("vue").ComputedRef<number[]>;
weekdaySkips: import("vue").ComputedRef<number[]>;
parsedStart: import("vue").ComputedRef<CalendarTimestamp>;
parsedEnd: import("vue").ComputedRef<CalendarTimestamp>;
days: import("vue").ComputedRef<CalendarTimestamp[]>;
dayFormatter: import("vue").ComputedRef<import("../types.js").CalendarFormatter>;
weekdayFormatter: import("vue").ComputedRef<import("../types.js").CalendarFormatter>;
getColorProps: (colors: {
background?: import("../../../composables/color.js").ColorValue;
text?: import("../../../composables/color.js").ColorValue;
}) => {
class: string[];
style: import("vue").CSSProperties;
};
getRelativeClasses: (timestamp: CalendarTimestamp, outside?: boolean) => {
'v-present': boolean;
'v-past': boolean;
'v-future': boolean;
'v-outside': boolean;
};
getWeekNumber: (timestamp: CalendarTimestamp) => number;
getStartOfWeek: (timestamp: CalendarTimestamp) => CalendarTimestamp;
getEndOfWeek: (timestamp: CalendarTimestamp) => CalendarTimestamp;
getFormatter: (options: Intl.DateTimeFormatOptions) => import("../types.js").CalendarFormatter;
updateTimes: () => void;
noEvents: import("vue").ComputedRef<boolean>;
parsedEvents: import("vue").ComputedRef<CalendarEventParsed[]>;
parsedEventOverlapThreshold: import("vue").ComputedRef<number>;
eventTimedFunction: import("vue").ComputedRef<CalendarEventTimedFunction>;
eventCategoryFunction: import("vue").ComputedRef<CalendarEventCategoryFunction>;
eventTextColorFunction: import("vue").ComputedRef<CalendarEventColorFunction>;
eventNameFunction: import("vue").ComputedRef<CalendarEventNameFunction>;
eventModeFunction: import("vue").ComputedRef<CalendarEventOverlapMode>;
eventWeekdays: import("vue").ComputedRef<number[]>;
categoryMode: import("vue").ComputedRef<boolean>;
eventColorFunction: (e: CalendarEvent) => string | undefined;
eventsRef: import("vue").Ref<HTMLElement[], HTMLElement[]>;
updateEventVisibility: () => void;
getEventsMap: () => VDailyEventsMap;
genDayEvent: ({ event }: CalendarEventVisual, day: CalendarDaySlotScope) => VNode;
genTimedEvent: ({ event, left, width }: CalendarEventVisual, day: CalendarDayBodySlotScope) => VNode | false;
genEvent: (event: CalendarEventParsed, scopeInput: VEventScopeInput, timedEvent: boolean, data: Record<string, unknown>) => VNode;
genName: (eventSummary: () => string | VNode) => VNode;
genPlaceholder: (day: CalendarTimestamp) => VNode;
genMore: (day: CalendarDaySlotScope) => VNode;
getVisibleEvents: () => CalendarEventParsed[];
isEventForCategory: (event: CalendarEventParsed, category: CalendarCategory) => boolean;
getEventsForDay: (day: CalendarDaySlotScope) => CalendarEventParsed[];
getEventsForDayAll: (day: CalendarDaySlotScope) => CalendarEventParsed[];
getEventsForDayTimed: (day: CalendarDaySlotScope) => CalendarEventParsed[];
getScopedSlots: () => any;
};
@@ -0,0 +1,473 @@
import { createElementVNode as _createElementVNode, createTextVNode as _createTextVNode, mergeProps as _mergeProps, withDirectives as _withDirectives } from "vue";
// Styles
import "./calendarWithEvents.css";
// Composables
import { useCalendarBase } from "./calendarBase.js"; // Directives
import vRipple from "../../../directives/ripple/index.js"; // Utilities
import { computed, ref } from 'vue';
import { CalendarEventOverlapModes } from "../modes/index.js";
import { isEventHiddenOn, isEventOn, isEventOnDay, isEventOverlapping, isEventStart, parseEvent } from "../util/events.js";
import { diffMinutes, getDayIdentifier } from "../util/timestamp.js";
import { getPrefixedEventHandlers, propsFactory } from "../../../util/index.js"; // Types
// Constants
const WIDTH_FULL = 100;
const WIDTH_START = 95;
// const MINUTES_IN_DAY = 1440
// Prevent import from being erased
void vRipple;
export const makeCalendarWithEventsProps = propsFactory({
events: {
type: Array,
default: () => []
},
eventStart: {
type: String,
default: 'start'
},
eventEnd: {
type: String,
default: 'end'
},
eventTimed: {
type: [String, Function],
default: 'timed'
},
eventCategory: {
type: [String, Function],
default: 'category'
},
eventHeight: {
type: Number,
default: 20
},
eventColor: {
type: [String, Function],
default: 'primary'
},
eventTextColor: {
type: [String, Function]
},
eventName: {
type: [String, Function],
default: 'name'
},
eventOverlapThreshold: {
type: [String, Number],
default: 60
},
eventOverlapMode: {
type: [String, Function],
default: 'stack',
validate: mode => mode in CalendarEventOverlapModes || typeof mode === 'function'
},
eventMore: {
type: Boolean,
default: true
},
eventMoreText: {
type: String,
default: '$vuetify.calendar.moreEvents'
},
eventRipple: {
type: [Boolean, Object],
default: null
},
eventMarginBottom: {
type: Number,
default: 1
}
}, 'VCalendar-events');
export function useCalendarWithEvents(props, slots, attrs) {
const base = useCalendarBase(props);
const noEvents = computed(() => {
return !Array.isArray(props.events) || props.events.length === 0;
});
const categoryMode = computed(() => {
return props.type === 'category';
});
const eventTimedFunction = computed(() => {
return typeof props.eventTimed === 'function' ? props.eventTimed : event => !!event[props.eventTimed];
});
const eventCategoryFunction = computed(() => {
return typeof props.eventCategory === 'function' ? props.eventCategory : event => event[props.eventCategory];
});
const parsedEvents = computed(() => {
if (!props.events) return [];
return props.events.map((event, index) => parseEvent(event, index, props.eventStart || '', props.eventEnd || '', eventTimedFunction.value(event), categoryMode.value ? eventCategoryFunction.value(event) : false));
});
const parsedEventOverlapThreshold = computed(() => {
return parseInt(String(props.eventOverlapThreshold || 0));
});
const eventTextColorFunction = computed(() => {
return typeof props.eventTextColor === 'function' ? props.eventTextColor : () => props.eventTextColor;
});
const eventNameFunction = computed(() => {
return typeof props.eventName === 'function' ? props.eventName : (event, timedEvent) => event.input[props.eventName] || '';
});
const eventModeFunction = computed(() => {
return typeof props.eventOverlapMode === 'function' ? props.eventOverlapMode : CalendarEventOverlapModes[props.eventOverlapMode];
});
const eventWeekdays = computed(() => {
return base.effectiveWeekdays.value;
});
function eventColorFunction(e) {
return typeof props.eventColor === 'function' ? props.eventColor(e) : e.color || props.eventColor;
}
const eventsRef = ref([]);
function updateEventVisibility() {
if (noEvents.value || !props.eventMore) {
return;
}
const eventHeight = props.eventHeight || 0;
const eventsMap = getEventsMap();
for (const date in eventsMap) {
const {
parent,
events,
more
} = eventsMap[date];
if (!more) {
break;
}
const parentBounds = parent.getBoundingClientRect();
const last = events.length - 1;
const eventsSorted = events.map(event => ({
event,
bottom: event.getBoundingClientRect().bottom
})).sort((a, b) => a.bottom - b.bottom);
let hidden = 0;
for (let i = 0; i <= last; i++) {
const bottom = eventsSorted[i].bottom;
const hide = i === last ? bottom > parentBounds.bottom : bottom + eventHeight > parentBounds.bottom;
if (hide) {
eventsSorted[i].event.style.display = 'none';
hidden++;
}
}
// TODO: avoid direct DOM manipulation
if (hidden) {
more.style.display = '';
more.innerHTML = base.locale.t(props.eventMoreText, hidden);
} else {
more.style.display = 'none';
}
}
}
function getEventsMap() {
const eventsMap = {};
const elements = eventsRef.value;
if (!elements || !elements.length) {
return eventsMap;
}
elements.forEach(el => {
const date = el.getAttribute('data-date');
if (el.parentElement && date) {
if (!(date in eventsMap)) {
eventsMap[date] = {
parent: el.parentElement,
more: null,
events: []
};
}
if (el.getAttribute('data-more')) {
eventsMap[date].more = el;
} else {
eventsMap[date].events.push(el);
el.style.display = '';
}
}
});
return eventsMap;
}
function genDayEvent({
event
}, day) {
const eventHeight = props.eventHeight || 0;
const eventMarginBottom = props.eventMarginBottom || 0;
const dayIdentifier = getDayIdentifier(day);
const week = day.week;
const start = dayIdentifier === event.startIdentifier;
let end = dayIdentifier === event.endIdentifier;
let width = WIDTH_START;
if (!categoryMode.value) {
for (let i = day.index + 1; i < week.length; i++) {
const weekdayIdentifier = getDayIdentifier(week[i]);
if (event.endIdentifier >= weekdayIdentifier) {
width += WIDTH_FULL;
end = end || weekdayIdentifier === event.endIdentifier;
} else {
end = true;
break;
}
}
}
const scope = {
eventParsed: event,
day,
start,
end,
timed: false
};
return genEvent(event, scope, false, {
class: ['v-event', {
'v-event-start': start,
'v-event-end': end
}],
style: {
height: `${eventHeight}px`,
width: `${width}%`,
marginBottom: `${eventMarginBottom}px`
},
'data-date': day.date
});
}
function genTimedEvent({
event,
left,
width
}, day) {
const startDelta = day.timeDelta(event.start, day);
const endDelta = day.timeDelta(event.end, day);
if (endDelta === false || startDelta === false || endDelta < 0 || startDelta >= 1 || isEventHiddenOn(event, day)) {
return false;
}
const dayIdentifier = getDayIdentifier(day);
const start = event.startIdentifier >= dayIdentifier;
const end = event.endIdentifier > dayIdentifier;
const top = day.timeToY(event.start, day);
const bottom = day.timeToY(event.end, day);
const height = Math.max(props.eventHeight || 0, bottom - top);
const scope = {
eventParsed: event,
day,
start,
end,
timed: true
};
return genEvent(event, scope, true, {
class: 'v-event-timed',
style: {
top: `${top}px`,
height: `${height}px`,
left: `${left}%`,
width: `${width}%`
}
});
}
function genEvent(event, scopeInput, timedEvent, data) {
const slot = slots.event;
const text = eventTextColorFunction.value(event.input);
const background = eventColorFunction(event.input);
const overlapsNoon = event.start.hour < 12 && event.end.hour >= 12;
const singline = diffMinutes(event.start, event.end) <= parsedEventOverlapThreshold.value;
const formatTime = (withTime, ampm) => {
const formatter = base.getFormatter({
timeZone: 'UTC',
hour: 'numeric',
minute: withTime.minute > 0 ? 'numeric' : undefined
});
return formatter(withTime, true);
};
const timeSummary = () => formatTime(event.start, overlapsNoon) + ' - ' + formatTime(event.end, true);
const eventSummary = () => {
const name = eventNameFunction.value(event, timedEvent);
if (event.start.hasTime) {
if (timedEvent) {
const time = timeSummary();
const delimiter = singline ? ', ' : _createElementVNode("br", null, null);
return _createElementVNode("span", {
"class": "v-event-summary"
}, [_createElementVNode("strong", null, [name]), delimiter, time]);
} else {
const time = formatTime(event.start, true);
return _createElementVNode("span", {
"class": "v-event-summary"
}, [_createElementVNode("strong", null, [time]), _createTextVNode(" "), name]);
}
}
return _createElementVNode("span", {
"class": "v-event-summary"
}, [name]);
};
const scope = {
...scopeInput,
event: event.input,
outside: scopeInput.day.outside,
singline,
overlapsNoon,
formatTime,
timeSummary,
eventSummary
};
const events = getPrefixedEventHandlers(attrs, ':event', nativeEvent => ({
...scope,
nativeEvent
}));
return _withDirectives(_createElementVNode("div", _mergeProps(base.getColorProps({
text,
background
}), events, data, {
"ref_for": true,
"ref": eventsRef
}), [slot?.(scope) ?? genName(eventSummary)]), [[vRipple, props.eventRipple ?? true]]);
}
function genName(eventSummary) {
return _createElementVNode("div", {
"class": "pl-1"
}, [eventSummary()]);
}
function genPlaceholder(day) {
const height = (props.eventHeight || 0) + (props.eventMarginBottom || 0);
return _createElementVNode("div", {
"style": {
height: `${height}px`
},
"data-date": day.date,
"ref_for": true,
"ref": eventsRef
}, null);
}
function genMore(day) {
const eventHeight = props.eventHeight || 0;
const eventMarginBottom = props.eventMarginBottom || 0;
const events = getPrefixedEventHandlers(attrs, ':more', nativeEvent => ({
nativeEvent,
...day
}));
return _withDirectives(_createElementVNode("div", _mergeProps({
"class": ['v-event-more pl-1', {
'v-outside': day.outside
}],
"data-date": day.date,
"data-more": "1",
"style": {
display: 'none',
height: `${eventHeight}px`,
marginBottom: `${eventMarginBottom}px`
},
"ref_for": true,
"ref": eventsRef
}, events), null), [[vRipple, props.eventRipple ?? true]]);
}
function getVisibleEvents() {
const days = base.days.value;
const start = getDayIdentifier(days[0]);
const end = getDayIdentifier(days[days.length - 1]);
return parsedEvents.value.filter(event => isEventOverlapping(event, start, end));
}
function isEventForCategory(event, category) {
return !categoryMode.value || typeof category === 'object' && category.categoryName && category.categoryName === event.category || typeof event.category === 'string' && category === event.category || typeof event.category !== 'string' && category === null;
}
function getEventsForDay(day) {
const identifier = getDayIdentifier(day);
const firstWeekday = eventWeekdays.value[0];
return parsedEvents.value.filter(event => isEventStart(event, day, identifier, firstWeekday));
}
function getEventsForDayAll(day) {
const identifier = getDayIdentifier(day);
const firstWeekday = eventWeekdays.value[0];
return parsedEvents.value.filter(event => event.allDay && (categoryMode.value ? isEventOn(event, identifier) : isEventStart(event, day, identifier, firstWeekday)) && isEventForCategory(event, day.category));
}
function getEventsForDayTimed(day) {
return parsedEvents.value.filter(event => !event.allDay && isEventOnDay(event, day, day.intervalRange) && isEventForCategory(event, day.category));
}
function getScopedSlots() {
if (noEvents.value) {
return {
...slots
};
}
const mode = eventModeFunction.value(parsedEvents.value, eventWeekdays.value[0], parsedEventOverlapThreshold.value);
const isNode = input => !!input;
const getSlotChildren = (day, getter, mapper, timed) => {
const events = getter(day);
const visuals = mode(day, events, timed, categoryMode.value);
if (timed) {
return visuals.map(visual => mapper(visual, day)).filter(isNode);
}
const children = [];
visuals.forEach((visual, index) => {
while (children.length < visual.column) {
children.push(genPlaceholder(day));
}
const mapped = mapper(visual, day);
if (mapped) {
children.push(mapped);
}
});
return children;
};
return {
...slots,
day: day => {
let children = getSlotChildren(day, getEventsForDay, genDayEvent, false);
if (children && children.length > 0 && props.eventMore) {
children.push(genMore(day));
}
if (slots.day) {
const slot = slots.day(day);
if (slot) {
children = children ? children.concat(slot) : slot;
}
}
return children;
},
'day-header': day => {
let children = getSlotChildren(day, getEventsForDayAll, genDayEvent, false);
if (slots['day-header']) {
const slot = slots['day-header'](day);
if (slot) {
children = children ? children.concat(slot) : slot;
}
}
return children;
},
'day-body': day => {
const events = getSlotChildren(day, getEventsForDayTimed, genTimedEvent, true);
let children = [_createElementVNode("div", {
"class": "v-event-timed-container"
}, [events])];
if (slots['day-body']) {
const slot = slots['day-body'](day);
if (slot) {
children = children.concat(slot);
}
}
return children;
}
};
}
return {
...base,
noEvents,
parsedEvents,
parsedEventOverlapThreshold,
eventTimedFunction,
eventCategoryFunction,
eventTextColorFunction,
eventNameFunction,
eventModeFunction,
eventWeekdays,
categoryMode,
eventColorFunction,
eventsRef,
updateEventVisibility,
getEventsMap,
genDayEvent,
genTimedEvent,
genEvent,
genName,
genPlaceholder,
genMore,
getVisibleEvents,
isEventForCategory,
getEventsForDay,
getEventsForDayAll,
getEventsForDayTimed,
getScopedSlots
};
}
//# sourceMappingURL=calendarWithEvents.js.map
File diff suppressed because one or more lines are too long
@@ -0,0 +1,69 @@
@use '../../../styles/tools'
@use '../../../styles/settings'
@use '../variables' as *
@include tools.layer('components')
.v-calendar-events
.v-event-more
background-color: $calendar-background
color: $calendar-on-background
&.v-outside
background-color: $calendar-outside-background
color: $calendar-on-outside-background
.v-calendar
.v-event
position: relative
overflow: hidden
text-overflow: ellipsis
white-space: nowrap
font-size: $calendar-event-font-size
cursor: pointer
line-height: $calendar-event-line-height
margin-right: -$calendar-line-width
z-index: 1
border-radius: $calendar-event-border-radius
.v-event-more
overflow: hidden
text-overflow: ellipsis
white-space: nowrap
font-size: $calendar-event-font-size
cursor: pointer
font-weight: bold
z-index: 1
position: relative
.v-event-timed-container
position: absolute
top: 0
bottom: 0
left: 0
right: 0
margin-right: $calendar-event-right-empty
pointer-events: none
.v-event-timed
position: absolute
white-space: nowrap
text-overflow: ellipsis
font-size: $calendar-event-font-size
cursor: pointer
border: $calendar-event-border-width solid $calendar-background
border-radius: $calendar-event-border-radius
pointer-events: all
.v-event-summary
display: inline-block
overflow: hidden
text-overflow: ellipsis
width: 100%
white-space: nowrap
&.v-calendar-events
.v-calendar-weekly__head-weekday
margin-right: -$calendar-line-width
.v-calendar-weekly__day
overflow: visible
margin-right: -$calendar-line-width
@@ -0,0 +1,232 @@
import { validateNumber, validateTime } from '../util/timestamp.js';
import type { PropType, StyleValue } from 'vue';
import type { CalendarBaseProps } from './calendarBase.js';
import type { CalendarDayBodySlotScope, CalendarFormatter, CalendarTimestamp } from '../types.js';
import type { VTime } from '../util/timestamp.js';
export declare const makeCalendarWithIntervalsProps: <Defaults extends {
maxDays?: unknown;
intervalHeight?: unknown;
intervalWidth?: unknown;
intervalMinutes?: unknown;
firstInterval?: unknown;
firstTime?: unknown;
intervalCount?: unknown;
intervalFormat?: unknown;
intervalStyle?: unknown;
showIntervalLabel?: unknown;
} = {}>(defaults?: Defaults | undefined) => {
maxDays: unknown extends Defaults["maxDays"] ? {
type: NumberConstructor;
default: number;
} : Omit<{
type: NumberConstructor;
default: number;
}, "default" | "type"> & {
type: PropType<unknown extends Defaults["maxDays"] ? number : number | Defaults["maxDays"]>;
default: unknown extends Defaults["maxDays"] ? number : number | Defaults["maxDays"];
};
intervalHeight: unknown extends Defaults["intervalHeight"] ? {
type: (NumberConstructor | StringConstructor)[];
default: number;
validate: typeof validateNumber;
} : Omit<{
type: (NumberConstructor | StringConstructor)[];
default: number;
validate: typeof validateNumber;
}, "default" | "type"> & {
type: PropType<unknown extends Defaults["intervalHeight"] ? string | number : string | number | Defaults["intervalHeight"]>;
default: unknown extends Defaults["intervalHeight"] ? string | number : Defaults["intervalHeight"] | NonNullable<string | number>;
};
intervalWidth: unknown extends Defaults["intervalWidth"] ? {
type: (NumberConstructor | StringConstructor)[];
default: number;
validate: typeof validateNumber;
} : Omit<{
type: (NumberConstructor | StringConstructor)[];
default: number;
validate: typeof validateNumber;
}, "default" | "type"> & {
type: PropType<unknown extends Defaults["intervalWidth"] ? string | number : string | number | Defaults["intervalWidth"]>;
default: unknown extends Defaults["intervalWidth"] ? string | number : Defaults["intervalWidth"] | NonNullable<string | number>;
};
intervalMinutes: unknown extends Defaults["intervalMinutes"] ? {
type: (NumberConstructor | StringConstructor)[];
default: number;
validate: typeof validateNumber;
} : Omit<{
type: (NumberConstructor | StringConstructor)[];
default: number;
validate: typeof validateNumber;
}, "default" | "type"> & {
type: PropType<unknown extends Defaults["intervalMinutes"] ? string | number : string | number | Defaults["intervalMinutes"]>;
default: unknown extends Defaults["intervalMinutes"] ? string | number : Defaults["intervalMinutes"] | NonNullable<string | number>;
};
firstInterval: unknown extends Defaults["firstInterval"] ? {
type: (NumberConstructor | StringConstructor)[];
default: number;
validate: typeof validateNumber;
} : Omit<{
type: (NumberConstructor | StringConstructor)[];
default: number;
validate: typeof validateNumber;
}, "default" | "type"> & {
type: PropType<unknown extends Defaults["firstInterval"] ? string | number : string | number | Defaults["firstInterval"]>;
default: unknown extends Defaults["firstInterval"] ? string | number : Defaults["firstInterval"] | NonNullable<string | number>;
};
firstTime: unknown extends Defaults["firstTime"] ? {
type: PropType<VTime>;
validate: typeof validateTime;
} : Omit<{
type: PropType<VTime>;
validate: typeof validateTime;
}, "default" | "type"> & {
type: PropType<unknown extends Defaults["firstTime"] ? VTime : Defaults["firstTime"] | VTime>;
default: unknown extends Defaults["firstTime"] ? VTime : Defaults["firstTime"] | NonNullable<VTime>;
};
intervalCount: unknown extends Defaults["intervalCount"] ? {
type: (NumberConstructor | StringConstructor)[];
default: number;
validate: typeof validateNumber;
} : Omit<{
type: (NumberConstructor | StringConstructor)[];
default: number;
validate: typeof validateNumber;
}, "default" | "type"> & {
type: PropType<unknown extends Defaults["intervalCount"] ? string | number : string | number | Defaults["intervalCount"]>;
default: unknown extends Defaults["intervalCount"] ? string | number : Defaults["intervalCount"] | NonNullable<string | number>;
};
intervalFormat: unknown extends Defaults["intervalFormat"] ? {
type: PropType<CalendarFormatter>;
default: null;
} : Omit<{
type: PropType<CalendarFormatter>;
default: null;
}, "default" | "type"> & {
type: PropType<unknown extends Defaults["intervalFormat"] ? CalendarFormatter : CalendarFormatter | Defaults["intervalFormat"]>;
default: unknown extends Defaults["intervalFormat"] ? CalendarFormatter : CalendarFormatter | Defaults["intervalFormat"];
};
intervalStyle: unknown extends Defaults["intervalStyle"] ? {
type: PropType<(interval: CalendarTimestamp) => StyleValue>;
default: null;
} : Omit<{
type: PropType<(interval: CalendarTimestamp) => StyleValue>;
default: null;
}, "default" | "type"> & {
type: PropType<unknown extends Defaults["intervalStyle"] ? (interval: CalendarTimestamp) => StyleValue : ((interval: CalendarTimestamp) => StyleValue) | Defaults["intervalStyle"]>;
default: unknown extends Defaults["intervalStyle"] ? (interval: CalendarTimestamp) => StyleValue : ((interval: CalendarTimestamp) => StyleValue) | Defaults["intervalStyle"];
};
showIntervalLabel: unknown extends Defaults["showIntervalLabel"] ? {
type: PropType<(interval: CalendarTimestamp) => boolean>;
default: null;
} : Omit<{
type: PropType<(interval: CalendarTimestamp) => boolean>;
default: null;
}, "default" | "type"> & {
type: PropType<unknown extends Defaults["showIntervalLabel"] ? (interval: CalendarTimestamp) => boolean : ((interval: CalendarTimestamp) => boolean) | Defaults["showIntervalLabel"]>;
default: unknown extends Defaults["showIntervalLabel"] ? (interval: CalendarTimestamp) => boolean : ((interval: CalendarTimestamp) => boolean) | Defaults["showIntervalLabel"];
};
};
interface CalendarWithIntervalsProps extends CalendarBaseProps {
maxDays: number;
intervalHeight: string | number;
intervalMinutes: string | number;
firstInterval: string | number;
firstTime: VTime | undefined;
intervalCount: string | number;
intervalFormat: CalendarFormatter | string | undefined;
}
export declare function useCalendarWithIntervals(props: CalendarWithIntervalsProps): {
times: {
now: {
date: string;
time: string;
year: number;
month: number;
day: number;
weekday: number;
hour: number;
minute: number;
hasDay: boolean;
hasTime: boolean;
past: boolean;
present: boolean;
future: boolean;
category?: import("../types.js").CalendarCategory;
};
today: {
date: string;
time: string;
year: number;
month: number;
day: number;
weekday: number;
hour: number;
minute: number;
hasDay: boolean;
hasTime: boolean;
past: boolean;
present: boolean;
future: boolean;
category?: import("../types.js").CalendarCategory;
};
};
locale: {
name: string;
decimalSeparator: import("vue").ShallowRef<string>;
messages: import("vue").Ref<import("../../../types.js").LocaleMessages, import("../../../types.js").LocaleMessages>;
current: import("vue").Ref<string, string>;
fallback: import("vue").Ref<string, string>;
t: (key: string, ...params: unknown[]) => string;
n: (value: number) => string;
provide: (props: import("../../../types.js").LocaleOptions) => import("../../../types.js").LocaleInstance;
isRtl: import("vue").Ref<boolean, boolean>;
rtl: import("vue").Ref<Record<string, boolean>, Record<string, boolean>>;
rtlClasses: import("vue").Ref<string, string>;
};
parsedValue: import("vue").ComputedRef<CalendarTimestamp>;
parsedWeekdays: import("vue").ComputedRef<number[]>;
effectiveWeekdays: import("vue").ComputedRef<number[]>;
weekdaySkips: import("vue").ComputedRef<number[]>;
parsedStart: import("vue").ComputedRef<CalendarTimestamp>;
parsedEnd: import("vue").ComputedRef<CalendarTimestamp>;
dayFormatter: import("vue").ComputedRef<CalendarFormatter>;
weekdayFormatter: import("vue").ComputedRef<CalendarFormatter>;
getColorProps: (colors: {
background?: import("../../../composables/color.js").ColorValue;
text?: import("../../../composables/color.js").ColorValue;
}) => {
class: string[];
style: import("vue").CSSProperties;
};
getRelativeClasses: (timestamp: CalendarTimestamp, outside?: boolean) => {
'v-present': boolean;
'v-past': boolean;
'v-future': boolean;
'v-outside': boolean;
};
getWeekNumber: (timestamp: CalendarTimestamp) => number;
getStartOfWeek: (timestamp: CalendarTimestamp) => CalendarTimestamp;
getEndOfWeek: (timestamp: CalendarTimestamp) => CalendarTimestamp;
getFormatter: (options: Intl.DateTimeFormatOptions) => CalendarFormatter;
updateTimes: () => void;
scrollAreaRef: import("vue").ShallowRef<HTMLElement | undefined, HTMLElement | undefined>;
parsedFirstInterval: import("vue").ComputedRef<number>;
parsedIntervalMinutes: import("vue").ComputedRef<number>;
parsedIntervalCount: import("vue").ComputedRef<number>;
parsedIntervalHeight: import("vue").ComputedRef<number>;
parsedFirstTime: import("vue").ComputedRef<number | false>;
firstMinute: import("vue").ComputedRef<number>;
bodyHeight: import("vue").ComputedRef<number>;
days: import("vue").ComputedRef<CalendarTimestamp[]>;
intervals: import("vue").ComputedRef<CalendarTimestamp[][]>;
intervalFormatter: import("vue").ComputedRef<CalendarFormatter>;
showIntervalLabelDefault: (interval: CalendarTimestamp) => boolean;
intervalStyleDefault: (_interval: CalendarTimestamp) => StyleValue;
getTimestampAtEvent: (e: Event, day: CalendarTimestamp) => CalendarTimestamp;
getSlotScope: (timestamp: CalendarTimestamp) => CalendarDayBodySlotScope;
scrollToTime: (time: VTime) => boolean;
minutesToPixels: (minutes: number) => number;
timeToY: (time: VTime | CalendarTimestamp, targetDateOrClamp?: CalendarTimestamp | boolean) => number | false;
timeDelta: (time: VTime | CalendarTimestamp, targetDate?: CalendarTimestamp) => number | false;
};
@@ -0,0 +1,208 @@
// Composables
import { useCalendarBase } from "./calendarBase.js"; // Utilities
import { computed, shallowRef } from 'vue';
import { copyTimestamp, createDayList, createIntervalList, createNativeLocaleFormatter, getDayIdentifier, MINUTES_IN_DAY, parseTime, updateMinutes, validateNumber, validateTime } from "../util/timestamp.js";
import { propsFactory } from "../../../util/index.js";
import { Box, getTargetBox } from "../../../util/box.js"; // Types
export const makeCalendarWithIntervalsProps = propsFactory({
maxDays: {
type: Number,
default: 7
},
intervalHeight: {
type: [Number, String],
default: 48,
validate: validateNumber
},
intervalWidth: {
type: [Number, String],
default: 60,
validate: validateNumber
},
intervalMinutes: {
type: [Number, String],
default: 60,
validate: validateNumber
},
firstInterval: {
type: [Number, String],
default: 0,
validate: validateNumber
},
firstTime: {
type: [Number, String, Object],
validate: validateTime
},
intervalCount: {
type: [Number, String],
default: 24,
validate: validateNumber
},
intervalFormat: {
type: Function,
default: null
},
intervalStyle: {
type: Function,
default: null
},
showIntervalLabel: {
type: Function,
default: null
}
}, 'VCalendar-intervals');
export function useCalendarWithIntervals(props) {
const base = useCalendarBase(props);
const scrollAreaRef = shallowRef();
const parsedFirstInterval = computed(() => {
return parseInt(String(props.firstInterval || 0));
});
const parsedIntervalMinutes = computed(() => {
return parseInt(String(props.intervalMinutes || 60));
});
const parsedIntervalCount = computed(() => {
return parseInt(String(props.intervalCount || 24));
});
const parsedIntervalHeight = computed(() => {
return parseFloat(String(props.intervalHeight || 48));
});
const parsedFirstTime = computed(() => {
return parseTime(props.firstTime);
});
const firstMinute = computed(() => {
const time = parsedFirstTime.value;
return time !== false && time >= 0 && time <= MINUTES_IN_DAY ? time : parsedFirstInterval.value * parsedIntervalMinutes.value;
});
const bodyHeight = computed(() => {
return parsedIntervalCount.value * parsedIntervalHeight.value;
});
const days = computed(() => {
return createDayList(base.parsedStart.value, base.parsedEnd.value, base.times.today, base.weekdaySkips.value, props.maxDays);
});
const intervals = computed(() => {
const daysValue = days.value;
const first = firstMinute.value;
const minutes = parsedIntervalMinutes.value;
const count = parsedIntervalCount.value;
const now = base.times.now;
return daysValue.map(d => createIntervalList(d, first, minutes, count, now));
});
const intervalFormatter = computed(() => {
if (props.intervalFormat) {
return props.intervalFormat;
}
return createNativeLocaleFormatter(base.locale.current.value, (tms, short) => !short ? {
timeZone: 'UTC',
hour: '2-digit',
minute: '2-digit'
} : tms.minute === 0 ? {
timeZone: 'UTC',
hour: 'numeric'
} : {
timeZone: 'UTC',
hour: 'numeric',
minute: '2-digit'
});
});
function showIntervalLabelDefault(interval) {
const first = intervals.value[0][0];
const isFirst = first.hour === interval.hour && first.minute === interval.minute;
return !isFirst;
}
function intervalStyleDefault(_interval) {
return undefined;
}
function getTimestampAtEvent(e, day) {
const timestamp = copyTimestamp(day);
const bounds = new Box(e.currentTarget);
const baseMinutes = firstMinute.value;
const touchEvent = e;
const mouseEvent = e;
const touches = touchEvent.changedTouches || touchEvent.touches;
const target = touches && touches[0] ? touches[0] : mouseEvent;
const point = getTargetBox([target.clientX, target.clientY]);
const addIntervals = (point.y - bounds.top) / parsedIntervalHeight.value;
const addMinutes = Math.floor(addIntervals * parsedIntervalMinutes.value);
const minutes = baseMinutes + addMinutes;
return updateMinutes(timestamp, minutes, base.times.now);
}
function getSlotScope(timestamp) {
const scope = copyTimestamp(timestamp);
scope.timeToY = timeToY;
scope.timeDelta = timeDelta;
scope.minutesToPixels = minutesToPixels;
scope.week = days.value;
scope.intervalRange = [firstMinute.value, firstMinute.value + parsedIntervalCount.value * parsedIntervalMinutes.value];
return scope;
}
function scrollToTime(time) {
const y = timeToY(time);
const pane = scrollAreaRef.value;
if (y === false || !pane) {
return false;
}
pane.scrollTop = y;
return true;
}
function minutesToPixels(minutes) {
return minutes / parsedIntervalMinutes.value * parsedIntervalHeight.value;
}
function timeToY(time, targetDateOrClamp = false) {
const clamp = targetDateOrClamp !== false;
const targetDate = typeof targetDateOrClamp !== 'boolean' ? targetDateOrClamp : undefined;
let y = timeDelta(time, targetDate);
if (y === false) return y;
y *= bodyHeight.value;
if (clamp) {
if (y < 0) {
y = 0;
} else if (y > bodyHeight.value) {
y = bodyHeight.value;
}
} else {
if (y < 0) {
y = y + bodyHeight.value;
} else if (y > bodyHeight.value) {
y = y - bodyHeight.value;
}
}
return y;
}
function timeDelta(time, targetDate) {
let minutes = parseTime(time);
if (minutes === false) {
return false;
}
const gap = parsedIntervalCount.value * parsedIntervalMinutes.value;
if (targetDate && typeof time === 'object' && 'day' in time) {
const a = getDayIdentifier(time);
const b = getDayIdentifier(targetDate);
minutes += (a - b) * gap;
}
const min = firstMinute.value;
return (minutes - min) / gap;
}
return {
...base,
scrollAreaRef,
parsedFirstInterval,
parsedIntervalMinutes,
parsedIntervalCount,
parsedIntervalHeight,
parsedFirstTime,
firstMinute,
bodyHeight,
days,
intervals,
intervalFormatter,
showIntervalLabelDefault,
intervalStyleDefault,
getTimestampAtEvent,
getSlotScope,
scrollToTime,
minutesToPixels,
timeToY,
timeDelta
};
}
//# sourceMappingURL=calendarWithIntervals.js.map
File diff suppressed because one or more lines are too long
@@ -0,0 +1,45 @@
import type { CalendarTimestamp } from '../types.js';
export declare function useTimes(props: {
now: string | undefined;
}): {
times: {
now: {
date: string;
time: string;
year: number;
month: number;
day: number;
weekday: number;
hour: number;
minute: number;
hasDay: boolean;
hasTime: boolean;
past: boolean;
present: boolean;
future: boolean;
category?: import("../types.js").CalendarCategory;
};
today: {
date: string;
time: string;
year: number;
month: number;
day: number;
weekday: number;
hour: number;
minute: number;
hasDay: boolean;
hasTime: boolean;
past: boolean;
present: boolean;
future: boolean;
category?: import("../types.js").CalendarCategory;
};
};
parsedNow: import("vue").ComputedRef<CalendarTimestamp | null>;
updateTimes: () => void;
setPresent: () => void;
getNow: () => CalendarTimestamp;
updateDay: (now: CalendarTimestamp, target: CalendarTimestamp) => void;
updateTime: (now: CalendarTimestamp, target: CalendarTimestamp) => void;
};
@@ -0,0 +1,55 @@
// Utilities
import { computed, reactive, watch } from 'vue';
import { parseDate, parseTimestamp, validateTimestamp } from "../util/timestamp.js"; // Types
export function useTimes(props) {
const times = reactive({
now: parseTimestamp('0000-00-00 00:00', true),
today: parseTimestamp('0000-00-00', true)
});
const parsedNow = computed(() => {
return props.now && validateTimestamp(props.now) ? parseTimestamp(props.now, true) : null;
});
function setPresent() {
times.now.present = times.today.present = true;
times.now.past = times.today.past = false;
times.now.future = times.today.future = false;
}
function getNow() {
return parseDate(new Date());
}
function updateDay(now, target) {
if (now.date !== target.date) {
target.year = now.year;
target.month = now.month;
target.day = now.day;
target.weekday = now.weekday;
target.date = now.date;
}
}
function updateTime(now, target) {
if (now.time !== target.time) {
target.hour = now.hour;
target.minute = now.minute;
target.time = now.time;
}
}
function updateTimes() {
const now = parsedNow.value || getNow();
updateDay(now, times.now);
updateTime(now, times.now);
updateDay(now, times.today);
}
watch(parsedNow, updateTimes);
updateTimes();
setPresent();
return {
times,
parsedNow,
updateTimes,
setPresent,
getNow,
updateDay,
updateTime
};
}
//# sourceMappingURL=times.js.map
@@ -0,0 +1 @@
{"version":3,"file":"times.js","names":["computed","reactive","watch","parseDate","parseTimestamp","validateTimestamp","useTimes","props","times","now","today","parsedNow","setPresent","present","past","future","getNow","Date","updateDay","target","date","year","month","day","weekday","updateTime","time","hour","minute","updateTimes","value"],"sources":["../../../../src/components/VCalendar/composables/times.ts"],"sourcesContent":["// Utilities\nimport { computed, reactive, watch } from 'vue'\nimport {\n parseDate,\n parseTimestamp,\n validateTimestamp,\n} from '../util/timestamp'\n\n// Types\nimport type { CalendarTimestamp } from '../types'\n\nexport function useTimes (props: { now: string | undefined }) {\n const times = reactive({\n now: parseTimestamp('0000-00-00 00:00', true),\n today: parseTimestamp('0000-00-00', true),\n })\n\n const parsedNow = computed((): CalendarTimestamp | null => {\n return props.now && validateTimestamp(props.now) ? parseTimestamp(props.now, true) : null\n })\n\n function setPresent (): void {\n times.now.present = times.today.present = true\n times.now.past = times.today.past = false\n times.now.future = times.today.future = false\n }\n\n function getNow (): CalendarTimestamp {\n return parseDate(new Date())\n }\n\n function updateDay (now: CalendarTimestamp, target: CalendarTimestamp): void {\n if (now.date !== target.date) {\n target.year = now.year\n target.month = now.month\n target.day = now.day\n target.weekday = now.weekday\n target.date = now.date\n }\n }\n\n function updateTime (now: CalendarTimestamp, target: CalendarTimestamp): void {\n if (now.time !== target.time) {\n target.hour = now.hour\n target.minute = now.minute\n target.time = now.time\n }\n }\n\n function updateTimes (): void {\n const now: CalendarTimestamp = parsedNow.value || getNow()\n updateDay(now, times.now)\n updateTime(now, times.now)\n updateDay(now, times.today)\n }\n\n watch(parsedNow, updateTimes)\n\n updateTimes()\n setPresent()\n\n return {\n times,\n parsedNow,\n updateTimes,\n setPresent,\n getNow,\n updateDay,\n updateTime,\n }\n}\n"],"mappings":"AAAA;AACA,SAASA,QAAQ,EAAEC,QAAQ,EAAEC,KAAK,QAAQ,KAAK;AAAA,SAE7CC,SAAS,EACTC,cAAc,EACdC,iBAAiB,gCAGnB;AAGA,OAAO,SAASC,QAAQA,CAAEC,KAAkC,EAAE;EAC5D,MAAMC,KAAK,GAAGP,QAAQ,CAAC;IACrBQ,GAAG,EAAEL,cAAc,CAAC,kBAAkB,EAAE,IAAI,CAAC;IAC7CM,KAAK,EAAEN,cAAc,CAAC,YAAY,EAAE,IAAI;EAC1C,CAAC,CAAC;EAEF,MAAMO,SAAS,GAAGX,QAAQ,CAAC,MAAgC;IACzD,OAAOO,KAAK,CAACE,GAAG,IAAIJ,iBAAiB,CAACE,KAAK,CAACE,GAAG,CAAC,GAAGL,cAAc,CAACG,KAAK,CAACE,GAAG,EAAE,IAAI,CAAC,GAAG,IAAI;EAC3F,CAAC,CAAC;EAEF,SAASG,UAAUA,CAAA,EAAU;IAC3BJ,KAAK,CAACC,GAAG,CAACI,OAAO,GAAGL,KAAK,CAACE,KAAK,CAACG,OAAO,GAAG,IAAI;IAC9CL,KAAK,CAACC,GAAG,CAACK,IAAI,GAAGN,KAAK,CAACE,KAAK,CAACI,IAAI,GAAG,KAAK;IACzCN,KAAK,CAACC,GAAG,CAACM,MAAM,GAAGP,KAAK,CAACE,KAAK,CAACK,MAAM,GAAG,KAAK;EAC/C;EAEA,SAASC,MAAMA,CAAA,EAAuB;IACpC,OAAOb,SAAS,CAAC,IAAIc,IAAI,CAAC,CAAC,CAAC;EAC9B;EAEA,SAASC,SAASA,CAAET,GAAsB,EAAEU,MAAyB,EAAQ;IAC3E,IAAIV,GAAG,CAACW,IAAI,KAAKD,MAAM,CAACC,IAAI,EAAE;MAC5BD,MAAM,CAACE,IAAI,GAAGZ,GAAG,CAACY,IAAI;MACtBF,MAAM,CAACG,KAAK,GAAGb,GAAG,CAACa,KAAK;MACxBH,MAAM,CAACI,GAAG,GAAGd,GAAG,CAACc,GAAG;MACpBJ,MAAM,CAACK,OAAO,GAAGf,GAAG,CAACe,OAAO;MAC5BL,MAAM,CAACC,IAAI,GAAGX,GAAG,CAACW,IAAI;IACxB;EACF;EAEA,SAASK,UAAUA,CAAEhB,GAAsB,EAAEU,MAAyB,EAAQ;IAC5E,IAAIV,GAAG,CAACiB,IAAI,KAAKP,MAAM,CAACO,IAAI,EAAE;MAC5BP,MAAM,CAACQ,IAAI,GAAGlB,GAAG,CAACkB,IAAI;MACtBR,MAAM,CAACS,MAAM,GAAGnB,GAAG,CAACmB,MAAM;MAC1BT,MAAM,CAACO,IAAI,GAAGjB,GAAG,CAACiB,IAAI;IACxB;EACF;EAEA,SAASG,WAAWA,CAAA,EAAU;IAC5B,MAAMpB,GAAsB,GAAGE,SAAS,CAACmB,KAAK,IAAId,MAAM,CAAC,CAAC;IAC1DE,SAAS,CAACT,GAAG,EAAED,KAAK,CAACC,GAAG,CAAC;IACzBgB,UAAU,CAAChB,GAAG,EAAED,KAAK,CAACC,GAAG,CAAC;IAC1BS,SAAS,CAACT,GAAG,EAAED,KAAK,CAACE,KAAK,CAAC;EAC7B;EAEAR,KAAK,CAACS,SAAS,EAAEkB,WAAW,CAAC;EAE7BA,WAAW,CAAC,CAAC;EACbjB,UAAU,CAAC,CAAC;EAEZ,OAAO;IACLJ,KAAK;IACLG,SAAS;IACTkB,WAAW;IACXjB,UAAU;IACVI,MAAM;IACNE,SAAS;IACTO;EACF,CAAC;AACH","ignoreList":[]}
+1
View File
@@ -0,0 +1 @@
export { VCalendar } from './VCalendar.js';
+5
View File
@@ -0,0 +1,5 @@
export { VCalendar } from "./VCalendar.js"; // export { VCalendarCategory as VCalendarCategory } from './VCalendarDaily'
// export { VCalendarDaily as VCalendarDaily } from './VCalendarWeekly'
// export { VCalendarWeekly as VCalendarWeekly } from './VCalendarMonthly'
// export { VCalendarMonthly as VCalendarMonthly } from './VCalendarCategory'
//# sourceMappingURL=index.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"index.js","names":["VCalendar"],"sources":["../../../src/components/VCalendar/index.ts"],"sourcesContent":["export { VCalendar } from './VCalendar'\n// export { VCalendarCategory as VCalendarCategory } from './VCalendarDaily'\n// export { VCalendarDaily as VCalendarDaily } from './VCalendarWeekly'\n// export { VCalendarWeekly as VCalendarWeekly } from './VCalendarMonthly'\n// export { VCalendarMonthly as VCalendarMonthly } from './VCalendarCategory'\n"],"mappings":"SAASA,SAAS,0BAClB;AACA;AACA;AACA","ignoreList":[]}
@@ -0,0 +1,2 @@
import type { CalendarEventOverlapMode } from '../types.js';
export declare const column: CalendarEventOverlapMode;
+17
View File
@@ -0,0 +1,17 @@
// Types
import { getOverlapGroupHandler } from "./common.js";
const FULL_WIDTH = 100;
export const column = (events, firstWeekday, overlapThreshold) => {
const handler = getOverlapGroupHandler(firstWeekday);
return (day, dayEvents, timed, reset) => {
const visuals = handler.getVisuals(day, dayEvents, timed, reset);
if (timed) {
visuals.forEach(visual => {
visual.left = visual.column * FULL_WIDTH / visual.columnCount;
visual.width = FULL_WIDTH / visual.columnCount;
});
}
return visuals;
};
};
//# sourceMappingURL=column.js.map
@@ -0,0 +1 @@
{"version":3,"file":"column.js","names":["getOverlapGroupHandler","FULL_WIDTH","column","events","firstWeekday","overlapThreshold","handler","day","dayEvents","timed","reset","visuals","getVisuals","forEach","visual","left","columnCount","width"],"sources":["../../../../src/components/VCalendar/modes/column.ts"],"sourcesContent":["// Types\nimport { getOverlapGroupHandler } from './common'\nimport type { CalendarEventOverlapMode } from '../types'\n\nconst FULL_WIDTH = 100\n\nexport const column: CalendarEventOverlapMode = (events, firstWeekday, overlapThreshold) => {\n const handler = getOverlapGroupHandler(firstWeekday)\n\n return (day, dayEvents, timed, reset) => {\n const visuals = handler.getVisuals(day, dayEvents, timed, reset)\n\n if (timed) {\n visuals.forEach(visual => {\n visual.left = visual.column * FULL_WIDTH / visual.columnCount\n visual.width = FULL_WIDTH / visual.columnCount\n })\n }\n\n return visuals\n }\n}\n"],"mappings":"AAAA;AAAA,SACSA,sBAAsB;AAG/B,MAAMC,UAAU,GAAG,GAAG;AAEtB,OAAO,MAAMC,MAAgC,GAAGA,CAACC,MAAM,EAAEC,YAAY,EAAEC,gBAAgB,KAAK;EAC1F,MAAMC,OAAO,GAAGN,sBAAsB,CAACI,YAAY,CAAC;EAEpD,OAAO,CAACG,GAAG,EAAEC,SAAS,EAAEC,KAAK,EAAEC,KAAK,KAAK;IACvC,MAAMC,OAAO,GAAGL,OAAO,CAACM,UAAU,CAACL,GAAG,EAAEC,SAAS,EAAEC,KAAK,EAAEC,KAAK,CAAC;IAEhE,IAAID,KAAK,EAAE;MACTE,OAAO,CAACE,OAAO,CAACC,MAAM,IAAI;QACxBA,MAAM,CAACC,IAAI,GAAGD,MAAM,CAACZ,MAAM,GAAGD,UAAU,GAAGa,MAAM,CAACE,WAAW;QAC7DF,MAAM,CAACG,KAAK,GAAGhB,UAAU,GAAGa,MAAM,CAACE,WAAW;MAChD,CAAC,CAAC;IACJ;IAEA,OAAOL,OAAO;EAChB,CAAC;AACH,CAAC","ignoreList":[]}
@@ -0,0 +1,21 @@
import type { CalendarEventParsed, CalendarEventVisual, CalendarTimestamp } from '../types.js';
export type GetRange = (event: CalendarEventParsed) => [number, number];
export declare function getVisuals(events: CalendarEventParsed[], minStart?: number): CalendarEventVisual[];
export interface ColumnGroup {
start: number;
end: number;
visuals: CalendarEventVisual[];
}
export declare function hasOverlap(s0: number, e0: number, s1: number, e1: number, exclude?: boolean): boolean;
export declare function setColumnCount(groups: ColumnGroup[]): void;
export declare function getRange(event: CalendarEventParsed): [number, number];
export declare function getDayRange(event: CalendarEventParsed): [number, number];
export declare function getNormalizedRange(event: CalendarEventParsed, dayStart: number): [number, number];
export declare function getOpenGroup(groups: ColumnGroup[], start: number, end: number, timed: boolean): number;
export declare function getOverlapGroupHandler(firstWeekday: number): {
groups: ColumnGroup[];
min: number;
max: number;
reset: () => void;
getVisuals: (day: CalendarTimestamp, dayEvents: CalendarEventParsed[], timed: boolean, reset?: boolean) => CalendarEventVisual[];
};
+108
View File
@@ -0,0 +1,108 @@
// Types
import { getTimestampIdentifier } from "../util/timestamp.js";
const MILLIS_IN_DAY = 86400000;
export function getVisuals(events, minStart = 0) {
const visuals = events.map(event => ({
event,
columnCount: 0,
column: 0,
left: 0,
width: 100
}));
visuals.sort((a, b) => {
return Math.max(minStart, a.event.startTimestampIdentifier) - Math.max(minStart, b.event.startTimestampIdentifier) || b.event.endTimestampIdentifier - a.event.endTimestampIdentifier;
});
return visuals;
}
export function hasOverlap(s0, e0, s1, e1, exclude = true) {
return exclude ? !(s0 >= e1 || e0 <= s1) : !(s0 > e1 || e0 < s1);
}
export function setColumnCount(groups) {
groups.forEach(group => {
group.visuals.forEach(groupVisual => {
groupVisual.columnCount = groups.length;
});
});
}
export function getRange(event) {
return [event.startTimestampIdentifier, event.endTimestampIdentifier];
}
export function getDayRange(event) {
return [event.startIdentifier, event.endIdentifier];
}
export function getNormalizedRange(event, dayStart) {
return [Math.max(dayStart, event.startTimestampIdentifier), Math.min(dayStart + MILLIS_IN_DAY, event.endTimestampIdentifier)];
}
export function getOpenGroup(groups, start, end, timed) {
for (let i = 0; i < groups.length; i++) {
const group = groups[i];
let intersected = false;
if (hasOverlap(start, end, group.start, group.end, timed)) {
for (let k = 0; k < group.visuals.length; k++) {
const groupVisual = group.visuals[k];
const [groupStart, groupEnd] = timed ? getRange(groupVisual.event) : getDayRange(groupVisual.event);
if (hasOverlap(start, end, groupStart, groupEnd, timed)) {
intersected = true;
break;
}
}
}
if (!intersected) {
return i;
}
}
return -1;
}
export function getOverlapGroupHandler(firstWeekday) {
const handler = {
groups: [],
min: -1,
max: -1,
reset: () => {
handler.groups = [];
handler.min = handler.max = -1;
},
getVisuals: (day, dayEvents, timed, reset = false) => {
if (day.weekday === firstWeekday || reset) {
handler.reset();
}
const dayStart = getTimestampIdentifier(day);
const visuals = getVisuals(dayEvents, dayStart);
visuals.forEach(visual => {
const [start, end] = timed ? getRange(visual.event) : getDayRange(visual.event);
if (handler.groups.length > 0 && !hasOverlap(start, end, handler.min, handler.max, timed)) {
setColumnCount(handler.groups);
handler.reset();
}
let targetGroup = getOpenGroup(handler.groups, start, end, timed);
if (targetGroup === -1) {
targetGroup = handler.groups.length;
handler.groups.push({
start,
end,
visuals: []
});
}
const target = handler.groups[targetGroup];
target.visuals.push(visual);
target.start = Math.min(target.start, start);
target.end = Math.max(target.end, end);
visual.column = targetGroup;
if (handler.min === -1) {
handler.min = start;
handler.max = end;
} else {
handler.min = Math.min(handler.min, start);
handler.max = Math.max(handler.max, end);
}
});
setColumnCount(handler.groups);
if (timed) {
handler.reset();
}
return visuals;
}
};
return handler;
}
//# sourceMappingURL=common.js.map
File diff suppressed because one or more lines are too long
@@ -0,0 +1,2 @@
import type { CalendarEventOverlapMode } from '../types.js';
export declare const CalendarEventOverlapModes: Record<string, CalendarEventOverlapMode>;
@@ -0,0 +1,8 @@
// Types
import { column } from "./column.js";
import { stack } from "./stack.js";
export const CalendarEventOverlapModes = {
stack,
column
};
//# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
{"version":3,"file":"index.js","names":["column","stack","CalendarEventOverlapModes"],"sources":["../../../../src/components/VCalendar/modes/index.ts"],"sourcesContent":["// Types\nimport { column } from './column'\nimport { stack } from './stack'\nimport type { CalendarEventOverlapMode } from '../types'\n\nexport const CalendarEventOverlapModes: Record<string, CalendarEventOverlapMode> = {\n stack,\n column,\n}\n"],"mappings":"AAAA;AAAA,SACSA,MAAM;AAAA,SACNC,KAAK;AAGd,OAAO,MAAMC,yBAAmE,GAAG;EACjFD,KAAK;EACLD;AACF,CAAC","ignoreList":[]}
@@ -0,0 +1,15 @@
import type { CalendarEventOverlapMode } from '../types.js';
/**
* Variation of column mode where events can be stacked. The priority of this
* mode is to stack events together taking up the least amount of space while
* trying to ensure the content of the event is always visible as well as its
* start and end. A sibling column has intersecting event content and must be
* placed beside each other. Non-sibling columns are offset by 5% from the
* previous column. The width is scaled by 1.7 so the events overlap and
* whitespace is reduced. If there is a hole in columns the event width is
* scaled up so it intersects with the next column. The columns have equal
* width in the space they are given. If the event doesn't have any to the
* right of it that intersect with it's content it's right side is extended
* to the right side.
*/
export declare const stack: CalendarEventOverlapMode;
+202
View File
@@ -0,0 +1,202 @@
// Types
import { getNormalizedRange, getOverlapGroupHandler, getVisuals, hasOverlap } from "./common.js";
import { getTimestampIdentifier } from "../util/timestamp.js";
const FULL_WIDTH = 100;
const DEFAULT_OFFSET = 5;
const WIDTH_MULTIPLIER = 1.7;
/**
* Variation of column mode where events can be stacked. The priority of this
* mode is to stack events together taking up the least amount of space while
* trying to ensure the content of the event is always visible as well as its
* start and end. A sibling column has intersecting event content and must be
* placed beside each other. Non-sibling columns are offset by 5% from the
* previous column. The width is scaled by 1.7 so the events overlap and
* whitespace is reduced. If there is a hole in columns the event width is
* scaled up so it intersects with the next column. The columns have equal
* width in the space they are given. If the event doesn't have any to the
* right of it that intersect with it's content it's right side is extended
* to the right side.
*/
export const stack = (events, firstWeekday, overlapThreshold) => {
const handler = getOverlapGroupHandler(firstWeekday);
// eslint-disable-next-line max-statements
return (day, dayEvents, timed, reset) => {
if (!timed) {
return handler.getVisuals(day, dayEvents, timed, reset);
}
const dayStart = getTimestampIdentifier(day);
const visuals = getVisuals(dayEvents, dayStart);
const groups = getGroups(visuals, dayStart);
for (const group of groups) {
const nodes = [];
for (const visual of group.visuals) {
const child = getNode(visual, dayStart);
const index = getNextIndex(child, nodes);
if (index === false) {
const parent = getParent(child, nodes);
if (parent) {
child.parent = parent;
child.sibling = hasOverlap(child.start, child.end, parent.start, addTime(parent.start, overlapThreshold));
child.index = parent.index + 1;
parent.children.push(child);
}
} else {
const [parent] = getOverlappingRange(child, nodes, index - 1, index - 1);
const children = getOverlappingRange(child, nodes, index + 1, index + nodes.length, true);
child.children = children;
child.index = index;
if (parent) {
child.parent = parent;
child.sibling = hasOverlap(child.start, child.end, parent.start, addTime(parent.start, overlapThreshold));
parent.children.push(child);
}
for (const grand of children) {
if (grand.parent === parent) {
grand.parent = child;
}
const grandNext = grand.index - child.index <= 1;
if (grandNext && child.sibling && hasOverlap(child.start, addTime(child.start, overlapThreshold), grand.start, grand.end)) {
grand.sibling = true;
}
}
}
nodes.push(child);
}
calculateBounds(nodes, overlapThreshold);
}
visuals.sort((a, b) => a.left - b.left || a.event.startTimestampIdentifier - b.event.startTimestampIdentifier);
return visuals;
};
};
function calculateBounds(nodes, overlapThreshold) {
for (const node of nodes) {
const {
visual,
parent
} = node;
const columns = getMaxChildIndex(node) + 1;
const spaceLeft = parent ? parent.visual.left : 0;
const spaceWidth = FULL_WIDTH - spaceLeft;
const offset = Math.min(DEFAULT_OFFSET, FULL_WIDTH / columns);
const columnWidthMultiplier = getColumnWidthMultiplier(node, nodes);
const columnOffset = spaceWidth / (columns - node.index + 1);
const columnWidth = spaceWidth / (columns - node.index + (node.sibling ? 1 : 0)) * columnWidthMultiplier;
if (parent) {
visual.left = node.sibling ? spaceLeft + columnOffset : spaceLeft + offset;
}
visual.width = hasFullWidth(node, nodes, overlapThreshold) ? FULL_WIDTH - visual.left : Math.min(FULL_WIDTH - visual.left, columnWidth * WIDTH_MULTIPLIER);
}
}
function getColumnWidthMultiplier(node, nodes) {
if (!node.children.length) {
return 1;
}
const maxColumn = node.index + nodes.length;
const minColumn = node.children.reduce((min, c) => Math.min(min, c.index), maxColumn);
return minColumn - node.index;
}
function getOverlappingIndices(node, nodes) {
const indices = [];
for (const other of nodes) {
if (hasOverlap(node.start, node.end, other.start, other.end)) {
indices.push(other.index);
}
}
return indices;
}
function getNextIndex(node, nodes) {
const indices = getOverlappingIndices(node, nodes);
indices.sort();
for (let i = 0; i < indices.length; i++) {
if (i < indices[i]) {
return i;
}
}
return false;
}
function getOverlappingRange(node, nodes, indexMin, indexMax, returnFirstColumn = false) {
const overlapping = [];
for (const other of nodes) {
if (other.index >= indexMin && other.index <= indexMax && hasOverlap(node.start, node.end, other.start, other.end)) {
overlapping.push(other);
}
}
if (returnFirstColumn && overlapping.length > 0) {
const first = overlapping.reduce((min, n) => Math.min(min, n.index), overlapping[0].index);
return overlapping.filter(n => n.index === first);
}
return overlapping;
}
function getParent(node, nodes) {
let parent = null;
for (const other of nodes) {
if (hasOverlap(node.start, node.end, other.start, other.end) && (parent === null || other.index > parent.index)) {
parent = other;
}
}
return parent;
}
function hasFullWidth(node, nodes, overlapThreshold) {
for (const other of nodes) {
if (other !== node && other.index > node.index && hasOverlap(node.start, addTime(node.start, overlapThreshold), other.start, other.end)) {
return false;
}
}
return true;
}
function getGroups(visuals, dayStart) {
const groups = [];
for (const visual of visuals) {
const [start, end] = getNormalizedRange(visual.event, dayStart);
let added = false;
for (const group of groups) {
if (hasOverlap(start, end, group.start, group.end)) {
group.visuals.push(visual);
group.end = Math.max(group.end, end);
added = true;
break;
}
}
if (!added) {
groups.push({
start,
end,
visuals: [visual]
});
}
}
return groups;
}
function getNode(visual, dayStart) {
const [start, end] = getNormalizedRange(visual.event, dayStart);
return {
parent: null,
sibling: true,
index: 0,
visual,
start,
end,
children: []
};
}
function getMaxChildIndex(node) {
let max = node.index;
for (const child of node.children) {
const childMax = getMaxChildIndex(child);
if (childMax > max) {
max = childMax;
}
}
return max;
}
function addTime(identifier, minutes) {
const removeMinutes = identifier % 100;
const totalMinutes = removeMinutes + minutes;
const addHours = Math.floor(totalMinutes / 60);
const addMinutes = totalMinutes % 60;
return identifier - removeMinutes + addHours * 100 + addMinutes;
}
//# sourceMappingURL=stack.js.map
File diff suppressed because one or more lines are too long
+64
View File
@@ -0,0 +1,64 @@
import type { VNode } from 'vue';
export type CalendarCategory = string | {
[key: string]: any;
name?: string;
categoryName?: string;
};
export type CalendarCategoryTextFunction = (category: CalendarCategory) => string;
export interface CalendarTimestamp {
date: string;
time: string;
year: number;
month: number;
day: number;
weekday: number;
hour: number;
minute: number;
hasDay: boolean;
hasTime: boolean;
past: boolean;
present: boolean;
future: boolean;
category?: CalendarCategory;
}
export type CalendarFormatter = (timestamp: CalendarTimestamp, short: boolean) => string;
export interface CalendarEvent {
[prop: string]: any;
}
export interface CalendarEventParsed {
input: CalendarEvent;
start: CalendarTimestamp;
startIdentifier: number;
startTimestampIdentifier: number;
end: CalendarTimestamp;
endIdentifier: number;
endTimestampIdentifier: number;
allDay: boolean;
index: number;
category: string | false;
}
export interface CalendarEventVisual {
event: CalendarEventParsed;
columnCount: number;
column: number;
left: number;
width: number;
}
export interface CalendarDaySlotScope extends CalendarTimestamp {
outside: boolean;
index: number;
week: CalendarTimestamp[];
category: CalendarCategory;
intervalRange?: [number, number];
}
export type CalendarTimeToY = (time: CalendarTimestamp | number | string, targetDateOrClamp?: CalendarTimestamp | boolean) => number;
export type CalendarTimeDelta = (time: CalendarTimestamp | number | string, targetDate?: CalendarTimestamp) => number | false;
export interface CalendarDayBodySlotScope extends CalendarDaySlotScope {
timeToY: CalendarTimeToY;
timeDelta: CalendarTimeDelta;
}
export type CalendarEventOverlapMode = (events: CalendarEventParsed[], firstWeekday: number, overlapThreshold: number) => (day: CalendarDaySlotScope, dayEvents: CalendarEventParsed[], timed: boolean, reset: boolean) => CalendarEventVisual[];
export type CalendarEventColorFunction = (event: CalendarEvent) => string | undefined;
export type CalendarEventTimedFunction = (event: CalendarEvent) => boolean;
export type CalendarEventCategoryFunction = (event: CalendarEvent) => string;
export type CalendarEventNameFunction = (event: CalendarEventParsed, timedEvent: boolean) => string | VNode;
+2
View File
@@ -0,0 +1,2 @@
export {};
//# sourceMappingURL=types.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"types.js","names":[],"sources":["../../../src/components/VCalendar/types.ts"],"sourcesContent":["// Types\nimport type { VNode } from 'vue'\n\nexport type CalendarCategory =\n | string\n | {\n [key: string]: any\n name?: string\n categoryName?: string\n }\n\nexport type CalendarCategoryTextFunction = (\n category: CalendarCategory\n) => string\n\nexport interface CalendarTimestamp {\n date: string\n time: string\n year: number\n month: number\n day: number\n weekday: number\n hour: number\n minute: number\n hasDay: boolean\n hasTime: boolean\n past: boolean\n present: boolean\n future: boolean\n category?: CalendarCategory\n}\n\nexport type CalendarFormatter = (timestamp: CalendarTimestamp, short: boolean) => string\n\nexport interface CalendarEvent {\n [prop: string]: any\n}\n\nexport interface CalendarEventParsed {\n input: CalendarEvent\n start: CalendarTimestamp\n startIdentifier: number\n startTimestampIdentifier: number\n end: CalendarTimestamp\n endIdentifier: number\n endTimestampIdentifier: number\n allDay: boolean\n index: number\n category: string | false\n}\n\nexport interface CalendarEventVisual {\n event: CalendarEventParsed\n columnCount: number\n column: number\n left: number\n width: number\n}\n\nexport interface CalendarDaySlotScope extends CalendarTimestamp {\n outside: boolean\n index: number\n week: CalendarTimestamp[]\n category: CalendarCategory\n intervalRange?: [number, number]\n}\n\nexport type CalendarTimeToY = (\n time: CalendarTimestamp | number | string,\n targetDateOrClamp?: CalendarTimestamp | boolean\n) => number\n\nexport type CalendarTimeDelta = (\n time: CalendarTimestamp | number | string,\n targetDate?: CalendarTimestamp\n) => number | false\n\nexport interface CalendarDayBodySlotScope extends CalendarDaySlotScope {\n timeToY: CalendarTimeToY\n timeDelta: CalendarTimeDelta\n}\n\nexport type CalendarEventOverlapMode = (\n events: CalendarEventParsed[],\n firstWeekday: number,\n overlapThreshold: number\n) => (\n day: CalendarDaySlotScope,\n dayEvents: CalendarEventParsed[],\n timed: boolean,\n reset: boolean\n) => CalendarEventVisual[]\n\nexport type CalendarEventColorFunction = (event: CalendarEvent) => string | undefined\n\nexport type CalendarEventTimedFunction = (event: CalendarEvent) => boolean\n\nexport type CalendarEventCategoryFunction = (event: CalendarEvent) => string\n\nexport type CalendarEventNameFunction = (event: CalendarEventParsed, timedEvent: boolean) => string | VNode\n"],"mappings":"","ignoreList":[]}
@@ -0,0 +1 @@
export declare function isLeapYear(year: number): boolean;
@@ -0,0 +1,4 @@
export function isLeapYear(year) {
return year % 4 === 0 && year % 100 !== 0 || year % 400 === 0;
}
//# sourceMappingURL=dateTimeUtils.js.map
@@ -0,0 +1 @@
{"version":3,"file":"dateTimeUtils.js","names":["isLeapYear","year"],"sources":["../../../../src/components/VCalendar/util/dateTimeUtils.ts"],"sourcesContent":["export function isLeapYear (year: number): boolean {\n return ((year % 4 === 0) && (year % 100 !== 0)) || (year % 400 === 0)\n}\n"],"mappings":"AAAA,OAAO,SAASA,UAAUA,CAAEC,IAAY,EAAW;EACjD,OAASA,IAAI,GAAG,CAAC,KAAK,CAAC,IAAMA,IAAI,GAAG,GAAG,KAAK,CAAE,IAAMA,IAAI,GAAG,GAAG,KAAK,CAAE;AACvE","ignoreList":[]}
@@ -0,0 +1,7 @@
import type { CalendarEvent, CalendarEventParsed, CalendarTimestamp } from '../types.js';
export declare function parseEvent(input: CalendarEvent, index: number, startProperty: string, endProperty: string, timed?: boolean, category?: string | false): CalendarEventParsed;
export declare function isEventOn(event: CalendarEventParsed, dayIdentifier: number): boolean;
export declare function isEventOnDay(event: CalendarEventParsed, day: CalendarTimestamp, inRange?: [number, number]): boolean;
export declare function isEventHiddenOn(event: CalendarEventParsed, day: CalendarTimestamp): boolean;
export declare function isEventStart(event: CalendarEventParsed, day: CalendarTimestamp, dayIdentifier: number, firstWeekday: number): boolean;
export declare function isEventOverlapping(event: CalendarEventParsed, startIdentifier: number, endIdentifier: number): boolean;
+50
View File
@@ -0,0 +1,50 @@
import { copyTimestamp, getDayIdentifier, getTimestampIdentifier, isTimedless, nextMinutes, parseTimestamp, updateHasTime } from "./timestamp.js"; // Types
export function parseEvent(input, index, startProperty, endProperty, timed = false, category = false) {
const startInput = input[startProperty];
const endInput = input[endProperty];
const startParsed = parseTimestamp(startInput, true);
const endParsed = endInput ? parseTimestamp(endInput, true) : startParsed;
const start = isTimedless(startInput) ? updateHasTime(startParsed, timed) : startParsed;
const end = isTimedless(endInput) ? updateHasTime(endParsed, timed) : endParsed;
const startIdentifier = getDayIdentifier(start);
const startTimestampIdentifier = getTimestampIdentifier(start);
const endIdentifier = getDayIdentifier(end);
const endOffset = start.hasTime ? 0 : 2359;
const endTimestampIdentifier = getTimestampIdentifier(end) + endOffset;
const allDay = !start.hasTime;
return {
input,
start,
startIdentifier,
startTimestampIdentifier,
end,
endIdentifier,
endTimestampIdentifier,
allDay,
index,
category
};
}
export function isEventOn(event, dayIdentifier) {
return dayIdentifier >= event.startIdentifier && dayIdentifier <= event.endIdentifier;
}
export function isEventOnDay(event, day, inRange) {
if (inRange) {
const dayStart = nextMinutes(copyTimestamp(day), inRange[0]);
const dayEnd = nextMinutes(copyTimestamp(day), inRange[1]);
const starts = event.startTimestampIdentifier < getTimestampIdentifier(dayEnd);
const ends = event.endTimestampIdentifier > getTimestampIdentifier(dayStart);
return starts && ends;
}
return isEventOn(event, getDayIdentifier(day));
}
export function isEventHiddenOn(event, day) {
return event.end.time === '00:00' && event.end.date === day.date && event.start.date !== day.date;
}
export function isEventStart(event, day, dayIdentifier, firstWeekday) {
return dayIdentifier === event.startIdentifier || firstWeekday === day.weekday && isEventOn(event, dayIdentifier);
}
export function isEventOverlapping(event, startIdentifier, endIdentifier) {
return startIdentifier <= event.endIdentifier && endIdentifier >= event.startIdentifier;
}
//# sourceMappingURL=events.js.map
File diff suppressed because one or more lines are too long
@@ -0,0 +1,3 @@
import type { CalendarCategory, CalendarCategoryTextFunction } from '../types.js';
export declare function parsedCategoryText(category: CalendarCategory, categoryText: string | CalendarCategoryTextFunction | undefined): string;
export declare function getParsedCategories(categories: CalendarCategory | CalendarCategory[], categoryText: string | CalendarCategoryTextFunction | undefined): CalendarCategory[];
+20
View File
@@ -0,0 +1,20 @@
// Types
export function parsedCategoryText(category, categoryText) {
return typeof categoryText === 'function' ? categoryText(category) : typeof categoryText === 'string' && typeof category === 'object' && category ? category[categoryText] : typeof category === 'string' ? category : '';
}
export function getParsedCategories(categories, categoryText) {
if (typeof categories === 'string') return categories.split(/\s*,\s/);
if (Array.isArray(categories)) {
return categories.map(category => {
if (typeof category === 'string') return category;
const categoryName = typeof category.categoryName === 'string' ? category.categoryName : parsedCategoryText(category, categoryText);
return {
...category,
categoryName
};
});
}
return [];
}
//# sourceMappingURL=parser.js.map
@@ -0,0 +1 @@
{"version":3,"file":"parser.js","names":["parsedCategoryText","category","categoryText","getParsedCategories","categories","split","Array","isArray","map","categoryName"],"sources":["../../../../src/components/VCalendar/util/parser.ts"],"sourcesContent":["// Types\nimport type { CalendarCategory, CalendarCategoryTextFunction } from '../types'\n\nexport function parsedCategoryText (\n category: CalendarCategory,\n categoryText: string | CalendarCategoryTextFunction | undefined\n): string {\n return typeof categoryText === 'function' ? categoryText(category)\n : typeof categoryText === 'string' && typeof category === 'object' && category ? category[categoryText]\n : typeof category === 'string' ? category\n : ''\n}\n\nexport function getParsedCategories (\n categories: CalendarCategory | CalendarCategory[],\n categoryText: string | CalendarCategoryTextFunction | undefined\n): CalendarCategory[] {\n if (typeof categories === 'string') return categories.split(/\\s*,\\s/)\n if (Array.isArray(categories)) {\n return categories.map((category: CalendarCategory) => {\n if (typeof category === 'string') return category\n\n const categoryName = typeof category.categoryName === 'string'\n ? category.categoryName\n : parsedCategoryText(category, categoryText)\n return { ...category, categoryName }\n })\n }\n return []\n}\n"],"mappings":"AAAA;;AAGA,OAAO,SAASA,kBAAkBA,CAChCC,QAA0B,EAC1BC,YAA+D,EACvD;EACR,OAAO,OAAOA,YAAY,KAAK,UAAU,GAAGA,YAAY,CAACD,QAAQ,CAAC,GAC9D,OAAOC,YAAY,KAAK,QAAQ,IAAI,OAAOD,QAAQ,KAAK,QAAQ,IAAIA,QAAQ,GAAGA,QAAQ,CAACC,YAAY,CAAC,GACrG,OAAOD,QAAQ,KAAK,QAAQ,GAAGA,QAAQ,GACvC,EAAE;AACR;AAEA,OAAO,SAASE,mBAAmBA,CACjCC,UAAiD,EACjDF,YAA+D,EAC3C;EACpB,IAAI,OAAOE,UAAU,KAAK,QAAQ,EAAE,OAAOA,UAAU,CAACC,KAAK,CAAC,QAAQ,CAAC;EACrE,IAAIC,KAAK,CAACC,OAAO,CAACH,UAAU,CAAC,EAAE;IAC7B,OAAOA,UAAU,CAACI,GAAG,CAAEP,QAA0B,IAAK;MACpD,IAAI,OAAOA,QAAQ,KAAK,QAAQ,EAAE,OAAOA,QAAQ;MAEjD,MAAMQ,YAAY,GAAG,OAAOR,QAAQ,CAACQ,YAAY,KAAK,QAAQ,GAC1DR,QAAQ,CAACQ,YAAY,GACrBT,kBAAkB,CAACC,QAAQ,EAAEC,YAAY,CAAC;MAC9C,OAAO;QAAE,GAAGD,QAAQ;QAAEQ;MAAa,CAAC;IACtC,CAAC,CAAC;EACJ;EACA,OAAO,EAAE;AACX","ignoreList":[]}
@@ -0,0 +1,75 @@
import type { CalendarFormatter, CalendarTimestamp } from '../types.js';
export declare const PARSE_REGEX: RegExp;
export declare const PARSE_TIME: RegExp;
export declare const DAYS_IN_MONTH: number[];
export declare const DAYS_IN_MONTH_LEAP: number[];
export declare const DAYS_IN_MONTH_MIN = 28;
export declare const DAYS_IN_MONTH_MAX = 31;
export declare const MONTH_MAX = 12;
export declare const MONTH_MIN = 1;
export declare const DAY_MIN = 1;
export declare const DAYS_IN_WEEK = 7;
export declare const MINUTES_IN_HOUR = 60;
export declare const MINUTE_MAX = 59;
export declare const MINUTES_IN_DAY: number;
export declare const HOURS_IN_DAY = 24;
export declare const HOUR_MAX = 23;
export declare const FIRST_HOUR = 0;
export declare const OFFSET_YEAR = 10000;
export declare const OFFSET_MONTH = 100;
export declare const OFFSET_HOUR = 100;
export declare const OFFSET_TIME = 10000;
type CalendarTimestampFormatOptions = (timestamp: CalendarTimestamp, short: boolean) => Intl.DateTimeFormatOptions;
type CalendarTimestampOperation = (timestamp: CalendarTimestamp) => CalendarTimestamp;
export type VTime = number | string | {
hour: number;
minute: number;
};
export type VTimestampInput = number | string | Date;
export declare function getStartOfWeek(timestamp: CalendarTimestamp, weekdays: number[], today?: CalendarTimestamp): CalendarTimestamp;
export declare function getEndOfWeek(timestamp: CalendarTimestamp, weekdays: number[], today?: CalendarTimestamp): CalendarTimestamp;
export declare function getStartOfMonth(timestamp: CalendarTimestamp): CalendarTimestamp;
export declare function getEndOfMonth(timestamp: CalendarTimestamp): CalendarTimestamp;
export declare function validateNumber(input: any): boolean;
export declare function validateTime(input: any): input is VTime;
export declare function parseTime(input: any): number | false;
export declare function validateTimestamp(input: any): input is VTimestampInput;
export declare function parseTimestamp(input: VTimestampInput | null, required?: false, now?: CalendarTimestamp | null): CalendarTimestamp | null;
export declare function parseTimestamp(input: VTimestampInput, required: true, now?: CalendarTimestamp): CalendarTimestamp;
export declare function parseDate(date: Date): CalendarTimestamp;
export declare function getDayIdentifier(timestamp: {
year: number;
month: number;
day: number;
}): number;
export declare function getTimeIdentifier(timestamp: {
hour: number;
minute: number;
}): number;
export declare function getTimestampIdentifier(timestamp: CalendarTimestamp): number;
export declare function updateRelative(timestamp: CalendarTimestamp, now: CalendarTimestamp, time?: boolean): CalendarTimestamp;
export declare function isTimedless(input: VTimestampInput): input is (Date | number);
export declare function updateHasTime(timestamp: CalendarTimestamp, hasTime: boolean, now?: CalendarTimestamp): CalendarTimestamp;
export declare function updateMinutes(timestamp: CalendarTimestamp, minutes: number, now?: CalendarTimestamp): CalendarTimestamp;
export declare function updateWeekday(timestamp: CalendarTimestamp): CalendarTimestamp;
export declare function updateFormatted(timestamp: CalendarTimestamp): CalendarTimestamp;
export declare function getWeekday(timestamp: CalendarTimestamp): number;
export declare function daysInMonth(year: number, month: number): number;
export declare function copyTimestamp(timestamp: null): null;
export declare function copyTimestamp(timestamp: CalendarTimestamp): CalendarTimestamp;
export declare function padNumber(x: number, length: number): string;
export declare function getDate(timestamp: CalendarTimestamp): string;
export declare function getTime(timestamp: CalendarTimestamp): string;
export declare function nextMinutes(timestamp: CalendarTimestamp, minutes: number): CalendarTimestamp;
export declare function nextDay(timestamp: CalendarTimestamp): CalendarTimestamp;
export declare function prevDay(timestamp: CalendarTimestamp): CalendarTimestamp;
export declare function relativeDays(timestamp: CalendarTimestamp, mover?: CalendarTimestampOperation, days?: number): CalendarTimestamp;
export declare function diffMinutes(min: CalendarTimestamp, max: CalendarTimestamp): number;
export declare function findWeekday(timestamp: CalendarTimestamp, weekday: number, mover?: CalendarTimestampOperation, maxDays?: number): CalendarTimestamp;
export declare function getWeekdaySkips(weekdays: number[]): number[];
export declare function timestampToDate(timestamp: CalendarTimestamp): Date;
export declare function createDayList(start: CalendarTimestamp, end: CalendarTimestamp, now: CalendarTimestamp, weekdaySkips: number[], max?: number, min?: number): CalendarTimestamp[];
export declare function createIntervalList(timestamp: CalendarTimestamp, first: number, minutes: number, count: number, now?: CalendarTimestamp): CalendarTimestamp[];
export declare function createNativeLocaleFormatter(locale: string, getOptions: CalendarTimestampFormatOptions): CalendarFormatter;
export declare function validateWeekdays(input: string | (number | string)[]): boolean;
@@ -0,0 +1,437 @@
import { isLeapYear } from "./dateTimeUtils.js"; // Types
export const PARSE_REGEX = /^(\d{4})-(\d{1,2})(-(\d{1,2}))?([^\d]+(\d{1,2}))?(:(\d{1,2}))?(:(\d{1,2}))?$/;
export const PARSE_TIME = /(\d\d?)(:(\d\d?)|)(:(\d\d?)|)/;
export const DAYS_IN_MONTH = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
export const DAYS_IN_MONTH_LEAP = [0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
export const DAYS_IN_MONTH_MIN = 28;
export const DAYS_IN_MONTH_MAX = 31;
export const MONTH_MAX = 12;
export const MONTH_MIN = 1;
export const DAY_MIN = 1;
export const DAYS_IN_WEEK = 7;
export const MINUTES_IN_HOUR = 60;
export const MINUTE_MAX = 59;
export const MINUTES_IN_DAY = 24 * 60;
export const HOURS_IN_DAY = 24;
export const HOUR_MAX = 23;
export const FIRST_HOUR = 0;
export const OFFSET_YEAR = 10000;
export const OFFSET_MONTH = 100;
export const OFFSET_HOUR = 100;
export const OFFSET_TIME = 10000;
export function getStartOfWeek(timestamp, weekdays, today) {
const start = copyTimestamp(timestamp);
findWeekday(start, weekdays[0], prevDay);
updateFormatted(start);
if (today) {
updateRelative(start, today, start.hasTime);
}
return start;
}
export function getEndOfWeek(timestamp, weekdays, today) {
const end = copyTimestamp(timestamp);
findWeekday(end, weekdays[weekdays.length - 1]);
updateFormatted(end);
if (today) {
updateRelative(end, today, end.hasTime);
}
return end;
}
export function getStartOfMonth(timestamp) {
const start = copyTimestamp(timestamp);
start.day = DAY_MIN;
updateWeekday(start);
updateFormatted(start);
return start;
}
export function getEndOfMonth(timestamp) {
const end = copyTimestamp(timestamp);
end.day = daysInMonth(end.year, end.month);
updateWeekday(end);
updateFormatted(end);
return end;
}
export function validateNumber(input) {
return isFinite(parseInt(input));
}
export function validateTime(input) {
return typeof input === 'number' && isFinite(input) || !!PARSE_TIME.exec(input) || typeof input === 'object' && isFinite(input.hour) && isFinite(input.minute);
}
export function parseTime(input) {
if (typeof input === 'number') {
// when a number is given, it's minutes since 12:00am
return input;
} else if (typeof input === 'string') {
// when a string is given, it's a hh:mm:ss format where seconds are optional
const parts = PARSE_TIME.exec(input);
if (!parts) {
return false;
}
return parseInt(parts[1]) * 60 + parseInt(parts[3] || 0);
} else if (typeof input === 'object') {
// when an object is given, it must have hour and minute
if (typeof input.hour !== 'number' || typeof input.minute !== 'number') {
return false;
}
return input.hour * 60 + input.minute;
} else {
// unsupported type
return false;
}
}
export function validateTimestamp(input) {
return typeof input === 'number' && isFinite(input) || typeof input === 'string' && !!PARSE_REGEX.exec(input) || input instanceof Date;
}
export function parseTimestamp(input, required = false, now) {
if (typeof input === 'number' && isFinite(input)) {
input = new Date(input);
}
if (input instanceof Date) {
const date = parseDate(input);
if (now) {
updateRelative(date, now, date.hasTime);
}
return date;
}
if (typeof input !== 'string') {
if (required) {
throw new Error(`${input} is not a valid timestamp. It must be a Date, number of milliseconds since Epoch, or a string in the format of YYYY-MM-DD or YYYY-MM-DD hh:mm. Zero-padding is optional and seconds are ignored.`);
}
return null;
}
// YYYY-MM-DD hh:mm:ss
const parts = PARSE_REGEX.exec(input);
if (!parts) {
if (required) {
throw new Error(`${input} is not a valid timestamp. It must be a Date, number of milliseconds since Epoch, or a string in the format of YYYY-MM-DD or YYYY-MM-DD hh:mm. Zero-padding is optional and seconds are ignored.`);
}
return null;
}
const timestamp = {
date: input,
time: '',
year: parseInt(parts[1]),
month: parseInt(parts[2]),
day: parseInt(parts[4]) || 1,
hour: parseInt(parts[6]) || 0,
minute: parseInt(parts[8]) || 0,
weekday: 0,
hasDay: !!parts[4],
hasTime: !!(parts[6] && parts[8]),
past: false,
present: false,
future: false
};
updateWeekday(timestamp);
updateFormatted(timestamp);
if (now) {
updateRelative(timestamp, now, timestamp.hasTime);
}
return timestamp;
}
export function parseDate(date) {
return updateFormatted({
date: '',
time: '',
year: date.getFullYear(),
month: date.getMonth() + 1,
day: date.getDate(),
weekday: date.getDay(),
hour: date.getHours(),
minute: date.getMinutes(),
hasDay: true,
hasTime: true,
past: false,
present: true,
future: false
});
}
export function getDayIdentifier(timestamp) {
return timestamp.year * OFFSET_YEAR + timestamp.month * OFFSET_MONTH + timestamp.day;
}
export function getTimeIdentifier(timestamp) {
return timestamp.hour * OFFSET_HOUR + timestamp.minute;
}
export function getTimestampIdentifier(timestamp) {
return getDayIdentifier(timestamp) * OFFSET_TIME + getTimeIdentifier(timestamp);
}
export function updateRelative(timestamp, now, time = false) {
let a = getDayIdentifier(now);
let b = getDayIdentifier(timestamp);
let present = a === b;
if (timestamp.hasTime && time && present) {
a = getTimeIdentifier(now);
b = getTimeIdentifier(timestamp);
present = a === b;
}
timestamp.past = b < a;
timestamp.present = present;
timestamp.future = b > a;
return timestamp;
}
export function isTimedless(input) {
return input instanceof Date || typeof input === 'number' && isFinite(input);
}
export function updateHasTime(timestamp, hasTime, now) {
if (timestamp.hasTime !== hasTime) {
timestamp.hasTime = hasTime;
if (!hasTime) {
timestamp.hour = HOUR_MAX;
timestamp.minute = MINUTE_MAX;
timestamp.time = getTime(timestamp);
}
if (now) {
updateRelative(timestamp, now, timestamp.hasTime);
}
}
return timestamp;
}
export function updateMinutes(timestamp, minutes, now) {
timestamp.hasTime = true;
timestamp.hour = 0;
timestamp.minute = 0;
nextMinutes(timestamp, minutes);
updateFormatted(timestamp);
if (now) {
updateRelative(timestamp, now, true);
}
return timestamp;
}
export function updateWeekday(timestamp) {
timestamp.weekday = getWeekday(timestamp);
return timestamp;
}
export function updateFormatted(timestamp) {
timestamp.time = getTime(timestamp);
timestamp.date = getDate(timestamp);
return timestamp;
}
export function getWeekday(timestamp) {
if (timestamp.hasDay) {
const _ = Math.floor;
const k = timestamp.day;
const m = (timestamp.month + 9) % MONTH_MAX + 1;
const C = _(timestamp.year / 100);
const Y = timestamp.year % 100 - (timestamp.month <= 2 ? 1 : 0);
return ((k + _(2.6 * m - 0.2) - 2 * C + Y + _(Y / 4) + _(C / 4)) % 7 + 7) % 7;
}
return timestamp.weekday;
}
export function daysInMonth(year, month) {
return isLeapYear(year) ? DAYS_IN_MONTH_LEAP[month] : DAYS_IN_MONTH[month];
}
export function copyTimestamp(timestamp) {
if (timestamp == null) return null;
const {
date,
time,
year,
month,
day,
weekday,
hour,
minute,
hasDay,
hasTime,
past,
present,
future
} = timestamp;
return {
date,
time,
year,
month,
day,
weekday,
hour,
minute,
hasDay,
hasTime,
past,
present,
future
};
}
export function padNumber(x, length) {
let padded = String(x);
while (padded.length < length) {
padded = '0' + padded;
}
return padded;
}
export function getDate(timestamp) {
let str = `${padNumber(timestamp.year, 4)}-${padNumber(timestamp.month, 2)}`;
if (timestamp.hasDay) str += `-${padNumber(timestamp.day, 2)}`;
return str;
}
export function getTime(timestamp) {
if (!timestamp.hasTime) {
return '';
}
return `${padNumber(timestamp.hour, 2)}:${padNumber(timestamp.minute, 2)}`;
}
export function nextMinutes(timestamp, minutes) {
timestamp.minute += minutes;
while (timestamp.minute >= MINUTES_IN_HOUR) {
timestamp.minute -= MINUTES_IN_HOUR;
timestamp.hour++;
if (timestamp.hour >= HOURS_IN_DAY) {
nextDay(timestamp);
timestamp.hour = FIRST_HOUR;
}
}
return timestamp;
}
export function nextDay(timestamp) {
timestamp.day++;
timestamp.weekday = (timestamp.weekday + 1) % DAYS_IN_WEEK;
if (timestamp.day > DAYS_IN_MONTH_MIN && timestamp.day > daysInMonth(timestamp.year, timestamp.month)) {
timestamp.day = DAY_MIN;
timestamp.month++;
if (timestamp.month > MONTH_MAX) {
timestamp.month = MONTH_MIN;
timestamp.year++;
}
}
return timestamp;
}
export function prevDay(timestamp) {
timestamp.day--;
timestamp.weekday = (timestamp.weekday + 6) % DAYS_IN_WEEK;
if (timestamp.day < DAY_MIN) {
timestamp.month--;
if (timestamp.month < MONTH_MIN) {
timestamp.year--;
timestamp.month = MONTH_MAX;
}
timestamp.day = daysInMonth(timestamp.year, timestamp.month);
}
return timestamp;
}
export function relativeDays(timestamp, mover = nextDay, days = 1) {
while (--days >= 0) mover(timestamp);
return timestamp;
}
export function diffMinutes(min, max) {
const Y = (max.year - min.year) * 525600;
const M = (max.month - min.month) * 43800;
const D = (max.day - min.day) * 1440;
const h = (max.hour - min.hour) * 60;
const m = max.minute - min.minute;
return Y + M + D + h + m;
}
export function findWeekday(timestamp, weekday, mover = nextDay, maxDays = 6) {
while (timestamp.weekday !== weekday && --maxDays >= 0) mover(timestamp);
return timestamp;
}
export function getWeekdaySkips(weekdays) {
const skips = [1, 1, 1, 1, 1, 1, 1];
const filled = [0, 0, 0, 0, 0, 0, 0];
for (let i = 0; i < weekdays.length; i++) {
filled[weekdays[i]] = 1;
}
for (let k = 0; k < DAYS_IN_WEEK; k++) {
let skip = 1;
for (let j = 1; j < DAYS_IN_WEEK; j++) {
const next = (k + j) % DAYS_IN_WEEK;
if (filled[next]) {
break;
}
skip++;
}
skips[k] = filled[k] * skip;
}
return skips;
}
export function timestampToDate(timestamp) {
const time = `${padNumber(timestamp.hour, 2)}:${padNumber(timestamp.minute, 2)}`;
const date = timestamp.date;
return new Date(`${date}T${time}:00+00:00`);
}
export function createDayList(start, end, now, weekdaySkips, max = 42, min = 0) {
const stop = getDayIdentifier(end);
const days = [];
let current = copyTimestamp(start);
let currentIdentifier = 0;
let stopped = currentIdentifier === stop;
if (stop < getDayIdentifier(start)) {
throw new Error('End date is earlier than start date.');
}
while ((!stopped || days.length < min) && days.length < max) {
currentIdentifier = getDayIdentifier(current);
stopped = stopped || currentIdentifier === stop;
if (weekdaySkips[current.weekday] === 0) {
current = nextDay(current);
continue;
}
const day = copyTimestamp(current);
updateFormatted(day);
updateRelative(day, now);
days.push(day);
current = relativeDays(current, nextDay, weekdaySkips[current.weekday]);
}
if (!days.length) throw new Error('No dates found using specified start date, end date, and weekdays.');
return days;
}
export function createIntervalList(timestamp, first, minutes, count, now) {
const intervals = [];
for (let i = 0; i < count; i++) {
const mins = first + i * minutes;
const int = copyTimestamp(timestamp);
intervals.push(updateMinutes(int, mins, now));
}
return intervals;
}
export function createNativeLocaleFormatter(locale, getOptions) {
const emptyFormatter = (_t, _s) => '';
if (typeof Intl === 'undefined' || typeof Intl.DateTimeFormat === 'undefined') {
return emptyFormatter;
}
return (timestamp, short) => {
try {
const intlFormatter = new Intl.DateTimeFormat(locale || undefined, getOptions(timestamp, short));
return intlFormatter.format(timestampToDate(timestamp));
} catch (e) {
return '';
}
};
}
export function validateWeekdays(input) {
if (typeof input === 'string') {
input = input.split(',');
}
if (Array.isArray(input)) {
const ints = input.map(x => parseInt(x));
if (ints.length > DAYS_IN_WEEK || ints.length === 0) {
return false;
}
const visited = {};
let wrapped = false;
for (let i = 0; i < ints.length; i++) {
const x = ints[i];
if (!isFinite(x) || x < 0 || x >= DAYS_IN_WEEK) {
return false;
}
if (i > 0) {
const d = x - ints[i - 1];
if (d < 0) {
if (wrapped) {
return false;
}
wrapped = true;
} else if (d === 0) {
return false;
}
}
if (visited[x]) {
return false;
}
visited[x] = true;
}
return true;
}
return false;
}
//# sourceMappingURL=timestamp.js.map
File diff suppressed because one or more lines are too long