Componente DayFlowCalendar

DayFlowCalendar es el componente de alto nivel que renderiza la vista activa, se encarga del diseño y conecta la interfaz opcional, como la barra lateral o el diálogo de detalle del evento. Combínalo con useCalendarApp y las funciones de creación de vistas para tener un calendario plenamente funcional con muy poco código.

Uso básico

import {
  DayFlowCalendar,
  useCalendarApp,
  createWeekView,
  ViewType,
} from '@dayflow/react';
import { createSidebarPlugin } from '@dayflow/plugin-sidebar';
import '@dayflow/core/dist/styles.css';

export function CalendarDemo() {
  const calendar = useCalendarApp({
    views: [createWeekView()],
    defaultView: ViewType.WEEK,
    initialDate: new Date(),
    events: [],
    plugins: [createSidebarPlugin()],
  });

  return <DayFlowCalendar calendar={calendar} />;
}
<template>
  <DayFlowCalendar :calendar="calendar" />
</template>

<script setup>
import { DayFlowCalendar, useCalendarApp } from '@dayflow/vue';
import { createWeekView, ViewType } from '@dayflow/core';
import { createSidebarPlugin } from '@dayflow/plugin-sidebar';
import '@dayflow/core/dist/styles.css';

const calendar = useCalendarApp({
  views: [createWeekView()],
  defaultView: ViewType.WEEK,
  initialDate: new Date(),
  events: [],
  plugins: [createSidebarPlugin()],
});
</script>
import { Component } from '@angular/core';
import { createWeekView, ViewType } from '@dayflow/core';
import { createSidebarPlugin } from '@dayflow/plugin-sidebar';
import { DayFlowCalendarModule } from '@dayflow/angular';
import '@dayflow/core/dist/styles.css';

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [DayFlowCalendarModule],
  template: `
    <dayflow-calendar [calendar]="calendar"></dayflow-calendar>
  `
})
export class AppComponent {
  calendar = {
    views: [createWeekView()],
    defaultView: ViewType.WEEK,
    initialDate: new Date(),
    events: [],
    plugins: [createSidebarPlugin()],
  };
}
<script>
  import { DayFlowCalendar, useCalendarApp } from '@dayflow/svelte';
  import { createWeekView, ViewType } from '@dayflow/core';
  import { createSidebarPlugin } from '@dayflow/plugin-sidebar';
  import '@dayflow/core/dist/styles.css';

  const calendar = useCalendarApp({
    views: [createWeekView()],
    defaultView: ViewType.WEEK,
    initialDate: new Date(),
    events: [],
    plugins: [createSidebarPlugin()],
  });
</script>

<DayFlowCalendar {calendar} />

El componente recibe el objeto calendar de useCalendarApp, consulta la vista activa y renderiza el componente de vista correspondiente. Puedes colocar tu propia barra de herramientas o interfaz junto a DayFlowCalendar, aunque este ya incluye:

  • Una barra lateral de calendarios opcional (se añade con createSidebarPlugin).
  • Soporte para el diálogo de detalle del evento (controlado por useEventDetailDialog o un renderizador propio).
  • Actualización automática del diseño al mostrar u ocultar calendarios o al cambiar de vista.

Props

PropTipoObligatorioDescripción
calendarUseCalendarAppReturnObligatorioResultado de useCalendarApp. Aporta el estado, las vistas registradas, la configuración de la barra lateral y las acciones del calendario.
collapsedSafeAreaLeftnumberOpcionalRelleno izquierdo (px) cuando la barra lateral está plegada, por ejemplo para dejar sitio a los botones de ventana de macOS.
searchCalendarSearchPropsOpcionalConfiguración de la búsqueda integrada.

La personalización mediante slots (contenido del evento, contenido del panel de detalle, diálogo de detalle, selector de color, etc.) se realiza con slots nativos de cada framework, no con props. Consulta Content Slots para ver la lista completa.

Configuración de la búsqueda

La prop search te permite personalizar el comportamiento de la búsqueda integrada. De forma predeterminada, busca localmente en los títulos y las descripciones de los eventos.

<DayFlowCalendar
  calendar={calendar}
  search={{
    debounceDelay: 500,
    emptyText: 'No events found',
    onSearch: async keyword => {
      // Custom async search (e.g., from an API)
      return fetch(`/api/search?q=${keyword}`).then(res => res.json());
    },
  }}
/>
<template>
  <DayFlowCalendar
    :calendar="calendar"
    :search="{
      debounceDelay: 500,
      emptyText: 'No events found',
      onSearch: handleSearch,
    }"
  />
</template>

<script setup>
import { DayFlowCalendar } from '@dayflow/vue';

const handleSearch = async (keyword) => {
  // Custom async search (e.g., from an API)
  return fetch(`/api/search?q=${keyword}`).then(res => res.json());
};
</script>
import { Component } from '@angular/core';
import { DayFlowCalendarModule } from '@dayflow/angular';

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [DayFlowCalendarModule],
  template: `
    <dayflow-calendar
      [calendar]="calendar"
      [search]="searchConfig"
    >
    </dayflow-calendar>
  `
})
export class AppComponent {
  calendar = {
    // ... calendar app config
  };

