DayFlowCalendar

DayFlowCalendar は現在のビューを描画し、サイドバーやイベント詳細ダイアログなどの UI をひとまとめに扱うコンポーネントです。useCalendarApp から返される calendar オブジェクトを渡すだけで、選択中のビューが自動的に切り替わります。

基本的な使い方

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-calendar-demo',
  standalone: true,
  imports: [DayFlowCalendarModule],
  template: `
    <dayflow-calendar [calendar]="calendar"></dayflow-calendar>
  `
})
export class CalendarDemoComponent {
  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} />

このコンポーネントが担うのは以下のような処理です。

  • サイドバーの表示・折りたたみ(createSidebarPlugin を追加した場合)
  • イベント詳細パネル/ダイアログの切り替え
  • ビュー変更やカレンダーの可視状態に合わせたレイアウト更新

Props

Prop必須説明
calendarUseCalendarAppReturn必須useCalendarApp の戻り値。状態やビュー、アクションを内包。
collapsedSafeAreaLeftnumber任意サイドバー折りたたみ時の左パディング(px)。Mac のトラフィックライト領域の考慮に使用。
searchCalendarSearchProps任意組み込み検索機能の設定。

検索設定

search プロップを使用すると、組み込みの検索動作をカスタマイズできます。デフォルトでは、イベントのタイトルと説明をローカルで検索します。

<DayFlowCalendar
  calendar={calendar}
  search={{
    debounceDelay: 500,
    emptyText: 'イベントが見つかりませんでした',
    onSearch: async keyword => {
      // カスタム非同期検索(例:APIから取得)
      return fetch(`/api/search?q=${keyword}`).then(res => res.json());
    },
  }}
/>
<template>
  <DayFlowCalendar
    :calendar="calendar"
    :search="searchConfig"
  />
</template>

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

