### Run Development Server Source: https://github.com/dayflow-js/calendar/blob/main/website/README.md Use these commands to start the development server for your Next.js application. Ensure you have Node.js and npm, pnpm, or yarn installed. ```bash npm run dev # or pnpm dev # or yarn dev ``` -------------------------------- ### Start CalDAV Proxy with Environment Variables Source: https://github.com/dayflow-js/calendar/blob/main/website/content/docs/caldav/caldav.mdx Example command to launch the Node.js CalDAV proxy server. Ensure that the CalDAV server URL, username, and password are provided as environment variables. ```bash CALDAV_BASE_URL=https://caldav.icloud.com \ CALDAV_USERNAME=alice@icloud.com \ CALDAV_PASSWORD=xxxx-xxxx-xxxx-xxxx \ node proxy.mjs ``` -------------------------------- ### Run create-dayflow CLI with pnpm Source: https://github.com/dayflow-js/calendar/blob/main/packages/create-dayflow/README.md Initiate the DayFlow setup wizard using pnpm. This command ensures the correct adapter and plugins are installed for your project. ```bash pnpm dlx create-dayflow ``` -------------------------------- ### Advanced Calendar Configuration Example Source: https://github.com/dayflow-js/calendar/blob/main/website/content/docs/introduction/use-calendar-app.mdx An advanced example demonstrating the integration of multiple views, custom calendars, plugins, and callbacks for a comprehensive calendar application setup. ```tsx import { useCalendarApp, DayFlowCalendar, createMonthView, createWeekView, ViewType, } from '@dayflow/react'; // or '@dayflow/vue', '@dayflow/svelte', '@dayflow/angular' import { createSidebarPlugin } from '@dayflow/plugin-sidebar'; import '@dayflow/core/dist/styles.css'; const calendars = [ { id: 'work', name: 'Work', colors: { eventColor: '#2563eb', eventSelectedColor: '#1d4ed8', lineColor: '#1e40af', textColor: '#ffffff', }, }, { id: 'personal', name: 'Personal', colors: { eventColor: '#f97316', eventSelectedColor: '#ea580c', lineColor: '#c2410c', textColor: '#ffffff', }, }, ]; export function AdvancedCalendar() { const calendar = useCalendarApp({ views: [createMonthView(), createWeekView()], defaultView: ViewType.WEEK, initialDate: new Date('2024-10-01'), events: [], calendars, defaultCalendar: 'work', switcherMode: 'select', callbacks: { onEventUpdate: event => api.events.update(event), onVisibleRangeChange: (start, end, reason) => preloadVisibleRange(start, end, reason), }, plugins: [ createSidebarPlugin({ width: 280, initialCollapsed: false, }), ], useEventDetailDialog: true, }); return ; } ``` -------------------------------- ### Start Development Server Source: https://github.com/dayflow-js/calendar/blob/main/CONTRIBUTING.md Navigate to the core package and start the development server using pnpm. The application will be available at http://localhost:5529. ```bash cd packages/core pnpm run dev ``` -------------------------------- ### CalDAV Configuration for Backend Source: https://github.com/dayflow-js/calendar/blob/main/website/content/docs/caldav/overview.mdx Configuration examples for different CalDAV providers. These environment variables should be kept on the backend and not sent to the browser. Specific providers may have recommended setup methods. ```bash # iCloud CALDAV_BASE_URL=https://caldav.icloud.com/ CALDAV_USERNAME=alice@icloud.com CALDAV_PASSWORD=xxxx-xxxx-xxxx-xxxx # Nextcloud # CALDAV_BASE_URL=https://nextcloud.example.com/remote.php/dav/ # CALDAV_USERNAME=alice # CALDAV_PASSWORD=nextcloud-app-password # Radicale # CALDAV_BASE_URL=https://radicale.example.com/ # Fastmail # CALDAV_BASE_URL=https://caldav.fastmail.com/dav/ ``` -------------------------------- ### Install Project Dependencies Source: https://github.com/dayflow-js/calendar/blob/main/CONTRIBUTING.md Install all necessary project dependencies using pnpm. This command should be run after cloning the repository. ```bash pnpm install ``` -------------------------------- ### Start Proxy Server Source: https://github.com/dayflow-js/calendar/blob/main/website/content/docs/caldav/google-sync.mdx Command to start the Node.js proxy server for testing with a provided access token. ```bash # Quick test with an access token GOOGLE_ACCESS_TOKEN=ya29.xxx node proxy.mjs ``` -------------------------------- ### Advanced Calendar Configuration Example Source: https://github.com/dayflow-js/calendar/blob/main/website/content/docs-zh/introduction/use-calendar-app.mdx An example demonstrating advanced setup of the DayFlow Calendar with multiple views, custom calendars, plugins like the sidebar, and event callbacks. This configuration is suitable for complex application requirements. ```tsx import { useCalendarApp, DayFlowCalendar, createMonthView, createWeekView, ViewType, } from '@dayflow/react'; // or '@dayflow/vue', '@dayflow/svelte', '@dayflow/angular' import { createSidebarPlugin } from '@dayflow/plugin-sidebar'; import '@dayflow/core/dist/styles.css'; const calendars = [ { id: 'work', name: '工作', colors: { eventColor: '#2563eb', eventSelectedColor: '#1d4ed8', lineColor: '#1e40af', textColor: '#ffffff', }, }, { id: 'personal', name: '个人', colors: { eventColor: '#f97316', eventSelectedColor: '#ea580c', lineColor: '#c2410c', textColor: '#ffffff', }, }, ]; export function AdvancedCalendar() { const calendar = useCalendarApp({ views: [createMonthView(), createWeekView()], defaultView: ViewType.WEEK, initialDate: new Date('2024-10-01'), events: [], calendars, defaultCalendar: 'work', switcherMode: 'select', callbacks: { onEventUpdate: event => api.events.update(event), onVisibleRangeChange: (start, end, reason) => preloadVisibleRange(start, end, reason), }, plugins: [ createSidebarPlugin({ width: 280, initialCollapsed: false, }), ], useEventDetailDialog: true, }); return ; } ``` -------------------------------- ### Install Drag & Drop Plugin Source: https://github.com/dayflow-js/calendar/blob/main/website/content/docs/plugins/drag.mdx Install the plugin using your preferred package manager. ```bash ``` -------------------------------- ### Basic Usage Example Source: https://github.com/dayflow-js/calendar/blob/main/website/content/docs/ui/context-menu.mdx Demonstrates how to render the ContextMenu at the cursor position captured from a 'contextmenu' event. ```APIDOC ## Basic Usage Render `ContextMenu` at the cursor position captured from a `contextmenu` event. ### Code Example ```tsx import { useState } from 'react'; import { ContextMenu, ContextMenuItem, ContextMenuSeparator, } from '@dayflow/ui-context-menu'; function MyComponent() { const [menu, setMenu] = useState<{ x: number; y: number } | null>(null); const handleContextMenu = (e: React.MouseEvent) => { e.preventDefault(); setMenu({ x: e.clientX, y: e.clientY }); }; return (
Right-click here {menu && ( setMenu(null)}> console.log('Edit')}>Edit console.log('Copy')}>Copy console.log('Delete')} danger> Delete )}
); } ``` ``` -------------------------------- ### Quick Start: Initialize Google Sync Source: https://github.com/dayflow-js/calendar/blob/main/packages/caldav/google-sync/README.md Demonstrates the basic setup for integrating Google Calendar sync into a DayFlow application. Requires creating an adapter with a base URL and fetch implementation, then attaching the sync controller to the DayFlow app. ```typescript import { attachGoogleSyncToDayFlow, createGoogleSync, createGoogleSyncAdapter, } from '@dayflow/google-sync'; const adapter = createGoogleSyncAdapter({ baseUrl: '/api/google-calendar', fetch, }); const sync = createGoogleSync(adapter); const controller = attachGoogleSyncToDayFlow(calendar.app, sync); await controller.start(); ``` -------------------------------- ### Start the CalDAV Proxy Source: https://github.com/dayflow-js/calendar/blob/main/examples/caldav-proxy/README.md Launches the Node.js CalDAV proxy server. ```sh node proxy.mjs # CalDAV proxy listening on http://localhost:3001/api/caldav ``` -------------------------------- ### Install DayFlow Pro Packages Source: https://github.com/dayflow-js/calendar/blob/main/website/content/docs/introduction/pro-installation.mdx Install the purchased DayFlow Pro packages using your package manager after configuring the private registry. ```bash pnpm add @dayflow-pro/license @dayflow-pro/resource-grid ``` -------------------------------- ### Run create-dayflow CLI with npx Source: https://github.com/dayflow-js/calendar/blob/main/packages/create-dayflow/README.md Use this command to initiate the interactive setup wizard for DayFlow in your project's root directory. ```bash npx create-dayflow ``` -------------------------------- ### Start DayFlow Application Source: https://github.com/dayflow-js/calendar/blob/main/examples/sync-connectivity/README.md Start the DayFlow core application in development mode using pnpm. ```sh pnpm --filter @dayflow/core dev ``` -------------------------------- ### Start the Proxy Server Source: https://github.com/dayflow-js/calendar/blob/main/examples/sync-connectivity/README.md Run the local Node.js proxy server to handle calendar API requests. ```sh node examples/sync-connectivity/proxy.mjs ``` -------------------------------- ### Commit Message Examples Source: https://github.com/dayflow-js/calendar/blob/main/CONTRIBUTING.md Examples of commit messages following the project's prefix convention for features and bug fixes. ```bash feat: add drag-and-drop event support fix: resolve timezone offset issue in calendar view ``` -------------------------------- ### Browser Backend Proxy Example Source: https://github.com/dayflow-js/calendar/blob/main/website/content/docs/caldav/overview.mdx This example demonstrates how the browser communicates with your backend proxy, which then forwards requests to the CalDAV API. The DayFlow sync engine uses an authenticated fetch function provided by your backend. ```typescript const adapter = createCalDAVAdapter({ calendarHomeUrl: 'https://caldav.example.com/calendars/alice/', fetch: (url, init) => fetch('/api/caldav-proxy', { method: 'POST', body: JSON.stringify({ url, init }), }), }); ``` -------------------------------- ### Run create-dayflow CLI with bun Source: https://github.com/dayflow-js/calendar/blob/main/packages/create-dayflow/README.md Launch the DayFlow interactive setup using the bun runtime. This wizard helps in selecting DayFlow plugins and configuring necessary styles. ```bash bun x create-dayflow ``` -------------------------------- ### Context Menu with Labels and Icons Source: https://github.com/dayflow-js/calendar/blob/main/website/content/docs/ui/context-menu.mdx Example showcasing how to use labels and icons within the context menu items. ```APIDOC ## With Labels and Icons ```tsx Actions } onClick={() => onEdit()}> Edit Event } onClick={() => onDuplicate()}> Duplicate } onClick={() => onDelete()} danger> Delete ``` ``` -------------------------------- ### Quick Start: Basic Calendar Integration Source: https://github.com/dayflow-js/calendar/blob/main/website/content/docs/introduction/use-calendar-app.mdx Demonstrates how to initialize and render a basic DayFlow calendar using the useCalendarApp hook with month and week views. ```tsx import { useCalendarApp, DayFlowCalendar, createMonthView, createWeekView, ViewType, } from '@dayflow/react'; // or '@dayflow/vue', '@dayflow/svelte', '@dayflow/angular' import '@dayflow/core/dist/styles.css'; export function TeamCalendar() { const calendar = useCalendarApp({ views: [createMonthView(), createWeekView()], defaultView: ViewType.MONTH, initialDate: new Date(), events: [], }); return ; } ``` -------------------------------- ### Nested Submenus Example Source: https://github.com/dayflow-js/calendar/blob/main/website/content/docs/ui/context-menu.mdx Demonstrates how to create nested submenus using `ContextMenuSub`, `ContextMenuSubTrigger`, and `ContextMenuSubContent`. ```APIDOC ## Nested Submenus Wrap items with `ContextMenuSub` to create hover-triggered submenus. The submenu automatically repositions itself to avoid viewport overflow. ### Code Example ```tsx onEdit()}>Edit Move to onMove('work')}>Work onMove('personal')}>Personal onDelete()}>Delete ``` ``` -------------------------------- ### Quick Start: Configure Switcher Mode Source: https://github.com/dayflow-js/calendar/blob/main/website/content/docs/features/switcher-mode.mdx Demonstrates how to set the `switcherMode` to 'select' for a compact header view. The default mode is 'buttons'. ```tsx import { useCalendarApp, DayFlowCalendar, createMonthView, } from '@dayflow/react'; const calendar = useCalendarApp({ views: [createMonthView()], switcherMode: 'select', // default switcherMode: 'buttons' }); ; ``` -------------------------------- ### Start CalDAV Controller Source: https://github.com/dayflow-js/calendar/blob/main/website/content/docs/caldav/caldav.mdx Initiates the CalDAV controller to discover remote calendars, load initial events, and subscribe to DayFlow changes. Ensure the controller is started before interacting with CalDAV data. ```typescript // Discover remote calendars, load initial events, and subscribe to DayFlow changes await controller.start(); ``` -------------------------------- ### Backend Proxy: Node.js HTTP Server Example Source: https://github.com/dayflow-js/calendar/blob/main/website/content/docs/caldav/google-sync.mdx This Node.js example demonstrates a basic HTTP server acting as a proxy for the Google Calendar API. It handles token refreshing and forwards requests, injecting the Authorization header. ```js // proxy.mjs (Node.js example) import { createServer } from 'node:http'; const { GOOGLE_ACCESS_TOKEN, GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET, GOOGLE_REFRESH_TOKEN, PORT = '3002', } = process.env; const GOOGLE_API_BASE = 'https://www.googleapis.com/calendar/v3'; const ALLOWED_METHODS = new Set(['GET', 'POST', 'PUT', 'PATCH', 'DELETE']); let cachedToken = GOOGLE_ACCESS_TOKEN ? { token: GOOGLE_ACCESS_TOKEN, expiresAt: Infinity } : null; async function getAccessToken() { if (cachedToken && cachedToken.expiresAt > Date.now() + 30_000) { return cachedToken.token; } const res = await fetch('https://oauth2.googleapis.com/token', { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: new URLSearchParams({ client_id: GOOGLE_CLIENT_ID, client_secret: GOOGLE_CLIENT_SECRET, refresh_token: GOOGLE_REFRESH_TOKEN, grant_type: 'refresh_token', }), }); const data = await res.json(); cachedToken = { token: data.access_token, expiresAt: Date.now() + data.expires_in * 1000, }; return cachedToken.token; } createServer(async (req, res) => { const upstreamPath = req.url.replace(/^\/api\/google-calendar/, ''); const upstreamUrl = `${GOOGLE_API_BASE}${upstreamPath}`; if (!ALLOWED_METHODS.has(req.method)) { res.writeHead(405); res.end(); return; } const chunks = []; for await (const chunk of req) chunks.push(chunk); const body = req.method === 'GET' || req.method === 'DELETE' ? undefined : Buffer.concat(chunks).toString(); const token = await getAccessToken(); const upstream = await fetch(upstreamUrl, { method: req.method, headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${token}`, ...(req.headers['if-match'] ? { 'If-Match': req.headers['if-match'] } : {}), }, body, }); const responseBody = upstream.status === 204 ? '' : await upstream.text(); res.writeHead(upstream.status, { 'Content-Type': 'application/json' }); res.end(responseBody); }).listen(Number(PORT)); ``` -------------------------------- ### Run create-dayflow CLI with yarn Source: https://github.com/dayflow-js/calendar/blob/main/packages/create-dayflow/README.md Execute the create-dayflow setup wizard with yarn. It assists in configuring DayFlow components, including framework adapters and optional Tailwind CSS integration. ```bash yarn dlx create-dayflow ``` -------------------------------- ### Basic Dark Mode Setup Source: https://github.com/dayflow-js/calendar/blob/main/website/content/docs/features/dark-mode.mdx Enable dark mode by setting the `theme.mode` configuration to 'dark' when initializing the calendar. ```APIDOC ## Basic Dark Mode Setup ### Description Enable dark mode by setting the `theme.mode` configuration to 'dark' when initializing the calendar. ### Configuration ```typescript interface ThemeConfig { mode: 'light' | 'dark' | 'auto'; } const calendar = useCalendarApp({ theme: { mode: 'dark', }, }); ``` ``` -------------------------------- ### Color Picker Integration Source: https://github.com/dayflow-js/calendar/blob/main/website/content/docs/ui/context-menu.mdx Example of integrating the `ContextMenuColorPicker` for selecting calendar colors. ```APIDOC ## Color Picker `ContextMenuColorPicker` renders a row of preset swatches and an optional "Custom Color" action. ### Code Example ```tsx Calendar Color { updateCalendarColor(color); onClose(); }} onCustomColor={() => openColorDialog()} customColorLabel='Custom color...' /> ``` ``` -------------------------------- ### Quick Start: Initialize CalDAV Adapter and Sync Source: https://github.com/dayflow-js/calendar/blob/main/packages/caldav/core/README.md Sets up the CalDAV adapter, sync engine, and attaches it to a DayFlow calendar application. Requires a custom fetch implementation for proxying requests. ```typescript import { attachCalDAVToDayFlow, createCalDAVAdapter, createCalDAVSync, createNamespacedCalDAVEventId, mapCalDAVEventToDayFlow, } from '@dayflow/caldav'; const adapter = createCalDAVAdapter({ calendarHomeUrl: '/calendars/alice/', fetch: (url, init) => fetch('/api/caldav-proxy', { method: 'POST', body: JSON.stringify({ url, init }), }), }); const sync = createCalDAVSync({ adapter, storage, // Optional: split broad visible-range REPORTs into smaller windows. rangeChunkDays: 31, }); const controller = attachCalDAVToDayFlow(calendar.app, sync, { writable: true, refreshOnVisibleRangeChange: true, maxConcurrentCalendars: 4, createEventId: createNamespacedCalDAVEventId, eventMode: { recurring: 'read-only', }, }); await controller.start(); ``` -------------------------------- ### Create a Custom Calendar Plugin Source: https://github.com/dayflow-js/calendar/blob/main/website/content/docs/plugins/overview.mdx Implement the `CalendarPlugin` interface to create custom plugins. The `install` function is called with the `CalendarApp` instance, allowing you to extend its functionality. ```tsx import { CalendarPlugin, ICalendarApp } from '@dayflow/core'; export const myPlugin: CalendarPlugin = { name: 'my-custom-plugin', install(app: ICalendarApp) { console.log('Plugin installed!'); // Extend app functionality here }, }; ``` -------------------------------- ### Token Injection: Backend Proxy Setup Source: https://github.com/dayflow-js/calendar/blob/main/website/content/docs/caldav/google-sync.mdx Configure `createGoogleSyncAdapter` with a `baseUrl` pointing to your backend proxy when tokens are managed server-side. This is recommended for production to avoid exposing tokens in the browser. ```ts const adapter = createGoogleSyncAdapter({ baseUrl: '/api/google-calendar', // No getToken needed — your proxy injects Authorization }); ``` -------------------------------- ### Minimal Non-Tailwind CSS Setup Source: https://github.com/dayflow-js/calendar/blob/main/website/content/docs/guides/theme-customization.mdx Import DayFlow's full CSS bundle for projects not using Tailwind. This bundle includes a CSS reset. ```css /* app.css — for non-Tailwind projects */ @import '@dayflow/core/dist/styles.css'; ``` -------------------------------- ### Initialize Sidebar Plugin Source: https://github.com/dayflow-js/calendar/blob/main/website/content/docs/plugins/sidebar.mdx Import and create an instance of the sidebar plugin. Configure options like width and the create calendar mode. This snippet shows basic setup for React. ```tsx import { useCalendarApp, DayFlowCalendar } from '@dayflow/react'; // or '@dayflow/vue', '@dayflow/svelte', '@dayflow/angular' import { createSidebarPlugin } from '@dayflow/plugin-sidebar'; function MyCalendar() { const sidebarPlugin = createSidebarPlugin({ width: 280, createCalendarMode: 'modal', }); const calendar = useCalendarApp({ views: [ /* your views */ ], plugins: [sidebarPlugin], }); return ; } ``` -------------------------------- ### Multi-Calendar Events Example Source: https://github.com/dayflow-js/calendar/blob/main/website/content/docs/introduction/events.mdx Demonstrates how to assign an event to multiple calendars using `calendarIds`. Events with multiple calendars have distinct visual indicators. ```tsx import { createEvent, useCalendarApp, createWeekView } from '@dayflow/react'; // This event belongs to both "team" and "marketing" calendars const sharedEvent = createEvent({ id: 'shared-1', title: 'Company All-Hands', start: new Date(2024, 9, 15, 10, 0), end: new Date(2024, 9, 15, 11, 30), calendarIds: ['team', 'marketing'], // multi-calendar }); // All-day event spanning three calendars const crossCalendarDay = { id: 'shared-2', title: 'Team Offsite', start: Temporal.PlainDate.from('2024-10-20'), end: Temporal.PlainDate.from('2024-10-22'), allDay: true, calendarIds: ['team', 'personal', 'travel'], }; const calendars = [ { id: 'team', name: 'Team', colors: { eventColor: '#3b82f6', lineColor: '#3b82f6', eventSelectedColor: '#2563eb', textColor: '#fff', }, isVisible: true, }, { id: 'marketing', name: 'Marketing', colors: { eventColor: '#f59e0b', lineColor: '#f59e0b', eventSelectedColor: '#d97706', textColor: '#fff', }, isVisible: true, }, { id: 'personal', name: 'Personal', colors: { eventColor: '#10b981', lineColor: '#10b981', eventSelectedColor: '#059669', textColor: '#fff', }, isVisible: true, }, { id: 'travel', name: 'Travel', colors: { eventColor: '#8b5cf6', lineColor: '#8b5cf6', eventSelectedColor: '#7c3aed', textColor: '#fff', }, isVisible: true, }, ]; const calendar = useCalendarApp({ views: [createWeekView()], events: [sharedEvent, crossCalendarDay], calendars, }); ``` -------------------------------- ### Initialize DayFlow Calendar with Month View Source: https://github.com/dayflow-js/calendar/blob/main/website/content/docs/introduction/views.mdx Set up the DayFlow Calendar component using the Month View. This example shows basic initialization with views and default view settings. ```tsx import { useCalendarApp, DayFlowCalendar, createMonthView, ViewType, } from '@dayflow/react'; // or '@dayflow/vue', '@dayflow/svelte', '@dayflow/angular' function MyCalendar() { const calendar = useCalendarApp({ views: [createMonthView()], defaultView: ViewType.MONTH, initialDate: new Date(), }); return ; } ``` -------------------------------- ### Basic DayFlow Calendar Initialization Source: https://github.com/dayflow-js/calendar/blob/main/website/content/docs/introduction/index.mdx Initialize the DayFlow Calendar with views, plugins, calendar definitions, and initial events. This setup is suitable for basic calendar integration. ```javascript const calendar = useCalendarApp({ views: [createDayView(), createWeekView(), createMonthView()], plugins: [createDragPlugin(), createEventsPlugin()], calendars: [ { id: 'work', name: 'Work', colors: { lineColor: '#2563eb', eventColor: '#dbeafe', eventSelectedColor: '#bfdbfe', textColor: '#1e3a8a', }, }, ], events: [ createEvent({ id: '1', title: 'Team Meeting', start: new Date(2025, 10, 15, 10, 0), end: new Date(2025, 10, 15, 11, 0), calendarId: 'work', }), createAllDayEvent({ id: '2', title: 'Conference', start: new Date(2025, 10, 20), calendarId: 'work', }), ], initialDate: new Date(), }); ``` -------------------------------- ### Configure Private npm Registry Source: https://github.com/dayflow-js/calendar/blob/main/website/content/docs/introduction/pro-installation.mdx Add your DayFlow Pro npm token to your `.npmrc` file to enable installation of private packages. Ensure the `DAYFLOW_PRO_NPM_TOKEN` environment variable is set. ```ini @dayflow-pro:registry=https://gitlab.com/api/v4/projects/81880038/packages/npm/ //gitlab.com/api/v4/projects/81880038/packages/npm/:_authToken=${DAYFLOW_PRO_NPM_TOKEN} ``` -------------------------------- ### CalDAV Controller API Source: https://github.com/dayflow-js/calendar/blob/main/website/content/docs/caldav/caldav.mdx API for controlling the CalDAV synchronization process, including starting, stopping, refreshing, and getting sync status. ```APIDOC ## Controller API ### Description API for controlling the CalDAV synchronization process, including starting, stopping, refreshing, and getting sync status. ### Methods - **`controller.start()`** - Description: Discover remote calendars, load initial events, and subscribe to DayFlow changes. - Usage: `await controller.start();` - **`controller.stop()`** - Description: Unsubscribe all listeners (does not clear DayFlow state). - Usage: `controller.stop();` - **`controller.refresh(options?: { calendarId?: string; range?: { start: Date; end: Date } })`** - Description: Re-sync calendars. Can be used to re-sync all calendars, a specific calendar, or with an explicit date range. - Usage: - `await controller.refresh();` (Re-sync all calendars using the last known visible range) - `await controller.refresh({ calendarId: 'my-calendar-id' });` (Re-sync a specific calendar) - `await controller.refresh({ range: { start: new Date('2025-01-01'), end: new Date('2025-02-01') } });` (Re-sync with an explicit date range) - **`controller.getStatus()`** - Description: Get current sync status. - Returns: `{ state: 'idle' | 'syncing' | 'error', lastSyncedAt?: Date, error?: unknown }` - Usage: `const status = controller.getStatus();` ``` -------------------------------- ### Use Pro Packages in React Component Source: https://github.com/dayflow-js/calendar/blob/main/website/content/docs/introduction/pro-installation.mdx Integrate DayFlow Pro packages, such as the resource grid view, into your React application after installation and license registration. This example demonstrates creating and using a resource grid view within a DayFlow Calendar component. ```tsx import { DayFlowCalendar, useCalendarApp } from '@dayflow/react'; import { createResourceGridView } from '@dayflow-pro/resource-grid'; function App() { const calendar = useCalendarApp({ views: [ createResourceGridView({ mode: 'resourceView', resources: [ { id: 'room-a', title: 'Room A' }, { id: 'room-b', title: 'Room B' }, ], }), ], }); return ; } ``` -------------------------------- ### Initialize Keyboard Shortcuts Plugin Source: https://github.com/dayflow-js/calendar/blob/main/website/content/docs/plugins/keyboard-shortcuts.mdx Import and create the keyboard shortcuts plugin, optionally providing configuration. This is typically done within the `useCalendarApp` hook. ```tsx import { useCalendarApp, DayFlowCalendar } from '@dayflow/react'; import { createKeyboardShortcutsPlugin } from '@dayflow/plugin-keyboard-shortcuts'; function MyCalendar() { const calendar = useCalendarApp({ // ... plugins: [ createKeyboardShortcutsPlugin({ // Optional configuration }), ], }); return ; } ``` -------------------------------- ### Install Latest Dayflow Core Source: https://github.com/dayflow-js/calendar/blob/main/website/content/blog/v2.0.3.mdx Update to the latest version of @dayflow/core to use the new Year View features. This command installs the most recent stable release. ```bash npm install @dayflow/core@latest ``` -------------------------------- ### Quick Start: Initialize Google Sync in React Source: https://github.com/dayflow-js/calendar/blob/main/website/content/docs/caldav/google-sync.mdx This snippet shows how to initialize and attach the Google Sync controller to a DayFlow calendar instance within a React component. It handles starting and stopping the sync process and logging status changes and errors. ```tsx import { useRef, useEffect, useState } from 'react'; import { DayFlowCalendar, useCalendarApp, createMonthView, } from '@dayflow/react'; import { attachGoogleSyncToDayFlow, createGoogleSync, createGoogleSyncAdapter, type GoogleDayFlowController, type GoogleSyncStatus, } from '@dayflow/google-sync'; function MyCalendar() { const calendar = useCalendarApp({ views: [createMonthView()], calendars: [], events: [], }); const controllerRef = useRef(null); const [syncStatus, setSyncStatus] = useState({ state: 'idle', }); useEffect(() => { if (controllerRef.current) return; const adapter = createGoogleSyncAdapter({ baseUrl: '/api/google-calendar', }); const sync = createGoogleSync(adapter); const controller = attachGoogleSyncToDayFlow(calendar.app, sync, { writable: true, onStatusChange: setSyncStatus, onWriteError: (error, ctx) => console.error(`[google-sync] ${ctx.action} failed:`, error.message), onSyncComplete: delta => { console.log( `Sync done: +${delta.events.added} ~${delta.events.updated} -${delta.events.deleted}` ); }, }); controllerRef.current = controller; controller.start(); return () => { controller.stop(); controllerRef.current = null; }; }, [calendar.app]); return ; } ``` -------------------------------- ### Quick Start: Initialize Outlook Sync in React Source: https://github.com/dayflow-js/calendar/blob/main/website/content/docs/caldav/outlook-sync.mdx This snippet demonstrates how to initialize and attach the Outlook sync controller within a React component. It sets up the adapter, creates the sync instance, and attaches it to the DayFlow calendar app, starting the sync process. ```tsx import { useRef, useEffect, useState } from 'react'; import { DayFlowCalendar, useCalendarApp, createMonthView, } from '@dayflow/react'; import { attachOutlookSyncToDayFlow, createOutlookSync, createOutlookSyncAdapter, type OutlookDayFlowController, type OutlookSyncStatus, } from '@dayflow/outlook-sync'; function MyCalendar() { const calendar = useCalendarApp({ views: [createMonthView()], calendars: [], events: [], }); const controllerRef = useRef(null); const [syncStatus, setSyncStatus] = useState({ state: 'idle', }); useEffect(() => { if (controllerRef.current) return; const adapter = createOutlookSyncAdapter({ baseUrl: '/api/outlook-calendar', }); const sync = createOutlookSync(adapter); const controller = attachOutlookSyncToDayFlow(calendar.app, sync, { writable: true, onStatusChange: setSyncStatus, onWriteError: (error, ctx) => console.error(`[outlook-sync] ${ctx.action} failed:`, error.message), onSyncComplete: delta => { console.log( `Sync done: +${delta.events.added} ~${delta.events.updated} -${delta.events.deleted}` ); }, }); controllerRef.current = controller; controller.start(); return () => { controller.stop(); controllerRef.current = null; }; }, [calendar.app]); return ; } ``` -------------------------------- ### DayFlow Controller API for Google Sync Source: https://github.com/dayflow-js/calendar/blob/main/website/content/docs/caldav/google-sync.mdx Demonstrates essential controller methods for managing Google Calendar synchronization, including starting, stopping, and refreshing sync operations. Use `start()` to initiate sync, `stop()` to halt it, and `refresh()` to re-sync calendars or specific events. ```typescript // Load calendars, sync initial events, and subscribe to visible-range and event changes await controller.start(); // Unsubscribe all listeners controller.stop(); // Re-sync all calendars for the current visible range await controller.refresh(); // Re-sync a specific calendar await controller.refresh({ calendarId: 'primary' }); // Re-sync with an explicit range await controller.refresh({ calendarId: 'primary', range: { start: new Date('2025-01-01'), end: new Date('2025-02-01') }, }); // Current sync state const status = controller.getStatus(); ``` -------------------------------- ### Nextcloud CalDAV Discovery Flow Source: https://github.com/dayflow-js/calendar/blob/main/examples/caldav-proxy/README.md Demonstrates how to discover the calendar home set using a PROPFIND request with cURL. ```sh curl -u alice:app-token \ -X PROPFIND \ -H "Depth: 0" \ -H "Content-Type: application/xml" \ https://nextcloud.example.com/dav/principals/users/alice/ \ --data '' ``` -------------------------------- ### Quick Start: Integrate CalDAV with DayFlow React Calendar Source: https://github.com/dayflow-js/calendar/blob/main/website/content/docs/caldav/caldav.mdx This snippet shows how to initialize and attach a CalDAV adapter to a DayFlow calendar in a React application. It includes setting up the adapter with a proxy fetch, creating a sync engine, and starting the synchronization process. Ensure a '/api/caldav-proxy' endpoint is available to handle CalDAV requests. ```tsx import { useRef, useEffect } from 'react'; import { DayFlowCalendar, useCalendarApp, createMonthView, } from '@dayflow/react'; import { attachCalDAVToDayFlow, createCalDAVAdapter, createCalDAVSync, type CalDAVDayFlowController, } from '@dayflow/caldav'; function MyCalendar() { const calendar = useCalendarApp({ views: [createMonthView()], calendars: [], events: [], }); const controllerRef = useRef(null); useEffect(() => { if (controllerRef.current) return; const adapter = createCalDAVAdapter({ calendarHomeUrl: 'https://caldav.example.com/calendars/alice/', fetch: (url, init) => fetch('/api/caldav-proxy', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ url, init }), }), }); const sync = createCalDAVSync({ adapter }); const controller = attachCalDAVToDayFlow(calendar.app, sync, { writable: true, maxConcurrentCalendars: 4, onSyncComplete: delta => { console.log( `Sync done: +${delta.events.added} ~${delta.events.updated} -${delta.events.deleted}` ); }, }); controllerRef.current = controller; controller.start(); return () => { controller.stop(); controllerRef.current = null; }; }, [calendar.app]); return ; } ``` -------------------------------- ### CalDAV Provider Presets for Adapter Creation Source: https://github.com/dayflow-js/calendar/blob/main/website/content/docs/caldav/caldav.mdx This snippet demonstrates using built-in presets to simplify the creation of CalDAV adapters for common providers like iCloud, Nextcloud, Radicale, and Fastmail. For iCloud, dynamic discovery is mandatory. Ensure your `fetch` function handles authentication and CORS proxying if necessary. ```ts import { ICLOUD_CALDAV_SERVER, createCalDAVAdapterFromServer, nextcloudConfig, radicaleConfig, fastmailConfig, createCalDAVAdapter, } from '@dayflow/caldav'; // iCloud — must always discover dynamically const icloudAdapter = await createCalDAVAdapterFromServer( ICLOUD_CALDAV_SERVER, { fetch: proxiedFetch } ); // Nextcloud const nextcloudAdapter = createCalDAVAdapter({ ...nextcloudConfig('https://nextcloud.example.com', 'alice'), fetch: proxiedFetch, }); // Radicale const radicaleAdapter = createCalDAVAdapter({ ...radicaleConfig('https://radicale.example.com', 'alice'), fetch: proxiedFetch, }); // Fastmail const fastmailAdapter = createCalDAVAdapter({ ...fastmailConfig('https://caldav.fastmail.com/dav', 'alice@fastmail.com'), fetch: proxiedFetch, }); ``` -------------------------------- ### Disabled Context Menu Item Source: https://github.com/dayflow-js/calendar/blob/main/website/content/docs/ui/context-menu.mdx Example showing how to disable a context menu item based on a condition. ```APIDOC ## Disabled Items ```tsx onPaste()} disabled={!hasClipboard}> Paste ``` ``` -------------------------------- ### Get Events Source: https://github.com/dayflow-js/calendar/blob/main/website/content/docs/introduction/events.mdx Retrieve all events currently managed by the calendar instance or access the current state of events directly. ```tsx // Get all events const events = calendar.getEvents(); // Get current events from state const { events } = calendar; ``` -------------------------------- ### Basic Resource Grid Usage Source: https://github.com/dayflow-js/calendar/blob/main/website/content/docs/introduction/resource-grid.mdx Demonstrates how to set up the DayFlow Calendar with the resource grid view, defining resources and basic view configurations. ```tsx import { DayFlowCalendar, useCalendarApp } from '@dayflow/react'; import { createResourceGridView } from '@dayflow/pro/resource-grid'; function App() { const calendar = useCalendarApp({ views: [ createResourceGridView({ mode: 'resourceView', resources: [ { id: 'room-a', title: 'Room A' }, { id: 'room-b', title: 'Room B' }, ], visibleDays: 3, hourHeight: 72, firstHour: 8, lastHour: 20, }), ], }); return ; } ``` -------------------------------- ### CalDAV Adapter Creation with Server Discovery Source: https://github.com/dayflow-js/calendar/blob/main/website/content/docs/caldav/caldav.mdx Use `createCalDAVAdapterFromServer` for servers like iCloud that require dynamic discovery of the calendar home URL. This function performs the necessary PROPFIND requests in a single step. The `fetch` function must be provided to handle the actual HTTP requests, including authentication. ```ts import { createCalDAVAdapterFromServer, ICLOUD_CALDAV_SERVER, } from '@dayflow/caldav'; const adapter = await createCalDAVAdapterFromServer(ICLOUD_CALDAV_SERVER, { fetch: proxiedFetch, }); ``` -------------------------------- ### createCalDAVAdapterFromServer Options Source: https://github.com/dayflow-js/calendar/blob/main/website/content/docs/caldav/caldav.mdx Options for creating a CalDAV adapter from a server URL, performing internal discovery. ```APIDOC ## `createCalDAVAdapterFromServer` Options ### Description Options for creating a CalDAV adapter from a server URL, performing internal discovery. Performs discovery internally and returns a ready `CalDAVAdapter`. ### Parameters - **`serverUrl`** (string) - Required - CalDAV server root URL (e.g. `ICLOUD_CALDAV_SERVER`). - **`options`** (object) - Required - Same as `createCalDAVAdapter` options, minus `calendarHomeUrl`. ``` -------------------------------- ### Controller API Usage Source: https://github.com/dayflow-js/calendar/blob/main/website/content/docs/caldav/outlook-sync.mdx Demonstrates essential controller methods for managing Outlook calendar synchronization, including starting, stopping, and refreshing calendars. ```typescript // Load calendars, sync initial events, and subscribe to changes await controller.start(); ``` ```typescript // Unsubscribe all listeners controller.stop(); ``` ```typescript // Re-sync all calendars for the current visible range await controller.refresh(); ``` ```typescript // Re-sync a specific calendar await controller.refresh({ calendarId: 'AAMk...' }); ``` ```typescript // Re-sync with an explicit range await controller.refresh({ range: { start: new Date('2025-01-01'), end: new Date('2025-02-01') }, }); ``` ```typescript // Current sync state const status = controller.getStatus(); ``` -------------------------------- ### Initialize and Use Drag Plugin Source: https://github.com/dayflow-js/calendar/blob/main/website/content/docs/plugins/drag.mdx Initialize the drag plugin with desired configurations and add it to the calendar's plugins array. This enables drag, resize, and create functionalities. ```typescript import { useCalendarApp, ViewType } from '@dayflow/react'; // or '@dayflow/vue', '@dayflow/svelte', '@dayflow/angular' import { createDragPlugin } from '@dayflow/plugin-drag'; function MyCalendar() { const dragPlugin = createDragPlugin({ enableDrag: true, enableResize: true, enableCreate: true, onEventDrop: (updated, original) => { console.log('Event moved:', updated); }, onEventResize: (updated, original) => { console.log('Event resized:', updated); }, }); const calendar = useCalendarApp({ // ... views plugins: [dragPlugin], }); // ... } ``` -------------------------------- ### Milestone Event Configuration Source: https://github.com/dayflow-js/calendar/blob/main/website/content/docs/introduction/resource-timeline.mdx Define an event as a milestone by setting its start and end dates to be equal. This configuration is used to automatically render events as milestones. ```tsx const milestone = { id: 'release-gate', title: 'Release approval', start: new Date(2026, 4, 14, 10, 0), end: new Date(2026, 4, 14, 10, 0), resourceId: 'eng-bob', }; ``` -------------------------------- ### Custom All-Day Event Sorting Source: https://github.com/dayflow-js/calendar/blob/main/website/content/docs/introduction/use-calendar-app.mdx Provide a custom comparator function to control the order of all-day events. This example sorts events alphabetically by title. ```tsx const calendar = useCalendarApp({ allDaySortComparator: (a, b) => a.title.localeCompare(b.title), }); ``` -------------------------------- ### Radicale CalDAV Configuration Source: https://github.com/dayflow-js/calendar/blob/main/examples/caldav-proxy/README.md Sets the base URL for Radicale and the calendar home URL for client-side integration. Notes on read-only defaults are provided. ```text CALDAV_BASE_URL=https://radicale.example.com ``` ```typescript const CALENDAR_HOME_URL = '/alice/'; ``` -------------------------------- ### Override Specific i18n Messages Source: https://github.com/dayflow-js/calendar/blob/main/website/content/blog/v1.7.mdx Provide custom messages to the DayFlowCalendar component to override specific terms in the current locale. This example overrides 'today' and 'newEvent'. ```tsx const customMessages = { today: 'Today!', newEvent: 'New Appointment', // ... override other keys }; return ; ``` -------------------------------- ### CalDAV Proxy Architecture Source: https://github.com/dayflow-js/calendar/blob/main/examples/caldav-proxy/README.md Illustrates the request flow from the browser through the backend proxy to the CalDAV server, highlighting where credentials are injected. ```text Browser (DayFlow + @dayflow/caldav) → POST /api/caldav { url, init } (no auth) ↓ Backend proxy (proxy.mjs) → PROPFIND https://nextcloud.example.com/dav/... + Authorization: Basic ... (credentials injected here) ↓ CalDAV server ``` -------------------------------- ### Set Locale with Language Code String Source: https://github.com/dayflow-js/calendar/blob/main/website/content/blog/v1.7.mdx Initialize the calendar app with a language code string to use built-in translations. Example uses Japanese ('ja'). ```typescript const calendar = useCalendarApp({ // ... other config locale: 'ja', // Set locale to Japanese }); ``` -------------------------------- ### Programmatic Theme Changes Source: https://github.com/dayflow-js/calendar/blob/main/website/content/docs/introduction/use-calendar-app.mdx Control the calendar's theme programmatically. You can get the current theme, set a new theme, and subscribe to theme change events. ```javascript // Get current theme const currentTheme = calendar.app.getTheme(); // Set theme calendar.app.setTheme('dark'); // Subscribe to theme changes calendar.app.subscribeThemeChange(theme => { console.log('Theme changed to:', theme); }); ```