  searchConfig = {
    debounceDelay: 500,
    emptyText: 'No events found',
    onSearch: async (keyword: string) => {
      return fetch(`/api/search?q=${keyword}`).then(res => res.json());
    }
  };
}
<script>
  import { DayFlowCalendar } from '@dayflow/svelte';

  const handleSearch = async (keyword) => {
    return fetch(`/api/search?q=${keyword}`).then(res => res.json());
  };
</script>

<DayFlowCalendar
  {calendar}
  search={{
    debounceDelay: 500,
    emptyText: 'No events found',
    onSearch: handleSearch,
  }}
/>

Props de búsqueda

OpciónDescripción
debounceDelayTiempo de espera en milisegundos antes de lanzar la búsqueda.
onSearchFunción asíncrona que obtiene resultados a partir de una palabra clave.
customSearchFunción síncrona para filtrar eventos localmente con tu propia lógica.
onResultClickCallback opcional que se ejecuta al hacer clic en un resultado. Incluye un callback defaultAction para invocar la navegación integrada (ir a la fecha del evento, resaltarlo y cerrar la interfaz de búsqueda en móvil). Si no llamas a defaultAction(), tendrás que encargarte tú mismo de la navegación y del estado de la interfaz.
emptyTextTexto que se muestra cuando no hay resultados.
timeFormatFormato de hora usado al mostrar los resultados ('12h' o '24h'). Si hay un timeFormat global configurado en useCalendarApp, este tiene prioridad sobre esta opción.

Comportamiento de la barra lateral

La barra lateral se añade instalando el plugin @dayflow/plugin-sidebar:

import { createSidebarPlugin } from '@dayflow/plugin-sidebar';

const calendar = useCalendarApp({
  views: [createWeekView()],
  plugins: [
    createSidebarPlugin({
      width: 280,
      initialCollapsed: false,
      createCalendarMode: 'modal', // 'inline' or 'modal'
    }),
  ],
});

return <DayFlowCalendar calendar={calendar} />;
<template>
  <DayFlowCalendar :calendar="calendar" />
</template>

<script setup>
import { DayFlowCalendar, useCalendarApp } from '@dayflow/vue';
import { createWeekView } from '@dayflow/core';
import { createSidebarPlugin } from '@dayflow/plugin-sidebar';

const calendar = useCalendarApp({
  views: [createWeekView()],
  plugins: [
    createSidebarPlugin({
      width: 280,
      initialCollapsed: false,
      createCalendarMode: 'modal',
    }),
  ],
});
</script>
import { Component } from '@angular/core';
import { createWeekView } from '@dayflow/core';
import { createSidebarPlugin } from '@dayflow/plugin-sidebar';
import { DayFlowCalendarModule } from '@dayflow/angular';

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [DayFlowCalendarModule],
  template: `
    <dayflow-calendar [calendar]="calendar"></dayflow-calendar>
  `
})
export class AppComponent {
  calendar = {
    views: [createWeekView()],
    plugins: [
      createSidebarPlugin({
        width: 280,
        initialCollapsed: false,
        createCalendarMode: 'modal',
      }),
    ],
  };
}
<script>
  import { DayFlowCalendar, useCalendarApp } from '@dayflow/svelte';
  import { createWeekView } from '@dayflow/core';
  import { createSidebarPlugin } from '@dayflow/plugin-sidebar';

  const calendar = useCalendarApp({
    views: [createWeekView()],
    plugins: [
      createSidebarPlugin({
        width: 280,
        initialCollapsed: false,
        createCalendarMode: 'modal',
      }),
    ],
  });
</script>

<DayFlowCalendar {calendar} />
  • Al añadir createSidebarPlugin() a los plugins se renderiza la barra lateral predeterminada (DefaultCalendarSidebar), con filtros de calendario y controles para mostrar u ocultar todos.
  • Puedes personalizar el ancho, el estado plegado inicial, el modo de creación (createCalendarMode) o proporcionar tu propio renderizador mediante render o renderSidebarHeader. Tu renderizador recibe CalendarSidebarRenderProps (en render) o SidebarHeaderSlotArgs (en renderSidebarHeader), de modo que puedes reutilizar sus callbacks y datos.

Formas de mostrar el detalle de un evento

DayFlow ofrece tres opciones para mostrar el detalle de un evento:

  1. Modo panel (predeterminado): cuando useEventDetailDialog es false (valor por defecto), al abrir el detalle de un evento aparece el panel flotante integrado DefaultEventDetailPanel. En escritorio se abre con doble clic (eventDetailTrigger: 'dbClick') o con un solo clic si defines eventDetailTrigger: 'click'. En pantallas táctiles siempre basta con tocar.
  2. Modo diálogo: define useEventDetailDialog: true en useCalendarApp para activar el modal centrado integrado. Usa el slot eventDetailDialog si quieres sustituirlo por tu propio diálogo.
  3. Desactivarlo por completo: define useEventDetailPanel: false en useCalendarApp para suprimir el panel flotante si ya tienes tus propios modales controlados por los callbacks de la aplicación.