const searchConfig = ref({
  debounceDelay: 500,
  emptyText: 'イベントが見つかりませんでした',
  onSearch: async (keyword) => {
    // カスタム非同期検索(例: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 = { /* ... */ };
  searchConfig = {
    debounceDelay: 500,
    emptyText: 'イベントが見つかりませんでした',
    onSearch: async (keyword: string) => {
      // カスタム非同期検索(例:APIから取得)
      return fetch(`/api/search?q=${keyword}`).then(res => res.json());
    },
  };
}
<script>
  import { DayFlowCalendar } from '@dayflow/svelte';

  const searchConfig = {
    debounceDelay: 500,
    emptyText: 'イベントが見つかりませんでした',
    onSearch: async (keyword) => {
      // カスタム非同期検索(例:APIから取得)
      return fetch(`/api/search?q=${keyword}`).then(res => res.json());
    },
  };
</script>

<DayFlowCalendar {calendar} search={searchConfig} />

検索の設定 (Search Props)

オプション説明
debounceDelay検索を実行するまでのデバウンス時間 (ミリ秒)。
onSearchキーワードに基づいて結果を取得する非同期関数。
customSearchカスタムロジックを使用してローカルでイベントをフィルタリングする同期関数。
onResultClick検索結果をクリックした際の設定可能なコールバック。組み込みの遷移ロジック(イベントの日付への移動、イベントのハイライト、モバイル版での検索UIのクローズ)を実行するための defaultAction コールバックが含まれます。defaultAction() を呼び出さない場合は、遷移やUIの状態管理を独自に実装する必要があります。
emptyText結果が見つからない場合に表示されるテキスト。
timeFormat検索結果表示に使用する時間形式 ('12h' または '24h')。useCalendarApp にグローバルな timeFormat が設定されている場合は、それが優先されます。

サイドバー連携

サイドバーを表示するには、@dayflow/plugin-sidebar プラグインをインストールして plugins に追加します。

import { DayFlowCalendar, useCalendarApp, createWeekView } from '@dayflow/react';
import { createSidebarPlugin } from '@dayflow/plugin-sidebar';

function App() {
  const calendar = useCalendarApp({
    views: [createWeekView()],
    plugins: [
      createSidebarPlugin({
        width: 280,
        initialCollapsed: false,
        createCalendarMode: 'modal', // 'inline' または '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', // 'inline' または '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', // 'inline' または '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', // 'inline' または 'modal'
      }),
    ],
  });
</script>

<DayFlowCalendar {calendar} />
  • createSidebarPlugin() を追加すると、デフォルトのサイドバーが描画されます。
  • 幅や折りたたみ状態のほか、render または renderSidebarHeader による UI のカスタマイズも可能です。renderSidebarHeader を使用すると、サイドバー全体のレイアウトを維持したままヘッダー部分(タイトルや折りたたみボタン)のみを置き換えることができます。

イベント詳細 UI

DayFlow には 3 つのイベント詳細表示オプションがあります。

  1. デフォルトパネルモードuseEventDetailDialogfalse(デフォルト)の場合、イベント詳細を開くと組み込みのフローティングパネル DefaultEventDetailPanel が表示されます。デスクトップではデフォルトでダブルクリック(eventDetailTrigger: 'dbClick')で開き、eventDetailTrigger: 'click' を設定するとシングルクリックで開きます。タッチ入力では常にタップで開きます。
  2. ダイアログモードuseCalendarAppuseEventDetailDialog: true を設定すると組み込みのモーダルが有効になります。eventDetailDialog スロットで独自のダイアログ UI に置き換えられます。
  3. 完全に無効化 — アプリ側のコールバックで独自のモーダルを管理している場合は、useCalendarAppuseEventDetailPanel: false を設定するとフローティングパネルを完全に非表示にできます。
// 組み込みパネルを非表示にする — 別の場所でモーダルを管理
const calendar = useCalendarApp({
  ...
  useEventDetailPanel: false,
});

return <DayFlowCalendar calendar={calendar} />;
// カスタムパネルコンテンツ(デフォルトのパネル外枠を維持)
<DayFlowCalendar
  calendar={calendar}
  eventDetailContent={({ event, onClose }) => (
    <div className='p-4'>
      <h2>{event.title}</h2>
      <button onClick={onClose}>閉じる</button>
    </div>
  )}
/>
<template>
  <DayFlowCalendar :calendar="calendar">
    <!-- カスタムパネルコンテンツ(デフォルトのパネル外枠を維持) -->
    <template #eventDetailContent="{ event, onClose }">
      <div class="p-4">
        <h2>{{ event.title }}</h2>
        <button @click="onClose">閉じる</button>
      </div>
    </template>
  </DayFlowCalendar>
</template>

<script setup>
import { DayFlowCalendar } from '@dayflow/vue';
</script>
import { Component } from '@angular/core';
import { DayFlowCalendarModule } from '@dayflow/angular';

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [DayFlowCalendarModule],
  template: `
    <dayflow-calendar
      [calendar]="calendar"
      [eventDetailContent]="detailTemplate"
    >
    </dayflow-calendar>

    <!-- カスタムパネルコンテンツ(デフォルトのパネル外枠を維持) -->
    <ng-template #detailTemplate let-args>
      <div class="p-4">
        <h2>{{ args.event.title }}</h2>
        <button (click)="args.onClose()">閉じる</button>
      </div>
    </ng-template>
  `
})
export class AppComponent {
  calendar = { /* ... */ };
}
<!-- App.svelte -->
<script lang="ts">
  import { DayFlowCalendar } from '@dayflow/svelte';
  import CustomDetailContent from './CustomDetailContent.svelte';
</script>

<DayFlowCalendar {calendar} eventDetailContent={CustomDetailContent} />

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

<!-- カスタムパネルコンテンツ(デフォルトのパネル外枠を維持) -->
<div class="p-4">
  <h2>{event.title}</h2>
  <button onclick={onClose}>閉じる</button>
</div>
// カスタムダイアログ(useCalendarApp で useEventDetailDialog: true が必要)
<DayFlowCalendar
  calendar={calendar}
  eventDetailDialog={({ event, isOpen, onClose }) => (
    <MyDialog isOpen={isOpen} onClose={onClose}>
      <EventForm event={event} />
    </MyDialog>
  )}
/>
<template>
  <DayFlowCalendar :calendar="calendar">
    <!-- カスタムダイアログ(useCalendarApp で useEventDetailDialog: true が必要) -->
    <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>
import { Component } from '@angular/core';
import { DayFlowCalendarModule } from '@dayflow/angular';

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [DayFlowCalendarModule, MyDialogComponent, EventFormComponent],
  template: `
    <dayflow-calendar
      [calendar]="calendar"
      [eventDetailDialog]="dialogTemplate"
    >
    </dayflow-calendar>

    <!-- カスタムダイアログ(useCalendarApp で useEventDetailDialog: true が必要) -->
    <ng-template #dialogTemplate let-args>
      <app-my-dialog [isOpen]="args.isOpen" (close)="args.onClose()">
        <app-event-form [event]="args.event"></app-event-form>
      </app-my-dialog>
    </ng-template>
  `
})
export class AppComponent {
  calendar = { /* ... */ };
}
<!-- App.svelte -->
<script lang="ts">
  import { DayFlowCalendar } from '@dayflow/svelte';
  import CustomDetailDialog from './CustomDetailDialog.svelte';
</script>

<DayFlowCalendar {calendar} eventDetailDialog={CustomDetailDialog} />

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

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

<!-- カスタムダイアログ(useCalendarApp で useEventDetailDialog: true が必要) -->
<MyDialog {isOpen} onclose={onClose}>
  <EventForm {event} />
</MyDialog>

つまり DayFlowCalendar は「レイアウトと補助 UI の制御」を一手に引き受け、開発者は useCalendarApp の設定や周辺 UI に集中できるようになっています。

関連ドキュメント

On this page