From dae42b1bd9652e66b471b328e91ab75f21e9531e Mon Sep 17 00:00:00 2001 From: Zack Arnett Date: Mon, 24 Aug 2020 12:59:50 -0500 Subject: [PATCH] Calendar Card: New Card (#5813) Co-authored-by: Bram Kragten --- package.json | 7 +- src/components/ha-button-toggle-group.ts | 42 ++-- src/panels/calendar/ha-full-calendar.ts | 209 ++++++++++++++--- src/panels/calendar/ha-panel-calendar.ts | 10 +- .../lovelace/cards/hui-calendar-card.ts | 213 ++++++++++++++++++ src/panels/lovelace/cards/types.ts | 6 + .../create-element/create-card-element.ts | 2 + .../hui-calendar-card-editor.ts | 133 +++++++++++ src/panels/lovelace/editor/lovelace-cards.ts | 4 + src/translations/en.json | 4 + src/types.ts | 14 +- yarn.lock | 52 ++++- 12 files changed, 619 insertions(+), 77 deletions(-) create mode 100644 src/panels/lovelace/cards/hui-calendar-card.ts create mode 100644 src/panels/lovelace/editor/config-elements/hui-calendar-card-editor.ts diff --git a/package.json b/package.json index 89fb7c3e93..5be452e00b 100644 --- a/package.json +++ b/package.json @@ -23,8 +23,11 @@ "license": "Apache-2.0", "dependencies": { "@formatjs/intl-pluralrules": "^1.5.8", - "@fullcalendar/core": "^5.0.0-beta.2", - "@fullcalendar/daygrid": "^5.0.0-beta.2", + "@fullcalendar/common": "5.1.0", + "@fullcalendar/core": "5.1.0", + "@fullcalendar/daygrid": "5.1.0", + "@fullcalendar/interaction": "5.1.0", + "@fullcalendar/list": "5.1.0", "@material/chips": "=8.0.0-canary.096a7a066.0", "@material/circular-progress": "=8.0.0-canary.a78ceb112.0", "@material/mwc-button": "^0.18.0", diff --git a/src/components/ha-button-toggle-group.ts b/src/components/ha-button-toggle-group.ts index a9ea972492..cc4c870d07 100644 --- a/src/components/ha-button-toggle-group.ts +++ b/src/components/ha-button-toggle-group.ts @@ -1,3 +1,4 @@ +import "@material/mwc-icon-button/mwc-icon-button"; import { customElement, html, @@ -8,14 +9,14 @@ import { css, } from "lit-element"; -import "./ha-icon-button"; - import { fireEvent } from "../common/dom/fire_event"; import type { ToggleButton } from "../types"; +import "./ha-svg-icon"; + @customElement("ha-button-toggle-group") export class HaButtonToggleGroup extends LitElement { - @property() public buttons!: ToggleButton[]; + @property({ attribute: false }) public buttons!: ToggleButton[]; @property() public active?: string; @@ -23,14 +24,16 @@ export class HaButtonToggleGroup extends LitElement { return html`
${this.buttons.map( - (button) => html` - ` + (button) => html` + + + + ` )}
`; @@ -48,12 +51,13 @@ export class HaButtonToggleGroup extends LitElement { --mdc-icon-button-size: var(--button-toggle-size, 36px); --mdc-icon-size: var(--button-toggle-icon-size, 20px); } - ha-icon-button { + mwc-icon-button { border: 1px solid var(--primary-color); border-right-width: 0px; position: relative; + cursor: pointer; } - ha-icon-button::before { + mwc-icon-button::before { top: 0; left: 0; width: 100%; @@ -65,22 +69,26 @@ export class HaButtonToggleGroup extends LitElement { content: ""; transition: opacity 15ms linear, background-color 15ms linear; } - ha-icon-button[active]::before { + mwc-icon-button[active]::before { opacity: var(--mdc-icon-button-ripple-opacity, 0.12); } - ha-icon-button:first-child { + mwc-icon-button:first-child { border-radius: 4px 0 0 4px; } - ha-icon-button:last-child { + mwc-icon-button:last-child { border-radius: 0 4px 4px 0; border-right-width: 1px; } + mwc-icon-button:only-child { + border-radius: 4px; + border-right-width: 1px; + } `; } } declare global { interface HTMLElementTagNameMap { - "ha-button-toggle-button": HaButtonToggleGroup; + "ha-button-toggle-group": HaButtonToggleGroup; } } diff --git a/src/panels/calendar/ha-full-calendar.ts b/src/panels/calendar/ha-full-calendar.ts index e3b0e6af15..8b0bdfddc1 100644 --- a/src/panels/calendar/ha-full-calendar.ts +++ b/src/panels/calendar/ha-full-calendar.ts @@ -1,3 +1,4 @@ +import "@material/mwc-button"; import { property, internalProperty, @@ -9,13 +10,19 @@ import { unsafeCSS, TemplateResult, } from "lit-element"; +import { mdiViewModule, mdiViewWeek, mdiViewDay, mdiViewAgenda } from "@mdi/js"; import { Calendar } from "@fullcalendar/core"; +import type { CalendarOptions } from "@fullcalendar/core"; import dayGridPlugin from "@fullcalendar/daygrid"; +import listPlugin from "@fullcalendar/list"; +import interactionPlugin from "@fullcalendar/interaction"; // @ts-ignore -import fullcalendarStyle from "@fullcalendar/core/main.css"; +import fullcalendarStyle from "@fullcalendar/common/main.css"; // @ts-ignore import daygridStyle from "@fullcalendar/daygrid/main.css"; -import "@material/mwc-button"; +// @ts-ignore +import listStyle from "@fullcalendar/list/main.css"; +import memoize from "memoize-one"; import "../../components/ha-icon-button"; import "../../components/ha-button-toggle-group"; @@ -25,43 +32,56 @@ import type { CalendarEvent, ToggleButton, HomeAssistant, + FullCalendarView, } from "../../types"; import { fireEvent } from "../../common/dom/fire_event"; import { haStyle } from "../../resources/styles"; declare global { + interface HTMLElementTagNameMap { + "ha-full-calendar": HAFullCalendar; + } interface HASSDomEvents { "view-changed": CalendarViewChanged; } } -const fullCalendarConfig = { +const defaultFullCalendarConfig: CalendarOptions = { headerToolbar: false, - plugins: [dayGridPlugin], + plugins: [dayGridPlugin, listPlugin, interactionPlugin], initialView: "dayGridMonth", dayMaxEventRows: true, height: "parent", + eventDisplay: "list-item", }; const viewButtons: ToggleButton[] = [ - { label: "Month View", value: "dayGridMonth", icon: "hass:view-module" }, - { label: "Week View", value: "dayGridWeek", icon: "hass:view-week" }, - { label: "Day View", value: "dayGridDay", icon: "hass:view-day" }, + { label: "Month View", value: "dayGridMonth", iconPath: mdiViewModule }, + { label: "Week View", value: "dayGridWeek", iconPath: mdiViewWeek }, + { label: "Day View", value: "dayGridDay", iconPath: mdiViewDay }, + { label: "List View", value: "listWeek", iconPath: mdiViewAgenda }, ]; class HAFullCalendar extends LitElement { public hass!: HomeAssistant; - @property() public events: CalendarEvent[] = []; + @property({ type: Boolean, reflect: true }) public narrow = false; - @property({ type: Boolean, reflect: true }) - public narrow!: boolean; + @property({ attribute: false }) public events: CalendarEvent[] = []; + + @property({ attribute: false }) public views: FullCalendarView[] = [ + "dayGridMonth", + "dayGridWeek", + "dayGridDay", + ]; @internalProperty() private calendar?: Calendar; - @internalProperty() private _activeView = "dayGridMonth"; + @internalProperty() private _activeView: FullCalendarView = "dayGridMonth"; protected render(): TemplateResult { + const viewToggleButtons = this._viewToggleButtons(this.views); + return html` ${this.calendar ? html` @@ -96,27 +116,12 @@ class HAFullCalendar extends LitElement { ${this.calendar.view.title} ` : html` -
- ${this.hass.localize( - "ui.panel.calendar.today" - )} - -

${this.calendar.view.title} @@ -138,6 +143,21 @@ class HAFullCalendar extends LitElement {

+
+ ${this.hass.localize( + "ui.panel.calendar.today" + )} + +
`} ` @@ -157,14 +177,25 @@ class HAFullCalendar extends LitElement { this.calendar.removeAllEventSources(); this.calendar.addEventSource(this.events); } + + if (changedProps.has("views") && !this.views.includes(this._activeView)) { + this._activeView = this.views[0]; + this.calendar!.changeView(this._activeView); + this._fireViewChanged(); + } } protected firstUpdated(): void { - const config = { ...fullCalendarConfig, locale: this.hass.language }; + const config: CalendarOptions = { + ...defaultFullCalendarConfig, + locale: this.hass.language, + }; + + config.dateClick = this._handleDateClick; + config.eventClick = this._handleEventClick; this.calendar = new Calendar( this.shadowRoot!.getElementById("calendar")!, - // @ts-ignore config ); @@ -172,6 +203,25 @@ class HAFullCalendar extends LitElement { this._fireViewChanged(); } + private _handleEventClick(info): void { + if (info.view.type !== "dayGridMonth") { + return; + } + + this._activeView = "dayGridDay"; + this.calendar!.changeView("dayGridDay"); + this.calendar!.gotoDate(info.event.startStr); + } + + private _handleDateClick(info): void { + if (info.view.type !== "dayGridMonth") { + return; + } + this._activeView = "dayGridDay"; + this.calendar!.changeView("dayGridDay"); + this.calendar!.gotoDate(info.dateStr); + } + private _handleNext(): void { this.calendar!.next(); this._fireViewChanged(); @@ -201,14 +251,21 @@ class HAFullCalendar extends LitElement { }); } + private _viewToggleButtons = memoize((views) => + viewButtons.filter((button) => + views.includes(button.value as FullCalendarView) + ) + ); + static get styles(): CSSResult[] { return [ haStyle, css` ${unsafeCSS(fullcalendarStyle)} ${unsafeCSS(daygridStyle)} - - :host { + ${unsafeCSS(listStyle)} + + :host { display: flex; flex-direction: column; --fc-theme-standard-border-color: var(--divider-color); @@ -262,6 +319,15 @@ class HAFullCalendar extends LitElement { #calendar { flex-grow: 1; background-color: var(--card-background-color); + min-height: 400px; + --fc-neutral-bg-color: var(--card-background-color); + --fc-list-event-hover-bg-color: var(--card-background-color); + --fc-theme-standard-border-color: var(--divider-color); + --fc-border-color: var(--divider-color); + } + + a { + color: inherit !important; } .fc-theme-standard .fc-scrollgrid { @@ -273,15 +339,20 @@ class HAFullCalendar extends LitElement { } th.fc-col-header-cell.fc-day { - color: #70757a; + color: var(--secondary-text-color); font-size: 11px; font-weight: 400; text-transform: uppercase; } + .fc-daygrid-dot-event:hover { + background-color: inherit + } + .fc-daygrid-day-top { text-align: center; - padding-top: 8px; + padding-top: 5px; + justify-content: center; } table.fc-scrollgrid-sync-table @@ -296,13 +367,21 @@ class HAFullCalendar extends LitElement { font-size: 12px; } - td.fc-day-today { + .fc .fc-daygrid-day-number { + padding: 3px !important; + } + + .fc .fc-daygrid-day.fc-day-today { background: inherit; } + td.fc-day-today .fc-daygrid-day-top { + padding-top: 4px; + } + td.fc-day-today .fc-daygrid-day-number { height: 24px; - color: var(--text-primary-color); + color: var(--text-primary-color) !important; background-color: var(--primary-color); border-radius: 50%; display: inline-block; @@ -342,6 +421,66 @@ class HAFullCalendar extends LitElement { .fc-popover-header { background-color: var(--secondary-background-color) !important; } + + .fc-theme-standard .fc-list-day-frame { + background-color: transparent; + } + + .fc-list.fc-view, + .fc-list-event.fc-event td { + border: none; + } + + .fc-list-day.fc-day th { + border-bottom: none; + border-top: 1px solid var(--fc-theme-standard-border-color, #ddd) !important; + } + + .fc-list-day-text { + font-size: 16px; + font-weight: 400; + } + + .fc-list-day-side-text { + font-weight: 400; + font-size: 16px; + color: var(--primary-color); + } + + .fc-list-table td, + .fc-list-day-frame { + padding-top: 12px; + padding-bottom: 12px; + } + + :host([narrow]) .fc-dayGridMonth-view + .fc-daygrid-dot-event + .fc-event-time, + :host([narrow]) .fc-dayGridMonth-view + .fc-daygrid-dot-event + .fc-event-title, + :host([narrow]) .fc-dayGridMonth-view .fc-daygrid-day-bottom { + display: none; + } + + :host([narrow]) .fc .fc-dayGridMonth-view .fc-daygrid-event-harness-abs { + visibility: visible !important; + position: static; + } + + :host([narrow]) .fc-dayGridMonth-view .fc-daygrid-day-events { + display: flex; + min-height: 2em !important; + justify-content: center; + flex-wrap: wrap; + max-height: 2em; + height: 2em; + overflow: hidden; + } + + :host([narrow]) .fc-dayGridMonth-view .fc-scrollgrid-sync-table { + overflow: hidden; + } `, ]; } diff --git a/src/panels/calendar/ha-panel-calendar.ts b/src/panels/calendar/ha-panel-calendar.ts index ea7d2bb69b..58aefd8146 100644 --- a/src/panels/calendar/ha-panel-calendar.ts +++ b/src/panels/calendar/ha-panel-calendar.ts @@ -53,12 +53,6 @@ class PanelCalendar extends LitElement { selected: true, calendar, })); - - if (!this._start || !this._end) { - return; - } - - this._fetchEvents(this._start, this._end, this._selectedCalendars); } protected render(): TemplateResult { @@ -88,8 +82,8 @@ class PanelCalendar extends LitElement { { + await import( + /* webpackChunkName: "hui-calendar-card-editor" */ "../editor/config-elements/hui-calendar-card-editor" + ); + return document.createElement("hui-calendar-card-editor"); + } + + public static getStubConfig( + hass: HomeAssistant, + entities: string[], + entitiesFill: string[] + ) { + const includeDomains = ["calendar"]; + const maxEntities = 2; + const foundEntities = findEntities( + hass, + maxEntities, + entities, + entitiesFill, + includeDomains + ); + + return { + entities: foundEntities, + }; + } + + @property({ attribute: false }) public hass?: HomeAssistant; + + @property({ attribute: false }) public _events: CalendarEvent[] = []; + + @internalProperty() private _config?: CalendarCardConfig; + + @internalProperty() private _calendars: Calendar[] = []; + + @internalProperty() private _narrow = false; + + @internalProperty() private _veryNarrow = false; + + private _resizeObserver?: ResizeObserver; + + public setConfig(config: CalendarCardConfig): void { + if (!config.entities) { + throw new Error("Entities must be defined"); + } + + if (config.entities && !Array.isArray(config.entities)) { + throw new Error("Entities need to be an array"); + } + + this._calendars = config!.entities.map((entity, idx) => { + return { + entity_id: entity, + backgroundColor: `#${HA_COLOR_PALETTE[idx % HA_COLOR_PALETTE.length]}`, + }; + }); + + this._config = config; + } + + public getCardSize(): number { + return 4; + } + + public connectedCallback(): void { + super.connectedCallback(); + this.updateComplete.then(() => this._attachObserver()); + } + + public disconnectedCallback(): void { + if (this._resizeObserver) { + this._resizeObserver.disconnect(); + } + } + + protected render(): TemplateResult { + if (!this._config || !this.hass || !this._calendars.length) { + return html``; + } + + const views: FullCalendarView[] = this._veryNarrow + ? ["listWeek"] + : ["listWeek", "dayGridMonth", "dayGridDay"]; + + return html` + +
${this._config.title}
+ +
+ `; + } + + protected updated(changedProps: PropertyValues) { + super.updated(changedProps); + if (!this._config || !this.hass) { + return; + } + + const oldHass = changedProps.get("hass") as HomeAssistant | undefined; + const oldConfig = changedProps.get("_config") as + | CalendarCardConfig + | undefined; + + if ( + !oldHass || + !oldConfig || + (changedProps.has("hass") && oldHass.themes !== this.hass.themes) || + (changedProps.has("_config") && oldConfig.theme !== this._config.theme) + ) { + applyThemesOnElement(this, this.hass.themes, this._config!.theme); + } + } + + private async _handleViewChanged( + ev: HASSDomEvent + ): Promise { + this._events = await fetchCalendarEvents( + this.hass!, + ev.detail.start, + ev.detail.end, + this._calendars + ); + } + + private _measureCard() { + const card = this.shadowRoot!.querySelector("ha-card"); + if (!card) { + return; + } + this._narrow = card.offsetWidth < 870; + this._veryNarrow = card.offsetWidth < 350; + } + + private async _attachObserver(): Promise { + if (!this._resizeObserver) { + await installResizeObserver(); + this._resizeObserver = new ResizeObserver( + debounce(() => this._measureCard(), 250, false) + ); + } + const card = this.shadowRoot!.querySelector("ha-card"); + // If we show an error or warning there is no ha-card + if (!card) { + return; + } + this._resizeObserver.observe(card); + } + + static get styles(): CSSResult { + return css` + ha-card { + position: relative; + padding: 0 8px 8px; + } + + .header { + color: var(--ha-card-header-color, --primary-text-color); + font-size: var(--ha-card-header-font-size, 24px); + line-height: 1.2; + padding-top: 16px; + padding-left: 8px; + } + `; + } +} + +declare global { + interface HTMLElementTagNameMap { + "hui-calendar-card": HuiCalendarCard; + } +} diff --git a/src/panels/lovelace/cards/types.ts b/src/panels/lovelace/cards/types.ts index 8ea3d859b5..ac3feafc79 100644 --- a/src/panels/lovelace/cards/types.ts +++ b/src/panels/lovelace/cards/types.ts @@ -12,6 +12,12 @@ export interface AlarmPanelCardConfig extends LovelaceCardConfig { theme?: string; } +export interface CalendarCardConfig extends LovelaceCardConfig { + entities: string[]; + title?: string; + theme?: string; +} + export interface ConditionalCardConfig extends LovelaceCardConfig { card: LovelaceCardConfig; conditions: Condition[]; diff --git a/src/panels/lovelace/create-element/create-card-element.ts b/src/panels/lovelace/create-element/create-card-element.ts index e7061c1727..bf62823dbb 100644 --- a/src/panels/lovelace/create-element/create-card-element.ts +++ b/src/panels/lovelace/create-element/create-card-element.ts @@ -1,5 +1,6 @@ import { LovelaceCardConfig } from "../../../data/lovelace"; import "../cards/hui-button-card"; +import "../cards/hui-calendar-card"; import "../cards/hui-entities-card"; import "../cards/hui-entity-button-card"; import "../cards/hui-entity-card"; @@ -52,6 +53,7 @@ const LAZY_LOAD_TYPES = { map: () => import("../cards/hui-map-card"), markdown: () => import("../cards/hui-markdown-card"), picture: () => import("../cards/hui-picture-card"), + calendar: () => import("../cards/hui-calendar-card"), }; // This will not return an error card but will throw the error diff --git a/src/panels/lovelace/editor/config-elements/hui-calendar-card-editor.ts b/src/panels/lovelace/editor/config-elements/hui-calendar-card-editor.ts new file mode 100644 index 0000000000..5a7cd7049a --- /dev/null +++ b/src/panels/lovelace/editor/config-elements/hui-calendar-card-editor.ts @@ -0,0 +1,133 @@ +import { + customElement, + html, + LitElement, + property, + TemplateResult, + internalProperty, +} from "lit-element"; +import { fireEvent } from "../../../../common/dom/fire_event"; +import type { HomeAssistant } from "../../../../types"; +import type { CalendarCardConfig } from "../../cards/types"; +import "../../components/hui-entity-editor"; +import "../../../../components/entity/ha-entities-picker"; +import "../../components/hui-theme-select-editor"; +import type { LovelaceCardEditor } from "../../types"; +import type { EditorTarget, EntitiesEditorEvent } from "../types"; +import { configElementStyle } from "./config-elements-style"; +import { + string, + optional, + object, + boolean, + array, + union, + assert, +} from "superstruct"; + +const cardConfigStruct = object({ + type: string(), + title: optional(union([string(), boolean()])), + theme: optional(string()), + entities: array(string()), +}); + +@customElement("hui-calendar-card-editor") +export class HuiCalendarCardEditor extends LitElement + implements LovelaceCardEditor { + @property({ attribute: false }) public hass?: HomeAssistant; + + @property({ attribute: false }) private _config?: CalendarCardConfig; + + @internalProperty() private _configEntities?: string[]; + + public setConfig(config: CalendarCardConfig): void { + assert(config, cardConfigStruct); + this._config = config; + this._configEntities = config.entities; + } + + get _title(): string { + return this._config!.title || ""; + } + + get _theme(): string { + return this._config!.theme || ""; + } + + protected render(): TemplateResult { + if (!this.hass || !this._config) { + return html``; + } + + return html` + ${configElementStyle} +
+
+ + +
+
+

+ ${"Calendar Entities" + + " (" + + this.hass!.localize("ui.panel.lovelace.editor.card.config.required") + + ")"} +

+ + + `; + } + + private _valueChanged(ev: EntitiesEditorEvent | CustomEvent): void { + if (!this._config || !this.hass) { + return; + } + + const target = ev.target! as EditorTarget; + + if (this[`_${target.configValue}`] === target.value) { + return; + } + + if (ev.detail && ev.detail.value && Array.isArray(ev.detail.value)) { + this._config = { ...this._config, entities: ev.detail.value }; + } else if (target.configValue) { + if (target.value === "") { + delete this._config[target.configValue!]; + } else { + this._config = { + ...this._config, + [target.configValue]: target.value, + }; + } + } + + fireEvent(this, "config-changed", { config: this._config }); + } +} + +declare global { + interface HTMLElementTagNameMap { + "hui-calendar-card-editor": HuiCalendarCardEditor; + } +} diff --git a/src/panels/lovelace/editor/lovelace-cards.ts b/src/panels/lovelace/editor/lovelace-cards.ts index 9d777fa942..13c099a791 100644 --- a/src/panels/lovelace/editor/lovelace-cards.ts +++ b/src/panels/lovelace/editor/lovelace-cards.ts @@ -9,6 +9,10 @@ export const coreCards: Card[] = [ type: "button", showElement: true, }, + { + type: "calendar", + showElement: true, + }, { type: "entities", showElement: true, diff --git a/src/translations/en.json b/src/translations/en.json index 7d665900a5..caa70d5a03 100755 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -2134,6 +2134,10 @@ "available_states": "Available States", "description": "The Alarm Panel card allows you to Arm and Disarm your alarm control panel integrations." }, + "calendar": { + "name": "Calendar", + "description": "The Calendar card displays a calendar including day, week and list views" + }, "conditional": { "name": "Conditional", "description": "The Conditional card displays another card based on entity states.", diff --git a/src/types.ts b/src/types.ts index 7639f1ea43..a6f27ee768 100644 --- a/src/types.ts +++ b/src/types.ts @@ -118,8 +118,8 @@ export interface Panels { export interface Calendar { entity_id: string; - name: string; - backgroundColor: string; + name?: string; + backgroundColor?: string; } export interface SelectedCalendar { @@ -144,9 +144,15 @@ export interface CalendarViewChanged { view: string; } +export type FullCalendarView = + | "dayGridMonth" + | "dayGridWeek" + | "dayGridDay" + | "listWeek"; + export interface ToggleButton { - label?: string; - icon: string; + label: string; + iconPath: string; value: string; } diff --git a/yarn.lock b/yarn.lock index 1e7c5ffa8d..83cd0d1794 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1184,20 +1184,45 @@ resolved "https://registry.yarnpkg.com/@formatjs/intl-utils/-/intl-utils-2.2.5.tgz#eaafd94df3d102ee13e54e80f992a33868a6b1e8" integrity sha512-p7gcmazKROteL4IECCp03Qrs790fZ8tbemUAjQu0+K0AaAlK49rI1SIFFq3LzDUAqXIshV95JJhRe/yXxkal5g== -"@fullcalendar/core@^5.0.0-beta.2": - version "5.0.0-beta.2" - resolved "https://registry.yarnpkg.com/@fullcalendar/core/-/core-5.0.0-beta.2.tgz#30a9cbbbf2d6476568f53cfa1c0746d06daa9660" - integrity sha512-9U/kk8Y4ackY1XZ1PHvX8rG1olixoKveStXdDsX3FCtKATR8fA/O+4Pd5qyH7nGcih8TrgreUjZ+dB+DEaomqQ== +"@fullcalendar/common@5.1.0", "@fullcalendar/common@~5.1.0": + version "5.1.0" + resolved "https://registry.yarnpkg.com/@fullcalendar/common/-/common-5.1.0.tgz#a45e01ebdcf00654f4d45f0457926cf2f5909820" + integrity sha512-ubwf9T0BDocGLh0AK8achrmc0siQdrp3Wn6Rmg/Ht4/WnwBtjc5gumzJ0ezG/xHE0GWG+Pz6Tm0IJF/jE7NJHw== dependencies: - preact "^10.0.5" - tslib "^1.9.3" + tslib "^2.0.0" -"@fullcalendar/daygrid@^5.0.0-beta.2": - version "5.0.0-beta.2" - resolved "https://registry.yarnpkg.com/@fullcalendar/daygrid/-/daygrid-5.0.0-beta.2.tgz#fae2a7cba8a6afc23c9d6faaa88150d820e59a73" - integrity sha512-Dd2VLsMPWPH1W1HQ+K1iftHVXF1MYOM/lo33FUdFKM8jc0MHnF620TVyOgPojAC26u2hApbURKIY2eY87vFulg== +"@fullcalendar/core@5.1.0": + version "5.1.0" + resolved "https://registry.yarnpkg.com/@fullcalendar/core/-/core-5.1.0.tgz#0d9813b0564f24fe6285e31f8313d9366c6db411" + integrity sha512-C9OA9LHD1zgfcMABQ17TaxvAO/iubYFLDrgTIRCe77LatC0G36UBafthevUlMRqCR6rt5SBcw0oBt23HqSJO3A== dependencies: - tslib "^1.9.3" + "@fullcalendar/common" "~5.1.0" + preact "^10.0.5" + tslib "^2.0.0" + +"@fullcalendar/daygrid@5.1.0": + version "5.1.0" + resolved "https://registry.yarnpkg.com/@fullcalendar/daygrid/-/daygrid-5.1.0.tgz#4f8cb30e99ff00600f064645942d21e8f668c946" + integrity sha512-zdO/EFer8wWrr+kvkMfyizPi/F7yvOCpGOb6Arz6QqyOgFl1ffNUQoRf1iQf7h2PnIEvZWZdZs+3wuMwwmhb3g== + dependencies: + "@fullcalendar/common" "~5.1.0" + tslib "^2.0.0" + +"@fullcalendar/interaction@5.1.0": + version "5.1.0" + resolved "https://registry.yarnpkg.com/@fullcalendar/interaction/-/interaction-5.1.0.tgz#0e7c6fe17bf8532de2c994bde5fc6e9220c71a89" + integrity sha512-RuCtsVFXvGYk4vYz3Aq9+G8SMOG6iX+xNJmHELdmPfAatHTVyUSCD4GznxR1/fzUu74mb98X01DVkLwSB+78oA== + dependencies: + "@fullcalendar/common" "~5.1.0" + tslib "^2.0.0" + +"@fullcalendar/list@5.1.0": + version "5.1.0" + resolved "https://registry.yarnpkg.com/@fullcalendar/list/-/list-5.1.0.tgz#e08b011cce8259fdee46ef8737bf98b31e6eac1a" + integrity sha512-FDLsInaLv0H/BwpoJ4RbC69M8yoJ3xoRnkulChAzhIBrwXAKOHJth5P+iNFJVVYI7DaPgSi0BzEwiu0dJdStHQ== + dependencies: + "@fullcalendar/common" "~5.1.0" + tslib "^2.0.0" "@gfx/zopfli@^1.0.9": version "1.0.11" @@ -11747,6 +11772,11 @@ tslib@^1.10.0, tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3: resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.10.0.tgz#c3c19f95973fb0a62973fb09d90d961ee43e5c8a" integrity sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ== +tslib@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.0.0.tgz#18d13fc2dce04051e20f074cc8387fd8089ce4f3" + integrity sha512-lTqkx847PI7xEDYJntxZH89L2/aXInsyF2luSafe/+0fHOMjlBNXdH6th7f70qxLDhul7KZK0zC8V5ZIyHl0/g== + tsutils@^3.17.1: version "3.17.1" resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.17.1.tgz#ed719917f11ca0dee586272b2ac49e015a2dd759"