// Suppress the built-in panel — use your own modal triggered elsewhere
const calendar = useCalendarApp({
  ...
  useEventDetailPanel: false,
});

return <DayFlowCalendar calendar={calendar} />;
<template>
  <DayFlowCalendar :calendar="calendar" />
</template>

<script setup>
import { DayFlowCalendar, useCalendarApp } from '@dayflow/vue';

// Suppress the built-in panel — use your own modal triggered elsewhere
const calendar = useCalendarApp({
  ...
  useEventDetailPanel: false,
});
</script>
import { Component } from '@angular/core';
import { DayFlowCalendarModule } from '@dayflow/angular';

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [DayFlowCalendarModule],
  template: `
    <dayflow-calendar [calendar]="calendar"></dayflow-calendar>
  `
})
export class AppComponent {
  // Suppress the built-in panel — use your own modal triggered elsewhere
  calendar = {
    ...
    useEventDetailPanel: false,
  };
}
<script>
  import { DayFlowCalendar, useCalendarApp } from '@dayflow/svelte';

  // Suppress the built-in panel — use your own modal triggered elsewhere
  const calendar = useCalendarApp({
    ...
    useEventDetailPanel: false,
  });
</script>

<DayFlowCalendar {calendar} />
// Custom panel content (keeps the default panel chrome)
<DayFlowCalendar
  calendar={calendar}
  eventDetailContent={({ event, onClose }) => (
    <div className='p-4'>
      <h2>{event.title}</h2>
      <button onClick={onClose}>Close</button>
    </div>
  )}
/>
<template>
  <DayFlowCalendar :calendar="calendar">
    <!-- Custom panel content (keeps the default panel chrome) -->
    <template #eventDetailContent="{ event, onClose }">
      <div class="p-4">
        <h2>{{ event.title }}</h2>
        <button @click="onClose()">Close</button>
      </div>
    </template>
  </DayFlowCalendar>
</template>

<script setup>
import { DayFlowCalendar } from '@dayflow/vue';
</script>
<!-- Custom panel content (keeps the default panel chrome) -->
<dayflow-calendar
  [calendar]="calendar"
  [eventDetailContent]="detailContent"
>
</dayflow-calendar>

<ng-template #detailContent let-args>
  <div class="p-4">
    <h2>{{ args.event.title }}</h2>
    <button (click)="args.onClose()">Close</button>
  </div>
</ng-template>
<DayFlowCalendar {calendar} eventDetailContent={CustomDetailContent} />

<!-- CustomDetailContent.svelte -->
<script lang="ts">
  import type { EventDetailContentSlotArgs } from '@dayflow/core';
  let { event, onClose } = $props<EventDetailContentSlotArgs>();
</script>

<div class="p-4">
  <h2>{event.title}</h2>
  <button onclick={onClose}>Close</button>
</div>
// Custom dialog (requires useEventDetailDialog: true in useCalendarApp)
<DayFlowCalendar
  calendar={calendar}
  eventDetailDialog={({ event, isOpen, onClose }) => (
    <MyDialog isOpen={isOpen} onClose={onClose}>
      <EventForm event={event} />
    </MyDialog>
  )}
/>
<template>
  <DayFlowCalendar :calendar="calendar">
    <!-- Custom dialog -->
    <template #eventDetailDialog="{ event, isOpen, onClose }">
      <MyDialog :isOpen="isOpen" @close="onClose()">
        <EventForm :event="event" />
      </MyDialog>
    </template>
  </DayFlowCalendar>
</template>

<script setup>
import { DayFlowCalendar } from '@dayflow/vue';
import MyDialog from './MyDialog.vue';
import EventForm from './EventForm.vue';
</script>
<!-- Custom dialog -->
<dayflow-calendar
  [calendar]="calendar"
  [eventDetailDialog]="dialog"
>
</dayflow-calendar>

<ng-template #dialog let-args>
  <my-dialog [isOpen]="args.isOpen" (close)="args.onClose()">
    <event-form [event]="args.event"></event-form>
  </my-dialog>
</ng-template>
<DayFlowCalendar {calendar} eventDetailDialog={MyCustomDialog} />

<!-- MyCustomDialog.svelte -->
<script lang="ts">
  import type { EventDetailDialogSlotArgs } from '@dayflow/core';
  import MyDialog from './MyDialog.svelte';
  import EventForm from './EventForm.svelte';

  let { event, isOpen, onClose } = $props<EventDetailDialogSlotArgs>();
</script>

<MyDialog {isOpen} {onClose}>
  <EventForm {event} />
</MyDialog>

En resumen, DayFlowCalendar se encarga de la capa de orquestación —diseño, integración de la barra lateral y fontanería del detalle de eventos— para que tú puedas centrarte en configurar useCalendarApp y construir el producto que lo rodea.

En esta página