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 | 型 | 必須 | 説明 |
|---|---|---|---|
calendar | UseCalendarAppReturn | 必須 | useCalendarApp の戻り値。状態やビュー、アクションを内包。 |
collapsedSafeAreaLeft | number | 任意 | サイドバー折りたたみ時の左パディング(px)。Mac のトラフィックライト領域の考慮に使用。 |
search | CalendarSearchProps | 任意 | 組み込み検索機能の設定。 |
検索設定
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 つのイベント詳細表示オプションがあります。
- デフォルトパネルモード —
useEventDetailDialogがfalse(デフォルト)の場合、イベント詳細を開くと組み込みのフローティングパネルDefaultEventDetailPanelが表示されます。デスクトップではデフォルトでダブルクリック(eventDetailTrigger: 'dbClick')で開き、eventDetailTrigger: 'click'を設定するとシングルクリックで開きます。タッチ入力では常にタップで開きます。 - ダイアログモード —
useCalendarAppでuseEventDetailDialog: trueを設定すると組み込みのモーダルが有効になります。eventDetailDialogスロットで独自のダイアログ UI に置き換えられます。 - 完全に無効化 — アプリ側のコールバックで独自のモーダルを管理している場合は、
useCalendarAppでuseEventDetailPanel: 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 に集中できるようになっています。
関連ドキュメント
- useCalendarApp - カレンダーアプリ Hook
- クイックスタート - セットアップガイド
- ビュー - 利用可能なビュー